Merge pull request #36 from vas-dav/thread-manager

Thread manager
This commit is contained in:
RedHawk 2023-05-11 00:41:49 +03:00 committed by GitHub
commit 39a297c8a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 667 additions and 65 deletions

View File

@ -50,7 +50,9 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/master}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/user_interface}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src/threads/rotary}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/src/threads/manager}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/peripherals}&quot;"/>
</option>
<option id="com.crt.advproject.cpp.misc.dialect.4036734" name="Language standard" superClass="com.crt.advproject.cpp.misc.dialect" useByScannerDiscovery="true" value="com.crt.advproject.misc.dialect.cpp17" valueType="enumerated"/>
@ -82,6 +84,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/master}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/user_interface}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/peripherals}&quot;"/>
</option>
<option id="com.crt.advproject.c.misc.dialect.82852045" name="Language standard" superClass="com.crt.advproject.c.misc.dialect" useByScannerDiscovery="true" value="com.crt.advproject.misc.dialect.c17" valueType="enumerated"/>
@ -101,6 +104,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/master}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/user_interface}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/peripherals}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1836378919" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
@ -199,6 +203,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/peripherals}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/FreeRTOSCPP}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/user_interface}&quot;"/>
</option>
<inputType id="com.crt.advproject.compiler.cpp.input.903614193" superClass="com.crt.advproject.compiler.cpp.input"/>
</tool>
@ -228,6 +233,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/peripherals}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/FreeRTOSCPP}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/user_interface}&quot;"/>
</option>
<option id="com.crt.advproject.c.misc.dialect.1008527937" name="Language standard" superClass="com.crt.advproject.c.misc.dialect" useByScannerDiscovery="true" value="com.crt.advproject.misc.dialect.c17" valueType="enumerated"/>
<inputType id="com.crt.advproject.compiler.input.246185412" superClass="com.crt.advproject.compiler.input"/>
@ -248,6 +254,7 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/peripherals}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/FreeRTOSCPP}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/common}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/shoh/src/threads/user_interface}&quot;"/>
</option>
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1117166373" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
<inputType id="com.crt.advproject.assembler.input.2071009798" name="Additional Assembly Source Files" superClass="com.crt.advproject.assembler.input"/>

View File

@ -3,13 +3,13 @@
#include "FreeRTOS.h"
#include "task.h"
#include <cr_section_macros.h>
#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<void*>(qmanager));
manager->createTask(rotary_thread, "rotary",
manager->createTask(thread_manager, "manager",
configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
static_cast<void*>(qmanager));
manager->createTask(thread_rotary, "rotary",
configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
static_cast<void*>(qmanager));
manager->createTask(thread_user_interface, "user_interface",
configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
static_cast<void*>(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...");
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,102 @@
/*
* Counter.h
*
* Created on: Sep 1, 2022
* Author: tylen
*/
#ifndef COUNTER_H_
#define COUNTER_H_
#include "chip.h"
template <class CounterDataType> 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 <class CounterDataType>
void
Counter<CounterDataType>::inc ()
{
if ((init + _step) <= up_lim)
{
init += _step;
}
}
template <class CounterDataType>
void
Counter<CounterDataType>::dec ()
{
if (init - _step >= down_lim)
{
init -= _step;
}
}
template <class CounterDataType>
CounterDataType
Counter<CounterDataType>::getCurrent ()
{
return this->init;
}
template <class CounterDataType>
Counter<CounterDataType>::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 <class CounterDataType>
void
Counter<CounterDataType>::setCurrent (CounterDataType num)
{
if (num > up_lim)
{
init = up_lim;
}
else if (num < down_lim)
{
init = down_lim;
}
else
{
init = num;
}
}
#endif /* COUNTER_H_ */

View File

@ -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<Event>(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<ThreadCommon::QueueManager*>(pvParams));
m.taskFunction();
}

View File

@ -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_ */

View File

@ -0,0 +1,182 @@
/*
* Menu.cpp
*
* Created on: 29 Apr 2023
* Author: dave
*/
#include "Menu.h"
#include <assert.h>
#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<ThreadCommon::RotaryAction>(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<UserInterface::InterfaceWithData>(
ThreadCommon::QueueManager::ui_event_manager, &ud, portMAX_DELAY);
}

View File

@ -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<EventRawData> ext_temp;
Counter<EventRawData> 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_ */

View File

@ -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_ */

View File

@ -16,24 +16,29 @@ void Master::taskFunction() {
Event data(Event::Null, 0);
bool LedState = true;
for (;;) {
_qm->receive<Event>(ThreadCommon::QueueManager::master_event_all, &data, portMAX_DELAY);
if(!_qm->receive<Event>(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<Event>(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<Event>(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<Event>(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<Event>(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<ThreadCommon::QueueManager*>(pvParams));
m.taskFunction();
}

View File

@ -26,7 +26,7 @@ private:
ThreadCommon::QueueManager* _qm;
};
void master_thread(void* pvParams);
void thread_master(void* pvParams);
#endif /* THREADS_MASTER_MASTER_H_ */

View File

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

View File

@ -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_ */

View File

@ -0,0 +1,97 @@
/*
* UserInterface.cpp
*
* Created on: 8 May 2023
*/
#include "UserInterface.h"
#include <cstring>
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<UserInterface::InterfaceWithData>(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<ThreadCommon::QueueManager*>(pvParams));
ui.taskFunction();
}

View File

@ -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_ */