From e7db0bc1dcb5a4f209ed79b3945ba5e67ffd1603 Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Wed, 2 Sep 2026 20:22:00 +0200 Subject: [PATCH] Make Triple VFO and Beam overlay services optional --- App/CMakeLists.txt | 6 ++++++ App/apps/app_api.h | 4 ++-- App/apps/app_overlay.c | 35 ++++++++++++++++++++++++++++++----- App/apps/app_overlay.h | 2 ++ App/apps/beam/build.sh | 2 +- App/apps/pack_app.py | 2 ++ App/apps/trivfo/build.sh | 2 +- CMakePresets.json | 2 ++ 8 files changed, 46 insertions(+), 9 deletions(-) diff --git a/App/CMakeLists.txt b/App/CMakeLists.txt index d3b6dd30..e3e5b5d8 100644 --- a/App/CMakeLists.txt +++ b/App/CMakeLists.txt @@ -201,9 +201,15 @@ enable_feature(ENABLE_FEAT_F4HWN_OVERLAY_APPS apps/app_overlay.c apps/app_menu.c ) +enable_feature(ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO) +enable_feature(ENABLE_FEAT_F4HWN_OVERLAY_BEAM) if(ENABLE_FEAT_F4HWN_OVERLAY_APPS AND NOT ENABLE_FEAT_F4HWN_MULTIBOOT_OVERLAY) message(FATAL_ERROR "ENABLE_FEAT_F4HWN_OVERLAY_APPS requires ENABLE_FEAT_F4HWN_MULTIBOOT_OVERLAY (the 4 KiB overlay workspace).") endif() +if((ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO OR ENABLE_FEAT_F4HWN_OVERLAY_BEAM) AND + NOT ENABLE_FEAT_F4HWN_OVERLAY_APPS) + message(FATAL_ERROR "Overlay Triple VFO/Beam services require ENABLE_FEAT_F4HWN_OVERLAY_APPS.") +endif() enable_feature(ENABLE_FEAT_F4HWN_K5VIEWER k5viewer.c ) diff --git a/App/apps/app_api.h b/App/apps/app_api.h index 96355154..6a286fe2 100644 --- a/App/apps/app_api.h +++ b/App/apps/app_api.h @@ -255,7 +255,7 @@ typedef struct app_api { * Returns 0 for any other key. Keep get_key() raw for spatial controls. */ int8_t (*nav_dir)(uint8_t key); - /* ---- triple VFO (API level 1 baseline) ---- + /* ---- triple VFO (optional resident capability APP_CAP_TRIVFO) ---- * A and B are the live Main Display VFOs. C is a resident temporary VFO * loaded from c_channel (or the first valid memory after B when invalid). * tick is called every 20 ms by the app and returns APP_TRIVFO_* state. */ @@ -267,7 +267,7 @@ typedef struct app_api { uint8_t (*trivfo_tick)(void); uint8_t (*trivfo_ptt)(bool pressed); /* physical PTT edge; resident applies SetPTT */ - /* ---- BEAM channel transfer (API level 1 baseline) ---- */ + /* ---- BEAM channel transfer (optional resident capability APP_CAP_BEAM) ---- */ void (*beam_prepare)(void); /* tune the fixed narrow-band FSK channel */ void (*beam_leave)(void); /* defensively stop FSK before app return */ void (*beam_get)(app_beam_channel_t *channel); /* export selected VFO */ diff --git a/App/apps/app_overlay.c b/App/apps/app_overlay.c index 9113a274..912eb1ee 100644 --- a/App/apps/app_overlay.c +++ b/App/apps/app_overlay.c @@ -54,11 +54,18 @@ _Static_assert(sizeof(app_header_t) == 64, "app_header_t must be 64 bytes"); _Static_assert(sizeof(app_api_t) <= UINT16_MAX, "app_api_t size field overflow"); +enum { + APP_AVAILABLE_CAPS = 0u #ifdef ENABLE_FMRADIO - #define APP_AVAILABLE_CAPS APP_CAP_FM -#else - #define APP_AVAILABLE_CAPS 0u + | APP_CAP_FM #endif +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO + | APP_CAP_TRIVFO +#endif +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_BEAM + | APP_CAP_BEAM +#endif +}; /* ---- ABI wrappers: the few resident calls that are not a direct signature match ---- */ static bool app_allow_screen_saver; @@ -137,7 +144,8 @@ static void app_play_tone(uint16_t tone, uint16_t ms) AUDIO_AudioPathOff(); } -/* ---- API level 1: resident triple-VFO engine ---------------------------- +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO +/* ---- optional resident triple-VFO engine -------------------------------- * The overlay owns the UI and key timing, while this resident engine owns all * radio details. Keeping VFO_Info_t and BK4819 sequencing on this side makes * the app independent of feature-dependent firmware layouts. */ @@ -532,8 +540,10 @@ static uint8_t app_trivfo_ptt(bool pressed) app_trivfo_tx_ticks = 0; return 0; } +#endif -/* ---- API level 1: BEAM radio/channel bridge ------------------------------- +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_BEAM +/* ---- optional BEAM radio/channel bridge ----------------------------------- * The modal app owns the packet format, CRC, UI and state machine. Resident * code only translates the stable ABI channel structure and performs the FSK * operations which depend on VFO_Info_t and the BK4819 driver. */ @@ -757,6 +767,7 @@ static void app_beam_draw(const char *status) memset(gFrameBuffer[line], 0, LCD_WIDTH); UI_PrintStringSmallBold(status, 2, LCD_WIDTH - 1u, line); } +#endif /* ---- radio wrappers ---- */ static int16_t app_rssi_dbm(void) { return BK4819_GetRSSI_dBm() + dBmCorrTable[gRxVfo->Band]; } @@ -803,8 +814,10 @@ static void app_battery_sample(void) /* The resident scheduler deliberately skips ADC battery updates while the * PA is keyed. Do the same for Triple VFO: sampling the loaded voltage as * capacity made an 80% pack appear to fall immediately to about 16%. */ +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO if (app_trivfo_transmitting) return; +#endif BATTERY_Sample(false); } @@ -1039,6 +1052,7 @@ static const app_api_t app_api = { .fm_commit = app_fm_commit, #endif .nav_dir = app_nav_dir, +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO .trivfo_enter = app_trivfo_enter, .trivfo_leave = app_trivfo_leave, .trivfo_get = app_trivfo_get, @@ -1046,6 +1060,8 @@ static const app_api_t app_api = { .trivfo_step = app_trivfo_step, .trivfo_tick = app_trivfo_tick, .trivfo_ptt = app_trivfo_ptt, +#endif +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_BEAM .beam_prepare = app_beam_prepare, .beam_leave = app_beam_leave, .beam_get = app_beam_get, @@ -1054,6 +1070,7 @@ static const app_api_t app_api = { .beam_rx = app_beam_rx, .beam_rx_poll = app_beam_rx_poll, .beam_draw = app_beam_draw, +#endif }; uint8_t APP_LaunchOverlay(uint8_t slot) @@ -1092,7 +1109,9 @@ uint8_t APP_LaunchOverlay(uint8_t slot) #ifdef ENABLE_FMRADIO app_fm_dirty = false; #endif +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_BEAM app_beam_dirty = false; +#endif app_allow_screen_saver = (h.flags & APP_FLAG_SCREEN_SAVER) != 0; app_screen_saver_wake = false; @@ -1129,7 +1148,9 @@ uint8_t APP_LaunchOverlay(uint8_t slot) app_screen_saver_wake = false; /* A defensive leave also covers an app returning through an error path. */ +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO app_trivfo_leave(); +#endif /* Restore the resident RX/dual-watch tuning the app ran on top of. */ gEeprom.RX_VFO = saved_rx_vfo; @@ -1139,8 +1160,11 @@ uint8_t APP_LaunchOverlay(uint8_t slot) /* The overlay held app code, not a valid config sector. */ PY25Q16_InvalidateCache(); +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_BEAM app_beam_commit(); +#endif +#ifdef ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO if (app_trivfo_ab_dirty) { SETTINGS_SaveVfoIndices(); app_trivfo_ab_dirty = false; @@ -1152,6 +1176,7 @@ uint8_t APP_LaunchOverlay(uint8_t slot) &gEeprom.VfoInfo[i], 1); } app_trivfo_freq_dirty = 0; +#endif /* Commit any deferred config the app staged (RMW keeps the slot header). */ if (app_cfg_len) { diff --git a/App/apps/app_overlay.h b/App/apps/app_overlay.h index 8c07e703..89c4f546 100644 --- a/App/apps/app_overlay.h +++ b/App/apps/app_overlay.h @@ -81,6 +81,8 @@ /* Optional resident facilities an app may require. Requirements live in the * previously reserved header bytes, so app_header_t remains 64 bytes. */ #define APP_CAP_FM 0x00000001u +#define APP_CAP_TRIVFO 0x00000002u +#define APP_CAP_BEAM 0x00000004u typedef struct __attribute__((packed)) { uint32_t magic; /* APP_MAGIC */ diff --git a/App/apps/beam/build.sh b/App/apps/beam/build.sh index aaf1c4c9..f8850ed5 100755 --- a/App/apps/beam/build.sh +++ b/App/apps/beam/build.sh @@ -26,7 +26,7 @@ step 1 compile ; "$CC" $CFLAGS $LDFLAGS "${APP}_app.c" -lgcc -o "${APP}.elf" step 2 objcopy ; "$OBJCOPY" -O binary "${APP}.elf" "${APP}.bin" step 3 pack ; python3 ../pack_app.py "${APP}.bin" "${OUT}.app" \ --name "$APP_NAME" --ver "$APP_VER" --api-min "$APP_API_MIN" --vma "${APP_VMA}" \ - --shortcut beam >/dev/null + --shortcut beam --require beam >/dev/null trap - ERR BYTES=$(wc -c < "${APP}.bin") diff --git a/App/apps/pack_app.py b/App/apps/pack_app.py index 8d6a7def..077b2d21 100644 --- a/App/apps/pack_app.py +++ b/App/apps/pack_app.py @@ -44,6 +44,8 @@ SHORTCUTS = { } CAPABILITIES = { "fm": cdefine("app_overlay.h", "APP_CAP_FM"), + "trivfo": cdefine("app_overlay.h", "APP_CAP_TRIVFO"), + "beam": cdefine("app_overlay.h", "APP_CAP_BEAM"), } def field(s: str, n: int) -> bytes: diff --git a/App/apps/trivfo/build.sh b/App/apps/trivfo/build.sh index b8bafb88..233a5136 100755 --- a/App/apps/trivfo/build.sh +++ b/App/apps/trivfo/build.sh @@ -14,7 +14,7 @@ LDFLAGS="-nostdlib -nostartfiles -T app.ld -Wl,--defsym,APP_VMA=${APP_VMA} -Wl,- rm -f ./*.app ./*.elf ./*.bin "$CC" $CFLAGS $LDFLAGS "${APP}_app.c" -lgcc -o "${APP}.elf" "$OBJCOPY" -O binary "${APP}.elf" "${APP}.bin" -python3 ../pack_app.py "${APP}.bin" "${OUT}.app" --name "$APP_NAME" --ver "$APP_VER" --api-min "$APP_API_MIN" --vma "${APP_VMA}" --screensaver >/dev/null +python3 ../pack_app.py "${APP}.bin" "${OUT}.app" --name "$APP_NAME" --ver "$APP_VER" --api-min "$APP_API_MIN" --vma "${APP_VMA}" --require trivfo --screensaver >/dev/null BYTES=$(wc -c < "${APP}.bin") test "$BYTES" -le 4096 printf ' ✅ %-13s %4d B (%d%% of 4 KiB) -> %s.app\n' \ diff --git a/CMakePresets.json b/CMakePresets.json index f3d571a4..204c1abe 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -183,6 +183,8 @@ "ENABLE_FEAT_F4HWN_BEAM": false, "ENABLE_FEAT_F4HWN_GAME": false, "ENABLE_FEAT_F4HWN_OVERLAY_APPS": true, + "ENABLE_FEAT_F4HWN_OVERLAY_TRIVFO": false, + "ENABLE_FEAT_F4HWN_OVERLAY_BEAM": true, "EDITION_STRING": "Labs", "TARGET": "f4hwn.labs" }