Browse Source

Got menus and stuff working!

v1
Adam PIppin 3 years ago
parent
commit
f6149aeb26
  1. 76
      watchos/Kernel.cpp
  2. 296
      watchos/Module_Menu.cpp
  3. 35
      watchos/Module_Menu.h
  4. 30
      watchos/Module_UI.cpp
  5. 1
      watchos/Module_UI.h
  6. 1
      watchos/TODO.md
  7. 2
      watchos/Task_Battery.cpp
  8. 1
      watchos/Task_Clock.cpp
  9. 3
      watchos/Task_Counter.cpp
  10. 289
      watchos/Task_Menu.cpp
  11. 2
      watchos/__vm/Compile.vmps.xml
  12. 2
      watchos/__vm/Upload.vmps.xml
  13. 24
      watchos/watchos.ino
  14. 6
      watchos/watchos.vcxproj
  15. 12
      watchos/watchos.vcxproj.filters
  16. 1
      watchos/watchos_consts.h

76
watchos/Kernel.cpp

@ -14,6 +14,15 @@
Kernel* Kernel::s_kernel = nullptr;
char scope[SCOPE_SIZE];
struct EventSubscription
{
void (*callback)(Event* e); // module, event, param1, param2
Task* target;
byte source_mask = 0;
byte event_mask = 0;
};
Kernel::Kernel()
{
sprintf(scope, "[SYSTEM]");
@ -31,6 +40,12 @@ Kernel::Kernel()
{
m_module[i] = nullptr;
}
// Initialize event callbacks
for (int i = 0; i < KERNEL_MAX_EVENT_SUBSCRIPTIONS; i++)
{
m_event_subscription[i] = nullptr;
}
}
/**
@ -76,9 +91,11 @@ Kernel* Kernel::get()
void Kernel::panic(char* message)
{
// TODO: Would be good to print to screen once display module exists
// TODO: Track active pid/module/whatever and include in output
Serial.printf("Kernel panic!\n");
Serial.printf("Scope: %s\n", scope);
if (xPortGetCoreID() == 0)
Serial.printf("Scope: %s\n", scope);
else
Serial.printf("Scope: UI Draw\n");
Serial.printf("%s\n", message);
while (true) {}
}
@ -189,18 +206,63 @@ Module* Kernel::getModule(int module_id)
Kernel::panic("Module not found");
}
void Kernel::event(byte module, byte event, byte param1, byte param2)
void Kernel::event(byte source, byte event, byte param1, byte param2)
{
Event* e = new Event();
e->source = module;
e->source = source;
e->event = event;
e->param1 = param1;
e->param2 = param2;
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
for (int i = 0; i < KERNEL_MAX_EVENT_SUBSCRIPTIONS; i++)
{
if (m_task[i] != nullptr)
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);
}
}
}
}
}
void 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_task[i]->pushEvent(e);
m_event_subscription[i] = new EventSubscription();
m_event_subscription[i]->callback = callback;
m_event_subscription[i]->source_mask = source_mask;
m_event_subscription[i]->event_mask = event_mask;
return;
}
}
Kernel::panic("Exceeded KERNEL_MAX_EVENT_SUBSCRIPTIONS!");
}
void 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]->target = task;
m_event_subscription[i]->source_mask = source_mask;
m_event_subscription[i]->event_mask = event_mask;
return;
}
}
Kernel::panic("Exceeded KERNEL_MAX_EVENT_SUBSCRIPTIONS!");
}

296
watchos/Module_Menu.cpp

@ -1,6 +1,8 @@
#include "watchos.h"
#include "Module_Menu.h"
#define MENU_EAT_OFFSET 3
#include "Module_EAT.h"
#include "Module_UI.h"
#include "watchos_fonts.h"
// Maximum number of items any menu can contain
#define MODULE_MENU_MAX_OPTIONS 16
@ -9,3 +11,293 @@
// How long menu labels can be
#define MODULE_MENU_MAX_OPTION_LENGTH 15
#define MODULE_MENU_EAT_OFFSET 3
#define MODULE_MENU_EAT_ENTRY_LENGTH 16 // MODULE_MENU_MAX_OPTION_LENGTH + 1
Module_EAT* eat;
Module_Menu* menu;
Module_UI* ui;
struct MenuItem
{
byte id;
char label[MODULE_MENU_MAX_OPTION_LENGTH];
};
void menu_draw(int hwnd, int x, int y, int width, int height)
{
menu->draw(hwnd, x, y, width, height);
}
void menu_event(Event* e)
{
menu->event(e);
}
Module_Menu::Module_Menu()
{
menu = this;
eat = (Module_EAT*)Kernel::get()->getModule(MODULE_EAT);
ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
for (int i = 0; i < MODULE_MENU_MAX_OPTIONS; i++)
{
m_item[i] = nullptr;
}
if (eat->allocate(MODULE_MENU, MODULE_MENU_EAT_OFFSET + (MODULE_MENU_EAT_ENTRY_LENGTH * MODULE_MENU_MAX_OPTIONS)))
{
commit();
}
else
{
read();
}
m_hwnd = ui->createWindow(menu_draw, -1, 0);
ui->setLayoutMode(m_hwnd, MODULE_UI_LAYOUT_MODE_SPLIT_HORIZONTAL);
for (int i = 0; i < MODULE_MENU_SHOW_OPTIONS; i++)
{
m_hwnd_item[i] = ui->createWindow(menu_draw, m_hwnd, 0);
}
m_events = new EventQueue();
Kernel::get()->subscribe(menu_event, MODULE_INPUT, MODULE_INPUT_EVENT_PRESS);
}
void Module_Menu::initialize()
{
}
void Module_Menu::tick()
{
Event* e;
int prev_selected = m_selected;
bool scroll_up = false, scroll_down = false;
while (m_events->hasEvent())
{
e = m_events->pop();
if (!ui->isVisible(m_hwnd)) continue;
if ((e->param1 & MODULE_INPUT_BUTTON_UP) == MODULE_INPUT_BUTTON_UP)
{
if (m_selected > 0)
{
m_selected -= 1;
scroll_up = true;
Kernel::debug("Scroll up!");
}
}
if ((e->param1 & MODULE_INPUT_BUTTON_DOWN) == MODULE_INPUT_BUTTON_DOWN)
{
if (m_selected < MODULE_MENU_MAX_OPTIONS && m_item[m_selected + 1] != nullptr)
{
m_selected += 1;
scroll_down = true;
Kernel::debug("Scroll down!");
}
}
if ((e->param1 & MODULE_INPUT_BUTTON_OK) == MODULE_INPUT_BUTTON_OK)
{
m_result_select = true;
hide();
return;
}
if ((e->param1 & MODULE_INPUT_BUTTON_BACK) == MODULE_INPUT_BUTTON_BACK)
{
m_result_cancel = true;
hide();
return;
}
}
if (scroll_up && m_selected < m_scroll_offset)
{
m_scroll_offset -= MODULE_MENU_SHOW_OPTIONS;
if (m_scroll_offset < 0) m_scroll_offset = 0;
}
else if (scroll_down && m_selected >= m_scroll_offset + MODULE_MENU_SHOW_OPTIONS)
{
m_scroll_offset += MODULE_MENU_SHOW_OPTIONS;
}
if (prev_selected != m_selected)
{
ui->setDirty(m_hwnd);
for (int i = 0; i < MODULE_MENU_SHOW_OPTIONS; i++)
{
ui->setDirty(m_hwnd_item[i]);
}
}
}
void Module_Menu::suspend()
{
commit();
}
int Module_Menu::getId()
{
return MODULE_MENU;
}
void Module_Menu::read()
{
m_selected = eat->read(MODULE_MENU, 0);
m_scroll_offset = eat->read(MODULE_MENU, 1);
m_prev_root_hwnd = eat->read(MODULE_MENU, 2);
byte id;
for (int i = 0; i < MODULE_MENU_MAX_OPTIONS; i++)
{
id = eat->read(MODULE_MENU, MODULE_MENU_EAT_OFFSET + (i * MODULE_MENU_EAT_ENTRY_LENGTH));
if (id != 0xFF)
{
m_item[i] = new MenuItem();
m_item[i]->id = id;
for (int j = 0; j < MODULE_MENU_MAX_OPTION_LENGTH; j++)
{
m_item[i]->label[j] = (char)eat->read(MODULE_MENU, MODULE_MENU_EAT_OFFSET + (i * MODULE_MENU_EAT_ENTRY_LENGTH) + j + 1);
if (m_item[i]->label[j] == '\0')
{
break;
}
}
}
else
{
break;
}
}
}
void Module_Menu::commit()
{
eat->write(MODULE_MENU, 0, (byte)m_selected);
eat->write(MODULE_MENU, 1, (byte)m_scroll_offset);
eat->write(MODULE_MENU, 2, (byte)m_prev_root_hwnd);
for (int i = 0; i < MODULE_MENU_MAX_OPTIONS; i++)
{
if (m_item[i] == nullptr)
{
eat->write(MODULE_MENU, MODULE_MENU_EAT_OFFSET + (i * MODULE_MENU_EAT_ENTRY_LENGTH), 0xFF);
}
else
{
eat->write(MODULE_MENU, MODULE_MENU_EAT_OFFSET + (i * MODULE_MENU_EAT_ENTRY_LENGTH), m_item[i]->id);
for (int j = 0; j < MODULE_MENU_MAX_OPTION_LENGTH; j++)
{
eat->write(MODULE_MENU, MODULE_MENU_EAT_OFFSET + (i * MODULE_MENU_EAT_ENTRY_LENGTH) + j + 1, (byte)(m_item[i]->label[j]));
}
}
}
}
void Module_Menu::addItem(byte id, char* label)
{
for (int i = 0; i < MODULE_MENU_MAX_OPTIONS; i++)
{
if (m_item[i] == nullptr)
{
m_item[i] = new MenuItem();
m_item[i]->id = id;
strcpy(m_item[i]->label, label);
return;
}
}
Kernel::panic("Tried to add more menu options than MODULE_MENU_MAX_OPTIONS.");
}
void Module_Menu::reset()
{
for (int i = 0; i < MODULE_MENU_MAX_OPTIONS; i++)
{
if (m_item[i] != nullptr)
{
delete m_item[i];
m_item[i] = nullptr;
}
}
m_selected = 0;
m_scroll_offset = 0;
m_prev_root_hwnd = -1;
m_result_select = false;
m_result_cancel = false;
}
void Module_Menu::show()
{
m_prev_root_hwnd = ui->getRootWindow();
ui->setRootWindow(m_hwnd);
}
void Module_Menu::hide()
{
ui->setRootWindow(m_prev_root_hwnd);
}
bool Module_Menu::isVisible()
{
return ui->getRootWindow() == m_hwnd;
}
void Module_Menu::draw(int hwnd, int x, int y, int width, int height)
{
if (hwnd == m_hwnd)
{
ui->getGfx()->fillRect(x, y, width, height, COLOUR_SECONDARY);
}
else
{
for (int i = 0; i < MODULE_MENU_SHOW_OPTIONS; i++)
{
if (m_hwnd_item[i] == hwnd)
{
int idx = m_scroll_offset + i;
if (m_item[idx] != nullptr)
{
ui->getGfx()->setFont(&FreeMono12pt7b);
if (idx == m_selected)
{
ui->getGfx()->fillRect(x, y, width, height, COLOUR_PRIMARY);
ui->getGfx()->setTextColor(COLOUR_SECONDARY);
}
else
{
ui->getGfx()->fillRect(x, y, width, height, COLOUR_SECONDARY);
ui->getGfx()->setTextColor(COLOUR_PRIMARY);
}
ui->getGfx()->setCursor(x, y + height - (int)((height - 12) / 2));
ui->getGfx()->print(m_item[idx]->label);
}
}
}
}
}
void Module_Menu::event(Event* e)
{
m_events->push(e);
}
int Module_Menu::getSelected()
{
return m_item[m_selected]->id;
}
bool Module_Menu::isSelected()
{
return m_result_select;
}
bool Module_Menu::isCancelled()
{
return m_result_cancel;
}

35
watchos/Module_Menu.h

@ -2,24 +2,49 @@
#define MODULE_MENU_H
#include "watchos.h"
#include "Events.h"
struct MenuItem;
class Module_Menu : public Module
{
ButtonState* m_button[MODULE_INPUT_BUTTONS];
EventQueue* m_events;
MenuItem* m_item[MODULE_MENU_MAX_OPTIONS];
byte m_selected = 0;
byte m_scroll_offset = 0;
byte m_focused = 0;
int m_prev_root_hwnd;
void poll();
bool m_result_select = false;
bool m_result_cancel = false;
int m_hwnd;
int m_hwnd_item[MODULE_MENU_SHOW_OPTIONS];
void read();
void commit();
public:
Module_Input();
Module_Menu();
void initialize();
void suspend();
int getId();
void tick();
bool isAnyPressed();
bool isPressed(byte button);
void draw(int hwnd, int x, int y, int width, int height);
void event(Event* e);
void addItem(byte id, char* label);
void reset();
void show();
void hide();
bool isVisible();
int getSelected();
bool isSelected();
bool isCancelled();
};
#endif

30
watchos/Module_UI.cpp

@ -45,18 +45,13 @@ Module_UI::Module_UI()
module_power = (Module_Power*)Kernel::get()->getModule(MODULE_POWER);
module_eat = (Module_EAT*)Kernel::get()->getModule(MODULE_EAT);
char msg[255];
if (module_eat->allocate(MODULE_UI, 1))
{
sprintf(msg, "Wrote default root window: %d", m_root_window);
Kernel::debug(msg);
module_eat->write(MODULE_UI, 0, 0);
}
else
{
m_root_window = module_eat->read(MODULE_UI, 0);
sprintf(msg, "Read root window: %d", m_root_window);
Kernel::debug(msg);
}
}
@ -80,9 +75,6 @@ void Module_UI::suspend()
if (m_initialized)
gfx.hibernate();
module_eat->write(MODULE_UI, 0, (byte)m_root_window);
char msg[255];
sprintf(msg, "Wrote root window: %d", m_root_window);
Kernel::debug(msg);
}
int Module_UI::getId()
@ -226,6 +218,28 @@ void Module_UI::setDirty(int hwnd)
}
}
bool Module_UI::isVisible(int hwnd)
{
UI_Window* window = nullptr;
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->hwnd == hwnd)
{
window = m_window[i];
break;
}
}
while (window != nullptr)
{
if (window->hwnd == m_root_window)
return true;
window = window->parent;
}
return false;
}
void Module_UI::draw(bool spawn_task)
{
if (spawn_task && (m_dirty || m_redraw) && draw_task == nullptr)

1
watchos/Module_UI.h

@ -32,6 +32,7 @@ public:
void setLayoutMode(int hwnd, byte layout_mode);
void setDirty(int hwnd);
bool isVisible(int hwnd);
void setRootWindow(int hwnd);
int getRootWindow();

1
watchos/TODO.md

@ -0,0 +1 @@
* Add "Scenes" to group tasks/etc and simplify separating input and figuring out what to draw

2
watchos/Task_Battery.cpp

@ -33,8 +33,6 @@ public:
void tick(unsigned int signal)
{
while (this->hasEvent()) { this->popEvent(); }
int new_voltage = getBatteryVoltage();
// TODO: The voltage fluctuates enough in ADC readings that we're just kinda constantly
// drawing it. Rate limiting it a bit at least prevents it from stopping power management

1
watchos/Task_Clock.cpp

@ -18,6 +18,7 @@ public:
{
ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
hwnd = ui->createWindow((Task*)this, parent_hwnd, 0);
Kernel::get()->subscribe(this, MODULE_RTC, MODULE_RTC_EVENT_MINUTE);
}
void initialize()

3
watchos/Task_Counter.cpp

@ -24,6 +24,8 @@ public:
// Read count
count = (eat->read(3, 0) << 24) | (eat->read(3, 1) << 16) | (eat->read(3, 2) << 8) | eat->read(3, 3);
}
Kernel::get()->subscribe(this, MODULE_INPUT);
}
void initialize()
@ -40,6 +42,7 @@ public:
if (e->source == MODULE_INPUT && e->event == MODULE_INPUT_EVENT_PRESS)
{
Kernel::debug("Button press!");
count++;
dirty = true;
}

289
watchos/Task_Menu.cpp

@ -1,312 +1,75 @@
#include "watchos.h"
#include "Module_EAT.h"
#include "Module_UI.h"
#include "watchos_fonts.h"
#include "Module_Menu.h"
#include "Events.h"
struct MenuItem
{
byte id;
char label[MENU_MAX_OPTION_LENGTH];
int window_hwnd;
};
/*
* EAT Layout
* byte selected_idx
* byte view_offset
*
* each entry:
* byte id
* char[31] label
*/
class Task_Menu : public Task
{
private:
int m_hwnd;
Module_UI* ui;
Module_EAT* eat;
MenuItem* m_item[MENU_MAX_OPTIONS];
int m_hwnd_menu_option[MENU_SHOW_OPTIONS];
int m_prev_root_hwnd;
int m_view_offset = 0;
int m_selected = 0;
bool m_result_ok = false;
bool m_result_back = false;
Module_Menu* menu;
bool m_waiting_for_menu = false;
public:
Task_Menu()
{
ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
m_hwnd = ui->createWindow((Task*)this, -1, 0);
ui->setLayoutMode(m_hwnd, MODULE_UI_LAYOUT_MODE_SPLIT_HORIZONTAL);
for (int i = 0; i < MENU_SHOW_OPTIONS; i++)
{
m_hwnd_menu_option[i] = ui->createWindow((Task*)this, m_hwnd, 0);
}
for (int i = 0; i < MENU_MAX_OPTIONS; i++)
{
m_item[i] = nullptr;
}
eat = (Module_EAT*)Kernel::get()->getModule(MODULE_EAT);
int item_length = (1 + MENU_MAX_OPTION_LENGTH);
if (!eat->allocate(MENU_EAT_ID, MENU_EAT_OFFSET + item_length * MENU_MAX_OPTIONS))
{
m_selected = eat->read(MENU_EAT_ID, 0);
m_view_offset = eat->read(MENU_EAT_ID, 1);
m_prev_root_hwnd = eat->read(MENU_EAT_ID, 2);
byte id;
for (int i = 0; i < MENU_MAX_OPTIONS; i++)
{
id = eat->read(MENU_EAT_ID, MENU_EAT_OFFSET + (i * item_length));
if (id != 0xFF)
{
m_item[i] = new MenuItem();
m_item[i]->id = id;
for (int j = 0; j < MENU_MAX_OPTION_LENGTH; j++)
{
m_item[i]->label[j] = (char)eat->read(MENU_EAT_ID, MENU_EAT_OFFSET + (i * item_length) + j + 1);
if (m_item[i]->label[j] == '\0')
{
break;
}
}
}
else
{
break;
}
}
}
menu = (Module_Menu*)Kernel::get()->getModule(MODULE_MENU);
Kernel::get()->subscribe(this, MODULE_INPUT, MODULE_INPUT_EVENT_PRESS);
}
void initialize()
{
ui->setDirty(m_hwnd);
for (int i = 0; i < MENU_SHOW_OPTIONS; i++)
{
ui->setDirty(m_hwnd_menu_option[i]);
}
}
void tick(unsigned int signal)
{
char msg[255];
Event* e;
int prev_selected = -1;
byte scroll_direction = 128; // not const'ing this... 128=middle, 0=up, 255=down
while (this->hasEvent())
{
e = this->popEvent();
if (ui->getRootWindow() != m_hwnd) continue;
if (e->source == MODULE_INPUT && e->event == MODULE_INPUT_EVENT_PRESS)
if (m_waiting_for_menu && (menu->isSelected() || menu->isCancelled()))
{
if ((e->param1 & MODULE_INPUT_BUTTON_UP) != 0)
{
Kernel::debug("Scroll up");
prev_selected = m_selected;
m_selected -= 1;
if (m_selected < 0)
m_selected = 0;
else
scroll_direction = 0;
}
if ((e->param1 & MODULE_INPUT_BUTTON_DOWN) != 0)
{
Kernel::debug("Scroll down");
prev_selected = m_selected;
m_selected += 1;
if (m_item[m_selected] == nullptr)
m_selected -= 1;
else
scroll_direction = 255;
}
if ((e->param1 & MODULE_INPUT_BUTTON_OK) != 0)
if (menu->isSelected())
{
Kernel::debug("OK");
hide();
m_result_ok = true;
return;
sprintf(msg, "Selected option %d", menu->getSelected());
Kernel::debug(msg);
}
if ((e->param1 & MODULE_INPUT_BUTTON_BACK) != 0)
else if (menu->isCancelled())
{
Kernel::debug("Back");
m_result_back = true;
return;
Kernel::debug("Menu cancelled!");
}
m_waiting_for_menu = false;
}
}
if (scroll_direction == 0 && m_selected < m_view_offset)
{
m_view_offset -= MENU_SHOW_OPTIONS;
if (m_view_offset < 0) m_view_offset = 0;
}
else if (scroll_direction == 255 && m_selected >= m_view_offset + MENU_SHOW_OPTIONS)
{
m_view_offset += MENU_SHOW_OPTIONS;
}
// if (scroll)
// elseif (dirty individual items)
// Drawing individual menu items is sloooow, let's just refresh everything.
/*
if (prev_selected >= 0 && m_selected != prev_selected)
{
if (prev_selected - m_view_offset >= 0 && prev_selected - m_view_offset < MENU_MAX_OPTIONS)
// Hacky, but it'll work for now
else if (ui->getRootWindow() == 0 && (e->param1 & MODULE_INPUT_BUTTON_OK) == MODULE_INPUT_BUTTON_OK)
{
ui->setDirty(m_hwnd_menu_option[prev_selected - m_view_offset]);
sprintf(msg, "Marking dirty idx %d hwnd %d", prev_selected - m_view_offset, m_hwnd_menu_option[prev_selected - m_view_offset]);
Kernel::debug(msg);
}
if (m_selected - m_view_offset >= 0 && m_selected - m_view_offset < MENU_MAX_OPTIONS)
{
ui->setDirty(m_hwnd_menu_option[m_selected - m_view_offset]);
sprintf(msg, "Marking dirty idx %d hwnd %d", m_selected - m_view_offset, m_hwnd_menu_option[m_selected - m_view_offset]);
Kernel::debug(msg);
}
}
*/
if (prev_selected >= 0 && m_selected != prev_selected)
{
ui->setDirty(m_hwnd);
for (int i = 0; i < MENU_SHOW_OPTIONS; i++)
{
ui->setDirty(m_hwnd_menu_option[i]);
Kernel::debug("show menu");
show();
m_waiting_for_menu = true;
}
}
}
void suspend()
{
eat->write(MENU_EAT_ID, 0, (byte)m_selected);
eat->write(MENU_EAT_ID, 1, (byte)m_view_offset);
eat->write(MENU_EAT_ID, 2, (byte)m_prev_root_hwnd);
int item_length = (1 + MENU_MAX_OPTION_LENGTH);
for (int i = 0; i < MENU_MAX_OPTIONS; i++)
{
if (m_item[i] == nullptr)
{
eat->write(MENU_EAT_ID, MENU_EAT_OFFSET + (i * item_length), 0xFF);
}
else
{
eat->write(MENU_EAT_ID, MENU_EAT_OFFSET + (i * item_length), m_item[i]->id);
for (int j = 0; j < MENU_MAX_OPTION_LENGTH && m_item[i]->label[j] != '\0'; j++)
{
eat->write(MENU_EAT_ID, MENU_EAT_OFFSET + (i * item_length) + j + 1, (byte)(m_item[i]->label[j]));
}
}
}
}
void draw(int hwnd, int x, int y, int width, int height)
{
if (hwnd == m_hwnd)
{
// Root window
ui->getGfx()->fillRect(x, y, width, height, COLOUR_SECONDARY);
}
else
{
// Menu option
for (int i = 0; i < MENU_SHOW_OPTIONS; i++)
{
if (m_hwnd_menu_option[i] == hwnd)
{
int idx = m_view_offset + i;
if (m_item[idx] != nullptr)
{
ui->getGfx()->setFont(&FreeMono12pt7b);
if (idx == m_selected)
{
ui->getGfx()->fillRect(x, y, width, height, COLOUR_PRIMARY);
ui->getGfx()->setTextColor(COLOUR_SECONDARY);
}
else
{
ui->getGfx()->fillRect(x, y, width, height, COLOUR_SECONDARY);
ui->getGfx()->setTextColor(COLOUR_PRIMARY);
}
ui->getGfx()->setCursor(x, y + height - (int)((height - 12) / 2));
ui->getGfx()->print(m_item[idx]->label);
}
}
}
}
}
void addItem(byte id, char* label)
{
for (int i = 0; i < MENU_MAX_OPTIONS; i++)
{
if (m_item[i] == nullptr)
{
m_item[i] = new MenuItem();
m_item[i]->id = id;
strcpy(m_item[i]->label, label);
return;
}
}
Kernel::panic("Tried to add more options to menu than MENU_MAX_OPTIONS.");
}
void clear()
{
for (int i = 0; i < MENU_MAX_OPTIONS; i++)
{
if (m_item[i] != nullptr)
{
delete m_item[i];
m_item[i] = nullptr;
}
}
}
void show()
{
m_prev_root_hwnd = ui->getRootWindow();
ui->setRootWindow(m_hwnd);
}
void hide()
{
ui->setRootWindow(m_prev_root_hwnd);
m_prev_root_hwnd = NULL;
}
bool isSelected()
{
return m_result_ok;
}
bool isCancelled()
{
return m_result_back;
}
bool isDone()
{
return m_result_ok || m_result_back;
}
byte getSelectedId()
{
return m_item[m_selected]->id;
Kernel::debug("Task_Menu::show");
menu->reset();
menu->addItem(1, "Option 1");
menu->addItem(2, "Option Two");
menu->addItem(3, "Option Tres");
menu->show();
}
};

2
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

24
watchos/watchos.ino

@ -6,6 +6,7 @@
#include "Module_RTC.h"
#include "Module_Input.h"
#include "Module_Power.h"
#include "Module_Menu.h"
#include "Task_Clock.cpp"
#include "Task_Counter.cpp"
@ -81,10 +82,32 @@ void setup()
Module_RTC* module_rtc = new Module_RTC();
k->registerModule(module_rtc);
Module_Menu* module_menu = new Module_Menu();
k->registerModule(module_menu);
k->registerTask(new Task_Clock(top_hwnd));
k->registerTask(new Task_Counter(bottom_hwnd));
k->registerTask(new Task_Battery(bottom_hwnd));
k->registerTask(new Task_Menu());
if (is_reset)
{
/*module_menu->addItem(1, "First");
module_menu->addItem(2, "Second");
module_menu->addItem(3, "Third");
module_menu->addItem(4, "Fourth");
module_menu->addItem(5, "Fifth");
module_menu->addItem(6, "Sixth");
module_menu->addItem(7, "Seventh");
module_menu->addItem(8, "Eighth");
module_menu->addItem(9, "Ninth");
module_menu->addItem(10, "Tenth");
module_menu->addItem(11, "Eleventh");
module_menu->addItem(12, "Twelfth");
module_menu->show();*/
}
/*
Task_Menu* tm = new Task_Menu();
if (is_reset)
{
@ -103,6 +126,7 @@ void setup()
tm->show();
}
k->registerTask(tm);
*/
// TODO: Figure out why we woke up
wakeup();

6
watchos/watchos.vcxproj

File diff suppressed because one or more lines are too long

12
watchos/watchos.vcxproj.filters

@ -66,6 +66,9 @@
<ClInclude Include="Module_Power.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Module_Menu.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Kernel.cpp">
@ -98,5 +101,14 @@
<ClCompile Include="Task_Counter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Task_Battery.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Task_Menu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Module_Menu.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

1
watchos/watchos_consts.h

@ -8,6 +8,7 @@
// running tasks. This sets how many we support.
#define KERNEL_MAX_MODULES 8
#define KERNEL_MAX_TASKS 16
#define KERNEL_MAX_EVENT_SUBSCRIPTIONS 32
// Each task has a ring buffer to hold pending events. This sets
// how large that buffer is. i.e., how many events can be queued

Loading…
Cancel
Save