Browse Source

Add counter+battery tasks

Improve power management
Improve... basically everything else
v1
Adam PIppin 3 years ago
parent
commit
a8fc1a662e
  1. 2
      watchos/Events.cpp
  2. 57
      watchos/Kernel.cpp
  3. 111
      watchos/Module_Input.cpp
  4. 25
      watchos/Module_Input.h
  5. 102
      watchos/Module_Power.cpp
  6. 24
      watchos/Module_Power.h
  7. 6
      watchos/Module_RTC.cpp
  8. 1
      watchos/Module_RTC.h
  9. 121
      watchos/Module_UI.cpp
  10. 7
      watchos/Module_UI.h
  11. 63
      watchos/Task_Battery.cpp
  12. 25
      watchos/Task_Clock.cpp
  13. 75
      watchos/Task_Counter.cpp
  14. 4
      watchos/__vm/Compile.vmps.xml
  15. 2
      watchos/__vm/Upload.vmps.xml
  16. 53
      watchos/watchos.ino
  17. 7
      watchos/watchos.vcxproj
  18. 19
      watchos/watchos.vcxproj.filters
  19. 18
      watchos/watchos_consts.h
  20. 5
      watchos/watchos_hw.h

2
watchos/Events.cpp

@ -24,8 +24,6 @@ int EventQueue::next(int n)
void EventQueue::push(Event* event)
{
delay(500);
if (m_full)
{
// We're full

57
watchos/Kernel.cpp

@ -14,23 +14,48 @@
Kernel* Kernel::s_kernel = nullptr;
char scope[SCOPE_SIZE];
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;
}
}
/**
* Create a singleton instance of the kernel
*/
void Kernel::initialize()
{
Serial.begin(115200);
s_kernel = new Kernel();
sprintf(scope, "[SYSTEM]");
Wire.begin(HW_I2C_SDA, HW_I2C_SCL);
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();
}
}
// Initialize empty tasks
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
s_kernel->m_task[i] = nullptr;
if (m_task[i] != nullptr)
{
sprintf(scope, "[TASK:%d]", m_task[i]->getId());
m_task[i]->initialize();
}
}
sprintf(scope, "[SYSTEM]");
}
/**
@ -38,6 +63,10 @@ void Kernel::initialize()
*/
Kernel* Kernel::get()
{
if (s_kernel == nullptr)
{
s_kernel = new Kernel();
}
return s_kernel;
}
@ -94,13 +123,25 @@ void Kernel::tick()
*/
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]");
}
/**
@ -114,7 +155,6 @@ void Kernel::registerTask(Task* task)
{
m_task[i] = task;
task->setId(i); // TODO: real pid
task->initialize();
return;
}
}
@ -131,7 +171,6 @@ void Kernel::registerModule(Module* module)
if (m_module[i] == nullptr)
{
m_module[i] = module;
module->initialize();
return;
}
}

111
watchos/Module_Input.cpp

@ -0,0 +1,111 @@
#include "watchos.h"
#include "watchos_hw.h"
#include "Module_Input.h"
struct ButtonState
{
byte button;
byte pin;
uint64_t mask;
bool pressed = false;
byte reserved1;
};
uint64_t wakeup_bits;
Module_Input::Module_Input()
{
for (int i = 0; i < MODULE_INPUT_BUTTONS; i++)
{
m_button[i] = new ButtonState();
}
// TODO: Figure out a way to not hardcode this
m_button[0]->button = MODULE_INPUT_BUTTON_BACK;
m_button[0]->pin = HW_BUTTON_TL;
m_button[0]->mask = HW_BUTTON_TL_MASK;
m_button[1]->button = MODULE_INPUT_BUTTON_MENU;
m_button[1]->pin = HW_BUTTON_BL;
m_button[1]->mask = HW_BUTTON_BL_MASK;
m_button[2]->button = MODULE_INPUT_BUTTON_UP;
m_button[2]->pin = HW_BUTTON_TR;
m_button[2]->mask = HW_BUTTON_TR_MASK;
m_button[3]->button = MODULE_INPUT_BUTTON_DOWN;
m_button[3]->pin = HW_BUTTON_BR;
m_button[3]->mask = HW_BUTTON_BR_MASK;
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT1)
{
wakeup_bits = esp_sleep_get_ext1_wakeup_status();
}
else
{
wakeup_bits = 0;
}
}
void Module_Input::initialize()
{
}
void Module_Input::suspend()
{
}
int Module_Input::getId()
{
return MODULE_INPUT;
}
void Module_Input::tick()
{
poll();
wakeup_bits = 0;
}
void Module_Input::poll()
{
byte pressed = 0;
char msg[255];
for (int i = 0; i < MODULE_INPUT_BUTTONS; i++)
{
if (digitalRead(m_button[i]->pin) == 1 || (wakeup_bits & m_button[i]->mask) != 0)
{
if (!m_button[i]->pressed)
{
sprintf(msg, "Button pressed: %d", i);
Kernel::debug(msg);
pressed |= m_button[i]->button;
m_button[i]->pressed = true;
}
}
else
{
m_button[i]->pressed = false;
}
}
if (pressed != 0)
{
Kernel::get()->event(MODULE_INPUT, MODULE_INPUT_EVENT_PRESS, pressed, 0);
}
}
bool Module_Input::isAnyPressed()
{
for (int i = 0; i < MODULE_INPUT_BUTTONS; i++)
{
if (m_button[i]->pressed)
{
return true;
}
}
return false;
}
bool Module_Input::isPressed(byte button)
{
return m_button[button]->pressed;
}

25
watchos/Module_Input.h

@ -0,0 +1,25 @@
#ifndef MODULE_INPUT_H
#define MODULE_INPUT_H
#include "watchos.h"
struct ButtonState;
class Module_Input : public Module
{
ButtonState* m_button[MODULE_INPUT_BUTTONS];
void poll();
public:
Module_Input();
void initialize();
void suspend();
int getId();
void tick();
bool isAnyPressed();
bool isPressed(byte button);
};
#endif

102
watchos/Module_Power.cpp

@ -0,0 +1,102 @@
#include "watchos_hw.h"
#include "Module_Power.h"
#include "Module_Input.h"
#include "Events.h"
Module_Input* module_input;
Module_Power::Module_Power()
{
module_input = (Module_Input*)Kernel::get()->getModule(MODULE_INPUT);
m_last_tick = 0;
m_accumulator = 0;
switch (esp_sleep_get_wakeup_cause())
{
case ESP_SLEEP_WAKEUP_EXT1: // Button press
// Button press
m_light_sleep_delay = 2000;
m_deep_sleep_delay = 5000;
break;
case ESP_SLEEP_WAKEUP_EXT0: // External RTC
case ESP_SLEEP_WAKEUP_TIMER: // Internal RTC
default:
m_light_sleep_delay = 100;
m_deep_sleep_delay = 1000;
break;
}
}
void Module_Power::initialize()
{
}
void Module_Power::suspend()
{
}
int Module_Power::getId()
{
return MODULE_POWER;
}
void Module_Power::disableSleep()
{
m_sleep_enabled = false;
}
void Module_Power::enableSleep()
{
m_sleep_enabled = true;
}
void Module_Power::tick()
{
if (m_last_tick == 0)
{
m_accumulator = 0;
}
else if (m_sleep_enabled)
{
m_accumulator += millis() - m_last_tick;
}
m_last_tick = millis();
if (module_input->isAnyPressed())
{
// In case we woke up because of RTC/etc, but have since received a button press
m_light_sleep_delay = 2000;
m_deep_sleep_delay = 5000;
m_accumulator = 0;
}
if (m_accumulator > m_deep_sleep_delay)
{
Kernel::debug("Going into deep sleep");
m_accumulator = 0;
Kernel::get()->suspend();
// TODO: Configure a... hourly? alarm to wake up and refresh other things
// Interrogate tasks for next required wakeup?
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER);
esp_sleep_enable_ext0_wakeup(HW_RTC, 0);
esp_sleep_enable_ext1_wakeup(HW_BUTTON_MASK, ESP_EXT1_WAKEUP_ANY_HIGH);
esp_deep_sleep_start();
}
else if (m_accumulator > m_light_sleep_delay)
{
Kernel::debug("Going into light sleep");
// If nothing else happens, wake up when it's time to hibernate.
esp_sleep_enable_timer_wakeup((m_deep_sleep_delay * 1000) - m_accumulator);
// Wake up if the RTC fires
esp_sleep_enable_ext0_wakeup(HW_RTC, 0);
// Wake up if any button presses
esp_sleep_enable_ext1_wakeup(HW_BUTTON_MASK, ESP_EXT1_WAKEUP_ANY_HIGH);
// Go into light sleep
esp_light_sleep_start();
// And we're back, let everything continue
}
}

24
watchos/Module_Power.h

@ -0,0 +1,24 @@
#ifndef MODULE_POWER_H
#define MODULE_POWER_H
#include "watchos.h"
class Module_Power : public Module
{
int m_light_sleep_delay = 0;
int m_deep_sleep_delay = 0;
int m_accumulator = 0;
unsigned long m_last_tick;
bool m_sleep_enabled = true;
public:
Module_Power();
void initialize();
void suspend();
int getId();
void tick();
void disableSleep();
void enableSleep();
};
#endif

6
watchos/Module_RTC.cpp

@ -7,13 +7,17 @@ DS3232RTC RTC;
tmElements_t lastTime;
Module_RTC::Module_RTC()
{
refresh();
}
void Module_RTC::initialize()
{
RTC.squareWave(SQWAVE_NONE);
RTC.setAlarm(ALM2_EVERY_MINUTE, 0, 0, 0, 0);
RTC.alarmInterrupt(ALARM_2, true);
RTC.alarmInterrupt(ALARM_1, false);
refresh();
}
void Module_RTC::tick()

1
watchos/Module_RTC.h

@ -6,6 +6,7 @@
class Module_RTC : public Module
{
public:
Module_RTC();
void initialize();
void suspend();
int getId();

121
watchos/Module_UI.cpp

@ -1,11 +1,15 @@
#include "watchos.h"
#include "watchos_hw.h"
#include "Module_UI.h"
#include "Module_Power.h"
#include "Task.h"
#include <GxEPD2_BW.h>
GxEPD2_BW<GxEPD2_154_D67, GxEPD2_154_D67::HEIGHT> gfx = GxEPD2_154_D67(HW_DISPLAY_CS, HW_DISPLAY_DC, HW_DISPLAY_RESET, HW_DISPLAY_BUSY);
Module_UI* module_ui;
Module_Power* module_power;
TaskHandle_t draw_task;
struct UI_Window
{
@ -15,11 +19,18 @@ struct UI_Window
void (*callback)(int, int, int, int, int); // hwnd, x, y, width, height
bool dirty = false;
Task* task = nullptr;
byte reserved1;
byte reserved2;
bool needs_draw = false;
byte draw_x, draw_y, draw_w, draw_h;
};
void Module_UI::initialize()
void draw_wrapper(void* parameter)
{
module_ui->draw(false);
draw_task = nullptr;
vTaskDelete(NULL);
}
Module_UI::Module_UI()
{
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
@ -29,19 +40,25 @@ void Module_UI::initialize()
// Create root window
createWindow(-1, 0);
module_power = (Module_Power*)Kernel::get()->getModule(MODULE_POWER);
}
void Module_UI::initialize()
{
gfx.init(0, false); // init(bitrate, initial)?
gfx.setFullWindow();
gfx.fillScreen(GxEPD_WHITE);
gfx.fillScreen(COLOUR_SECONDARY);
gfx.display(true);
m_redraw = true;
}
void Module_UI::tick()
{
}
void Module_UI::suspend()
{
gfx.hibernate();
}
int Module_UI::getId()
@ -72,7 +89,6 @@ int Module_UI::createWindow(void (*callback)(int, int, int, int, int), int paren
}
m_window[i]->layout_mode = MODULE_UI_LAYOUT_MODE_NONE;
m_window[i]->callback = callback;
m_window[i]->dirty = true;
return m_window[i]->hwnd;
}
}
@ -97,7 +113,6 @@ int Module_UI::createWindow(Task* task, int parent, int zorder)
}
m_window[i]->layout_mode = MODULE_UI_LAYOUT_MODE_NONE;
m_window[i]->task = task;
m_window[i]->dirty = true;
return m_window[i]->hwnd;
}
}
@ -157,17 +172,46 @@ void Module_UI::setDirty(int hwnd)
}
}
window->dirty = true;
/*
while (window != nullptr)
{
window->dirty = true;
window = window->parent;
}
*/
m_dirty = true;
}
void Module_UI::draw()
void Module_UI::draw(bool spawn_task)
{
draw(0, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
getGfx()->display(true);
if (spawn_task && (m_dirty || m_redraw) && draw_task == nullptr)
{
m_dirty = false;
m_redraw = false;
module_ui = this;
xTaskCreatePinnedToCore(draw_wrapper, "Draw", MODULE_UI_MULTICORE_STACK_SIZE, NULL, 0, &draw_task, 0);
}
else if (!spawn_task)
{
module_power->disableSleep();
getGfx()->init(0, false);
draw(0, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
// TODO: optimize, if areas covering the whole screen need drawing, just make one call
//getGfx()->display(true);
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->needs_draw)
{
getGfx()->displayWindow(m_window[i]->draw_x, m_window[i]->draw_y, m_window[i]->draw_w, m_window[i]->draw_h);
}
}
getGfx()->hibernate();
delay(500);
module_power->enableSleep();
}
}
void Module_UI::draw(int hwnd, int x, int y, int width, int height)
@ -186,16 +230,34 @@ void Module_UI::draw(int hwnd, int x, int y, int width, int height)
Kernel::panic("Trying to draw non-existent window!");
}
char msg[255];
// Draw window if applicable
if (window->dirty)
if (window->dirty || m_redraw)
{
sprintf(msg, "Drawing hwnd %d", window->hwnd);
Kernel::debug(msg);
bool did_draw = false;
window->dirty = false;
if (window->callback != nullptr)
{
(window->callback)(hwnd, x, y, width, height);
did_draw = true;
}
else if (window->task != nullptr)
{
window->task->draw(hwnd, x, y, width, height);
did_draw = true;
}
if (did_draw)
{
window->draw_x = x;
window->draw_y = y;
window->draw_w = width;
window->draw_h = height;
window->needs_draw = true;
}
}
@ -215,44 +277,39 @@ void Module_UI::draw(int hwnd, int x, int y, int width, int height)
return;
}
// Grab all children
// TODO: This is really unnecessary I guess. We could just loop the whole array again.
// We really only need child_count to figure out layouts.
UI_Window** children = (UI_Window**)calloc(child_count, sizeof(UI_Window*));
int next_child = 0;
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->parent == window)
{
children[next_child++] = m_window[i];
}
}
int layout_mode = window->layout_mode;
int child_offset = 0;
int child_height, child_width;
switch (layout_mode)
{
case MODULE_UI_LAYOUT_MODE_NONE:
for (int i = 0; i < child_count; i++)
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
draw(children[i]->hwnd, x, y, width, height);
if (m_window[i] != nullptr && m_window[i]->parent == window)
{
draw(m_window[i]->hwnd, x, y, width, height);
}
}
break;
case MODULE_UI_LAYOUT_MODE_SPLIT_HORIZONTAL:
child_height = height / child_count;
for (int i = 0; i < child_count; i++)
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
draw(children[i]->hwnd, x, y + (i * child_height), width, child_height);
if (m_window[i] != nullptr && m_window[i]->parent == window)
{
draw(m_window[i]->hwnd, x, y + (child_offset++ * child_height), width, child_height);
}
}
break;
case MODULE_UI_LAYOUT_MODE_SPLIT_VERTICAL:
child_width = width / child_count;
for (int i = 0; i < child_count; i++)
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
draw(children[i]->hwnd, x + (i * child_width), y, child_width, height);
if (m_window[i] != nullptr && m_window[i]->parent == window)
{
draw(m_window[i]->hwnd, x + (child_offset++ * child_width), y, child_width, height);
}
}
break;
}
free(children);
}

7
watchos/Module_UI.h

@ -11,9 +11,11 @@ class Module_UI : public Module
{
UI_Window* m_window[MODULE_UI_MAX_WINDOWS];
int m_nextHwnd = 0;
void draw(int hwnd, int x, int y, int width, int height);
bool m_dirty = false, m_redraw = false;
public:
Module_UI();
void initialize();
void suspend();
int getId();
@ -22,7 +24,8 @@ public:
int createWindow(void (*callback)(int, int, int, int, int), int parent = 0, int zorder = 0);
int createWindow(Task* task, int parent = 0, int zorder = 0);
int createWindow(int parent = 0, int zorder = 0);
void draw();
void draw(bool spawn_task = MODULE_UI_MULTICORE_RENDERING);
void draw(int hwnd, int x, int y, int width, int height);
GxEPD2_GFX* getGfx();
void setLayoutMode(int hwnd, byte layout_mode);
void setDirty(int hwnd);

63
watchos/Task_Battery.cpp

@ -0,0 +1,63 @@
#include "watchos.h"
#include "watchos_hw.h"
#include "Module_UI.h"
#include "watchos_fonts.h"
#include "Events.h"
class Task_Battery : public Task
{
private:
int hwnd;
Module_UI* ui;
int voltage = 0;
int last_update;
int getBatteryVoltage()
{
float raw_value = (analogRead(HW_BATTERY_ADC_PIN) / 4096.0 * 7.23);
return (int)round(raw_value * 10);
}
public:
Task_Battery(int parent_hwnd)
{
ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
hwnd = ui->createWindow((Task*)this, parent_hwnd, 0);
voltage = getBatteryVoltage();
}
void initialize()
{
ui->setDirty(hwnd);
}
void tick(unsigned int signal)
{
while (this->hasEvent()) { this->popEvent(); }
int new_voltage = getBatteryVoltage();
if (voltage != new_voltage && (millis() - last_update > 1000))
{
last_update = millis();
ui->setDirty(hwnd);
voltage = new_voltage;
}
}
void suspend()
{
}
void draw(int hwnd, int x, int y, int width, int height)
{
char str[8];
float voltage_display = ((float)voltage) / 10.0f;
sprintf(str, "%.1fv", voltage_display);
Module_UI* ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
ui->getGfx()->fillRect(x, y, width, height, COLOUR_SECONDARY);
ui->getGfx()->setFont(&FreeMono12pt7b);
ui->getGfx()->setTextColor(COLOUR_PRIMARY);
ui->getGfx()->setCursor(x, y + height);
ui->getGfx()->print(str);
}
};

25
watchos/Task_Clock.cpp

@ -1,5 +1,6 @@
#include "watchos.h"
#include "Module_UI.h"
#include "Module_RTC.h"
#include "watchos_fonts.h"
#include "Events.h"
@ -11,11 +12,21 @@ private:
byte hour, minute;
public:
void initialize()
Task_Clock(int parent_hwnd)
{
ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
hwnd = ui->createWindow((Task*)this, 0, 0);
hwnd = ui->createWindow((Task*)this, parent_hwnd, 0);
}
void initialize()
{
Module_RTC* rtc = (Module_RTC*)Kernel::get()->getModule(MODULE_RTC);
hour = rtc->getHour();
minute = rtc->getMinute();
ui->setDirty(hwnd);
}
void tick(unsigned int signal)
{
bool dirty = false;
@ -24,16 +35,14 @@ public:
while (this->hasEvent())
{
Event* e = this->popEvent();
sprintf(msg, "event source %d id %d", e->source, e->event);
sprintf(msg, "event source %d id %d param1 %d", e->source, e->event, e->param1);
Kernel::debug(msg);
if (e->source == MODULE_RTC && e->event == MODULE_RTC_EVENT_MINUTE)
{
sprintf(msg, "old %d:%d new %d:%d", hour, minute, e->param1, e->param2);
Kernel::debug(msg);
if (e->param1 != hour || e->param2 != minute)
{
Kernel::debug("Processed RTC event");
hour = e->param1;
minute = e->param2;
dirty = true;
@ -58,10 +67,10 @@ public:
sprintf(time, "%02d:%02d", hour, minute);
Module_UI* ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
ui->getGfx()->fillRect(x, y, width, height, GxEPD_WHITE);
ui->getGfx()->fillRect(x, y, width, height, COLOUR_SECONDARY);
ui->getGfx()->setFont(&DSEG7_Classic_Bold_53);
ui->getGfx()->setTextColor(GxEPD_BLACK);
ui->getGfx()->setCursor(0, y+height);
ui->getGfx()->setTextColor(COLOUR_PRIMARY);
ui->getGfx()->setCursor(x, y+height);
ui->getGfx()->print(time);
}
};

75
watchos/Task_Counter.cpp

@ -0,0 +1,75 @@
#include "watchos.h"
#include "Module_UI.h"
#include "Module_EAT.h"
#include "watchos_fonts.h"
#include "Events.h"
class Task_Counter : public Task
{
private:
int hwnd;
Module_UI* ui;
Module_EAT* eat;
int count = 0;
public:
Task_Counter(int parent_hwnd)
{
ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
hwnd = ui->createWindow((Task*)this, parent_hwnd, 0);
eat = (Module_EAT*)Kernel::get()->getModule(MODULE_EAT);
if (!eat->allocate(3, 4))
{
// Read count
count = (eat->read(3, 0) << 24) | (eat->read(3, 1) << 16) | (eat->read(3, 2) << 8) | eat->read(3, 3);
}
}
void initialize()
{
ui->setDirty(hwnd);
}
void tick(unsigned int signal)
{
bool dirty = false;
while (this->hasEvent())
{
Event* e = this->popEvent();
if (e->source == MODULE_INPUT && e->event == MODULE_INPUT_EVENT_PRESS)
{
count++;
dirty = true;
}
}
if (dirty)
{
Module_UI* ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
ui->setDirty(hwnd);
}
}
void suspend()
{
eat->write(3, 0, (byte)(count >> 24));
eat->write(3, 1, (byte)(count >> 16));
eat->write(3, 2, (byte)(count >> 8));
eat->write(3, 3, (byte)count);
}
void draw(int hwnd, int x, int y, int width, int height)
{
char str[5];
sprintf(str, "%04d", count);
Module_UI* ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
ui->getGfx()->fillRect(x, y, width, height, COLOUR_SECONDARY);
ui->getGfx()->setFont(&FreeMono12pt7b);
ui->getGfx()->setTextColor(COLOUR_PRIMARY);
ui->getGfx()->setCursor(x, y + height);
ui->getGfx()->print(str);
}
};

4
watchos/__vm/Compile.vmps.xml

File diff suppressed because one or more lines are too long

2
watchos/__vm/Upload.vmps.xml

File diff suppressed because one or more lines are too long

53
watchos/watchos.ino

@ -4,8 +4,12 @@
#include "Module_EAT.h"
#include "Module_UI.h"
#include "Module_RTC.h"
#include "Module_Input.h"
#include "Module_Power.h"
#include "Task_Clock.cpp"
#include "Task_Counter.cpp"
#include "Task_Battery.cpp"
#include <GxEPD2_BW.h>
@ -27,12 +31,11 @@ void test_draw(int hwnd, int x, int y, int width, int height)
*/
}
void setup() {
Kernel::initialize();
void setup()
{
Serial.begin(115200);
k = Kernel::get();
delay(1000);
Serial.printf("Started!\n");
// Initialize eeprom module
@ -45,45 +48,36 @@ void setup() {
// Register module with the kernel
k->registerModule(module_eat);
// Initialize UI module
Module_Input* module_input = new Module_Input();
k->registerModule(module_input);
Module_Power* module_power = new Module_Power();
k->registerModule(module_power);
Module_UI* module_ui = new Module_UI();
k->registerModule(module_ui);
module_ui->setLayoutMode(0, MODULE_UI_LAYOUT_MODE_SPLIT_HORIZONTAL);
/*module_ui->createWindow(&test_draw, 0);
int shwnd = module_ui->createWindow();
module_ui->setLayoutMode(shwnd, MODULE_UI_LAYOUT_MODE_SPLIT_VERTICAL);
module_ui->createWindow(&test_draw, shwnd);
module_ui->createWindow(&test_draw, shwnd);*/
module_ui->draw();
int top_hwnd = module_ui->createWindow(0);
int bottom_hwnd = module_ui->createWindow(0);
module_ui->setLayoutMode(bottom_hwnd, MODULE_UI_LAYOUT_MODE_SPLIT_VERTICAL);
Module_RTC* module_rtc = new Module_RTC();
k->registerModule(module_rtc);
k->registerTask(new Task_Clock());
k->registerTask(new Task_Clock());
k->registerTask(new Task_Clock(top_hwnd));
k->registerTask(new Task_Counter(bottom_hwnd));
k->registerTask(new Task_Battery(bottom_hwnd));
// TODO: Figure out why we woke up
wakeup();
}
int iters = 0;
void loop() {
void loop()
{
k->tick();
if (iters++ == 5)
{
Module_UI* ui = (Module_UI*)k->getModule(MODULE_UI);
ui->draw();
Kernel::debug("Going to sleep!");
delay(500);
iters = 0;
esp_sleep_enable_timer_wakeup(100000000); // 1 second = 1000000 microseconds
esp_sleep_enable_ext0_wakeup(HW_RTC, 0);
esp_sleep_enable_ext1_wakeup(HW_BUTTON_MASK, ESP_EXT1_WAKEUP_ANY_HIGH);
esp_light_sleep_start();
wakeup();
}
Module_UI* ui = (Module_UI*)k->getModule(MODULE_UI);
ui->draw();
}
void wakeup()
@ -121,6 +115,7 @@ void wakeup()
break;
default:
Kernel::debug("Wakeup: Reset / First Boot");
k->initialize();
break;
}
}

7
watchos/watchos.vcxproj

@ -124,6 +124,8 @@
<ClInclude Include="..\..\..\..\..\Arduino\watchos\Module_EAT.h" />
<ClInclude Include="..\..\..\..\..\Arduino\watchos\Task.h" />
<ClInclude Include="..\..\..\..\..\Arduino\watchos\watchos.h" />
<ClInclude Include="Module_Input.h" />
<ClInclude Include="Module_Power.h" />
<ClInclude Include="watchos_consts.h" />
<ClInclude Include="Events.h" />
<ClInclude Include="watchos_fonts.h" />
@ -138,9 +140,12 @@
<ClCompile Include="..\..\..\..\..\Arduino\watchos\Task.cpp" />
<ClCompile Include="Events.cpp" />
<ClCompile Include="Kernel.cpp" />
<ClCompile Include="Module_Input.cpp" />
<ClCompile Include="Module_Power.cpp" />
<ClCompile Include="Module_RTC.cpp" />
<ClCompile Include="Module_UI.cpp" />
<ClCompile Include="TestTask.cpp" />
<ClCompile Include="Task_Clock.cpp" />
<ClCompile Include="Task_Counter.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

19
watchos/watchos.vcxproj.filters

@ -60,6 +60,12 @@
<ClInclude Include="watchos_types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Module_Input.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Module_Power.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Kernel.cpp">
@ -77,10 +83,19 @@
<ClCompile Include="Module_RTC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestTask.cpp">
<ClCompile Include="Events.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Events.cpp">
<ClCompile Include="Module_Input.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Module_Power.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Task_Clock.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Task_Counter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>

18
watchos/watchos_consts.h

@ -11,8 +11,11 @@
#define MODULE_EAT 0x0001
#define MODULE_UI 0x0002
#define MODULE_RTC 0x0004
#define MODULE_INPUT 0x0008
#define MODULE_POWER 0x0010
#define MODULE_RTC_EVENT_MINUTE 0x0001
#define MODULE_INPUT_EVENT_PRESS 0x0001
#define MODULE_EAT_MAGIC 0x4150
#define MODULE_EAT_VERSION 1
@ -25,5 +28,20 @@
#define MODULE_UI_LAYOUT_MODE_NONE 0
#define MODULE_UI_LAYOUT_MODE_SPLIT_VERTICAL 1
#define MODULE_UI_LAYOUT_MODE_SPLIT_HORIZONTAL 2
#define MODULE_UI_MULTICORE_RENDERING true
#define MODULE_UI_MULTICORE_STACK_SIZE 10240
#define COLOUR_PRIMARY 0xFFFF
#define COLOUR_SECONDARY 0x0000
#define MODULE_INPUT_BUTTONS 4
#define MODULE_INPUT_BUTTON_BACK 0x01
#define MODULE_INPUT_BUTTON_MENU 0x04
#define MODULE_INPUT_BUTTON_UP 0x08
#define MODULE_INPUT_BUTTON_DOWN 0x10
// 1000000us = 1000ms = 1 second
// Times given from last activity
#define MODULE_POWER_DEFAULT_LIGHT_SLEEP_DELAY_MS 2000
#define MODULE_POWER_DEFAULT_HIBERNATE_DELAY_MS 6000
#endif

5
watchos/watchos_hw.h

@ -32,6 +32,11 @@
#define ENABLE_GxEPD2_GFX 1
//////////
// ADC / Battery
#define HW_BATTERY_ADC_PIN 33
//////////
// Vibration Motor

Loading…
Cancel
Save