diff --git a/source/shoh/.cproject b/source/shoh/.cproject
index c20b11d..ff20bcd 100644
--- a/source/shoh/.cproject
+++ b/source/shoh/.cproject
@@ -50,7 +50,9 @@
+
+
@@ -82,6 +84,7 @@
+
@@ -101,6 +104,7 @@
+
@@ -199,6 +203,7 @@
+
@@ -228,6 +233,7 @@
+
@@ -248,6 +254,7 @@
+
diff --git a/source/shoh/src/main.cpp b/source/shoh/src/main.cpp
index d374f52..740e2b4 100644
--- a/source/shoh/src/main.cpp
+++ b/source/shoh/src/main.cpp
@@ -3,13 +3,13 @@
#include "FreeRTOS.h"
#include "task.h"
#include
+#include "retarget_uart.h"
+
#include "ThreadCommon.h"
#include "Master.h"
#include "Rotary.h"
-#include "retarget_uart.h"
-#include "LiquidCrystal.h"
-
-void lcd_starting();
+#include "Manager.h"
+#include "UserInterface.h"
int main(void)
{
@@ -19,8 +19,6 @@ int main(void)
retarget_init();
printf("Hello there!\r\n");
-
- lcd_starting();
ThreadCommon::ThreadManager* manager = new ThreadCommon::ThreadManager;
ThreadCommon::QueueManager* qmanager = new ThreadCommon::QueueManager;
@@ -28,11 +26,24 @@ int main(void)
qmanager->createQueue(100,
sizeof(Event),
ThreadCommon::QueueManager::master_event_all);
+ qmanager->createQueue(20,
+ sizeof(Event),
+ ThreadCommon::QueueManager::manager_event_master);
+ qmanager->createQueue(20,
+ sizeof(UserInterface::InterfaceWithData),
+ ThreadCommon::QueueManager::ui_event_manager);
+
//Creating tasks
- manager->createTask(master_thread, "master",
+ manager->createTask(thread_master, "master",
configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
static_cast(qmanager));
- manager->createTask(rotary_thread, "rotary",
+ manager->createTask(thread_manager, "manager",
+ configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
+ static_cast(qmanager));
+ manager->createTask(thread_rotary, "rotary",
+ configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
+ static_cast(qmanager));
+ manager->createTask(thread_user_interface, "user_interface",
configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
static_cast(qmanager));
@@ -41,44 +52,3 @@ int main(void)
return 1;
}
-
-/**
- * @brief While we don't have UI, this should do for LCD.
- *
- */
-void lcd_starting() {
- // LCD pins init.
- //Well, this lpc is a bit different with those. Table 83 from UM10732-11u68.pdf
- DigitalIoPin *rs = new DigitalIoPin(1, 9, false);
- Chip_IOCON_PinMuxSet (LPC_IOCON, 1, 9, (IOCON_FUNC0 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
-
- DigitalIoPin *en = new DigitalIoPin(0, 14, false);
- Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 14, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
-
- DigitalIoPin *d4 = new DigitalIoPin(0, 13, false);
- Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 13, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
-
- DigitalIoPin *d5 = new DigitalIoPin(0, 12, false);
- Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 12, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
-
- DigitalIoPin *d6 = new DigitalIoPin(0, 23, false);
- Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 23, (IOCON_FUNC0 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
-
- DigitalIoPin *d7 = new DigitalIoPin(0, 11, false);
- Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 11, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
-
- rs->write(false);
- en->write(false);
- d4->write(false);
- d5->write(false);
- d6->write(false);
- d7->write(false);
- // LCD init.
- LiquidCrystal *lcd = new LiquidCrystal(rs, en, d4, d5, d6, d7);
- // LCD configure display geometry.
- lcd->begin(16, 2);
- lcd->setCursor (0, 0);
- lcd->print("Hello there");
- lcd->setCursor (0, 1);
- lcd->print("Starting...");
-}
diff --git a/source/shoh/src/peripherals/DigitalIoPin.cpp b/source/shoh/src/peripherals/DigitalIoPin.cpp
index 51d4021..1028d3c 100644
--- a/source/shoh/src/peripherals/DigitalIoPin.cpp
+++ b/source/shoh/src/peripherals/DigitalIoPin.cpp
@@ -18,6 +18,12 @@ DigitalIoPin::DigitalIoPin (int port, int pin, bool input, bool pullup,
_io._invert = invert;
_io.IOCON_mode = IOCON_MODE_INACT;
_io.IOCON_inv = IOCON_FUNC0;
+ //Table 83 from UM10732-11u68.pdf
+ if(port == 0 && ((pin >= 10 && pin <= 15) || pin == 0))
+ _io.IOFunction = IOCON_FUNC1;
+ else
+ _io.IOFunction = IOCON_FUNC0;
+
if (isr){
_io.isr_i = isr_index;
setIsr();
@@ -48,7 +54,7 @@ DigitalIoPin::setIoPin ()
}
}
Chip_IOCON_PinMuxSet (LPC_IOCON, _io._port, _io._pin,
- (_io.IOCON_mode | _io.DigitalEn | _io.IOCON_inv));
+ (_io.IOFunction | _io.IOCON_mode | _io.DigitalEn | _io.IOCON_inv));
/** False direction equals input */
Chip_GPIO_SetPinDIR (LPC_GPIO, _io._port, _io._pin, direction);
}
@@ -75,9 +81,9 @@ DigitalIoPin::setIsr ()
Chip_Clock_SetIOCONFiltClockDiv(0, 64);
Chip_IOCON_PinMuxSet (LPC_IOCON, _io._port, _io._pin,
- (_io.IOCON_mode | _io.DigitalEn
- | _io.IOCON_inv | IOCON_CLKDIV(0)
- | IOCON_S_MODE(3)));
+ (_io.IOFunction | _io.IOCON_mode
+ | _io.DigitalEn | _io.IOCON_inv
+ | IOCON_CLKDIV(0) | IOCON_S_MODE(3)));
/** False direction equals input */
Chip_GPIO_SetPinDIR (LPC_GPIO, _io._port, _io._pin, direction);
diff --git a/source/shoh/src/peripherals/DigitalIoPin.h b/source/shoh/src/peripherals/DigitalIoPin.h
index 19c6c7b..6241aa9 100644
--- a/source/shoh/src/peripherals/DigitalIoPin.h
+++ b/source/shoh/src/peripherals/DigitalIoPin.h
@@ -23,6 +23,7 @@ typedef struct DigitalIOConfigStruct
uint32_t IOCON_mode;
uint32_t IOCON_inv;
uint32_t DigitalEn;
+ uint32_t IOFunction;
IRQn_Type isr_i;
} DigitalIOConfigStruct;
diff --git a/source/shoh/src/peripherals/LiquidCrystal.cpp b/source/shoh/src/peripherals/LiquidCrystal.cpp
index 2b9b636..ac49f8d 100644
--- a/source/shoh/src/peripherals/LiquidCrystal.cpp
+++ b/source/shoh/src/peripherals/LiquidCrystal.cpp
@@ -104,6 +104,8 @@ LiquidCrystal::LiquidCrystal(DigitalIoPin *rs, DigitalIoPin *enable,
begin(16, 2); // default to 16x2 display
}
+LiquidCrystal::~LiquidCrystal() {}
+
void LiquidCrystal::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
if (lines > 1) {
_displayfunction |= LCD_2LINE;
@@ -193,15 +195,17 @@ void LiquidCrystal::home()
void LiquidCrystal::print(std::string const &s)
{
- print(s.c_str());
+ print(s.c_str());
}
void LiquidCrystal::print(const char *s)
{
- while(*s) {
- write(*s);
- ++s;
- }
+ for (uint8_t i = 0; *s != '\0' && i <= 1; i++) {
+ for (size_t q = 0; *s != '\0' && q < 16; q++, s++) {
+ this->setCursor(q, i);
+ this->write(*s);
+ }
+ }
}
void LiquidCrystal::setCursor(uint8_t col, uint8_t row)
diff --git a/source/shoh/src/peripherals/LiquidCrystal.h b/source/shoh/src/peripherals/LiquidCrystal.h
index 6954c3a..a33fcd9 100644
--- a/source/shoh/src/peripherals/LiquidCrystal.h
+++ b/source/shoh/src/peripherals/LiquidCrystal.h
@@ -50,6 +50,8 @@ public:
LiquidCrystal(DigitalIoPin *rs, DigitalIoPin *enable,
DigitalIoPin *d0, DigitalIoPin *d1, DigitalIoPin *d2, DigitalIoPin *d3);
+ virtual ~LiquidCrystal();
+
void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
void clear();
diff --git a/source/shoh/src/threads/common/Event.h b/source/shoh/src/threads/common/Event.h
index 5577b00..34a242a 100644
--- a/source/shoh/src/threads/common/Event.h
+++ b/source/shoh/src/threads/common/Event.h
@@ -23,9 +23,16 @@ public:
Rotary,
InternalTemp,
ExternalTemp,
- SetPoint
+ SetPoint,
+ NotifyUI
};
+ typedef struct _EventPair
+ {
+ EventRawData rd;
+ EventType et;
+ } EventPair;
+
Event(Event::EventType type, EventRawData data)
{
events.insert({type, data});
diff --git a/source/shoh/src/threads/manager/Counter.h b/source/shoh/src/threads/manager/Counter.h
new file mode 100644
index 0000000..8efb2fc
--- /dev/null
+++ b/source/shoh/src/threads/manager/Counter.h
@@ -0,0 +1,102 @@
+/*
+ * Counter.h
+ *
+ * Created on: Sep 1, 2022
+ * Author: tylen
+ */
+
+#ifndef COUNTER_H_
+#define COUNTER_H_
+
+#include "chip.h"
+
+template class Counter
+{
+
+public:
+ Counter (CounterDataType lower_boundary, CounterDataType upper_boundary,
+ CounterDataType step);
+ void inc ();
+ void dec ();
+ CounterDataType getCurrent ();
+ void setCurrent (CounterDataType num);
+ ~Counter () = default;
+
+private:
+ CounterDataType init;
+ CounterDataType up_lim;
+ CounterDataType down_lim;
+ CounterDataType _step;
+};
+
+
+template
+void
+Counter::inc ()
+{
+ if ((init + _step) <= up_lim)
+ {
+ init += _step;
+ }
+}
+
+template
+void
+Counter::dec ()
+{
+ if (init - _step >= down_lim)
+ {
+ init -= _step;
+ }
+}
+
+template
+CounterDataType
+Counter::getCurrent ()
+{
+ return this->init;
+}
+
+template
+Counter::Counter (CounterDataType lower_boundary,
+ CounterDataType upper_boundary,
+ CounterDataType step)
+{
+ up_lim = upper_boundary;
+ down_lim = lower_boundary;
+ _step = step;
+ if (down_lim > up_lim)
+ {
+ init = up_lim;
+ }
+ else if (down_lim < 0)
+ {
+ init = 0;
+ }
+ else
+ {
+ init = down_lim;
+ }
+}
+
+template
+void
+Counter::setCurrent (CounterDataType num)
+{
+ if (num > up_lim)
+ {
+ init = up_lim;
+ }
+ else if (num < down_lim)
+ {
+ init = down_lim;
+ }
+ else
+ {
+ init = num;
+ }
+}
+
+
+
+#endif /* COUNTER_H_ */
\ No newline at end of file
diff --git a/source/shoh/src/threads/manager/Manager.cpp b/source/shoh/src/threads/manager/Manager.cpp
new file mode 100644
index 0000000..2f4e9ca
--- /dev/null
+++ b/source/shoh/src/threads/manager/Manager.cpp
@@ -0,0 +1,54 @@
+/*
+ * Manager.cpp
+ *
+ * Created on: 29 Apr 2023
+ * Author: dave
+ */
+
+#include "Manager.h"
+#include "ThreadCommon.h"
+
+Manager::Manager(ThreadCommon::QueueManager* qm)
+: _qm(qm), _menu{qm}
+{
+}
+
+Manager::~Manager()
+{
+ // TODO Auto-generated destructor stub
+}
+
+Event::EventPair Manager::parseEvent(Event* e)
+{
+ EventRawData raw_data;
+ for(Event::EventType i :
+ {Event::Rotary, Event::InternalTemp,
+ Event::ExternalTemp})
+ {
+ raw_data = e->getDataOf(i);
+ if(raw_data != ERROR_RETURN)
+ {
+ Event::EventPair p = {raw_data, i};
+ return p;
+ }
+ }
+ return {ERROR_RETURN, Event::Null};
+}
+
+void Manager::taskFunction()
+{
+ Event data(Event::Null, 0);
+ Event::EventPair event_pair = {0, Event::EventType::Null};
+ for(;;)
+ {
+ _qm->receive(ThreadCommon::QueueManager::manager_event_master, &data, portMAX_DELAY);
+ event_pair= this->parseEvent(&data);
+ _menu.HandleEventPair(&event_pair);
+ }
+}
+
+void thread_manager(void* pvParams)
+{
+ Manager m(static_cast(pvParams));
+ m.taskFunction();
+}
diff --git a/source/shoh/src/threads/manager/Manager.h b/source/shoh/src/threads/manager/Manager.h
new file mode 100644
index 0000000..7a8e844
--- /dev/null
+++ b/source/shoh/src/threads/manager/Manager.h
@@ -0,0 +1,32 @@
+/*
+ * Manager.h
+ *
+ * Created on: 29 Apr 2023
+ * Author: dave
+ */
+
+#ifndef THREADS_MANAGER_MANAGER_H_
+#define THREADS_MANAGER_MANAGER_H_
+
+#include "ThreadCommon.h"
+#include "Event.h"
+#include "Counter.h"
+#include "Menu.h"
+
+
+class Manager {
+public:
+ Manager(ThreadCommon::QueueManager* qm);
+ virtual ~Manager();
+ void taskFunction();
+private:
+ Event::EventPair parseEvent(Event* e);
+ ThreadCommon::QueueManager* _qm;
+ Menu _menu;
+
+ EventRawData rotary_action;
+};
+
+void thread_manager(void* pvParams);
+
+#endif /* THREADS_MANAGER_MANAGER_H_ */
diff --git a/source/shoh/src/threads/manager/Menu.cpp b/source/shoh/src/threads/manager/Menu.cpp
new file mode 100644
index 0000000..b7765f1
--- /dev/null
+++ b/source/shoh/src/threads/manager/Menu.cpp
@@ -0,0 +1,182 @@
+/*
+ * Menu.cpp
+ *
+ * Created on: 29 Apr 2023
+ * Author: dave
+ */
+
+#include "Menu.h"
+#include
+#include "UserInterface.h"
+
+Menu::Menu(ThreadCommon::QueueManager* qm): _qm(qm),
+current(&Menu::sInitView), ext_temp(-99, 99, 1), set_point(-99, 99, 1),
+main_text ("CURRENT %3d DESIRED %3d "),
+set_point_text("CURRENT %3d DESIRED[%3d] ")
+{
+ this->SetState(&Menu::sInitView);
+ ext_temp.setCurrent(0);
+ set_point.setCurrent(0);
+}
+
+Menu::~Menu()
+{
+}
+
+void Menu::HandleEventPair (Event::EventPair *ep)
+{
+ switch(ep->et/*EventType*/)
+ {
+ case Event::Rotary:
+ // can be wrapped in a function, but this was found to be more clear solution,
+ // since we are still handling eventpair here, although nested
+ switch(static_cast(ep->rd)/*RawData*/)
+ {
+ case ThreadCommon::RotaryAction::Right:
+ this->HandleObj(MenuObjEvent (MenuObjEvent::eRollClockWise));
+ break;
+ case ThreadCommon::RotaryAction::Left:
+ this->HandleObj(MenuObjEvent (MenuObjEvent::eRollCClockWise));
+ break;
+ case ThreadCommon::RotaryAction::Press:
+ this->HandleObj(MenuObjEvent (MenuObjEvent::eClick));
+ break;
+ case ThreadCommon::RotaryAction::Idle:
+ /*I guess this is left for debugging purposes ;D*/
+ this->HandleObj(MenuObjEvent (MenuObjEvent::eRefresh));
+ break;
+ default:
+ assert(0);
+ /* Pretty damn bad code if reached here */
+ break;
+ }
+ break;
+ case Event::ExternalTemp:
+ //Change ExternalTemp value. -99 <= ext_temp <= 99
+ this->ext_temp.setCurrent(ep->rd);
+ //Refresh the menu screen.
+ this->HandleObj(MenuObjEvent (MenuObjEvent::eRefresh));
+ break;
+ default:
+ assert(0);
+ /* Manager has big issues... */
+ break;
+ }
+ return;
+}
+
+/* States */
+void Menu::sInitView(const MenuObjEvent &e)
+{
+ switch (e.type)
+ {
+ case MenuObjEvent::eFocus:
+ this->NotifyAndRefreshUI("Loading...");
+ break;
+ case MenuObjEvent::eUnFocus:
+ printf("NOTE: leave sInitView\n");
+ this->NotifyAndRefreshUI("");
+ break;
+ case MenuObjEvent::eRollClockWise:
+ break;
+ case MenuObjEvent::eRollCClockWise:
+ break;
+ case MenuObjEvent::eClick:
+ this->SetState(&Menu::sMainView);
+ break;
+ case MenuObjEvent::eRefresh:
+ printf("NOTE: sInitView handled eRefresh.\n");
+ this->SetState(&Menu::sMainView);
+ break;
+ default:
+ break;
+ }
+}
+
+void Menu::sMainView(const MenuObjEvent &e)
+{
+ static char screen_text[64];
+ switch (e.type)
+ {
+ case MenuObjEvent::eFocus:
+ sprintf(screen_text, main_text, this->ext_temp.getCurrent(),
+ this->set_point.getCurrent());
+ this->NotifyAndRefreshUI(screen_text);
+ break;
+ case MenuObjEvent::eUnFocus:
+ this->NotifyAndRefreshUI("");
+ break;
+ case MenuObjEvent::eRollClockWise:
+ break;
+ case MenuObjEvent::eRollCClockWise:
+ break;
+ case MenuObjEvent::eClick:
+ this->SetState(&Menu::sSetPointMod);
+ break;
+ case MenuObjEvent::eRefresh:
+ sprintf(screen_text, main_text, this->ext_temp.getCurrent(),
+ this->set_point.getCurrent());
+ this->NotifyAndRefreshUI(screen_text);
+ break;
+ default:
+ break;
+ }
+}
+
+void Menu::sSetPointMod(const MenuObjEvent &e)
+{
+ static char screen_text[64];
+ switch (e.type)
+ {
+ case MenuObjEvent::eFocus:
+ sprintf(screen_text, set_point_text, this->ext_temp.getCurrent(),
+ this->set_point.getCurrent());
+ this->NotifyAndRefreshUI(screen_text);
+ break;
+ case MenuObjEvent::eUnFocus:
+ this->NotifyAndRefreshUI("");
+ break;
+ case MenuObjEvent::eRollClockWise:
+ set_point.inc();
+ sprintf(screen_text, set_point_text, this->ext_temp.getCurrent(),
+ this->set_point.getCurrent());
+ this->NotifyAndRefreshUI(screen_text);
+ break;
+ case MenuObjEvent::eRollCClockWise:
+ set_point.dec();
+ sprintf(screen_text, set_point_text, this->ext_temp.getCurrent(),
+ this->set_point.getCurrent());
+ this->NotifyAndRefreshUI(screen_text);
+ break;
+ case MenuObjEvent::eClick:
+ this->SetState(&Menu::sMainView);
+ break;
+ case MenuObjEvent::eRefresh:
+ sprintf(screen_text, set_point_text, this->ext_temp.getCurrent(),
+ this->set_point.getCurrent());
+ this->NotifyAndRefreshUI(screen_text);
+ break;
+ default:
+ break;
+ }
+}
+
+void Menu::SetState (p_state new_state)
+{
+ (this->*current) (MenuObjEvent (MenuObjEvent::eUnFocus));
+ current = new_state;
+ (this->*current) (MenuObjEvent (MenuObjEvent::eFocus));
+}
+
+void Menu::HandleObj (const MenuObjEvent &event)
+{
+ (this->*current) (event);
+}
+
+void Menu::NotifyAndRefreshUI (const char *str)
+{
+ //Send string on a queue to UI task.
+ UserInterface::InterfaceWithData ud = {UserInterface::LCD1, str};
+ this->_qm->send(
+ ThreadCommon::QueueManager::ui_event_manager, &ud, portMAX_DELAY);
+}
diff --git a/source/shoh/src/threads/manager/Menu.h b/source/shoh/src/threads/manager/Menu.h
new file mode 100644
index 0000000..676ceb0
--- /dev/null
+++ b/source/shoh/src/threads/manager/Menu.h
@@ -0,0 +1,44 @@
+/*
+ * Menu.h
+ *
+ * Created on: 29 Apr 2023
+ * Author: dave
+ */
+
+#ifndef THREADS_MANAGER_MENU_H_
+#define THREADS_MANAGER_MENU_H_
+
+#include "Counter.h"
+#include "MenuObjEvent.h"
+#include "ThreadCommon.h"
+#include "Event.h"
+
+class Menu;
+typedef void (Menu::*p_state) (const MenuObjEvent &);
+
+class Menu
+{
+public:
+ Menu (ThreadCommon::QueueManager* qm);
+ virtual ~Menu ();
+ void HandleEventPair (Event::EventPair *ep);
+
+private:
+ /* Variables and objects */
+ ThreadCommon::QueueManager* _qm;
+ p_state current;
+ Counter ext_temp;
+ Counter set_point;
+ const char main_text[64];
+ const char set_point_text[64];
+ /* States */
+ void sInitView(const MenuObjEvent &e);
+ void sMainView(const MenuObjEvent &e);
+ void sSetPointMod(const MenuObjEvent &e);
+ /* Methods */
+ void SetState (p_state new_state);
+ void HandleObj (const MenuObjEvent &event);
+ void NotifyAndRefreshUI (const char *str);
+};
+
+#endif /* THREADS_MANAGER_MENU_H_ */
diff --git a/source/shoh/src/threads/manager/MenuObjEvent.h b/source/shoh/src/threads/manager/MenuObjEvent.h
new file mode 100644
index 0000000..2123817
--- /dev/null
+++ b/source/shoh/src/threads/manager/MenuObjEvent.h
@@ -0,0 +1,37 @@
+/*
+ * MenuObjEvent.h
+ *
+ * Created on: Dec 11, 2022
+ * Author: tylen
+ */
+
+#ifndef MENU_MENUOBJEVENT_H_
+#define MENU_MENUOBJEVENT_H_
+
+class MenuObjEvent
+{
+public:
+ virtual ~MenuObjEvent (){};
+
+ enum EventType
+ {
+ /** Start of the event */
+ eFocus,
+ /** End of the event*/
+ eUnFocus,
+ /** Refresh event */
+ eRefresh,
+ /** Button toggle event type */
+ eClick,
+ /** Rotary clockwise */
+ eRollClockWise,
+ /** Rotary counter clockwise */
+ eRollCClockWise,
+ };
+ MenuObjEvent (EventType e = eFocus) : type (e){};
+ EventType type;
+};
+
+
+
+#endif /* MENU_MENUOBJEVENT_H_ */
diff --git a/source/shoh/src/threads/master/Master.cpp b/source/shoh/src/threads/master/Master.cpp
index c7cea1c..aaf4588 100644
--- a/source/shoh/src/threads/master/Master.cpp
+++ b/source/shoh/src/threads/master/Master.cpp
@@ -16,24 +16,29 @@ void Master::taskFunction() {
Event data(Event::Null, 0);
bool LedState = true;
for (;;) {
- _qm->receive(ThreadCommon::QueueManager::master_event_all, &data, portMAX_DELAY);
+ if(!_qm->receive(ThreadCommon::QueueManager::master_event_all, &data, 10000))
+ data.setDataOf(Event::Rotary, ThreadCommon::RotaryAction::Idle);
switch(data.getDataOf(Event::Rotary))
{
case ThreadCommon::RotaryAction::Right:
Board_LED_Set(ThreadCommon::RotaryAction::Right, LedState);
printf("Right\r\n");
+ _qm->send(ThreadCommon::QueueManager::manager_event_master, &data, 0);
break;
case ThreadCommon::RotaryAction::Left:
Board_LED_Set(ThreadCommon::RotaryAction::Left, LedState);
printf("Left\r\n");
+ _qm->send(ThreadCommon::QueueManager::manager_event_master, &data, 0);
break;
case ThreadCommon::RotaryAction::Press:
Board_LED_Set(ThreadCommon::RotaryAction::Press, LedState);
printf("Press\r\n");
+ _qm->send(ThreadCommon::QueueManager::manager_event_master, &data, 0);
break;
case ThreadCommon::RotaryAction::Idle:
- Board_LED_Set(ThreadCommon::RotaryAction::Right, LedState);
+ //Board_LED_Set(ThreadCommon::RotaryAction::Right, LedState);
printf("Idle\r\n");
+ _qm->send(ThreadCommon::QueueManager::manager_event_master, &data, 0);
break;
}
LedState = !LedState;
@@ -41,7 +46,7 @@ void Master::taskFunction() {
}
-void master_thread(void* pvParams) {
+void thread_master(void* pvParams) {
Master m(static_cast(pvParams));
m.taskFunction();
}
diff --git a/source/shoh/src/threads/master/Master.h b/source/shoh/src/threads/master/Master.h
index e5dceae..3a5e790 100644
--- a/source/shoh/src/threads/master/Master.h
+++ b/source/shoh/src/threads/master/Master.h
@@ -26,7 +26,7 @@ private:
ThreadCommon::QueueManager* _qm;
};
-void master_thread(void* pvParams);
+void thread_master(void* pvParams);
#endif /* THREADS_MASTER_MASTER_H_ */
diff --git a/source/shoh/src/threads/rotary/Rotary.cpp b/source/shoh/src/threads/rotary/Rotary.cpp
index da1d8ed..eb9f19d 100644
--- a/source/shoh/src/threads/rotary/Rotary.cpp
+++ b/source/shoh/src/threads/rotary/Rotary.cpp
@@ -64,7 +64,7 @@ void Rotary::taskFunction()
}
}
-void rotary_thread(void* pvParams)
+void thread_rotary(void* pvParams)
{
// Special case for ISR
QueueHandle_t rotary_isr_q = xQueueCreate(15, sizeof(char));
diff --git a/source/shoh/src/threads/rotary/Rotary.h b/source/shoh/src/threads/rotary/Rotary.h
index 56fdf17..dafe910 100644
--- a/source/shoh/src/threads/rotary/Rotary.h
+++ b/source/shoh/src/threads/rotary/Rotary.h
@@ -25,6 +25,6 @@ private:
{ 1, 8, true, false, false, true, PIN_INT2_IRQn} };
};
-void rotary_thread(void* pvParams);
+void thread_rotary(void* pvParams);
#endif /* THREADS_ROTARY_ROTARY_H_ */
diff --git a/source/shoh/src/threads/user_interface/UserInterface.cpp b/source/shoh/src/threads/user_interface/UserInterface.cpp
new file mode 100644
index 0000000..bafd5d4
--- /dev/null
+++ b/source/shoh/src/threads/user_interface/UserInterface.cpp
@@ -0,0 +1,97 @@
+/*
+ * UserInterface.cpp
+ *
+ * Created on: 8 May 2023
+ */
+
+#include "UserInterface.h"
+#include
+
+UserInterface::UserInterface(ThreadCommon::QueueManager* qm) :
+_qm(qm), lcd1(nullptr)
+{
+ this->initLCD1();
+}
+
+UserInterface::~UserInterface()
+{
+ delete this->lcd1;
+ delete this->lcd1_rs;
+ delete this->lcd1_en;
+ delete this->lcd1_d4;
+ delete this->lcd1_d5;
+ delete this->lcd1_d6;
+ delete this->lcd1_d7;
+}
+
+void UserInterface::taskFunction()
+{
+ InterfaceWithData ui_with_data;
+
+ for (;;)
+ {
+ this->_qm->receive(ThreadCommon::QueueManager::ui_event_manager, &ui_with_data, portMAX_DELAY);
+ this->handleEvent(&ui_with_data);
+ }
+
+}
+
+void UserInterface::handleEvent(InterfaceWithData* ui_data)
+{
+ switch (ui_data->display)
+ {
+ case LCD1:
+ this->handleLCD(this->lcd1, ui_data->data.str);
+ break;
+ default:
+ //Should never happen.
+ printf("WARNING: [UserInterface::handleEvent] executed default case.\n");
+ break;
+ }
+}
+
+/******************************/
+/*Interface specific functions*/
+/******************************/
+
+void UserInterface::handleLCD(LiquidCrystal *lcd, const char *str)
+{
+ //Interpret empty string as clear.
+ if(!strlen(str))
+ lcd->clear();
+ //Print the text otherwise.
+ else
+ {
+ lcd->setCursor(0, 0);
+ lcd->print(str);
+ }
+}
+
+void UserInterface::initLCD1()
+{
+ this->lcd1_rs = new DigitalIoPin(1, 9, false);
+ this->lcd1_en = new DigitalIoPin(0, 14, false);
+ this->lcd1_d4 = new DigitalIoPin(0, 13, false);
+ this->lcd1_d5 = new DigitalIoPin(0, 12, false);
+ this->lcd1_d6 = new DigitalIoPin(0, 23, false);
+ this->lcd1_d7 = new DigitalIoPin(0, 11, false);
+
+ this->lcd1_rs->write(false);
+ this->lcd1_en->write(false);
+ this->lcd1_d4->write(false);
+ this->lcd1_d5->write(false);
+ this->lcd1_d6->write(false);
+ this->lcd1_d7->write(false);
+ // LCD init.
+ this->lcd1 = new LiquidCrystal(this->lcd1_rs, this->lcd1_en, this->lcd1_d4,
+ this->lcd1_d5, this->lcd1_d6, this->lcd1_d7);
+ // LCD configure display geometry.
+ this->lcd1->begin(16, 2);
+ this->lcd1->setCursor (0, 0);
+}
+
+void thread_user_interface(void* pvParams)
+{
+ UserInterface ui(static_cast(pvParams));
+ ui.taskFunction();
+}
diff --git a/source/shoh/src/threads/user_interface/UserInterface.h b/source/shoh/src/threads/user_interface/UserInterface.h
new file mode 100644
index 0000000..5974c5b
--- /dev/null
+++ b/source/shoh/src/threads/user_interface/UserInterface.h
@@ -0,0 +1,52 @@
+/*
+ * UserInterface.h
+ *
+ * Created on: 8 May 2023
+ */
+
+#ifndef THREADS_USER_INTERFACE_USERINTERFACE_H_
+#define THREADS_USER_INTERFACE_USERINTERFACE_H_
+
+#include "ThreadCommon.h"
+#include "Event.h"
+#include "LiquidCrystal.h"
+
+class UserInterface {
+public:
+ UserInterface(ThreadCommon::QueueManager* qm);
+ virtual ~UserInterface();
+
+ enum Interface
+ {
+ LCD1
+ };
+
+ union InterfaceData
+ {
+ const char* str;
+ };
+
+ struct InterfaceWithData
+ {
+ Interface display;
+ InterfaceData data;
+ };
+
+ void taskFunction();
+private:
+ /* Variables */
+ ThreadCommon::QueueManager* _qm;
+ LiquidCrystal* lcd1;
+ DigitalIoPin *lcd1_rs, *lcd1_en, *lcd1_d4, *lcd1_d5, *lcd1_d6, *lcd1_d7;
+
+ /* Methods */
+ void handleEvent(InterfaceWithData* ui_data);
+
+ //UIs
+ void handleLCD(LiquidCrystal *lcd, const char *str);
+ void initLCD1();
+};
+
+void thread_user_interface(void* pvParams);
+
+#endif /* THREADS_USER_INTERFACE_USERINTERFACE_H_ */