Moved the UI event queue inside the UI engine itself, UI FSM update now becomes a periodic task
This commit is contained in:
parent
fed368a4db
commit
4528e102a2
|
|
@ -27,7 +27,7 @@
|
||||||
*/
|
*/
|
||||||
enum eventType_t
|
enum eventType_t
|
||||||
{
|
{
|
||||||
EVENT_KBD = 0,
|
EVENT_KBD = 0,
|
||||||
EVENT_STATUS = 1
|
EVENT_STATUS = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@
|
||||||
#define FREQ_DIGITS 8
|
#define FREQ_DIGITS 8
|
||||||
// Time & Date digits
|
// Time & Date digits
|
||||||
#define TIMEDATE_DIGITS 10
|
#define TIMEDATE_DIGITS 10
|
||||||
|
// Max number of UI events
|
||||||
|
#define MAX_NUM_EVENTS 16
|
||||||
|
|
||||||
enum uiScreen
|
enum uiScreen
|
||||||
{
|
{
|
||||||
|
|
@ -218,6 +220,7 @@ void ui_init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function writes the OpenRTX splash screen image into the framebuffer.
|
* This function writes the OpenRTX splash screen image into the framebuffer.
|
||||||
|
*
|
||||||
* @param centered: if true the logo will be printed at the center of
|
* @param centered: if true the logo will be printed at the center of
|
||||||
* the screen, otherwise it will be printed at the top of the screen.
|
* the screen, otherwise it will be printed at the top of the screen.
|
||||||
*/
|
*/
|
||||||
|
|
@ -233,17 +236,24 @@ void ui_saveState();
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
* @param last_state: A local copy of the previous radio state
|
*
|
||||||
* @param event: An event from other threads
|
|
||||||
* @param sync_rtx: If true RTX needs to be synchronized
|
* @param sync_rtx: If true RTX needs to be synchronized
|
||||||
*/
|
*/
|
||||||
void ui_updateFSM(event_t event, bool *sync_rtx);
|
void ui_updateFSM(bool *sync_rtx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function redraws the GUI based on the last radio state.
|
* This function redraws the GUI based on the last radio state.
|
||||||
*/
|
*/
|
||||||
void ui_updateGUI();
|
void ui_updateGUI();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push an event to the UI event queue.
|
||||||
|
*
|
||||||
|
* @param event: event to be pushed.
|
||||||
|
* @return true on success false on failure.
|
||||||
|
*/
|
||||||
|
bool ui_pushEvent(const event_t event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function terminates the User Interface.
|
* This function terminates the User Interface.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@
|
||||||
#include <interfaces/radio.h>
|
#include <interfaces/radio.h>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
#include <rtx.h>
|
#include <rtx.h>
|
||||||
#include <queue.h>
|
|
||||||
#include <minmea.h>
|
#include <minmea.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <utils.h>
|
#include <utils.h>
|
||||||
|
|
@ -50,9 +49,6 @@ pthread_mutex_t rtx_mutex;
|
||||||
/* Mutex to avoid reading keyboard during display update */
|
/* Mutex to avoid reading keyboard during display update */
|
||||||
pthread_mutex_t display_mutex;
|
pthread_mutex_t display_mutex;
|
||||||
|
|
||||||
/* Queue for sending and receiving ui update requests */
|
|
||||||
queue_t ui_queue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \internal Task function in charge of updating the UI.
|
* \internal Task function in charge of updating the UI.
|
||||||
*/
|
*/
|
||||||
|
|
@ -78,16 +74,10 @@ void *ui_task(void *arg)
|
||||||
|
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
// Read from the keyboard queue (returns 0 if no message is present)
|
|
||||||
// Copy keyboard_t keys from received void * pointer msg
|
|
||||||
event_t event;
|
|
||||||
event.value = 0;
|
|
||||||
(void) queue_pend(&ui_queue, &event.value, true);
|
|
||||||
|
|
||||||
// Lock mutex, read and write state
|
// Lock mutex, read and write state
|
||||||
pthread_mutex_lock(&state_mutex);
|
pthread_mutex_lock(&state_mutex);
|
||||||
// React to keypresses and update FSM inside state
|
// React to keypresses and update FSM inside state
|
||||||
ui_updateFSM(event, &sync_rtx);
|
ui_updateFSM(&sync_rtx);
|
||||||
// Update state local copy
|
// Update state local copy
|
||||||
ui_saveState();
|
ui_saveState();
|
||||||
// Unlock mutex
|
// Unlock mutex
|
||||||
|
|
@ -127,10 +117,7 @@ void *ui_task(void *arg)
|
||||||
gfx_render();
|
gfx_render();
|
||||||
pthread_mutex_unlock(&display_mutex);
|
pthread_mutex_unlock(&display_mutex);
|
||||||
|
|
||||||
// We don't need a delay because we lock on incoming events
|
sleepFor(0u, 30u);
|
||||||
// TODO: Enable self refresh when a continuous visualization is enabled
|
|
||||||
// Update UI at ~33 FPS
|
|
||||||
//OSTimeDlyHMSM(0u, 0u, 0u, 30u, OS_OPT_TIME_HMSM_STRICT, &os_err);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,8 +145,7 @@ void *kbd_task(void *arg)
|
||||||
event_t event;
|
event_t event;
|
||||||
event.type = EVENT_KBD;
|
event.type = EVENT_KBD;
|
||||||
event.payload = msg.value;
|
event.payload = msg.value;
|
||||||
// Send keyboard status in queue
|
ui_pushEvent(event);
|
||||||
(void) queue_post(&ui_queue, event.value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read keyboard state at 40Hz
|
// Read keyboard state at 40Hz
|
||||||
|
|
@ -187,7 +173,7 @@ void *dev_task(void *arg)
|
||||||
event_t dev_msg;
|
event_t dev_msg;
|
||||||
dev_msg.type = EVENT_STATUS;
|
dev_msg.type = EVENT_STATUS;
|
||||||
dev_msg.payload = 0;
|
dev_msg.payload = 0;
|
||||||
(void) queue_post(&ui_queue, dev_msg.value);
|
ui_pushEvent(dev_msg);
|
||||||
|
|
||||||
// Execute state update thread every 1s
|
// Execute state update thread every 1s
|
||||||
sleepFor(1u, 0u);
|
sleepFor(1u, 0u);
|
||||||
|
|
@ -256,9 +242,6 @@ void create_threads()
|
||||||
// Create display mutex
|
// Create display mutex
|
||||||
pthread_mutex_init(&display_mutex, NULL);
|
pthread_mutex_init(&display_mutex, NULL);
|
||||||
|
|
||||||
// Create UI event queue
|
|
||||||
queue_init(&ui_queue);
|
|
||||||
|
|
||||||
// Create rtx radio thread
|
// Create rtx radio thread
|
||||||
pthread_t rtx_thread;
|
pthread_t rtx_thread;
|
||||||
pthread_attr_t rtx_attr;
|
pthread_attr_t rtx_attr;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
|
* Copyright (C) 2020 - 2022 by Federico Amedeo Izzo IU2NUO, *
|
||||||
* Niccolò Izzo IU2KIN *
|
* Niccolò Izzo IU2KIN *
|
||||||
* Frederik Saraci IU2NRO *
|
* 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 *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
|
@ -243,6 +243,11 @@ bool redraw_needed = true;
|
||||||
bool standby = false;
|
bool standby = false;
|
||||||
long long last_event_tick = 0;
|
long long last_event_tick = 0;
|
||||||
|
|
||||||
|
// UI event queue
|
||||||
|
uint8_t evQueue_rdPos;
|
||||||
|
uint8_t evQueue_wrPos;
|
||||||
|
event_t evQueue[MAX_NUM_EVENTS];
|
||||||
|
|
||||||
layout_t _ui_calculateLayout()
|
layout_t _ui_calculateLayout()
|
||||||
{
|
{
|
||||||
// Horizontal line height
|
// Horizontal line height
|
||||||
|
|
@ -929,7 +934,7 @@ void ui_saveState()
|
||||||
last_state = state;
|
last_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ui_updateFSM(event_t event, bool *sync_rtx)
|
void ui_updateFSM(bool *sync_rtx)
|
||||||
{
|
{
|
||||||
// User wants to power off the radio, so shutdown.
|
// User wants to power off the radio, so shutdown.
|
||||||
if(!platform_pwrButtonStatus())
|
if(!platform_pwrButtonStatus())
|
||||||
|
|
@ -940,6 +945,14 @@ void ui_updateFSM(event_t event, bool *sync_rtx)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for events
|
||||||
|
if(evQueue_wrPos == evQueue_rdPos) return;
|
||||||
|
|
||||||
|
// Pop an event from the queue
|
||||||
|
uint8_t newTail = (evQueue_rdPos + 1) % MAX_NUM_EVENTS;
|
||||||
|
event_t event = evQueue[evQueue_rdPos];
|
||||||
|
evQueue_rdPos = newTail;
|
||||||
|
|
||||||
// Check if battery has enough charge to operate.
|
// Check if battery has enough charge to operate.
|
||||||
// Check is skipped if there is an ongoing transmission, since the voltage
|
// Check is skipped if there is an ongoing transmission, since the voltage
|
||||||
// drop caused by the RF PA power absorption causes spurious triggers of
|
// drop caused by the RF PA power absorption causes spurious triggers of
|
||||||
|
|
@ -1779,6 +1792,19 @@ void ui_updateGUI()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ui_pushEvent(const event_t event)
|
||||||
|
{
|
||||||
|
uint8_t newHead = (evQueue_wrPos + 1) % MAX_NUM_EVENTS;
|
||||||
|
|
||||||
|
// Queue is full
|
||||||
|
if(newHead == evQueue_rdPos) return false;
|
||||||
|
|
||||||
|
evQueue[evQueue_wrPos] = event;
|
||||||
|
evQueue_wrPos = newHead;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void ui_terminate()
|
void ui_terminate()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
|
* Copyright (C) 2020 - 2022 by Federico Amedeo Izzo IU2NUO, *
|
||||||
* Niccolò Izzo IU2KIN *
|
* Niccolò Izzo IU2KIN *
|
||||||
* Frederik Saraci IU2NRO *
|
* 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 *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
|
* Copyright (C) 2020 - 2022 by Federico Amedeo Izzo IU2NUO, *
|
||||||
* Niccolò Izzo IU2KIN *
|
* Niccolò Izzo IU2KIN *
|
||||||
* Frederik Saraci IU2NRO *
|
* 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 *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
* Copyright (C) 2021 by Federico Amedeo Izzo IU2NUO, *
|
* Copyright (C) 2021 - 2022 by Federico Amedeo Izzo IU2NUO, *
|
||||||
* Niccolò Izzo IU2KIN *
|
* Niccolò Izzo IU2KIN *
|
||||||
* Frederik Saraci IU2NRO *
|
* 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 *
|
||||||
* it under the terms of the GNU General Public License as published by *
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue