From a8fd6927af4bad6c365802cda16019df12398e7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominic=20H=C3=B6glinger?= Date: Sat, 4 Oct 2025 14:22:39 +0200 Subject: [PATCH] RadioSet: Add various small improvements --- .../RadioSet/main/Source/LinkedList.h | 2 + .../RadioSet/main/Source/RadioSet.cpp | 75 +++++++++++-------- ExternalApps/RadioSet/main/Source/RadioSet.h | 10 ++- .../RadioSet/main/Source/SettingsView.cpp | 24 +++--- .../RadioSet/main/Source/SettingsView.h | 13 ++-- ExternalApps/RadioSet/main/Source/Utils.cpp | 43 +++++++++++ ExternalApps/RadioSet/main/Source/Utils.h | 10 +++ 7 files changed, 129 insertions(+), 48 deletions(-) diff --git a/ExternalApps/RadioSet/main/Source/LinkedList.h b/ExternalApps/RadioSet/main/Source/LinkedList.h index 42837608..10e26303 100644 --- a/ExternalApps/RadioSet/main/Source/LinkedList.h +++ b/ExternalApps/RadioSet/main/Source/LinkedList.h @@ -1,5 +1,7 @@ #pragma once +#include + template class LinkedList { diff --git a/ExternalApps/RadioSet/main/Source/RadioSet.cpp b/ExternalApps/RadioSet/main/Source/RadioSet.cpp index e0764732..b2952ed5 100644 --- a/ExternalApps/RadioSet/main/Source/RadioSet.cpp +++ b/ExternalApps/RadioSet/main/Source/RadioSet.cpp @@ -10,41 +10,12 @@ constexpr const char* TAG = "RadioSet"; -// Debug function which colors all children randomly -// TODO: Remove before flight -void clownvomit(lv_obj_t *obj) { - static auto rng = []() { - static int color = 0xC0FE; - const int a = 4711; - const int m = 0x10001; - color = (a * color) % m; - return color; - }; - - const int darken = 0x0E0E0E; - const int lighten = 0xFEFEFE; - lv_obj_set_style_bg_color(obj, lv_color_hex(rng() & darken), 0); - - uint32_t i; - for(i = 0; i < lv_obj_get_child_count(obj); i++) { - lv_obj_t * child = lv_obj_get_child(obj, i); - lv_obj_set_style_bg_color(child, lv_color_hex(rng() & darken), 0); - lv_obj_set_style_border_color(child, lv_color_hex(rng() | lighten), 0); - lv_obj_set_style_border_width(child, 1, 0); - clownvomit(child); - } -} /* void scrollbar_highlight(lv_event_t * e) { lv_obj_t * obj = lv_event_get_target(e); }*/ -class TermView { - -}; - - void RadioSet::onShow(AppHandle appHandle, lv_obj_t* parent) { lv_obj_remove_flag(parent, LV_OBJ_FLAG_SCROLLABLE); lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); @@ -75,18 +46,42 @@ void RadioSet::onShow(AppHandle appHandle, lv_obj_t* parent) { lv_obj_set_style_border_width(wrapper, 0, 0); lv_obj_remove_flag(wrapper, LV_OBJ_FLAG_SCROLLABLE); + termView = new TermView(wrapper); settingsView = new SettingsView(wrapper); auto presetMtEu868LongFast = new Preset("MT EU868 LongFast", MODULATION_LORA); presetMtEu868LongFast->addParameter(RADIO_FREQUENCY, 869.525); + presetMtEu868LongFast->addParameter(RADIO_POWER, 22.0); + presetMtEu868LongFast->addParameter(RADIO_BOOSTEDGAIN, true); presetMtEu868LongFast->addParameter(RADIO_BANDWIDTH, 250.0); presetMtEu868LongFast->addParameter(RADIO_SPREADFACTOR, 11); - presetMtEu868LongFast->addParameter(RADIO_CODINGRATE, 6); + presetMtEu868LongFast->addParameter(RADIO_CODINGRATE, 5); presetMtEu868LongFast->addParameter(RADIO_SYNCWORD, 0x2B); presetMtEu868LongFast->addParameter(RADIO_PREAMBLES, 16); settingsView->addPreset(presetMtEu868LongFast); settingsView->updatePresets(); + + for (auto iter = settingsView->radios.begin(); iter != settingsView->radios.end(); iter++) { + termView->addRadio(*iter); + } + + showView(View::Terminal); + + lv_obj_add_event_cb(uiDropDownMenu, [](lv_event_t * e) { + RadioSet* self = (RadioSet*)lv_event_get_user_data(e); + lv_obj_t* input = lv_event_get_target_obj(e); + switch (lv_dropdown_get_selected(input)) { + case 0: + self->showView(View::Terminal); + break; + case 1: + self->showView(View::Settings); + break; + default: + break; + } + }, LV_EVENT_VALUE_CHANGED, this); } @@ -99,5 +94,23 @@ RadioSet::~RadioSet() { } } -// ???? +void RadioSet::showView(View view) { + termView->setVisible(false); + settingsView->setVisible(false); + switch (view) { + case View::Terminal: + termView->setVisible(true); + break; + case View::Settings: + settingsView->setVisible(true); + break; + default: + break; + } +} + + +// This function is called with any "pure virtual" method, i.e. it should never happen +// TODO: I was wrong about it being related to the STL, it is a core feature that needs +// to be bridged with the tt_init.cpp symbol table extern "C" void __cxa_pure_virtual() { crash("Entered the Virtual Zone..."); } diff --git a/ExternalApps/RadioSet/main/Source/RadioSet.h b/ExternalApps/RadioSet/main/Source/RadioSet.h index 006d6318..d8c62131 100644 --- a/ExternalApps/RadioSet/main/Source/RadioSet.h +++ b/ExternalApps/RadioSet/main/Source/RadioSet.h @@ -1,14 +1,18 @@ #pragma once #include "SettingsView.h" +#include "TermView.h" #include "tt_app.h" #include "tt_hal_radio.h" #include -class TermView; - class RadioSet { + enum class View { + Terminal, + Settings + }; + lv_obj_t* mainView = nullptr; lv_obj_t* uiDropDownMenu = nullptr; lv_obj_t* progressBar = nullptr; @@ -22,4 +26,6 @@ public: ~RadioSet(); void onShow(AppHandle context, lv_obj_t* parent); + + void showView(View view); }; diff --git a/ExternalApps/RadioSet/main/Source/SettingsView.cpp b/ExternalApps/RadioSet/main/Source/SettingsView.cpp index 08a55fb0..6842cbbe 100644 --- a/ExternalApps/RadioSet/main/Source/SettingsView.cpp +++ b/ExternalApps/RadioSet/main/Source/SettingsView.cpp @@ -510,28 +510,25 @@ void SettingsView::queryRadios() { if(!tt_hal_device_find(DEVICE_TYPE_RADIO, devices, &device_count, MAX_RADIOS)) { // TT_LOG_W(TAG, "No radios registered with the system?"); } else { - size_t radios_allocated = 0; for (size_t i = 0; (i < device_count) && (i < MAX_RADIOS); ++i) { auto radio = tt_hal_radio_alloc(devices[i]); if (radio) { // TT_LOG_I(TAG, "Discovered radio \"%s\"", tt_hal_radio_get_name(radio)); - radios[radios_allocated] = radio; - radios_allocated++; + radios.pushBack(radio); } else { // TT_LOG_E(TAG, "Error allocating radio handle for id=%d", devId); } } - radioCount = radios_allocated; } } void SettingsView::getRadioNames(Str &names, const char* const separator) { int count = 1; names.clear(); - //for (auto radio : radios) { - for (size_t i = 0; i < radioCount; ++i) { - Str name(tt_hal_radio_get_name(radios[i])); - auto last = (i == (radioCount - 1)); + + for (auto iter = radios.begin(); iter != radios.end(); iter++) { + Str name(tt_hal_radio_get_name(*iter)); + auto last = is_last(iter, radios); if (name == "") { name.appendf("Unknown Radio %d", count); } @@ -679,7 +676,6 @@ void SettingsView::selectRadio(int index) { } radioSelected = radios[index]; - crashassert(radioSelected, "Radio selected not allocated"); for (size_t i = 0; i < MAX_MODEMS; ++i) { modemsAvailable[i] = MODULATION_NONE; @@ -879,7 +875,7 @@ void SettingsView::deactivateConfig() { void SettingsView::initUi(lv_obj_t *parent) { mainPanel = lv_obj_create(parent); - lv_obj_set_size(mainPanel, lv_pct(100), lv_pct(80)); + lv_obj_set_size(mainPanel, lv_pct(100), lv_pct(100)); lv_obj_set_flex_flow(mainPanel, LV_FLEX_FLOW_COLUMN); lv_obj_align(mainPanel, LV_ALIGN_TOP_MID, 0, 0); lv_obj_set_style_border_width(mainPanel, 0, 0); @@ -887,3 +883,11 @@ void SettingsView::initUi(lv_obj_t *parent) { deviceForm = initDeviceForm(mainPanel); } + +void SettingsView::setVisible(bool visible) { + if (visible) { + lv_obj_clear_flag(mainPanel, LV_OBJ_FLAG_HIDDEN); + } else { + lv_obj_add_flag(mainPanel, LV_OBJ_FLAG_HIDDEN); + } +} diff --git a/ExternalApps/RadioSet/main/Source/SettingsView.h b/ExternalApps/RadioSet/main/Source/SettingsView.h index 6da20976..5ccad22d 100644 --- a/ExternalApps/RadioSet/main/Source/SettingsView.h +++ b/ExternalApps/RadioSet/main/Source/SettingsView.h @@ -8,15 +8,12 @@ class ParameterInput; class SettingsView { - static constexpr size_t MAX_RADIOS = 32; static constexpr Modulation FIRST_MODULATION = MODULATION_NONE; static constexpr Modulation LAST_MODULATION = MODULATION_LRFHSS; + static constexpr size_t MAX_RADIOS = 32; static constexpr size_t MAX_MODEMS = LAST_MODULATION + 1; static constexpr size_t MAX_PARAMS = RADIO_NARROWGRID + 1; - RadioHandle radios[MAX_RADIOS] = {0}; - size_t radioCount = 0; - RadioHandle radioSelected = nullptr; RadioStateSubscriptionId radioStateSubId = -1; Modulation modemsAvailable[MAX_MODEMS] = {}; @@ -36,9 +33,11 @@ class SettingsView { lv_obj_t* modemDropdown = nullptr; lv_obj_t* modemPresetDropdown = nullptr; - lv_obj_t *propertiesForm = nullptr; + lv_obj_t* propertiesForm = nullptr; public: + LinkedList radios; + void addPreset(Preset* preset); void queryRadios(); void getRadioNames(Str &names, const char* const separator); @@ -65,8 +64,12 @@ public: void initUi(lv_obj_t *parent); + void setVisible(bool visible); + explicit SettingsView(lv_obj_t *parent) { queryRadios(); initUi(parent); } + + }; diff --git a/ExternalApps/RadioSet/main/Source/Utils.cpp b/ExternalApps/RadioSet/main/Source/Utils.cpp index d19c5e36..881f8db2 100644 --- a/ExternalApps/RadioSet/main/Source/Utils.cpp +++ b/ExternalApps/RadioSet/main/Source/Utils.cpp @@ -1,5 +1,7 @@ #include "Utils.h" +#include + #include void crash(const char* const message) { @@ -12,6 +14,22 @@ void crashassert(bool assertion, const char* const message) { } } +void hexdump(Str& out, const uint8_t* data, size_t size) { + out.clear(); + for (size_t i = 0; i < size; ++i) { + out.appendf("%02X ", data[i]); + } +} + +bool isPrintable(const uint8_t* data, size_t size) { + for (size_t i = 0; i < (size - 1); ++i) { + if (!isprint(data[i])) { + return false; + } + } + return true; +} + char *const toString(Modulation m) { switch (m) { case MODULATION_NONE: @@ -61,3 +79,28 @@ char *const toString(RadioParameter p) { crash("Unknown parameter passed."); return "Unknown"; } + +void clownvomit(lv_obj_t *obj) { + static auto rng = []() { + static int color = 0xCCC0FE; + const int a = 4711; + const int m = 0x10001; + color = (a * color) % m; + return color; + }; + + const int darken = 0x0E0E0E; + const int lighten = 0xFEFEFE; + lv_obj_set_style_bg_color(obj, lv_color_hex(rng() & darken), 0); + + uint32_t i; + for(i = 0; i < lv_obj_get_child_count(obj); i++) { + auto light = lv_color_lighten(lv_color_hex(rng()), 100); + auto dark = lv_color_darken(lv_color_hex(rng()), 100); + lv_obj_t * child = lv_obj_get_child(obj, i); + lv_obj_set_style_bg_color(child, dark, 0); + lv_obj_set_style_border_color(child, light, 0); + lv_obj_set_style_border_width(child, 1, 0); + clownvomit(child); + } +} diff --git a/ExternalApps/RadioSet/main/Source/Utils.h b/ExternalApps/RadioSet/main/Source/Utils.h index 468ef3b4..b707e17d 100644 --- a/ExternalApps/RadioSet/main/Source/Utils.h +++ b/ExternalApps/RadioSet/main/Source/Utils.h @@ -1,5 +1,8 @@ #pragma once +#include "Str.h" + +#include #include template @@ -15,5 +18,12 @@ bool is_last(Iterator i, const Container& c) { void crash(const char* const message); void crashassert(bool assertion, const char* const message); +void hexdump(Str& out, const uint8_t* data, size_t size); +bool isPrintable(const uint8_t* data, size_t size); + char *const toString(Modulation m); char *const toString(RadioParameter p); + +// Debug function which colors all children randomly +// TODO: Remove before flight +void clownvomit(lv_obj_t *obj);