Add shared state logic

replace/16d73ece1181eb1f0447cf50a1853127e667a2b3
Federico Amedeo Izzo 2020-11-21 10:46:39 +01:00
rodzic 310f19c6b7
commit 3370e5a3a7
5 zmienionych plików z 127 dodań i 81 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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