#include #include "Kernel.h" #include "Util.h" #include "Colours.h" #define MAX_TASKS 8 struct Task *Kernel_get_task(int pid); struct Task tasks[MAX_TASKS]; int next_pid = 1; unsigned long last_tick_start; unsigned long last_tick_duration; bool inputs[2] = {false, false}; void Kernel_panic(char* message) { M5.Lcd.setRotation(3); M5.Lcd.fillScreen(TFT_BLUE); M5.Lcd.setTextColor(TFT_WHITE, TFT_BLUE); M5.Lcd.setCursor(0, 0); M5.Lcd.print("Panic! "); M5.Lcd.print(message); while(true) {} } void Kernel_setup() { last_tick_start = millis(); last_tick_duration = 0; } int Kernel_start(int (*callback)(int, unsigned int), unsigned long interval) { struct Task *process = Kernel_get_task(0); if (process->pid == -1) { Kernel_panic("Could not start process -- reached MAX_TASKS"); } process->pid = next_pid++; process->callback = callback; process->run_interval = interval; process->run_accumulator = interval; process->signal = SIGNAL_START | SIGNAL_TICK; process->running = true; return process->pid; } void Kernel_enable(int pid) { struct Task *process = Kernel_get_task(pid); if (process->pid == pid) { process->running = true; } } void Kernel_disable(int pid) { struct Task *process = Kernel_get_task(pid); if (process->pid == pid) { process->running = false; } } void Kernel_reap(int pid) { struct Task *process = Kernel_get_task(pid); if (process->pid != pid || process->running) { return; } process->pid = 0; process->running = false; process->exit_code = 0; process->run_interval = 0; process->run_accumulator = 0; process->signal = SIGNAL_NONE; process->signal_mask = 0xFFFF; } void Kernel_signal(unsigned int signal) { for (int i=0; ipid == pid) { process->signal_pending |= signal; } } void Kernel_signal_mask(int pid, unsigned int signal_mask) { struct Task *process = Kernel_get_task(pid); if (process->pid == pid) { process->signal_mask = signal_mask; } } unsigned long Kernel_get_run_interval(int pid) { struct Task *process = Kernel_get_task(pid); return process->pid == pid ? process->run_interval : 0; } void Kernel_set_run_interval(int pid, unsigned long interval) { struct Task *process = Kernel_get_task(pid); if (process->pid == pid) { process->run_interval = interval; } } int Kernel_count_running_tasks() { int count = 0; for (int i=0; ipid != pid || process->running == true ? -1 : process->exit_code; Kernel_reap(pid); return exit_code; } bool Kernel_is_exited(int pid) { struct Task *process = Kernel_get_task(pid); return process->pid != pid || process->running == false; } bool Kernel_read_input(int input) { if (inputs[input] == true && ((input == 0 && digitalRead(BUTTON_A_PIN) == 1) || (input == 1 && digitalRead(BUTTON_B_PIN) == 1))) { inputs[input] = false; } return inputs[input]; } unsigned long Kernel_get_last_tick_duration() { return last_tick_duration; } struct Task *Kernel_get_task(int pid) { for (int i=0; i 0) { if (tasks[i].run_accumulator + last_tick_duration > tasks[i].run_interval) { // Set signal tasks[i].signal |= SIGNAL_TICK; // Reset accumulator so we can start counting again tasks[i].run_accumulator = 0; } else { // Otherwise, accumulate time tasks[i].run_accumulator += last_tick_duration; } } else { tasks[i].signal |= SIGNAL_TICK; } // If the process has any non-masked signals pending, run it if ((tasks[i].signal & tasks[i].signal_mask) != 0) { // Run the task int task_return = (*tasks[i].callback)(tasks[i].pid, tasks[i].signal); // If the tasks's return value was non-zero, it has exited. if (task_return != 0) { // Mark it as no longer running tasks[i].running = false; // Store the exit code tasks[i].exit_code = task_return; // Actually it's not running... running_tasks--; last_exit_code = task_return; } } // Check each task to see if it's the one scheduled to run on the next closest tick, and track it // so we can put the processor to sleep until then. if (tasks[i].running && tasks[i].run_interval > 0 && tasks[i].run_interval - tasks[i].run_accumulator < next_tick_due) { next_tick_due = tasks[i].run_interval - tasks[i].run_accumulator; } } } if (running_tasks == 0) { char panic_msg[255]; sprintf(panic_msg, "All processes exited! Last exit code: %d", last_exit_code); Kernel_panic(panic_msg); } bool signals_pending = false; for (int i=0; i