UI: [#35] Added UserInterface task.
This commit is contained in:
parent
d3f5cdebbc
commit
20fe16b46e
@ -50,6 +50,7 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/master}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/master}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/user_interface}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/threads/rotary}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/threads/rotary}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/threads/manager}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/${ProjName}/src/threads/manager}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
||||||
@ -83,6 +84,7 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/master}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/master}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/user_interface}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
||||||
</option>
|
</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"/>
|
<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"/>
|
||||||
@ -102,6 +104,7 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/master}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/master}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/user_interface}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
||||||
</option>
|
</option>
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1836378919" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1836378919" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||||
@ -200,6 +203,7 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/FreeRTOSCPP}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/FreeRTOSCPP}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/user_interface}""/>
|
||||||
</option>
|
</option>
|
||||||
<inputType id="com.crt.advproject.compiler.cpp.input.903614193" superClass="com.crt.advproject.compiler.cpp.input"/>
|
<inputType id="com.crt.advproject.compiler.cpp.input.903614193" superClass="com.crt.advproject.compiler.cpp.input"/>
|
||||||
</tool>
|
</tool>
|
||||||
@ -229,6 +233,7 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/FreeRTOSCPP}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/FreeRTOSCPP}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/user_interface}""/>
|
||||||
</option>
|
</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"/>
|
<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"/>
|
<inputType id="com.crt.advproject.compiler.input.246185412" superClass="com.crt.advproject.compiler.input"/>
|
||||||
@ -249,6 +254,7 @@
|
|||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/peripherals}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/FreeRTOSCPP}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/FreeRTOSCPP}""/>
|
||||||
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/common}""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${workspace_loc:/shoh/src/threads/user_interface}""/>
|
||||||
</option>
|
</option>
|
||||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1117166373" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
<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"/>
|
<inputType id="com.crt.advproject.assembler.input.2071009798" name="Additional Assembly Source Files" superClass="com.crt.advproject.assembler.input"/>
|
||||||
|
|||||||
@ -3,14 +3,13 @@
|
|||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include <cr_section_macros.h>
|
#include <cr_section_macros.h>
|
||||||
|
#include "retarget_uart.h"
|
||||||
|
|
||||||
#include "ThreadCommon.h"
|
#include "ThreadCommon.h"
|
||||||
#include "Master.h"
|
#include "Master.h"
|
||||||
#include "Rotary.h"
|
#include "Rotary.h"
|
||||||
#include "retarget_uart.h"
|
|
||||||
#include "LiquidCrystal.h"
|
|
||||||
#include "Manager.h"
|
#include "Manager.h"
|
||||||
|
#include "UserInterface.h"
|
||||||
void lcd_starting();
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
@ -20,8 +19,6 @@ int main(void)
|
|||||||
retarget_init();
|
retarget_init();
|
||||||
|
|
||||||
printf("Hello there!\r\n");
|
printf("Hello there!\r\n");
|
||||||
|
|
||||||
lcd_starting();
|
|
||||||
|
|
||||||
ThreadCommon::ThreadManager* manager = new ThreadCommon::ThreadManager;
|
ThreadCommon::ThreadManager* manager = new ThreadCommon::ThreadManager;
|
||||||
ThreadCommon::QueueManager* qmanager = new ThreadCommon::QueueManager;
|
ThreadCommon::QueueManager* qmanager = new ThreadCommon::QueueManager;
|
||||||
@ -32,6 +29,9 @@ int main(void)
|
|||||||
qmanager->createQueue(20,
|
qmanager->createQueue(20,
|
||||||
sizeof(Event),
|
sizeof(Event),
|
||||||
ThreadCommon::QueueManager::manager_event_master);
|
ThreadCommon::QueueManager::manager_event_master);
|
||||||
|
qmanager->createQueue(20,
|
||||||
|
sizeof(Event),
|
||||||
|
ThreadCommon::QueueManager::ui_event_manager);
|
||||||
|
|
||||||
//Creating tasks
|
//Creating tasks
|
||||||
manager->createTask(thread_master, "master",
|
manager->createTask(thread_master, "master",
|
||||||
@ -43,50 +43,12 @@ int main(void)
|
|||||||
manager->createTask(thread_rotary, "rotary",
|
manager->createTask(thread_rotary, "rotary",
|
||||||
configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
|
configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
|
||||||
static_cast<void*>(qmanager));
|
static_cast<void*>(qmanager));
|
||||||
|
manager->createTask(thread_user_interface, "user_interface",
|
||||||
|
configMINIMAL_STACK_SIZE * 10,tskIDLE_PRIORITY + 1UL,
|
||||||
|
static_cast<void*>(qmanager));
|
||||||
|
|
||||||
// Start the real time kernel with preemption.
|
// Start the real time kernel with preemption.
|
||||||
vTaskStartScheduler ();
|
vTaskStartScheduler ();
|
||||||
|
|
||||||
return 1;
|
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...");
|
|
||||||
}
|
|
||||||
|
|||||||
@ -23,7 +23,8 @@ public:
|
|||||||
Rotary,
|
Rotary,
|
||||||
InternalTemp,
|
InternalTemp,
|
||||||
ExternalTemp,
|
ExternalTemp,
|
||||||
SetPoint
|
SetPoint,
|
||||||
|
NotifyUI
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _EventPair
|
typedef struct _EventPair
|
||||||
|
|||||||
114
source/shoh/src/threads/user_interface/UserInterface.cpp
Normal file
114
source/shoh/src/threads/user_interface/UserInterface.cpp
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* UserInterface.cpp
|
||||||
|
*
|
||||||
|
* Created on: 8 May 2023
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "UserInterface.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
UserInterface::UserInterface(ThreadCommon::QueueManager* qm) :
|
||||||
|
_qm(qm), lcd1(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
Event data(Event::Null, 0);
|
||||||
|
//LCD1 init.
|
||||||
|
this->initLCD(this->lcd1, this->lcd1_rs, this->lcd1_en, this->lcd1_d4,
|
||||||
|
this->lcd1_d5, this->lcd1_d6, this->lcd1_d7);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
this->_qm->receive(ThreadCommon::QueueManager::ui_event_manager, &data, portMAX_DELAY);
|
||||||
|
//Don't mind the type, we care only about the raw_data.
|
||||||
|
EventRawData ed = data.getDataOf(Event::NotifyUI);
|
||||||
|
if(ed != ERROR_RETURN)
|
||||||
|
this->handleEvent(reinterpret_cast<UserInterface::InterfaceWithData*>(&ed));
|
||||||
|
else
|
||||||
|
printf("ERROR: [UserInterface::taskFunction] Event gave ERROR_RETURN 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.");
|
||||||
|
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::initLCD(LiquidCrystal *lcd,
|
||||||
|
DigitalIoPin *rs, DigitalIoPin *en,
|
||||||
|
DigitalIoPin *d4, DigitalIoPin *d5,
|
||||||
|
DigitalIoPin *d6, DigitalIoPin *d7)
|
||||||
|
{
|
||||||
|
rs = new DigitalIoPin(1, 9, false);
|
||||||
|
en = new DigitalIoPin(0, 14, false);
|
||||||
|
d4 = new DigitalIoPin(0, 13, false);
|
||||||
|
d5 = new DigitalIoPin(0, 12, false);
|
||||||
|
d6 = new DigitalIoPin(0, 23, false);
|
||||||
|
d7 = new DigitalIoPin(0, 11, false);
|
||||||
|
|
||||||
|
//Fix Pin Muxing.
|
||||||
|
Chip_IOCON_PinMuxSet (LPC_IOCON, 1, 9, (IOCON_FUNC0 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
|
Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 14, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
|
Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 13, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
|
Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 12, (IOCON_FUNC1 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
|
Chip_IOCON_PinMuxSet (LPC_IOCON, 0, 23, (IOCON_FUNC0 | IOCON_MODE_INACT | IOCON_DIGMODE_EN));
|
||||||
|
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.
|
||||||
|
lcd = new LiquidCrystal(rs, en, d4, d5, d6, d7);
|
||||||
|
// LCD configure display geometry.
|
||||||
|
lcd->begin(16, 2);
|
||||||
|
lcd->setCursor (0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_user_interface(void* pvParams)
|
||||||
|
{
|
||||||
|
UserInterface ui(static_cast<ThreadCommon::QueueManager*>(pvParams));
|
||||||
|
ui.taskFunction();
|
||||||
|
}
|
||||||
55
source/shoh/src/threads/user_interface/UserInterface.h
Normal file
55
source/shoh/src/threads/user_interface/UserInterface.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
char str[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
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 initLCD(LiquidCrystal *lcd,
|
||||||
|
DigitalIoPin *rs, DigitalIoPin *en,
|
||||||
|
DigitalIoPin *d4, DigitalIoPin *d5,
|
||||||
|
DigitalIoPin *d6, DigitalIoPin *d7);
|
||||||
|
};
|
||||||
|
|
||||||
|
void thread_user_interface(void* pvParams);
|
||||||
|
|
||||||
|
#endif /* THREADS_USER_INTERFACE_USERINTERFACE_H_ */
|
||||||
Loading…
x
Reference in New Issue
Block a user