Browse Source

Building out kernel/tasks, have queue I'm about to delete

master
Adam PIppin 3 years ago
parent
commit
0de96b28c5
  1. 26
      watchos2/EventListener.cpp
  2. 22
      watchos2/EventListener.h
  3. 12
      watchos2/Events.h
  4. 10
      watchos2/IDrawable.h
  5. 10
      watchos2/IRunnable.h
  6. 160
      watchos2/Kernel.cpp
  7. 63
      watchos2/Kernel.h
  8. 80
      watchos2/Queue.cpp
  9. 22
      watchos2/Queue.h
  10. 4
      watchos2/Queues.cpp
  11. 5
      watchos2/Task.cpp
  12. 13
      watchos2/Task.h
  13. 12
      watchos2/Task_Test.cpp
  14. 4
      watchos2/__vm/Compile.vmps.xml
  15. 12
      watchos2/__vm/Upload.vmps.xml
  16. 45
      watchos2/watchos.cpp
  17. 25
      watchos2/watchos.h
  18. 13
      watchos2/watchos2.ino
  19. 0
      watchos2/watchos_config.h
  20. 12
      watchos2/watchos_consts.h
  21. 63
      watchos2/watchos_hw.h
  22. 9
      watchos2/watchos_types.h

26
watchos2/EventListener.cpp

@ -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();
};

22
watchos2/EventListener.h

@ -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

12
watchos2/Events.h

@ -0,0 +1,12 @@
#ifndef _EVENTS_h
#define _EVENTS_h
struct Event
{
uint32_t source;
uint16_t event;
byte param1;
byte param2;
};
#endif

10
watchos2/IDrawable.h

@ -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

10
watchos2/IRunnable.h

@ -0,0 +1,10 @@
#ifndef _IRUNNABLE_h
#define _IRUNNABLE_h
class IRunnable
{
public:
virtual void tick() = 0;
};
#endif

160
watchos2/Kernel.cpp

@ -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();
}
}
}
}

63
watchos2/Kernel.h

@ -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

80
watchos2/Queue.cpp

@ -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;
}

22
watchos2/Queue.h

@ -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

4
watchos2/Queues.cpp

@ -0,0 +1,4 @@
#include "Queue.h"
#include "Queue.cpp"
template class Queue<int>;

5
watchos2/Task.cpp

@ -0,0 +1,5 @@
#include "Task.h"
void Task::initialize() {};
void Task::start() {};
void Task::suspend() {};

13
watchos2/Task.h

@ -0,0 +1,13 @@
#ifndef _TASK_h
#define _TASK_h
class Task
{
public:
virtual void initialize();
virtual void start();
virtual void suspend();
};
#endif

12
watchos2/Task_Test.cpp

@ -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!");
}
};

4
watchos2/__vm/Compile.vmps.xml

File diff suppressed because one or more lines are too long

12
watchos2/__vm/Upload.vmps.xml

File diff suppressed because one or more lines are too long

45
watchos2/watchos.cpp

@ -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
}

25
watchos2/watchos.h

@ -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

13
watchos2/watchos2.ino

@ -3,13 +3,22 @@
Created: 6/30/2021 9:38:10 PM
Author: Adam
*/
#include "watchos.h"
#include "Task_Test.cpp"
#include <Preferences.h>
// the setup function runs once when you press reset or power the board
void setup() {
delay(500);
watchos::initialize();
Kernel* kernel = watchos::kernel();
kernel->registerTask(new Task_Test());
watchos::debug("Setup done!");
}
// the loop function runs over and over again until power down or reset
void loop() {
watchos::kernel()->tick();
}

0
watchos2/watchos_config.h

12
watchos2/watchos_consts.h

@ -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

63
watchos2/watchos_hw.h

@ -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

9
watchos2/watchos_types.h

@ -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…
Cancel
Save