Browse Source

Initial commit

v1
Adam PIppin 3 years ago
commit
3c3547057c
  1. 6
      .gitignore
  2. 25
      watchos.sln
  3. 151
      watchos/Kernel.cpp
  4. 31
      watchos/Kernel.h
  5. 13
      watchos/Module.h
  6. 189
      watchos/Module_EAT.cpp
  7. 33
      watchos/Module_EAT.h
  8. 93
      watchos/Module_RTC.cpp
  9. 23
      watchos/Module_RTC.h
  10. 217
      watchos/Module_UI.cpp
  11. 29
      watchos/Module_UI.h
  12. 11
      watchos/Task.cpp
  13. 16
      watchos/Task.h
  14. 54
      watchos/TestTask.cpp
  15. 12
      watchos/__vm/Compile.vmps.xml
  16. 9
      watchos/__vm/Configuration.Debug.vmps.xml
  17. 9
      watchos/__vm/Configuration.Release.vmps.xml
  18. 12
      watchos/__vm/Upload.vmps.xml
  19. 7
      watchos/fonts.h
  20. 58
      watchos/hw.h
  21. 14
      watchos/src/arduino folders read me.txt
  22. 13
      watchos/watchos.h
  23. 125
      watchos/watchos.ino
  24. 149
      watchos/watchos.vcxproj
  25. 75
      watchos/watchos.vcxproj.filters

6
.gitignore

@ -0,0 +1,6 @@
/.vs/
*.swp
/watchos/__vm/.watchos.vsarduino.h
/watchos/watchos.vcxproj.user
/watchos/Debug/
/watchos/Release/

25
watchos.sln

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31105.61
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "watchos", "watchos\watchos.vcxproj", "{C5F80730-F44F-4478-BDAE-6634EFC2CA88}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.ActiveCfg = Debug|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.Build.0 = Debug|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.ActiveCfg = Release|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {0B0DCFBF-F360-4A90-8778-58D84486EAFB}
EndGlobalSection
EndGlobal

151
watchos/Kernel.cpp

@ -0,0 +1,151 @@
// Arduino System
#include <Arduino.h>
// RTC
#include <DS3232RTC.h>
// I2C Library
#include <Wire.h>
// Hardware information
#include "hw.h"
#include "Kernel.h"
#define SCOPE_SIZE 64
Kernel* Kernel::s_kernel = nullptr;
char scope[SCOPE_SIZE];
/**
* 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);
// Initialize empty tasks
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
s_kernel->m_task[i] = nullptr;
}
}
/**
* Fetch the singleton instance of the kernel
*/
Kernel* Kernel::get()
{
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
// TODO: Track active pid/module/whatever and include in output
Serial.printf("Kernel panic!\n");
Serial.printf("Scope: %s\n", scope);
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_TASKS; i++)
{
if (m_task[i] != nullptr)
{
m_task[i]->suspend();
}
}
}
/**
* Register a new task in the kernel
*/
void Kernel::registerTask(Task* task)
{
for (int i = 0; i < KERNEL_MAX_TASKS; i++)
{
if (m_task[i] == nullptr)
{
m_task[i] = task;
task->setId(i); // TODO: real pid
task->initialize();
return;
}
}
Kernel::panic("Exceeded KERNEL_MAX_TASKS!");
}
/**
* 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;
module->initialize();
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");
}

31
watchos/Kernel.h

@ -0,0 +1,31 @@
#ifndef KERNEL_H
#define KERNEL_H
#include "watchos.h"
#include "Task.h"
#include "Module.h"
class Kernel
{
static Kernel* s_kernel;
Task* m_task[KERNEL_MAX_TASKS];
Module* m_module[KERNEL_MAX_MODULES];
public:
static void initialize();
static Kernel* get();
static void panic(char* message);
static void debug(char* message);
void tick();
void suspend();
// Tasks
void registerTask(Task* task);
// Modules
void registerModule(Module* module);
};
#endif

13
watchos/Module.h

@ -0,0 +1,13 @@
#ifndef MODULE_H
#define MODULE_H
class Module
{
public:
virtual void initialize() = 0;
virtual void suspend() = 0;
virtual int getId() = 0;
virtual void tick() = 0;
};
#endif

189
watchos/Module_EAT.cpp

@ -0,0 +1,189 @@
#include <EEPROM.h>
#include "Module_EAT.h"
struct EAT_Entry
{
byte module;
byte length;
};
void Module_EAT::initialize()
{
for (int i=0; i<MODULE_EAT_MAX_ENTRIES; i++)
{
m_entry[i] = nullptr;
}
load();
}
void Module_EAT::tick()
{
}
void Module_EAT::suspend()
{
commit();
}
int Module_EAT::getId()
{
return MODULE_EAT;
}
void Module_EAT::load()
{
char msg[255];
EEPROM.begin(EEPROM_SIZE);
byte magic_h = EEPROM.read(0);
byte magic_l = EEPROM.read(1);
m_magic = (magic_h << 8) | magic_l;
m_version = EEPROM.read(2);
m_options = EEPROM.read(3);
if (m_magic != MODULE_EAT_MAGIC)
{
Kernel::panic("Invalid magic in EEPROM, corrupted or not initialize");
}
if (m_version != MODULE_EAT_VERSION)
{
sprintf(msg, "Unsupported version (%d)--please reinitialize EEPROM", m_version);
Kernel::panic(msg);
}
for (int i=0; i<MODULE_EAT_MAX_ENTRIES; i++)
{
byte module = EEPROM.read((i * 2) + MODULE_EAT_STATIC_OFFSET);
byte length = EEPROM.read((i * 2) + MODULE_EAT_STATIC_OFFSET + 1);
m_entry[i] = new EAT_Entry();
m_entry[i]->module = module;
m_entry[i]->length = length;
}
}
void Module_EAT::commit()
{
EEPROM.begin(EEPROM_SIZE);
EEPROM.write(0, (byte)(m_magic >> 8));
EEPROM.write(1, (byte)(m_magic));
EEPROM.write(2, m_version);
EEPROM.write(3, m_options);
for (int i=0; i<MODULE_EAT_MAX_ENTRIES; i++)
{
EEPROM.write((i * 2) + MODULE_EAT_STATIC_OFFSET, m_entry[i]->module);
EEPROM.write((i * 2) + MODULE_EAT_STATIC_OFFSET + 1, m_entry[i]->length);
}
EEPROM.commit();
}
void Module_EAT::reset()
{
m_magic = MODULE_EAT_MAGIC;
m_version = MODULE_EAT_VERSION;
m_options = 0;
for (int i=0; i<MODULE_EAT_MAX_ENTRIES; i++)
{
m_entry[i] = new EAT_Entry();
m_entry[i]->module = 0;
m_entry[i]->length = 0;
}
commit();
}
bool Module_EAT::allocate(byte module, byte length)
{
for (int i=0; i<MODULE_EAT_MAX_ENTRIES; i++)
{
if (m_entry[i]->module == module)
{
return false;
}
if (m_entry[i]->module == 0)
{
m_entry[i]->module = module;
m_entry[i]->length = length;
commit();
return true;
}
}
Kernel::panic("Cannot allocate storage in EAT--out of entries");
}
int Module_EAT::getLength(byte module)
{
for (int i=0; i<MODULE_EAT_MAX_ENTRIES; i++)
{
if (m_entry[i]->module == module)
{
return m_entry[i]->length;
}
}
return -1;
}
int Module_EAT::getOffset(byte module)
{
int offset = MODULE_EAT_STATIC_OFFSET;
for (int i=0; i<MODULE_EAT_MAX_ENTRIES; i++)
{
if (m_entry[i]->module == module)
{
return offset;
}
else
{
offset += m_entry[i]->length;
}
}
return -1;
}
byte Module_EAT::read(byte module, byte offset)
{
int entry_offset = getOffset(module);
#ifdef WATCHOS_DEBUG
if (entry_offset == -1)
{
Kernel::panic("Attempt to read from an uninitialized EAT module");
}
if (offset > getLength(module))
{
Kernel::panic("Attempt to read past the end of EAT allocation");
}
#endif
offset += entry_offset;
char msg[255];
sprintf(msg, "Reading from %d", offset);
Kernel::debug(msg);
return EEPROM.read(offset);
}
void Module_EAT::write(byte module, byte offset, byte value)
{
int entry_offset = getOffset(module);
#ifdef WATCHOS_DEBUG
if (entry_offset == -1)
{
Kernel::panic("Attempt to read from an uninitialized EAT module");
}
if (offset > getLength(module))
{
Kernel::panic("Attempt to read past the end of EAT allocation");
}
#endif
offset += entry_offset;
char msg[255];
sprintf(msg, "Writing %d to %d", value, offset);
Kernel::debug(msg);
EEPROM.write(offset, value);
EEPROM.commit();
}

33
watchos/Module_EAT.h

@ -0,0 +1,33 @@
#ifndef MODULE_EAT_H
#define MODULE_EAT_H
#include "watchos.h"
struct EAT_Entry;
class Module_EAT : public Module
{
uint16_t m_magic;
byte m_version;
byte m_options;
EAT_Entry* m_entry[MODULE_EAT_MAX_ENTRIES];
int getOffset(byte module);
public:
void initialize();
void suspend();
int getId();
void tick();
void load();
void commit();
void reset();
bool allocate(byte module, byte length);
int getLength(byte module);
void write(byte module, byte offset, byte value);
byte read(byte module, byte offset);
};
#endif

93
watchos/Module_RTC.cpp

@ -0,0 +1,93 @@
#include "Module_RTC.h"
#include <DS3232RTC.h>
DS3232RTC RTC;
// https://github.com/JChristensen/DS3232RTC
tmElements_t lastTime;
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()
{
if (RTC.alarm(ALARM_2))
{
// Refresh every time interrupt fires (every minute)
refresh();
// TODO: Signal kernel/processes/whatever?
}
}
void Module_RTC::suspend()
{
}
int Module_RTC::getId()
{
return MODULE_RTC;
}
void Module_RTC::refresh()
{
RTC.read(lastTime);
}
int Module_RTC::getHour()
{
return lastTime.Hour;
}
int Module_RTC::getMinute()
{
return lastTime.Minute;
}
int Module_RTC::getSecond()
{
return lastTime.Second;
}
int Module_RTC::getYear()
{
return lastTime.Year + 1970;
}
int Module_RTC::getMonth()
{
return lastTime.Month;
}
int Module_RTC::getDay()
{
return lastTime.Day;
}
char* Module_RTC::getDayOfWeek()
{
switch (lastTime.Wday)
{
case 1:
return "Sunday";
case 2:
return "Monday";
case 3:
return "Tuesday";
case 4:
return "Wednesday";
case 5:
return "Thursday";
case 6:
return "Friday";
case 7:
return "Saturday";
default:
return "Unknown";
}
}

23
watchos/Module_RTC.h

@ -0,0 +1,23 @@
#ifndef MODULE_RTC_H
#define MODULE_RTC_H
#include "watchos.h"
class Module_RTC : public Module
{
public:
void initialize();
void suspend();
int getId();
void tick();
void refresh();
int getHour();
int getMinute();
int getSecond();
int getYear();
int getMonth();
int getDay();
char* getDayOfWeek();
};
#endif

217
watchos/Module_UI.cpp

@ -0,0 +1,217 @@
#include "watchos.h"
#include "hw.h"
#include "Module_UI.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);
struct UI_Window
{
int hwnd = 0;
UI_Window* parent;
byte layout_mode = 0;
void (*callback)(int, int, int, int, int); // hwnd, x, y, width, height
bool dirty = false;
byte reserved1;
byte reserved2;
};
void Module_UI::initialize()
{
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
m_window[i] = nullptr;
}
// Create root window
createWindow(-1, 0);
gfx.init(0, false); // init(bitrate, initial)?
gfx.setFullWindow();
gfx.fillScreen(GxEPD_WHITE);
gfx.display(true);
}
void Module_UI::tick()
{
}
void Module_UI::suspend()
{
gfx.hibernate();
}
int Module_UI::getId()
{
return MODULE_UI;
}
GxEPD2_GFX* Module_UI::getGfx()
{
return &gfx;
}
int Module_UI::createWindow(void (*callback)(int, int, int, int, int), int parent, int zorder)
{
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] == nullptr)
{
m_window[i] = new UI_Window();
m_window[i]->hwnd = m_nextHwnd++;
m_window[i]->parent = nullptr;
for (int j = 0; j < MODULE_UI_MAX_WINDOWS; j++)
{
if (m_window[j] != nullptr && m_window[j]->hwnd == parent)
{
m_window[i]->parent = m_window[j];
}
}
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;
}
}
Kernel::panic("Exceeded MODULE_UI_MAX_WINDOWS!");
}
int Module_UI::createWindow(int parent, int zorder)
{
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] == nullptr)
{
m_window[i] = new UI_Window();
m_window[i]->hwnd = m_nextHwnd++;
m_window[i]->parent = nullptr;
for (int j = 0; j < MODULE_UI_MAX_WINDOWS; j++)
{
if (m_window[j] != nullptr && m_window[j]->hwnd == parent)
{
m_window[i]->parent = m_window[j];
}
}
m_window[i]->layout_mode = MODULE_UI_LAYOUT_MODE_NONE;
m_window[i]->callback = nullptr;
return m_window[i]->hwnd;
}
}
Kernel::panic("Exceeded MODULE_UI_MAX_WINDOWS!");
}
void Module_UI::setLayoutMode(int hwnd, byte layout_mode)
{
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->hwnd == hwnd)
{
m_window[i]->layout_mode = layout_mode;
return;
}
}
Kernel::panic("Window hwnd not found!");
}
void Module_UI::setDirty(int hwnd)
{
UI_Window* window = nullptr;
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i]->hwnd == hwnd)
{
window = m_window[i];
break;
}
}
while (window != nullptr)
{
window->dirty = true;
window = window->parent;
}
}
void Module_UI::draw()
{
draw(0, 0, 0, DISPLAY_WIDTH, DISPLAY_HEIGHT);
getGfx()->display(true);
}
void Module_UI::draw(int hwnd, int x, int y, int width, int height)
{
UI_Window* window = nullptr;
// Find the window and draw it if applicable
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->hwnd == hwnd)
{
window = m_window[i];
}
}
if (window == nullptr)
{
Kernel::panic("Trying to draw non-existent window!");
}
// Draw window if applicable
if (window->callback != nullptr && window->dirty)
{
(window->callback)(hwnd, x, y, width, height);
}
// Count children
int child_count = 0;
for (int i = 0; i < MODULE_UI_MAX_WINDOWS; i++)
{
if (m_window[i] != nullptr && m_window[i]->parent == window)
{
child_count++;
}
}
if (child_count == 0)
{
// No children to draw -- we're out of here!
return;
}
// Grab all children
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_height, child_width;
switch (layout_mode)
{
case MODULE_UI_LAYOUT_MODE_NONE:
for (int i = 0; i < child_count; i++)
{
draw(children[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++)
{
draw(children[i]->hwnd, x, y + (i * 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++)
{
draw(children[i]->hwnd, x + (i * child_width), y, child_width, height);
}
break;
}
}

29
watchos/Module_UI.h

@ -0,0 +1,29 @@
#ifndef MODULE_UI_H
#define MODULE_UI_H
#include "watchos.h"
#include <GxEPD2_GFX.h>
struct UI_Window;
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);
public:
void initialize();
void suspend();
int getId();
void tick();
int createWindow(void (*callback)(int, int, int, int, int), int parent = 0, int zorder = 0);
int createWindow(int parent = 0, int zorder = 0);
void draw();
GxEPD2_GFX* getGfx();
void setLayoutMode(int hwnd, byte layout_mode);
void setDirty(int hwnd);
};
#endif

11
watchos/Task.cpp

@ -0,0 +1,11 @@
#include "Task.h"
void Task::setId(int pid)
{
pid = pid;
}
int Task::getId()
{
return pid;
}

16
watchos/Task.h

@ -0,0 +1,16 @@
#ifndef TASK_H
#define TASK_H
class Task
{
private:
int pid;
public:
virtual void initialize() = 0;
virtual void tick(unsigned int signal) = 0;
virtual void suspend() = 0;
int getId();
void setId(int pid);
};
#endif

54
watchos/TestTask.cpp

@ -0,0 +1,54 @@
#include "watchos.h"
#include "Module_UI.h"
#include "Module_RTC.h"
#include "fonts.h"
class TestTask : public Task
{
private:
int hwnd;
Module_UI* ui;
int lastMinute = 0;
public:
void initialize()
{
ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
hwnd = ui->createWindow(&TestTask::draw, 0, 0);
}
void tick(unsigned int signal)
{
// TODO: Replace once there's a signal for RTC events
Module_RTC* rtc = (Module_RTC*)Kernel::get()->getModule(MODULE_RTC);
Module_UI* ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
if (rtc->getMinute() != lastMinute)
{
lastMinute = rtc->getMinute();
ui->setDirty(hwnd);
}
}
void suspend()
{
}
static void draw(int hwnd, int x, int y, int width, int height)
{
Module_RTC* rtc = (Module_RTC*)Kernel::get()->getModule(MODULE_RTC);
char time[5];
sprintf(time, "%02d:%02d", rtc->getHour(), rtc->getMinute());
Module_UI* ui = (Module_UI*)Kernel::get()->getModule(MODULE_UI);
ui->getGfx()->fillRect(x, y, width, height, GxEPD_WHITE);
ui->getGfx()->setFont(&DSEG7_Classic_Bold_53);
ui->getGfx()->setTextColor(GxEPD_BLACK);
ui->getGfx()->setCursor(0, y+height);
ui->getGfx()->print(time);
/*
ui->getGfx()->drawRect(x, y, width, height, GxEPD_BLACK);
ui->getGfx()->setFont(&FreeMono12pt7b);
ui->getGfx()->setTextColor(GxEPD_BLACK);
ui->getGfx()->setCursor(x, y + height);
ui->getGfx()->print("Hello!");
*/
}
};

12
watchos/__vm/Compile.vmps.xml

File diff suppressed because one or more lines are too long

9
watchos/__vm/Configuration.Debug.vmps.xml

File diff suppressed because one or more lines are too long

9
watchos/__vm/Configuration.Release.vmps.xml

File diff suppressed because one or more lines are too long

12
watchos/__vm/Upload.vmps.xml

File diff suppressed because one or more lines are too long

7
watchos/fonts.h

@ -0,0 +1,7 @@
#ifndef FONTS_H
#define FONTS_H
#include <DSEG7_Classic_Bold_53.h>
#include <Fonts/FreeMono12pt7b.h>
#endif

58
watchos/hw.h

@ -0,0 +1,58 @@
#ifndef HW_H
#define HW_H
//////////
// I2C
#define HW_I2C_SDA 21
#define HW_I2C_SCL 22
//////////
// RTC
// Pin
// #define HW_RTC 27
#define HW_RTC GPIO_NUM_27
//////////
// Display
// Controller pins
// Chip select?
#define HW_DISPLAY_CS 5
// Data/Command selector?
#define HW_DISPLAY_DC 10
#define HW_DISPLAY_RESET 9
#define HW_DISPLAY_BUSY 19
#define DISPLAY_WIDTH 200
#define DISPLAY_HEIGHT 200
// Enable GFX library in display driver
#define ENABLE_GxEPD2_GFX 1
//////////
// Vibration Motor
// Pin
#define HW_VIBRATION_MOTOR 13
//////////
// Buttons
// Pin assignments for buttons
#define HW_BUTTON_TL 25
#define HW_BUTTON_TR 32
#define HW_BUTTON_BL 26
#define HW_BUTTON_BR 4
// Masks for wakeups
#define HW_BUTTON_TL_MASK GPIO_SEL_25
#define HW_BUTTON_TR_MASK GPIO_SEL_32
#define HW_BUTTON_BL_MASK GPIO_SEL_26
#define HW_BUTTON_BR_MASK GPIO_SEL_4
// Combined mask for any button
#define HW_BUTTON_MASK HW_BUTTON_TL_MASK|HW_BUTTON_TR_MASK|HW_BUTTON_BL_MASK|HW_BUTTON_BR_MASK
#endif

14
watchos/src/arduino folders read me.txt

@ -0,0 +1,14 @@
#####################################################
Arduino How To: Use sub folders for source code
http://www.visualmicro.com/
#####################################################
* .INO code can exist in the project folder and '\src' folder.
* .Cpp/.c/.S/.h etc. can exist in the project folder, the '\src' folder and in any folder(s) below the '\src' folder.
* .Cpp/.c/.S/.h sources in shared code projects should follow the same folder rules (because they are merged with the project sources into a temporary build folder prior to compile).
* Use the 'Show All Files' icon above the 'Solution Explorer' to switch between 'included project files' and 'physical files/folders'.
* Source code in the project folder will always be compiled regardless of inclusion in the project. This functionality can be disabled in Global Options.

13
watchos/watchos.h

@ -0,0 +1,13 @@
#include "Kernel.h"
#define WATCHOS_DEBUG
#define KERNEL_MAX_MODULES 8
#define KERNEL_MAX_TASKS 16
#define MODULE_EAT 0x0001
#define MODULE_EAT_MAGIC 0x4150
#define MODULE_EAT_VERSION 1
#define MODULE_EAT_MAX_ENTRIES 16
#define MODULE_EAT_STATIC_OFFSET 4 + (MODULE_EAT_MAX_ENTRIES * 2)
#define EEPROM_SIZE 4096

125
watchos/watchos.ino

@ -0,0 +1,125 @@
#include "watchos.h"
#include "hw.h"
#include "Module_EAT.h"
#include "Module_UI.h"
#include "Module_RTC.h"
#include "TestTask.cpp"
#include <GxEPD2_BW.h>
Kernel* k;
int count = 0;
void wakeup();
void test_draw(int hwnd, int x, int y, int width, int height)
{
Kernel::debug("Test draw!");
/*
Module_UI* ui = (Module_UI*)k->getModule(MODULE_UI);
ui->getGfx()->drawRect(x, y, width, height, GxEPD_BLACK);
ui->getGfx()->setFont(&FreeMono12pt7b);
ui->getGfx()->setTextColor(GxEPD_BLACK);
ui->getGfx()->setCursor(x, y + height);
ui->getGfx()->print("Hello!");
*/
}
void setup() {
Kernel::initialize();
k = Kernel::get();
delay(1000);
Serial.printf("Started!\n");
// Initialize eeprom module
Module_EAT* module_eat = new Module_EAT();
// If the right magic bytes aren't there then create header + allocation table
if (!module_eat->hasValidHeader())
{
module_eat->reset();
}
// Register module with the kernel
k->registerModule(module_eat);
// Initialize UI module
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();
Module_RTC* module_rtc = new Module_RTC();
k->registerModule(module_rtc);
k->registerTask(new TestTask());
k->registerTask(new TestTask());
// TODO: Figure out why we woke up
wakeup();
}
int iters = 0;
void loop() {
k->tick();
if (iters++ == 5)
{
Module_UI* ui = (Module_UI*)k->getModule(MODULE_UI);
ui->draw();
Kernel::debug("Going to sleep!");
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();
}
}
void wakeup()
{
Kernel::debug("Wakeup!");
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
uint64_t wakeup_bits;
switch (wakeup_reason)
{
case ESP_SLEEP_WAKEUP_TIMER:
Kernel::debug("Wakeup: Internal RTC");
break;
case ESP_SLEEP_WAKEUP_EXT0:
Kernel::debug("Wakeup: External RTC");
break;
case ESP_SLEEP_WAKEUP_EXT1:
Kernel::debug("Wakeup: Button Press");
wakeup_bits = esp_sleep_get_ext1_wakeup_status();
if (digitalRead(HW_BUTTON_TL) == 1 || (wakeup_bits & HW_BUTTON_TL_MASK))
{
Kernel::debug("Pressed TL Button");
}
if (digitalRead(HW_BUTTON_TR) == 1 || (wakeup_bits & HW_BUTTON_TR_MASK))
{
Kernel::debug("Pressed TR Button");
}
if (digitalRead(HW_BUTTON_BL) == 1 || (wakeup_bits & HW_BUTTON_BL_MASK))
{
Kernel::debug("Pressed BL Button");
}
if (digitalRead(HW_BUTTON_BR) == 1 || (wakeup_bits & HW_BUTTON_BR_MASK))
{
Kernel::debug("Pressed BR Button");
}
break;
default:
Kernel::debug("Wakeup: Reset / First Boot");
break;
}
}

149
watchos/watchos.vcxproj

File diff suppressed because one or more lines are too long

75
watchos/watchos.vcxproj.filters

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Misc Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>xml;json;txt;rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="watchos.ino" />
<None Include="src\arduino folders read me.txt">
<Filter>Misc Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="__vm\.watchos.vsarduino.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\..\Arduino\watchos\Kernel.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\..\Arduino\watchos\Module.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\..\Arduino\watchos\Module_EAT.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\..\Arduino\watchos\Task.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\..\Arduino\watchos\watchos.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hw.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Module_UI.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Module_RTC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="fonts.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Kernel.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\..\Arduino\watchos\Module_EAT.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\..\Arduino\watchos\Task.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Module_UI.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Module_RTC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TestTask.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
Loading…
Cancel
Save