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 @@ + + @@ -199,6 +203,7 @@ + @@ -228,6 +233,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_ */