From a02be354e0eb5493518c00786cc2fd5643693d06 Mon Sep 17 00:00:00 2001 From: Adam Pippin Date: Fri, 17 Apr 2020 16:58:56 -0700 Subject: [PATCH] Initial commit --- Colours.h | 19 +++++ Kernel.cpp | 170 ++++++++++++++++++++++++++++++++++++++++++++ Kernel.h | 37 ++++++++++ PowerManagement.cpp | 10 +++ PowerManagement.h | 3 + Util.cpp | 16 +++++ Util.h | 2 + watchos.ino | 44 ++++++++++++ 8 files changed, 301 insertions(+) create mode 100644 Colours.h create mode 100644 Kernel.cpp create mode 100644 Kernel.h create mode 100644 PowerManagement.cpp create mode 100644 PowerManagement.h create mode 100644 Util.cpp create mode 100644 Util.h create mode 100644 watchos.ino diff --git a/Colours.h b/Colours.h new file mode 100644 index 0000000..64be257 --- /dev/null +++ b/Colours.h @@ -0,0 +1,19 @@ +#define TFT_BLACK 0x0000 +#define TFT_NAVY 0x000F +#define TFT_DARKGREEN 0x03E0 +#define TFT_MAROON 0x7800 +#define TFT_PURPLE 0x780F +#define TFT_OLIVE 0x7BE0 +#define TFT_LIGHTGREY 0xC618 +#define TFT_DARKGREY 0x7BEF +#define TFT_BLUE 0x001F +#define TFT_GREENYELLOW 0xB7E0 +#define TFT_GREEN 0x07E0 +#define TFT_YELLOW 0xFFE0 +#define TFT_ORANGE 0xFDA0 +#define TFT_PINK 0xFC9F +#define TFT_CYAN 0x07FF +#define TFT_DARKCYAN 0x03EF +#define TFT_RED 0xF800 +#define TFT_MAGENTA 0xF81F +#define TFT_WHITE 0xFFFF diff --git a/Kernel.cpp b/Kernel.cpp new file mode 100644 index 0000000..b59187c --- /dev/null +++ b/Kernel.cpp @@ -0,0 +1,170 @@ +#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; + +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 = millis(); +} + +void Kernel_start(int (*callback)(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; +} + +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; +} + +int Kernel_get_exit_code(int pid) +{ + struct Task *process = Kernel_get_task(pid); + int exit_code = process->pid != 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; +} + +struct Task *Kernel_get_task(int pid) +{ + for (int i=0; i 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 += duration; + } + + // 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].signal); + // Reset the signal + tasks[i].signal = SIGNAL_NONE; + + // 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; + } + } + + + // 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].run_interval - tasks[i].run_accumulator < next_tick_due) + { + next_tick_due = tasks[i].run_interval - tasks[i].run_accumulator; + } + } + } + + // Put processor to sleep until the next scheduled run of a task + // Leave the home button enabled to force a wake-up before then + esp_sleep_enable_timer_wakeup(next_tick_due * 1000); + esp_sleep_enable_ext0_wakeup((gpio_num_t)37, LOW); + esp_light_sleep_start(); +} diff --git a/Kernel.h b/Kernel.h new file mode 100644 index 0000000..78cf6f7 --- /dev/null +++ b/Kernel.h @@ -0,0 +1,37 @@ + +struct Task +{ + int pid = 0; + bool running = false; + int exit_code = 0; + int (*callback)(unsigned int); + unsigned long run_interval = 0; + unsigned long run_accumulator = 0; + unsigned int signal = 0; + unsigned int signal_mask = 0xFFFF; +}; + +void Kernel_setup(); +void Kernel_tick(); + +// Panic and stop everything +void Kernel_panic(char* message); + +// Start a new process +void Kernel_start(int (*callback)(unsigned int), unsigned long interval); +// Continue execution of a process +void Kernel_enable(int pid); +// Pause execution of a process +void Kernel_disable(int pid); +// Clean up exited process +void Kernel_reap(int pid); + +// Check if process has exited +bool Kernel_is_exited(int pid); +// Get exit code of process +int Kernel_get_exit_code(int pid); + +#define SIGNAL_NONE 0 +#define SIGNAL_TICK 1 +#define SIGNAL_START 2 +#define SIGNAL_STOP 4 diff --git a/PowerManagement.cpp b/PowerManagement.cpp new file mode 100644 index 0000000..1b0ef84 --- /dev/null +++ b/PowerManagement.cpp @@ -0,0 +1,10 @@ + +void PowerManagement_setup() +{ + +} + +void PowerManagement_tick() +{ + +} diff --git a/PowerManagement.h b/PowerManagement.h new file mode 100644 index 0000000..da44c18 --- /dev/null +++ b/PowerManagement.h @@ -0,0 +1,3 @@ + +void PowerManagement_setup(); +void PowerManagement_tick(); diff --git a/Util.cpp b/Util.cpp new file mode 100644 index 0000000..41356ba --- /dev/null +++ b/Util.cpp @@ -0,0 +1,16 @@ +#include +#include "Util.h" + +unsigned long millis_since(unsigned long timestamp) +{ + unsigned long now = millis(); + + if (now < timestamp) + { + return (4294967295 - timestamp) + millis(); + } + else + { + return millis() - timestamp; + } +} diff --git a/Util.h b/Util.h new file mode 100644 index 0000000..77ceed9 --- /dev/null +++ b/Util.h @@ -0,0 +1,2 @@ + +unsigned long millis_since(unsigned long timestamp); diff --git a/watchos.ino b/watchos.ino new file mode 100644 index 0000000..22a4d10 --- /dev/null +++ b/watchos.ino @@ -0,0 +1,44 @@ +#include +#include "PowerManagement.h" +#include "Kernel.h" +#include "Colours.h" + +int count = 0; +int test_func(unsigned int signal) +{ + M5.Lcd.fillScreen(TFT_DARKGREY); + M5.Lcd.setCursor(0, 0); + if (signal & SIGNAL_START) + { + M5.Lcd.setRotation(3); + M5.Lcd.print("Initializing..."); + } + if (signal & SIGNAL_STOP) + { + M5.Lcd.print("Stopping"); + return 255; + } + if (signal & SIGNAL_TICK) + { + count++; + M5.Lcd.print("Ran: "); + M5.Lcd.print(String(count)); + M5.Lcd.print(" times"); + } + return 0; +} + +void setup() +{ + M5.begin(); + Kernel_setup(); + PowerManagement_setup(); + + Kernel_start(&test_func, 1000); +} + +void loop() +{ + Kernel_tick(); + PowerManagement_tick(); +}