diff --git a/MDUV380_firmware/application/include/hardware/HX8353E.h b/MDUV380_firmware/application/include/hardware/HX8353E.h index aaf272f..ea920e0 100644 --- a/MDUV380_firmware/application/include/hardware/HX8353E.h +++ b/MDUV380_firmware/application/include/hardware/HX8353E.h @@ -263,6 +263,11 @@ uint16_t displayConvertRGB888ToNative(uint32_t RGB888); void displaySetForegroundAndBackgroundColours(uint16_t fgColour, uint16_t bgColour); void displayGetForegroundAndBackgroundColours(uint16_t *fgColour, uint16_t *bgColour); +#if defined(HAS_COLOURS) +// Render a numeric string as 7-segment "LED" digits with dimmed inactive segments. +void displayDrawFrequencySevenSeg(int16_t x, int16_t y, int16_t cellW, int16_t cellH, const char *str, themeItem_t fgItem); +#endif + #if defined(HAS_COLOURS) void themeInitToDefaultValues(DayTime_t daytime, bool invert); void themeInit(bool SPIFlashAvailable); diff --git a/MDUV380_firmware/application/source/hardware/HX8353E_display.c b/MDUV380_firmware/application/source/hardware/HX8353E_display.c index 7c697ee..c723a1e 100644 --- a/MDUV380_firmware/application/source/hardware/HX8353E_display.c +++ b/MDUV380_firmware/application/source/hardware/HX8353E_display.c @@ -1063,6 +1063,77 @@ void displayFillRect(int16_t x, int16_t y, int16_t width, int16_t height, bool i } } +#if defined(HAS_COLOURS) +// --- 7-segment ("LED") number rendering ------------------------------------ +// Segment bitmask per digit 0-9. Bits: a=0x01 b=0x02 c=0x04 d=0x08 e=0x10 f=0x20 g=0x40 +// +// aaa +// f b +// f b +// ggg +// e c +// e c +// ddd +static const uint8_t sevenSegDigits[10] = +{ + 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F +}; + +// Draw one digit's 7 segments inside a w x h cell. Lit segments use litColour, +// the rest use dimColour, giving the "inactive segments faintly visible" look. +static void displayDrawSevenSegDigit(int16_t x, int16_t y, int16_t w, int16_t h, uint8_t seg, uint16_t litColour, uint16_t dimColour, uint16_t bgColour) +{ + int16_t t = (h > 20) ? 3 : 2; // segment thickness + int16_t midY = y + (h / 2); + int16_t vLen = (h / 2) - t; // vertical segment length + +#define SEG_COL(bit) displaySetForegroundAndBackgroundColours((((seg) & (bit)) ? litColour : dimColour), bgColour) + SEG_COL(0x01); displayFillRect(x + t, y, w - (2 * t), t, false); // a top + SEG_COL(0x02); displayFillRect(x + w - t, y + t, t, vLen, false); // b top-right + SEG_COL(0x04); displayFillRect(x + w - t, midY, t, vLen, false); // c bottom-right + SEG_COL(0x08); displayFillRect(x + t, y + h - t, w - (2 * t), t, false); // d bottom + SEG_COL(0x10); displayFillRect(x, midY, t, vLen, false); // e bottom-left + SEG_COL(0x20); displayFillRect(x, y + t, t, vLen, false); // f top-left + SEG_COL(0x40); displayFillRect(x + t, midY - (t / 2), w - (2 * t), t, false); // g middle +#undef SEG_COL +} + +// Render a numeric string (digits, '.', spaces) as 7-segment "LED" characters, +// one cellW-wide cell per character, using the given theme foreground colour lit +// and a dimmed version of it for the inactive segments. +void displayDrawFrequencySevenSeg(int16_t x, int16_t y, int16_t cellW, int16_t cellH, const char *str, themeItem_t fgItem) +{ + uint16_t litColour = themeItems[DAYTIME_CURRENT][fgItem]; + uint16_t bgColour = themeItems[DAYTIME_CURRENT][THEME_ITEM_BG]; + + // dimColour: same hue at ~3/8 intensity (round-trip through RGB888) so the + // inactive segments stay clearly visible without washing out the lit ones. + uint32_t rgb = PLATFORM_COLOUR_FORMAT_TO_RGB888(__builtin_bswap16(litColour)); + uint32_t dimRgb = (((((rgb >> 16) & 0xFF) * 3) / 8) << 16) | (((((rgb >> 8) & 0xFF) * 3) / 8) << 8) | ((((rgb) & 0xFF) * 3) / 8); + uint16_t dimColour = __builtin_bswap16(RGB888_TO_PLATFORM_COLOUR_FORMAT(dimRgb)); + + for (const char *p = str; *p != '\0'; p++) + { + if ((*p >= '0') && (*p <= '9')) + { + displayDrawSevenSegDigit(x, y, (cellW - 1), cellH, sevenSegDigits[*p - '0'], litColour, dimColour, bgColour); + x += cellW; + } + else if (*p == '.') + { + // The decimal point takes half a cell so the wide digits still fit. + displaySetForegroundAndBackgroundColours(litColour, bgColour); + displayFillRect((x + 1), (y + cellH - 3), 3, 3, false); + x += (cellW / 2); + } + else + { + x += cellW; + } + } +} +#endif // HAS_COLOURS + /* * */ diff --git a/MDUV380_firmware/application/source/user_interface/uiUtilities.c b/MDUV380_firmware/application/source/user_interface/uiUtilities.c index 1e9965c..03cd57e 100644 --- a/MDUV380_firmware/application/source/user_interface/uiUtilities.c +++ b/MDUV380_firmware/application/source/user_interface/uiUtilities.c @@ -2504,7 +2504,14 @@ void uiUtilityDisplayFrequency(uint8_t y, bool isTX, bool hasFocus, uint32_t fre // Frequency snprintf(buffer, SCREEN_LINE_BUFFER_SIZE, "%d.%05d", val_before_dp, val_after_dp); +#if defined(HAS_COLOURS) + // 7-segment "LED" style with faint inactive segments. Digits are wider than the + // normal font (12 px cells) to fill the space up to the "MHz" label. + displayDrawFrequencySevenSeg(FREQUENCY_X_POS, yFont3, 12, (displayFocusAndDblHeight ? (FONT_SIZE_3_HEIGHT * 2) : FONT_SIZE_3_HEIGHT), + buffer, (isTX ? THEME_ITEM_FG_TX_FREQ : THEME_ITEM_FG_RX_FREQ)); +#else displayPrintAtDoubleHeight(FREQUENCY_X_POS, yFont3, buffer, FONT_SIZE_3, displayFocusAndDblHeight); +#endif displayPrintAtDoubleHeight(DISPLAY_SIZE_X - (3 * 8), yFont3, "MHz", FONT_SIZE_3, displayFocusAndDblHeight); displayThemeResetToDefault();