#include "schedule.h"
#include "task.h"

#define task0_mask 0x0000
#define task1_mask 0x0001
#define task2_mask 0x0003
#define task3_mask 0x0007
#define task4_mask 0x000F
#define task5_mask 0x001F
#define task6_mask 0x003F
#define task7_mask 0x007F
#define task8_mask 0x00FF

#define TASK_MAX_QTY 8

typedef struct
{

    uint32_t period;
    uint32_t delay;
} tag_task_list;

typedef union
{
    struct
    {
        uint8_t task0_flag : 1;
        uint8_t task1_flag : 1;
        uint8_t task2_flag : 1;
        uint8_t task3_flag : 1;
        uint8_t task4_flag : 1;
        uint8_t task5_flag : 1;
        uint8_t task6_flag : 1;
        uint8_t task7_flag : 1;
        uint8_t task8_flag : 1;
    } bits;

    uint8_t all;
} tag_tscw;

tag_task_list task_list[TASK_MAX_QTY];
tag_tscw      tscw;

void schedule(void)
{
    if (tscw.bits.task0_flag)
    {
        task0();
        tscw.bits.task0_flag = 0;
    }
    if (tscw.bits.task1_flag && (!(tscw.all & task1_mask)))
    {
        task1();
        tscw.bits.task1_flag = 0;
    }
    if (tscw.bits.task2_flag && (!(tscw.all & task2_mask)))
    {
        task2();
        tscw.bits.task2_flag = 0;
    }
    if (tscw.bits.task3_flag && (!(tscw.all & task3_mask)))
    {
        task3();
        tscw.bits.task3_flag = 0;
    }
    if (tscw.bits.task4_flag && (!(tscw.all & task4_mask)))
    {
        task4();
        tscw.bits.task4_flag = 0;
    }
    if (tscw.bits.task5_flag && (!(tscw.all & task5_mask)))
    {
        task5();
        tscw.bits.task5_flag = 0;
    }
    if (tscw.bits.task6_flag && (!(tscw.all & task6_mask)))
    {
        task6();
        tscw.bits.task6_flag = 0;
    }
    if (tscw.bits.task7_flag && (!(tscw.all & task7_mask)))
    {
        task7();
        tscw.bits.task7_flag = 0;
    }
    task8();
}

void schedule_init(uint32_t task_period)
{
    uint32_t i;
    for (i = 0; i < TASK_MAX_QTY; i++)
    {
        task_list[i].period = task_ass[i][0] / task_period;
        task_list[i].delay  = task_ass[i][1] / task_period;
    }
}

void schedule_clock(void)
{
    static volatile uint32_t sys_tick_count = 0;
    uint8_t                  i              = 0;
    sys_tick_count++;
    for (i = 0; i < TASK_MAX_QTY; i++)
    {
        if (sys_tick_count % task_list[i].period == task_list[i].delay)
        {
            tscw.all |= 0x01 << i;
        }
    }

    if (sys_tick_count > 4000000000)
    {
        sys_tick_count = 0;
    }
}
