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