diff --git a/App/app/menu.c b/App/app/menu.c index eb373e7e..94a8e816 100644 --- a/App/app/menu.c +++ b/App/app/menu.c @@ -457,6 +457,21 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) #endif #endif + case MENU_VOL: { + // SysInf paginates: page 0 = identity, +1 if F4HWN_MEM (Flash/SRAM), + // +2 if F4HWN_QRCODE (Code QR + Wiki QR). + int32_t vol_max = 0; + #ifdef ENABLE_FEAT_F4HWN_MEM + vol_max += 1; + #endif + #ifdef ENABLE_FEAT_F4HWN_QRCODE + vol_max += 2; + #endif + if (vol_max == 0) return -1; + *pMax = vol_max; + break; + } + default: return -1; } @@ -1030,6 +1045,11 @@ void MENU_ShowCurrentSetting(void) gSubMenuSelection = gEeprom.SQUELCH_LEVEL; break; + case MENU_VOL: + // SysInf is paginated; always start on page 0 (identity). + gSubMenuSelection = 0; + break; + case MENU_STEP: gSubMenuSelection = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING); break; diff --git a/App/main.c b/App/main.c index e77ab2c9..a6a54862 100644 --- a/App/main.c +++ b/App/main.c @@ -213,37 +213,13 @@ void Main(void) if (gEeprom.POWER_ON_DISPLAY_MODE != POWER_ON_DISPLAY_MODE_NONE) #endif { // 2.55 second boot-up screen -#ifdef ENABLE_FEAT_F4HWN_QRCODE - bool qr_view = false; -#endif while (boot_counter_10ms > 0) { -#ifdef ENABLE_FEAT_F4HWN_QRCODE - // Freeze the 2.5s auto-exit timer while the user is reading the QR - if (qr_view) - boot_counter_10ms = 250; -#endif - KEY_Code_t key = KEYBOARD_Poll(); - if (key == KEY_INVALID) - continue; - -#ifdef ENABLE_FEAT_F4HWN_QRCODE - if (key == KEY_MENU) - { // Toggle between welcome and fullscreen QR - qr_view = !qr_view; - if (qr_view) - UI_DisplayWelcomeQR(); - else - UI_DisplayWelcome(); - boot_counter_10ms = 250; - while (KEYBOARD_Poll() == KEY_MENU) ; // wait for release - SYSTEM_DelayMs(20); - continue; + if (KEYBOARD_Poll() != KEY_INVALID) + { // halt boot beeps + boot_counter_10ms = 0; + break; } -#endif - // Any other key halts boot beeps and exits - boot_counter_10ms = 0; - break; } RADIO_SetupRegisters(true); } diff --git a/App/ui/menu.c b/App/ui/menu.c index 03eedc84..aae4345d 100644 --- a/App/ui/menu.c +++ b/App/ui/menu.c @@ -41,6 +41,7 @@ #include "inputbox.h" #include "menu.h" #include "ui.h" +#include "welcome.h" const t_menu_item MenuList[] = @@ -1129,18 +1130,69 @@ void UI_DisplayMenu(void) strcpy(String, gSubMenu_ROGER[gSubMenuSelection]); break; - case MENU_VOL: + case MENU_VOL: { + // SysInf is paginated. Pages appear in this order, only when their + // feature flag is enabled — so indices compact automatically: + // 0 → identity (always) + // next → Flash / SRAM usage (ENABLE_FEAT_F4HWN_MEM) + // next, +1 → CODE / WIKI QR codes (ENABLE_FEAT_F4HWN_QRCODE) + // The post-incremented `p` walks through every enabled page slot. + const uint8_t page = (uint8_t)gSubMenuSelection; + uint8_t p = 0; + + if (page == p++) { + // Page 0: firmware identity. #ifdef ENABLE_FEAT_F4HWN - sprintf(String, "%s\n%s", - AUTHOR_STRING_2, - VERSION_STRING_2 - ); + sprintf(String, "%s\n%s", AUTHOR_STRING_2, VERSION_STRING_2); #else - sprintf(String, "%u.%02uV\n%u%%", - gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, - BATTERY_VoltsToPercent(gBatteryVoltageAverage)); + sprintf(String, "%u.%02uV\n%u%%", + gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, + BATTERY_VoltsToPercent(gBatteryVoltageAverage)); +#endif + break; + } +#ifdef ENABLE_FEAT_F4HWN_MEM + if (page == p++) { + uint16_t flash_pct = 0; + uint16_t ram_pct = 0; + UI_GetMemPercents(&flash_pct, &ram_pct); + + char val[16]; + + // MEMORY title capsule (6 chars → 45 px wide) centered in right zone, fb line 1. + UI_PrintStringSmallNormalInverse("MEMORY", 67, 0, 1); + + // Flash + SRAM values stacked below, normal small font, with a fb-line of breathing space. + sprintf(val, "FLASH %u.%01u%%", + (unsigned)(flash_pct / 100), (unsigned)((flash_pct % 100) / 10)); + UI_PrintStringSmallNormal(val, 49, 127, 3); + + sprintf(val, "SRAM %u.%01u%%", + (unsigned)(ram_pct / 100), (unsigned)((ram_pct % 100) / 10)); + UI_PrintStringSmallNormal(val, 49, 127, 5); + + already_printed = true; + break; + } +#endif +#ifdef ENABLE_FEAT_F4HWN_QRCODE + // Right zone: x=49..127 (79 px). QR centered at x=72..104. + // Capsule label above QR (small-font Inverse style at fb line 1). + if (page == p++) { + UI_PrintStringSmallNormalInverse("CODE", 74, 0, 1); + UI_DrawQRCode(false, 72, 28); + already_printed = true; + break; + } + if (page == p++) { + UI_PrintStringSmallNormalInverse("WIKI", 74, 0, 1); + UI_DrawQRCode(true, 72, 28); + already_printed = true; + break; + } #endif break; + } case MENU_RESET: strcpy(String, gSubMenu_RESET[gSubMenuSelection]); @@ -1364,8 +1416,8 @@ void UI_DisplayMenu(void) y = (small ? 3 : 2) - (lines / 2); - // only for SysInf - if(UI_MENU_GetCurrentMenuId() == MENU_VOL) + // only for SysInf, page 0 (identity); other pages own their layout + if(UI_MENU_GetCurrentMenuId() == MENU_VOL && gSubMenuSelection == 0) { sprintf(edit, "%u.%02uV %u%%", gBatteryVoltageAverage / 100, gBatteryVoltageAverage % 100, diff --git a/App/ui/welcome.c b/App/ui/welcome.c index 73c43c1b..eb585d09 100644 --- a/App/ui/welcome.c +++ b/App/ui/welcome.c @@ -115,6 +115,15 @@ static inline uint16_t pct_x100(uint32_t used, uint32_t total) { return (uint16_t)((used * 10000u) / total); // 7559 => 75.59% } + +void UI_GetMemPercents(uint16_t *flash_pct_x100, uint16_t *ram_pct_x100) +{ + uint32_t ram_used = 0; + uint32_t flash_used = 0; + build_usage(&ram_used, &flash_used); + if (flash_pct_x100) *flash_pct_x100 = pct_x100(flash_used, FLASH_SIZE_BYTES); + if (ram_pct_x100) *ram_pct_x100 = pct_x100(ram_used, RAM_SIZE_BYTES); +} #endif #ifdef ENABLE_FEAT_F4HWN_QRCODE @@ -146,80 +155,11 @@ static void QR_Draw(const uint8_t *bitmap, uint8_t size, uint8_t origin_x, uint8 } } -// Tiny-font capsule label drawn entirely inside the status line, mirroring the -// scan-list name pill (see status.c). Body uses 0x7F (bits 0..6 = 7 px tall), -// caps use 0x3E (bits 1..5 = 5 px tall) for rounded corners. -// Caller passes glyph_x = first glyph column. Capsule width = len*4 + 3 px. -static void DrawStatusCapsule(const char *text, uint8_t glyph_x) +void UI_DrawQRCode(bool wiki, uint8_t origin_x, uint8_t origin_y) { - const uint8_t len = (uint8_t)strlen(text); - if (len == 0) return; - - GUI_DisplaySmallest(text, glyph_x, 1, true, true); - - const uint8_t left_cap = (uint8_t)(glyph_x - 2u); - const uint8_t body_x0 = (uint8_t)(glyph_x - 1u); - const uint8_t body_x1 = (uint8_t)(glyph_x + (uint16_t)len * 4u - 1u); - const uint8_t right_cap = (uint8_t)(glyph_x + (uint16_t)len * 4u); - - gStatusLine[left_cap] ^= 0x3E; - for (uint8_t x = body_x0; x <= body_x1; x++) { - gStatusLine[x] ^= 0x7F; - } - gStatusLine[right_cap] ^= 0x3E; -} - -void UI_DisplayWelcomeQR(void) -{ - memset(gStatusLine, 0, sizeof(gStatusLine)); -#if defined(ENABLE_FEAT_F4HWN_CTR) || defined(ENABLE_FEAT_F4HWN_INV) - ST7565_ContrastAndInv(); -#endif - UI_DisplayClear(); - - // Capsule labels in the status line, same style as the scan-list name pill. - // Capsule width = 4*4 + 3 = 19 px → centered above each 33-px QR. - // glyph_x = QR_x + (33-19)/2 + 2 = QR_x + 9. - DrawStatusCapsule("CODE", 23); // 4 + 9 - DrawStatusCapsule("WIKI", 90); // 91 + 9 - - // Two QR codes (V4, 33x33) side by side, just below the status line. - // Left → repo : x=4..36, y=8..40 - // Right → wiki : x=91..123, y=8..40 - QR_Draw((const uint8_t *)BITMAP_QR_GitHub, 33, 14, 12); - QR_Draw((const uint8_t *)BITMAP_QR_GitHub_Wiki, 33, 81, 12); - - // "Open Source Firmware" tiny font at fb_y=42 → physical y=50..55, - // just above the MEM line (which is at physical y=58..63). - GUI_DisplaySmallest("OPEN SOURCE FIRMWARE", 24, 42, false, true); - -#ifdef ENABLE_FEAT_F4HWN_MEM - // FLASH + SRAM combined on the very bottom row, 3x5 tiny font (physical y=58..63). - { - char mem_line[32]; - uint32_t ram_used = 0; - uint32_t flash_used = 0; - build_usage(&ram_used, &flash_used); - - const uint16_t ram_pct = pct_x100(ram_used, RAM_SIZE_BYTES); - const uint16_t flash_pct = pct_x100(flash_used, FLASH_SIZE_BYTES); - - sprintf(mem_line, "FLASH %u.%02u %% - SRAM %u.%02u %%", - (unsigned)(flash_pct / 100), (unsigned)(flash_pct % 100), - (unsigned)(ram_pct / 100), (unsigned)(ram_pct % 100)); - - // 3x5 font, 4 px stride: 29 chars × 4 = 116 px → x=6 centers it. - // y=50 in framebuffer coords = physical y=58. - GUI_DisplaySmallest(mem_line, 6, 50, false, true); - } -#endif - - ST7565_BlitStatusLine(); - ST7565_BlitFullScreen(); - - #ifdef ENABLE_FEAT_F4HWN_SCREENSHOT - SCREENSHOT_Update(true); - #endif + QR_Draw(wiki ? (const uint8_t *)BITMAP_QR_GitHub_Wiki + : (const uint8_t *)BITMAP_QR_GitHub, + 33, origin_x, origin_y); } #endif diff --git a/App/ui/welcome.h b/App/ui/welcome.h index 54b76c64..0cfb26e2 100644 --- a/App/ui/welcome.h +++ b/App/ui/welcome.h @@ -17,10 +17,21 @@ #ifndef UI_WELCOME_H #define UI_WELCOME_H +#include +#include + void UI_DisplayReleaseKeys(void); void UI_DisplayWelcome(void); + #ifdef ENABLE_FEAT_F4HWN_QRCODE -void UI_DisplayWelcomeQR(void); +// Draw the embedded GitHub QR code (V4, 33x33) at (origin_x, origin_y). +// `wiki` selects the wiki URL bitmap, otherwise the repo URL bitmap. +void UI_DrawQRCode(bool wiki, uint8_t origin_x, uint8_t origin_y); +#endif + +#ifdef ENABLE_FEAT_F4HWN_MEM +// Compute current FLASH and SRAM usage as percentages × 100 (e.g. 7559 = 75.59%). +void UI_GetMemPercents(uint16_t *flash_pct_x100, uint16_t *ram_pct_x100); #endif #endif