Adam PIppin
3 years ago
22 changed files with 618 additions and 4 deletions
@ -0,0 +1,26 @@ |
|||
#include "EventListener.h" |
|||
|
|||
bool EventListener::hasEvent() |
|||
{ |
|||
} |
|||
|
|||
Event* EventListener::popEvent() |
|||
{ |
|||
} |
|||
|
|||
void EventListener::pushEvent(kernel_handle_t handle) |
|||
{ |
|||
} |
|||
|
|||
class IEventListener |
|||
{ |
|||
private: |
|||
Queue<Event*> m_events; |
|||
protected: |
|||
bool hasEvent(); |
|||
Event* popEvent(); |
|||
public: |
|||
void pushEvent(kernel_handle_t handle); |
|||
uint32_t getEventSourceMask(); |
|||
uint16_t getEventTypeMask(); |
|||
}; |
@ -0,0 +1,22 @@ |
|||
#ifndef _EVENTLISTENER_h |
|||
#define _EVENTLISTENER_h |
|||
|
|||
#include "watchos.h" |
|||
#include "Queue.h" |
|||
#include "Events.h" |
|||
|
|||
class EventListener |
|||
{ |
|||
private: |
|||
Queue<kernel_handle_t> m_event_queue; |
|||
protected: |
|||
bool hasEvent(); |
|||
Event* popEvent(); |
|||
void releaseEvent(kernel_handle_t handle); |
|||
public: |
|||
void pushEvent(kernel_handle_t handle); |
|||
uint32_t getEventSourceMask(); |
|||
uint16_t getEventTypeMask(); |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,12 @@ |
|||
#ifndef _EVENTS_h |
|||
#define _EVENTS_h |
|||
|
|||
struct Event |
|||
{ |
|||
uint32_t source; |
|||
uint16_t event; |
|||
byte param1; |
|||
byte param2; |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,10 @@ |
|||
#ifndef _IDRAWABLE_h |
|||
#define _IDRAWABLE_h |
|||
|
|||
class IDrawable |
|||
{ |
|||
public: |
|||
virtual void draw(int hwnd, int x, int y, int width, int height) = 0; |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,10 @@ |
|||
#ifndef _IRUNNABLE_h |
|||
#define _IRUNNABLE_h |
|||
|
|||
class IRunnable |
|||
{ |
|||
public: |
|||
virtual void tick() = 0; |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,160 @@ |
|||
#include "watchos.h" |
|||
#include "IRunnable.h" |
|||
|
|||
struct KernelHandle |
|||
{ |
|||
kernel_handle_t handle; |
|||
kernel_handle_destructor_t destructor; |
|||
void* object; |
|||
uint references; |
|||
uint32_t well_known = 0; |
|||
}; |
|||
|
|||
struct KernelTask |
|||
{ |
|||
kernel_handle_t handle; |
|||
Task* task; |
|||
}; |
|||
|
|||
void destruct_task(kernel_handle_t handle, void* object) |
|||
{ |
|||
delete object; |
|||
} |
|||
|
|||
Kernel::Kernel() |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_HANDLES; i++) |
|||
{ |
|||
m_handle[i] = nullptr; |
|||
} |
|||
|
|||
for (int i = 0; i < KERNEL_MAX_TASKS; i++) |
|||
{ |
|||
m_task[i] = nullptr; |
|||
} |
|||
} |
|||
|
|||
kernel_handle_t Kernel::allocHandle(byte type, void* object, kernel_handle_destructor_t destructor, uint32_t well_known) |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_HANDLES; i++) |
|||
{ |
|||
if (m_handle[i] == nullptr) |
|||
{ |
|||
m_handle[i] = new KernelHandle(); |
|||
m_handle[i]->handle = type | m_next_handle++; |
|||
m_handle[i]->destructor = destructor; |
|||
m_handle[i]->object = object; |
|||
m_handle[i]->references = 1; |
|||
m_handle[i]->well_known = well_known; |
|||
return m_handle[i]->handle; |
|||
} |
|||
} |
|||
watchos::panic("Exceeded KERNEL_MAX_HANDLES"); |
|||
} |
|||
|
|||
void Kernel::freeHandle(kernel_handle_t handle) |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_HANDLES; i++) |
|||
{ |
|||
if (m_handle[i] != nullptr && m_handle[i]->handle == handle) |
|||
{ |
|||
if (m_handle[i]->destructor != nullptr) |
|||
{ |
|||
(m_handle[i]->destructor)(handle, m_handle[i]->object); |
|||
} |
|||
delete m_handle[i]; |
|||
m_handle[i] = nullptr; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void* Kernel::getHandle(kernel_handle_t handle) |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_HANDLES; i++) |
|||
{ |
|||
if (m_handle[i] != nullptr && m_handle[i]->handle == handle) |
|||
{ |
|||
m_handle[i]->references++; |
|||
return m_handle[i]->object; |
|||
} |
|||
} |
|||
watchos::panic("Attempt to access invalid Kernel handle"); |
|||
} |
|||
|
|||
void* Kernel::getHandle(uint32_t well_known) |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_HANDLES; i++) |
|||
{ |
|||
if (m_handle[i] != nullptr && m_handle[i]->well_known == well_known) |
|||
{ |
|||
m_handle[i]->references++; |
|||
return m_handle[i]->object; |
|||
} |
|||
} |
|||
watchos::panic("Attempt to access invalid Kernel handle by well-known id: %#10x", well_known); |
|||
} |
|||
|
|||
void Kernel::releaseHandle(kernel_handle_t handle) |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_HANDLES; i++) |
|||
{ |
|||
if (m_handle[i] != nullptr && m_handle[i]->handle == handle) |
|||
{ |
|||
m_handle[i]->references--; |
|||
|
|||
if (m_handle[i]->references == 0) |
|||
{ |
|||
freeHandle(handle); |
|||
} |
|||
|
|||
return; |
|||
} |
|||
} |
|||
|
|||
watchos::panic("Attempt to release invalid Kernel handle"); |
|||
} |
|||
|
|||
kernel_handle_t Kernel::registerTask(Task* task) |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_TASKS; i++) |
|||
{ |
|||
if (m_task[i] == nullptr) |
|||
{ |
|||
m_task[i] = new KernelTask(); |
|||
m_task[i]->handle = allocHandle(WATCHOS_HANDLE_TYPE_TASK, (void*)destruct_task); |
|||
m_task[i]->task = task; |
|||
return m_task[i]->handle; |
|||
} |
|||
} |
|||
|
|||
watchos::panic("Exceeded KERNEL_MAX_TASKS"); |
|||
} |
|||
|
|||
void Kernel::unregisterTask(Task* task) |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_TASKS; i++) |
|||
{ |
|||
if (m_task[i] != nullptr && m_task[i]->task == task) |
|||
{ |
|||
releaseHandle(m_task[i]->handle); |
|||
delete m_task[i]; |
|||
m_task[i] = nullptr; |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
|
|||
void Kernel::tick() |
|||
{ |
|||
for (int i = 0; i < KERNEL_MAX_TASKS; i++) |
|||
{ |
|||
if (m_task[i] != nullptr) |
|||
{ |
|||
IRunnable* runnable = dynamic_cast<IRunnable*>(m_task[i]->task); |
|||
if (runnable != nullptr) |
|||
{ |
|||
runnable->tick(); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,63 @@ |
|||
#ifndef _KERNEL_h |
|||
#define _KERNEL_h |
|||
|
|||
#include "Task.h" |
|||
|
|||
#define KERNEL_MAX_HANDLES 256 |
|||
#define KERNEL_MAX_TASKS 32 |
|||
|
|||
typedef void (*kernel_handle_destructor_t)(kernel_handle_t, void*); |
|||
|
|||
struct KernelHandle; |
|||
struct KernelTask; |
|||
|
|||
class Kernel |
|||
{ |
|||
private: |
|||
KernelHandle* m_handle[KERNEL_MAX_HANDLES]; |
|||
int m_next_handle = 1; |
|||
KernelTask* m_task[KERNEL_MAX_TASKS]; |
|||
|
|||
void freeHandle(kernel_handle_t handle); |
|||
|
|||
public: |
|||
Kernel(); |
|||
|
|||
/// <summary>
|
|||
/// Create a new kernel handle pointing to an object
|
|||
/// </summary>
|
|||
/// <param name="type">Type of the handle, one of WATCHOS_HANDLE_TYPE_ consts</param>
|
|||
/// <param name="object">Pointer to the object this handle references</param>
|
|||
/// <param name="destructor">Function to call when this handle has released all references</param>
|
|||
/// <param name="well_known">Specify a 'well_known' value this pointer can be fetched by</param>
|
|||
/// <returns>A handle which can be used to fetch or release this object</returns>
|
|||
kernel_handle_t allocHandle(byte type, void* object, kernel_handle_destructor_t destructor = nullptr, byte well_known = 0); |
|||
|
|||
/// <summary>
|
|||
/// Fetch the object referenced by this handle, increasing the reference count
|
|||
/// </summary>
|
|||
/// <param name="handle">Handle to fetch</param>
|
|||
/// <returns>A pointer to the object the handle references</returns>
|
|||
void* getHandle(kernel_handle_t handle); |
|||
|
|||
/// <summary>
|
|||
/// Fetch an object by its well-known value, increasing the reference count
|
|||
/// </summary>
|
|||
/// <param name="well_known">Well-known id of handle</param>
|
|||
/// <returns>A pointer to the object the handle references</returns>
|
|||
void* getHandle(byte well_known); |
|||
|
|||
/// <summary>
|
|||
/// Release a fetched reference to this object
|
|||
/// </summary>
|
|||
/// <param name="handle">Handle to release</param>
|
|||
void releaseHandle(kernel_handle_t handle); |
|||
|
|||
kernel_handle_t registerTask(Task* task); |
|||
void unregisterTask(Task* task); |
|||
|
|||
void tick(); |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -0,0 +1,80 @@ |
|||
#include "Queue.h" |
|||
|
|||
template<typename T> |
|||
Queue<T>::Queue() |
|||
{ |
|||
for (int i = 0; i < QUEUE_RING_SIZE; i++) |
|||
{ |
|||
m_item[i] = nullptr; |
|||
} |
|||
} |
|||
|
|||
template<typename T> |
|||
void Queue<T>::push(T* item) |
|||
{ |
|||
if (m_full) |
|||
{ |
|||
watchos::panic("Cannot enqueue item: ring buffer full"); |
|||
} |
|||
|
|||
// Write at m_next
|
|||
m_item[m_write] = item; |
|||
|
|||
// Move the write position up
|
|||
m_write = next(m_write); |
|||
|
|||
// If the next position to write has looped back around to the next position
|
|||
// to read, then the buffer is full
|
|||
if (m_read == m_write) |
|||
{ |
|||
m_full = true; |
|||
} |
|||
} |
|||
|
|||
template<typename T> |
|||
T* Queue<T>::peek() |
|||
{ |
|||
// If the next position to read and write match but the buffer isn't full,
|
|||
// then the buffer is empty
|
|||
if (m_read == m_write && !m_full) |
|||
{ |
|||
watchos::panic("Cannot dequeue event: ring buffer empty"); |
|||
} |
|||
|
|||
return m_item[m_read]; |
|||
} |
|||
|
|||
template<typename T> |
|||
T* Queue<T>::pop() |
|||
{ |
|||
// If the next position to read and write match but the buffer isn't full,
|
|||
// then the buffer is empty
|
|||
if (m_read == m_write && !m_full) |
|||
{ |
|||
watchos::panic("Cannot dequeue event: ring buffer empty"); |
|||
} |
|||
|
|||
T* nextItem = m_item[m_read]; |
|||
// Move to the next read position
|
|||
m_read = next(m_read); |
|||
// We can never be full if we just removed an item
|
|||
m_full = false; |
|||
|
|||
return nextItem; |
|||
} |
|||
|
|||
template<typename T> |
|||
bool Queue<T>::isEmpty() |
|||
{ |
|||
return m_read == m_write && !m_full; |
|||
} |
|||
|
|||
template<typename T> |
|||
int Queue<T>::next(int n) |
|||
{ |
|||
if (n + 1 == QUEUE_RING_SIZE) |
|||
return 0; |
|||
else |
|||
return n + 1; |
|||
} |
|||
|
@ -0,0 +1,22 @@ |
|||
#ifndef _QUEUE_h |
|||
#define _QUEUE_h |
|||
|
|||
#define QUEUE_RING_SIZE 8 |
|||
|
|||
template<typename T> |
|||
class Queue |
|||
{ |
|||
private: |
|||
T* m_item[QUEUE_RING_SIZE]; |
|||
int m_read = 0, m_write = 0; |
|||
bool m_full = false; |
|||
int next(int n); |
|||
public: |
|||
Queue(); |
|||
void push(T* item); |
|||
T* pop(); |
|||
T* peek(); |
|||
bool isEmpty(); |
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,4 @@ |
|||
#include "Queue.h" |
|||
#include "Queue.cpp" |
|||
|
|||
template class Queue<int>; |
@ -0,0 +1,5 @@ |
|||
#include "Task.h" |
|||
|
|||
void Task::initialize() {}; |
|||
void Task::start() {}; |
|||
void Task::suspend() {}; |
@ -0,0 +1,13 @@ |
|||
#ifndef _TASK_h |
|||
#define _TASK_h |
|||
|
|||
class Task |
|||
{ |
|||
public: |
|||
virtual void initialize(); |
|||
virtual void start(); |
|||
virtual void suspend(); |
|||
}; |
|||
|
|||
#endif |
|||
|
@ -0,0 +1,12 @@ |
|||
#include "watchos.h" |
|||
#include "Task.h" |
|||
#include "IRunnable.h" |
|||
|
|||
class Task_Test : public IRunnable, public Task |
|||
{ |
|||
public: |
|||
void tick() |
|||
{ |
|||
watchos::debug("Tick!"); |
|||
} |
|||
}; |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,45 @@ |
|||
#include <stdarg.h> |
|||
|
|||
#include "watchos.h" |
|||
|
|||
Kernel* watchos::s_kernel = nullptr; |
|||
|
|||
void watchos::initialize() |
|||
{ |
|||
Serial.begin(115200); |
|||
} |
|||
|
|||
Kernel* watchos::kernel() |
|||
{ |
|||
if (s_kernel == nullptr) |
|||
{ |
|||
s_kernel = new Kernel(); |
|||
} |
|||
return s_kernel; |
|||
} |
|||
|
|||
void watchos::panic(char* fmt...) |
|||
{ |
|||
Serial.println("PANIC PANIC PANIC"); |
|||
va_list args; |
|||
char msg[512]; |
|||
va_start(args, fmt); |
|||
vsprintf(msg, fmt, args); |
|||
va_end(args); |
|||
Serial.println(msg); |
|||
delay(3000); |
|||
Serial.println("Resetting..."); |
|||
ESP.restart(); |
|||
} |
|||
|
|||
void watchos::debug(char* fmt...) |
|||
{ |
|||
#ifdef WATCHOS_DEBUG |
|||
va_list args; |
|||
char msg[512]; |
|||
va_start(args, fmt); |
|||
vsprintf(msg, fmt, args); |
|||
va_end(args); |
|||
Serial.println(msg); |
|||
#endif |
|||
} |
@ -0,0 +1,25 @@ |
|||
#ifndef _WATCHOS2_h |
|||
#define _WATCHOS2_h |
|||
|
|||
#include <Arduino.h> |
|||
#include "watchos_config.h" |
|||
#include "watchos_consts.h" |
|||
#include "watchos_hw.h" |
|||
#include "watchos_types.h" |
|||
|
|||
#include "Kernel.h" |
|||
|
|||
class watchos |
|||
{ |
|||
private: |
|||
static Kernel* s_kernel; |
|||
|
|||
public: |
|||
static void initialize(); |
|||
static Kernel* kernel(); |
|||
static void panic(char* fmt...); |
|||
static void debug(char* fmt...); |
|||
|
|||
}; |
|||
|
|||
#endif |
@ -0,0 +1,12 @@ |
|||
#ifndef _WATCHOS_CONSTS_h |
|||
#define _WATCHOS_CONSTS_h |
|||
|
|||
// If defined, enable debugging output.
|
|||
#define WATCHOS_DEBUG |
|||
|
|||
#define WATCHOS_WK_TEST 0x00000001 |
|||
|
|||
#define WATCHOS_HANDLE_NULL 0x00000000 |
|||
#define WATCHOS_HANDLE_TYPE_TASK 0x01 |
|||
|
|||
#endif |
@ -0,0 +1,63 @@ |
|||
#ifndef _WATCHOS_HW_h |
|||
#define _WATCHOS_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 |
|||
|
|||
|
|||
//////////
|
|||
// ADC / Battery
|
|||
#define HW_BATTERY_ADC_PIN 33 |
|||
|
|||
|
|||
//////////
|
|||
// 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 |
@ -0,0 +1,9 @@ |
|||
#ifndef _WATCHOS_TYPES_h |
|||
#define _WATCHOS_TYPES_h |
|||
|
|||
/// <summary>
|
|||
/// A handle to any kernel object
|
|||
/// </summary>
|
|||
typedef uint32_t kernel_handle_t; |
|||
|
|||
#endif |
Loading…
Reference in new issue