/*
* scheduler.cpp
*
* Created on: 17-Feb-2011
* Author: nrqm
* Based on code by Jacob Schwartz
* Modified on: 16 Aug 2013
* Auther: MHMC
*/
#include "scheduler.h"
#include "../include/includes.h"
#include "sdio_hardware.h"
#include "sdio_typedef.h"
// a descriptor for each "task" (time-triggered callback function)
typedef struct {
S32 period;
S32 remaining_time;
task_cb callback;
} task_t;
U8 next_task; // next entry in "tasks" that is not used
task_t tasks[MAXTASKS];
U32 last_runtime; // last updated current time
void Scheduler_Init(void)
{
last_runtime = now; // get the current time "now" in milliseconds
next_task = 0;
}
void Scheduler_StartTask(S16 start, S16 period, task_cb task)
{
if (next_task == MAXTASKS) return;
tasks[next_task].remaining_time = start;
tasks[next_task].period = period;
tasks[next_task].callback = task;
++next_task;
}
U32 min(U32 a,U32 b)
{
if(a>=b)
return b;
else
return a;
}
U32 Scheduler_Dispatch()
{
U8 i;
U32 ct = now; // get the current time again
U32 elapsed = ct - last_runtime; // how many milliseconds have elapsed since last "Dispatch()"?
last_runtime = ct;
task_cb running = NULL;
U32 idle_time = 0xFFFF;
// update each task's remaining time, and identify the "first" expired task (if there is one).
for (i = 0; i < next_task; i++)
{
// update the task's remaining time
tasks[i].remaining_time -= elapsed;
if (tasks[i].remaining_time <= 0)
{ // this task has expired
if (running == NULL)
{
// if this task is ready to run, and we haven't already selected a task to run,
// select this one.
running = tasks[i].callback;
// prepare for next cycle
tasks[i].remaining_time += tasks[i].period;
}
idle_time = 0;
}
else
{
// keep track of the "minimal" time that can be idle
idle_time = min((U32)tasks[i].remaining_time, idle_time);
}
// serial_puts("we are in loop i\n");
}
if (running != NULL)
{
// If a task was selected to run, call its function.
running();
return idle_time - (now -ct); // need to subtract the execution of "running()"
} else
return idle_time;
}