kopia lustrzana https://github.com/OpenRTX/OpenRTX
Add shared state logic
rodzic
310f19c6b7
commit
3370e5a3a7
|
@ -1,6 +1,7 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN, *
|
||||
* Frederik Saraci IU2NRO, *
|
||||
* Silvano Seva IU2KWO *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
@ -21,14 +22,17 @@
|
|||
#define STATE_H
|
||||
|
||||
#include <datatypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <rtc.h>
|
||||
|
||||
/**
|
||||
* Part of this structure has been commented because the corresponding
|
||||
* functionality is not yet implemented.
|
||||
* Uncomment once the related feature is ready
|
||||
*/
|
||||
|
||||
typedef struct state_t {
|
||||
curTime_t time;
|
||||
float v_bat;
|
||||
//enum ui_screen;
|
||||
//enum tuner_mode;
|
||||
//enum radio_mode;
|
||||
|
@ -59,27 +63,26 @@ typedef struct state_t {
|
|||
} state_t;
|
||||
|
||||
/**
|
||||
* This function initialises the Radio state, acquiring the information
|
||||
* needed to populate it from device drivers.
|
||||
* This structure is used to mark if the state has been modified
|
||||
* and by which thread.
|
||||
* The threads that are watching for state updates
|
||||
* check the variables of other threads, if they are set,
|
||||
* they know that the state have been modified
|
||||
*/
|
||||
typedef struct modified_t {
|
||||
bool ui_modified;
|
||||
bool rtx_modified;
|
||||
bool self_modified;
|
||||
} modified_t;
|
||||
|
||||
extern state_t state;
|
||||
extern modified_t state_flags;
|
||||
|
||||
|
||||
/**
|
||||
* This function initializes the Radio state, acquiring the information
|
||||
* needed to populate it from device drivers.
|
||||
*/
|
||||
void state_init();
|
||||
|
||||
/**
|
||||
* This function updates the state information by sourcing the
|
||||
* updated values of the various fields of the state_t struct
|
||||
* from corresponding device drivers.
|
||||
*/
|
||||
void state_update();
|
||||
|
||||
/**
|
||||
* Fetch current state.
|
||||
* @return current state.
|
||||
*/
|
||||
state_t state_getCurrentState();
|
||||
|
||||
/**
|
||||
* This function terminates the Radio state.
|
||||
*/
|
||||
void state_terminate();
|
||||
|
||||
#endif /* STATE_H */
|
||||
|
|
|
@ -32,10 +32,12 @@ void ui_init();
|
|||
|
||||
/**
|
||||
* This function advances the User Interface FSM, basing on the
|
||||
* current radio state and the keys pressed.
|
||||
* current radio state and the keys pressed and redraws the GUI.
|
||||
* @param last_state: A local copy of the previous radio state
|
||||
* @param keys: A bitmap containing the currently pressed keys
|
||||
* @return true if a screen refresh is needed after the update
|
||||
*/
|
||||
bool ui_update(state_t state, uint32_t keys);
|
||||
bool ui_update(state_t last_state, uint32_t keys);
|
||||
|
||||
/**
|
||||
* This function terminates the User Interface.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
|
||||
* Niccolò Izzo IU2KIN, *
|
||||
* Frederik Saraci IU2NRO, *
|
||||
* Silvano Seva IU2KWO *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
|
@ -20,26 +21,15 @@
|
|||
#include <stdio.h>
|
||||
#include <state.h>
|
||||
|
||||
state_t current_state;
|
||||
state_t state;
|
||||
modified_t state_flags;
|
||||
|
||||
void state_init()
|
||||
{
|
||||
/*TODO: Read current state parameters from hardware,
|
||||
* or initialize them to sane defaults */
|
||||
current_state.rx_freq = 0.0;
|
||||
current_state.tx_freq = 0.0;
|
||||
}
|
||||
|
||||
void state_update()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
state_t state_getCurrentState()
|
||||
{
|
||||
return current_state;
|
||||
}
|
||||
|
||||
void state_terminate()
|
||||
{
|
||||
state.time = rtc_getTime();
|
||||
state.v_bat = platform_getVbat();
|
||||
state.rx_freq = 0.0;
|
||||
state.tx_freq = 0.0;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include <platform.h>
|
||||
#include <hwconfig.h>
|
||||
|
||||
// Allocate state mutex
|
||||
static OS_MUTEX state_mutex;
|
||||
|
||||
// Allocate UI task control block and stack
|
||||
static OS_TCB ui_tcb;
|
||||
static CPU_STK ui_stk[UI_TASK_STKSIZE];
|
||||
|
@ -50,19 +53,15 @@ static void ui_task(void *arg)
|
|||
(void) arg;
|
||||
OS_ERR os_err;
|
||||
|
||||
// Initialise keyboard
|
||||
// Initialize keyboard
|
||||
kbd_init();
|
||||
|
||||
// Initialise graphics driver
|
||||
// Initialize graphics driver
|
||||
gfx_init();
|
||||
// Initialize user interface
|
||||
ui_init();
|
||||
|
||||
// Display splash screen
|
||||
point_t splash_origin = {0, SCREEN_HEIGHT / 2 + 6};
|
||||
color_t yellow_fab413 = {250, 180, 19};
|
||||
char *splash_buf = "OpenRTX";
|
||||
gfx_clearScreen();
|
||||
gfx_print(splash_origin, "OpenRTX", FONT_SIZE_12PT, TEXT_ALIGN_CENTER,
|
||||
yellow_fab413);
|
||||
ui_drawSplashScreen();
|
||||
gfx_render();
|
||||
while(gfx_renderingInProgress());
|
||||
// Wait 30ms to hide random pixels on screen
|
||||
|
@ -71,16 +70,25 @@ static void ui_task(void *arg)
|
|||
// Keep the splash screen for 1 second
|
||||
OSTimeDlyHMSM(0u, 0u, 1u, 0u, OS_OPT_TIME_HMSM_STRICT, &os_err);
|
||||
|
||||
// Clear screen
|
||||
gfx_clearScreen();
|
||||
gfx_render();
|
||||
while(gfx_renderingInProgress());
|
||||
// Get initial state local copy
|
||||
// Wait for unlocked mutex and lock it
|
||||
OSMutexPend(&state_mutex, 0u, OS_OPT_PEND_BLOCKING, 0u, &os_err);
|
||||
state_t last_state = state;
|
||||
// Unlock the mutex
|
||||
OSMutexPost(&state_mutex, OS_OPT_POST_NONE, &os_err);
|
||||
|
||||
while(1)
|
||||
{
|
||||
state_t state = state_getCurrentState();
|
||||
uint32_t keys = kbd_getKeys();
|
||||
bool renderNeeded = ui_update(state, keys);
|
||||
// Wait for unlocked mutex and lock it
|
||||
OSMutexPend(&state_mutex, 0u, OS_OPT_PEND_BLOCKING, 0u, &os_err);
|
||||
// React to keypresses and redraw GUI
|
||||
bool renderNeeded = ui_update(last_state, keys);
|
||||
// Update state local copy
|
||||
last_state = state;
|
||||
// Unlock the mutex
|
||||
OSMutexPost(&state_mutex, OS_OPT_POST_NONE, &os_err);
|
||||
|
||||
if(renderNeeded)
|
||||
{
|
||||
gfx_render();
|
||||
|
@ -92,25 +100,28 @@ static void ui_task(void *arg)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// State update task
|
||||
static void state_task(void *arg)
|
||||
{
|
||||
(void) arg;
|
||||
OS_ERR os_err;
|
||||
|
||||
// Initialise state
|
||||
state_init();
|
||||
|
||||
while(1)
|
||||
{
|
||||
// Execute state thread every 1s
|
||||
state_update();
|
||||
// Wait for unlocked mutex and lock it
|
||||
OSMutexPend(&state_mutex, 0u, OS_OPT_PEND_BLOCKING, 0u, &os_err);
|
||||
|
||||
state.time = rtc_getTime();
|
||||
state.v_bat = platform_getVbat();
|
||||
|
||||
// Unlock the mutex
|
||||
OSMutexPost(&state_mutex, OS_OPT_POST_NONE, &os_err);
|
||||
|
||||
// Execute state update thread every 1s
|
||||
OSTimeDlyHMSM(0u, 0u, 1u, 0u, OS_OPT_TIME_HMSM_STRICT, &os_err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// RTX task
|
||||
static void rtx_task(void *arg)
|
||||
{
|
||||
|
@ -146,9 +157,21 @@ void create_threads()
|
|||
{
|
||||
OS_ERR os_err;
|
||||
|
||||
// Create state mutex
|
||||
OSMutexCreate((OS_MUTEX *) &state_mutex,
|
||||
(CPU_CHAR *) "State Mutex",
|
||||
(OS_ERR *) &os_err);
|
||||
|
||||
// Wait for unlocked mutex and lock it
|
||||
OSMutexPend(&state_mutex, 0u, OS_OPT_PEND_BLOCKING, 0u, &os_err);
|
||||
// State initialization, execute before starting all tasks
|
||||
state_init();
|
||||
// Unlock the mutex
|
||||
OSMutexPost(&state_mutex, OS_OPT_POST_NONE, &os_err);
|
||||
|
||||
// Create UI thread
|
||||
OSTaskCreate((OS_TCB *) &ui_tcb,
|
||||
(CPU_CHAR *) " ",
|
||||
(CPU_CHAR *) "UI Task",
|
||||
(OS_TASK_PTR ) ui_task,
|
||||
(void *) 0,
|
||||
(OS_PRIO ) 10,
|
||||
|
@ -163,7 +186,7 @@ void create_threads()
|
|||
|
||||
// Create state thread
|
||||
OSTaskCreate((OS_TCB *) &state_tcb,
|
||||
(CPU_CHAR *) " ",
|
||||
(CPU_CHAR *) "State Task",
|
||||
(OS_TASK_PTR ) state_task,
|
||||
(void *) 0,
|
||||
(OS_PRIO ) 30,
|
||||
|
@ -178,7 +201,7 @@ void create_threads()
|
|||
|
||||
// Create rtx radio thread
|
||||
OSTaskCreate((OS_TCB *) &rtx_tcb,
|
||||
(CPU_CHAR *) " ",
|
||||
(CPU_CHAR *) "RTX Task",
|
||||
(OS_TASK_PTR ) rtx_task,
|
||||
(void *) 0,
|
||||
(OS_PRIO ) 5,
|
||||
|
@ -193,7 +216,7 @@ void create_threads()
|
|||
|
||||
// Create dmr radio thread
|
||||
OSTaskCreate((OS_TCB *) &dmr_tcb,
|
||||
(CPU_CHAR *) " ",
|
||||
(CPU_CHAR *) "DMR Task",
|
||||
(OS_TASK_PTR ) dmr_task,
|
||||
(void *) 0,
|
||||
(OS_PRIO ) 3,
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <ui.h>
|
||||
#include <rtc.h>
|
||||
#include <delays.h>
|
||||
#include <graphics.h>
|
||||
#include <keyboard.h>
|
||||
|
@ -91,8 +90,10 @@ typedef struct layout_t
|
|||
|
||||
layout_t layout;
|
||||
bool layout_ready = false;
|
||||
bool redraw_needed = true;
|
||||
color_t color_white = {255, 255, 255};
|
||||
color_t color_grey = {60, 60, 60};
|
||||
color_t yellow_fab413 = {250, 180, 19};
|
||||
|
||||
layout_t _ui_calculateLayout()
|
||||
{
|
||||
|
@ -203,19 +204,18 @@ void _ui_drawTopBar()
|
|||
{
|
||||
// Print clock on top bar
|
||||
char clock_buf[6] = "";
|
||||
curTime_t time = rtc_getTime();
|
||||
snprintf(clock_buf, sizeof(clock_buf), "%02d:%02d", time.hour, time.minute);
|
||||
snprintf(clock_buf, sizeof(clock_buf), "%02d:%02d", state.time.hour,
|
||||
state.time.minute);
|
||||
gfx_print(layout.top_pos, clock_buf, layout.top_font, TEXT_ALIGN_CENTER, color_white);
|
||||
|
||||
// Print battery voltage on top bar, use 4 px padding
|
||||
// TODO: Replace with battery icon
|
||||
char bat_buf[6] = "";
|
||||
float v_bat = platform_getVbat();
|
||||
snprintf(bat_buf, sizeof(bat_buf), "%02.1fV ", v_bat);
|
||||
snprintf(bat_buf, sizeof(bat_buf), "%02.1fV ", state.v_bat);
|
||||
gfx_print(layout.top_pos, bat_buf, layout.top_font, TEXT_ALIGN_RIGHT, color_white);
|
||||
}
|
||||
|
||||
void _ui_drawVFO(state_t state)
|
||||
void _ui_drawVFO()
|
||||
{
|
||||
// Print VFO frequencies
|
||||
char freq_buf[20] = "";
|
||||
|
@ -232,30 +232,58 @@ void _ui_drawBottomBar()
|
|||
gfx_print(layout.bottom_pos, bottom_buf, layout.bottom_font, TEXT_ALIGN_CENTER, color_white);
|
||||
}
|
||||
|
||||
void ui_drawMainScreen(state_t state)
|
||||
bool ui_drawMainScreen(state_t last_state)
|
||||
{
|
||||
_ui_drawBackground();
|
||||
_ui_drawTopBar();
|
||||
_ui_drawVFO(state);
|
||||
_ui_drawBottomBar();
|
||||
bool screen_update = false;
|
||||
// Total GUI redraw
|
||||
if(redraw_needed)
|
||||
{
|
||||
gfx_clearScreen();
|
||||
_ui_drawBackground();
|
||||
_ui_drawTopBar();
|
||||
_ui_drawVFO();
|
||||
_ui_drawBottomBar();
|
||||
screen_update = true;
|
||||
}
|
||||
// Partial GUI redraw
|
||||
// TODO: until gfx_clearRows() is implemented, we need to redraw everything
|
||||
else
|
||||
{
|
||||
gfx_clearScreen();
|
||||
_ui_drawBackground();
|
||||
_ui_drawTopBar();
|
||||
_ui_drawVFO();
|
||||
_ui_drawBottomBar();
|
||||
screen_update = true;
|
||||
}
|
||||
return screen_update;
|
||||
}
|
||||
|
||||
void ui_init()
|
||||
{
|
||||
redraw_needed = true;
|
||||
layout = _ui_calculateLayout();
|
||||
layout_ready = true;
|
||||
}
|
||||
|
||||
bool ui_update(state_t state, uint32_t keys)
|
||||
void ui_drawSplashScreen()
|
||||
{
|
||||
point_t splash_origin = {0, SCREEN_HEIGHT / 2 + 6};
|
||||
char *splash_buf = "OpenRTX";
|
||||
gfx_clearScreen();
|
||||
gfx_print(splash_origin, "OpenRTX", FONT_SIZE_12PT, TEXT_ALIGN_CENTER,
|
||||
yellow_fab413);
|
||||
}
|
||||
|
||||
bool ui_update(state_t last_state, uint32_t keys)
|
||||
{
|
||||
if(!layout_ready)
|
||||
{
|
||||
layout = _ui_calculateLayout();
|
||||
layout_ready = true;
|
||||
}
|
||||
gfx_clearScreen();
|
||||
ui_drawMainScreen(state);
|
||||
return true;
|
||||
bool screen_update = ui_drawMainScreen(last_state);
|
||||
return screen_update;
|
||||
}
|
||||
|
||||
void ui_terminate()
|
||||
|
|
Ładowanie…
Reference in New Issue