platform for developing on SQFMI's Watchy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

308 lines
6.2 KiB

// Arduino System
#include <Arduino.h>
// RTC
#include <DS3232RTC.h>
// I2C Library
#include <Wire.h>
// Hardware information
#include "watchos_hw.h"
#include "watchos.h"
#define SCOPE_SIZE 64
Kernel* Kernel::s_kernel = nullptr;
char scope[SCOPE_SIZE];
struct EventSubscription
{
int handle;
void (*callback)(Event* e); // module, event, param1, param2
Task* target;
byte source_mask = 0;
byte event_mask = 0;
};
Kernel::Kernel()
{
sprintf(scope, "[SYSTEM]");
Wire.begin(HW_I2C_SDA, HW_I2C_SCL);
// Initialize empty tasks
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
m_task[i] = nullptr;
}
// Initialize empty modules
for (int i = 0; i < KERNEL_MAX_MODULES; i++)
{
m_module[i] = nullptr;
}
// Initialize event callbacks
for (int i = 0; i < KERNEL_MAX_EVENT_SUBSCRIPTIONS; i++)
{
m_event_subscription[i] = nullptr;
}
}
/**
* Create a singleton instance of the kernel
*/
void Kernel::initialize()
{
for (int i = 0; i < KERNEL_MAX_MODULES; i++)
{
if (m_module[i] != nullptr)
{
sprintf(scope, "[MODULE:%d]", m_module[i]->getId());
m_module[i]->initialize();
}
}
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
if (m_task[i] != nullptr)
{
sprintf(scope, "[TASK:%d]", m_task[i]->getId());
m_task[i]->initialize();
}
}
sprintf(scope, "[SYSTEM]");
}
/**
* Fetch the singleton instance of the kernel
*/
Kernel* Kernel::get()
{
if (s_kernel == nullptr)
{
s_kernel = new Kernel();
}
return s_kernel;
}
/**
* Unrecoverable error -- shut everything down
*/
void Kernel::panic(char* message)
{
// TODO: Would be good to print to screen once display module exists
Serial.printf("Kernel panic!\n");
if (xPortGetCoreID() == 0)
Serial.printf("Scope: %s\n", scope);
else
Serial.printf("Scope: UI Draw\n");
Serial.printf("%s\n", message);
while (true) {}
}
/**
* Write out debug messaging
*/
void Kernel::debug(char* message)
{
// TODO: Print active PID
Serial.printf("%s %s\n", scope, message);
}
/**
* Tick -- run all processes/modules as appropriate
*/
void Kernel::tick()
{
for (int i = 0; i < KERNEL_MAX_MODULES; i++)
{
if (m_module[i] != nullptr)
{
sprintf(scope, "[MODULE:%d]", m_module[i]->getId());
m_module[i]->tick();
}
}
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
if (m_task[i] != nullptr)
{
sprintf(scope, "[TASK:%d]", m_task[i]->getId());
m_task[i]->tick(0);
}
}
sprintf(scope, "[SYSTEM]");
}
/**
* Tell all processes/modules to suspend
*/
void Kernel::suspend()
{
for (int i = 0; i < KERNEL_MAX_MODULES; i++)
{
if (m_module[i] != nullptr)
{
sprintf(scope, "[MODULE:%d]", m_module[i]->getId());
m_module[i]->suspend();
}
}
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
if (m_task[i] != nullptr)
{
sprintf(scope, "[TASK:%d]", m_task[i]->getId());
m_task[i]->suspend();
}
}
sprintf(scope, "[SYSTEM]");
}
/**
* Register a new task in the kernel
*/
int Kernel::registerTask(Task* task)
{
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
if (m_task[i] == nullptr)
{
m_task[i] = task;
task->setId(m_pid++); // TODO: real pid
return i;
}
}
Kernel::panic("Exceeded KERNEL_MAX_TASKS!");
}
void Kernel::unregisterTask(int pid)
{
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
if (m_task[i] != nullptr && m_task[i]->getId() == pid)
{
delete m_task[i];
m_task[i] = nullptr;
return;
}
}
}
bool Kernel::isTaskRunning(int pid)
{
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
if (m_task[i] != nullptr && m_task[i]->getId() == pid)
{
return true;
}
}
return false;
}
/**
* Register a new module in the kernel
*/
void Kernel::registerModule(Module* module)
{
for (int i = 0; i < KERNEL_MAX_MODULES; i++)
{
if (m_module[i] == nullptr)
{
m_module[i] = module;
return;
}
}
Kernel::panic("Exceeded KERNEL_MAX_MODULES!");
}
Module* Kernel::getModule(int module_id)
{
for (int i = 0; i < KERNEL_MAX_MODULES; i++)
{
if (m_module[i] != nullptr && m_module[i]->getId() == module_id)
{
return m_module[i];
}
}
Kernel::panic("Module not found");
}
void Kernel::event(byte source, byte event, byte param1, byte param2)
{
Event* e = new Event();
e->source = source;
e->event = event;
e->param1 = param1;
e->param2 = param2;
for (int i = 0; i < KERNEL_MAX_EVENT_SUBSCRIPTIONS; i++)
{
if (m_event_subscription[i] != nullptr)
{
if ((m_event_subscription[i]->source_mask & source) == source &&
(m_event_subscription[i]->event_mask & event) == event)
{
if (m_event_subscription[i]->callback != nullptr)
{
m_event_subscription[i]->callback(e);
}
else if (m_event_subscription[i]->target != nullptr)
{
m_event_subscription[i]->target->pushEvent(e);
}
}
}
}
}
int Kernel::subscribe(void (*callback)(Event* e), byte source_mask, byte event_mask)
{
for (int i = 0; i < KERNEL_MAX_EVENT_SUBSCRIPTIONS; i++)
{
if (m_event_subscription[i] == nullptr)
{
m_event_subscription[i] = new EventSubscription();
m_event_subscription[i]->handle = ++m_handle;
m_event_subscription[i]->callback = callback;
m_event_subscription[i]->source_mask = source_mask;
m_event_subscription[i]->event_mask = event_mask;
return m_event_subscription[i]->handle;
}
}
Kernel::panic("Exceeded KERNEL_MAX_EVENT_SUBSCRIPTIONS!");
}
int Kernel::subscribe(Task* task, byte source_mask, byte event_mask)
{
for (int i = 0; i < KERNEL_MAX_EVENT_SUBSCRIPTIONS; i++)
{
if (m_event_subscription[i] == nullptr)
{
m_event_subscription[i] = new EventSubscription();
m_event_subscription[i]->handle = ++m_handle;
m_event_subscription[i]->target = task;
m_event_subscription[i]->source_mask = source_mask;
m_event_subscription[i]->event_mask = event_mask;
return m_event_subscription[i]->handle;
}
}
Kernel::panic("Exceeded KERNEL_MAX_EVENT_SUBSCRIPTIONS!");
}
void Kernel::unsubscribe(int handle)
{
for (int i = 0; i < KERNEL_MAX_EVENT_SUBSCRIPTIONS; i++)
{
if (m_event_subscription[i] != nullptr && m_event_subscription[i]->handle == handle)
{
delete m_event_subscription[i];
return;
}
}
}