From ee88df71b8561012d8600f0bfebb895b05c2ce5e Mon Sep 17 00:00:00 2001 From: taco Date: Wed, 19 Aug 2026 09:34:12 +1000 Subject: [PATCH] refactored screen.c to allow other display sizes --- src/screen.c | 193 ++++++++++++++++++++++++++------------------------- 1 file changed, 97 insertions(+), 96 deletions(-) diff --git a/src/screen.c b/src/screen.c index 29543a5..5fef190 100644 --- a/src/screen.c +++ b/src/screen.c @@ -33,11 +33,10 @@ #include #include -// Overlap 4x chars by this much. -#define CHAR4_KERNING 3 - -// Width of a single 4x char, adjusted by kerning -#define CHAR4_KERNED_WIDTH (6 * 4 - CHAR4_KERNING) +// Size independent kerning +#define CHAR_ADV(n) (5 * (n) + 1) // cursor step between chars +#define CHAR_INK(n) (6 * (n)) // columns printch actually writes +#define TEXT_WIDTH(n, len) ((len) ? CHAR_ADV(n) * ((len) - 1) + CHAR_INK(n) : 0) #define COL0(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) #define COL(c) COL0((c >> 16) & 0xff, (c >> 8) & 0xff, c & 0xff) @@ -77,6 +76,56 @@ const uint16_t palette[] = { COL(0x000000), // 15 }; +// inital display-size agnostic hack +#ifndef SCREEN_BAR1_Y +#define SCREEN_BAR1_Y 0 +#endif +#ifndef SCREEN_BAR1_H +#define SCREEN_BAR1_H 52 +#endif + +#ifndef SCREEN_BAR2_Y +#define SCREEN_BAR2_Y 52 +#endif +#ifndef SCREEN_BAR2_H +#define SCREEN_BAR2_H 55 +#endif + +#ifndef SCREEN_BAR3_Y +#define SCREEN_BAR3_Y 107 +#endif +#ifndef SCREEN_BAR3_H +#define SCREEN_BAR3_H 14 +#endif +#ifndef fileLogo_X +#define fileLogo_X 0 +#endif +#ifndef arrowLogo_X +#define arrowLogo_X 65 +#endif +#ifndef pendriveLogo_X +#define pendriveLogo_X 129 +#endif +#ifndef DISPLAY_TITLE_Y +#define DISPLAY_TITLE_Y 5 +#endif +#ifndef UF2_VERSION_BASE_Y +#define UF2_VERSION_BASE_Y 40 +#endif +#ifndef BANNER_TEXT_X +#define BANNER_TEXT_X 23 +#endif +#ifndef BANNER_TEXT_Y +#define BANNER_TEXT_Y 110 +#endif +#ifndef BLE_OTA_Y +#define BLE_OTA_Y 65 +#endif +#ifndef FONT_SIZE_LARGE +#define FONT_SIZE_LARGE 4 +#endif + + // TODO only buffer partial screen to save SRAM // ESP32s2 can only statically allocated DRAM up to 160KB. // the remaining 160KB can only be allocated at runtime as heap. @@ -92,38 +141,16 @@ extern const uint8_t arrowLogo[]; // //--------------------------------------------------------------------+ -// print character with font size = 1 -static void printch(int x, int y, int color, const uint8_t* fnt) { - for (int i = 0; i < 6; ++i) { +// print character +static void printch(int x, int y, int color, const uint8_t* fnt, int size) { + for (int i = 0; i < 6 * size; ++i) { uint8_t* p = frame_buf + (x + i) * DISPLAY_HEIGHT + y; - uint8_t mask = 0x01; + uint8_t b = fnt[i / size]; for (int j = 0; j < 8; ++j) { - if (*fnt & mask) { - *p = color; + if (b & (1u << j)) { + for (int k = 0; k < size; ++k) p[k] = color; } - p++; - mask <<= 1; - } - fnt++; - } -} - -// print character with font size = 4 -static void printch4(int x, int y, int color, const uint8_t* fnt) { - for (int i = 0; i < 6 * 4; ++i) { - uint8_t* p = frame_buf + (x + i) * DISPLAY_HEIGHT + y; - uint8_t mask = 0x01; - for (int j = 0; j < 8; ++j) { - for (int k = 0; k < 4; ++k) { - if (*fnt & mask) { - *p = color; - } - p++; - } - mask <<= 1; - } - if ((i & 3) == 3) { - fnt++; + p += size; } } } @@ -175,45 +202,25 @@ static void printicon(int x, int y, int color, const uint8_t* icon) { } } -// print text with font size = 1 -static void print(int x, int y, int col, const char* text) { - int x0 = x; - while (*text) { - char c = *text++; - if (c == '\r') continue; - if (c == '\n') { - x = x0; - y += 10; - continue; - } - /* - if (x + 8 > DISPLAY_WIDTH) { - x = x0; - y += 10; - } - */ - if (c < ' ') c = '?'; - if (c >= 0x7f) c = '?'; - c -= ' '; - printch(x, y, col, &font8[c * 6]); - x += 6; - } -} - -// Print text with font size = 4 -static void print4(int x, int y, int color, const char* text) { +static void print(int x, int y, int color, const char* text, int size) { while (*text) { char c = *text++; c -= ' '; - printch4(x, y, color, &font8[c * 6]); - x += CHAR4_KERNED_WIDTH; - if (x + CHAR4_KERNED_WIDTH > DISPLAY_WIDTH) { + printch(x, y, color, &font8[c * 6], size); + x += CHAR_ADV(size); + if (x + CHAR_INK(size) > DISPLAY_WIDTH) { // Next char won't fit. return; } } } +static inline void print_centered(int y, int color, const char* text, int size) { + int len = (int) strlen(text); + int text_x = (DISPLAY_WIDTH - TEXT_WIDTH(size, len)) / 2; + print(text_x >= 0 ? text_x : 0, y, color, text, size); +} + //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ @@ -242,48 +249,42 @@ static void drawBar(int y, int h, int color) { // draw drag & drop screen void screen_draw_drag(void) { - drawBar(0, 52, COLOR_GREEN); - drawBar(52, 55, COLOR_BLUE); - drawBar(107, 14, COLOR_ORANGE); + drawBar(SCREEN_BAR1_Y, SCREEN_BAR1_H, COLOR_GREEN); + drawBar(SCREEN_BAR2_Y, SCREEN_BAR2_H, COLOR_BLUE); + drawBar(SCREEN_BAR3_Y, SCREEN_BAR3_H, COLOR_ORANGE); - // Center UF2_PRODUCT_NAME and UF2_VERSION_BASE. - int name_x = (DISPLAY_WIDTH - CHAR4_KERNED_WIDTH * (int) strlen(DISPLAY_TITLE)) / 2; - print4(name_x >= 0 ? name_x : 0, 5, COLOR_WHITE, DISPLAY_TITLE); - - int version_x = (DISPLAY_WIDTH - 6 * (int) strlen(UF2_VERSION_BASE)) / 2; - print(version_x >= 0 ? version_x : 0, 40, COLOR_PURPLE, UF2_VERSION_BASE); - - // TODO the reset should be center as well - print(23, 110, 1, BANNER_TEXT); + // Print title, version, banner. + print_centered(DISPLAY_TITLE_Y, COLOR_WHITE, DISPLAY_TITLE, FONT_SIZE_LARGE); + print_centered(UF2_VERSION_BASE_Y, COLOR_PURPLE, UF2_VERSION_BASE, 1); + print_centered(BANNER_TEXT_Y, COLOR_WHITE, BANNER_TEXT, 1); +#ifndef DRAG #define DRAG 70 +#endif +#ifndef DRAGX #define DRAGX 47 - printicon(DRAGX + 0, DRAG + 5, COLOR_WHITE, fileLogo); - printicon(DRAGX + 65, DRAG, COLOR_WHITE, arrowLogo); - printicon(DRAGX + 129, DRAG, COLOR_WHITE, pendriveLogo); - print(22, DRAG - 12, COLOR_WHITE, "firmware.uf2"); - print(160, DRAG - 12, COLOR_WHITE, UF2_VOLUME_LABEL); +#endif + printicon(DRAGX + fileLogo_X, DRAG + 5, COLOR_WHITE, fileLogo); + printicon(DRAGX + arrowLogo_X, DRAG, COLOR_WHITE, arrowLogo); + printicon(DRAGX + pendriveLogo_X, DRAG, COLOR_WHITE, pendriveLogo); + #ifndef NOLABELS + print(22, DRAG - 12, COLOR_WHITE, "firmware.uf2", 1); + print(160, DRAG - 12, COLOR_WHITE, UF2_VOLUME_LABEL, 1); + #endif // NOLABELS draw_screen(frame_buf); } void screen_draw_ble(void) { - drawBar(0, 52, COLOR_GREEN); - drawBar(52, 55, COLOR_BLUE); - drawBar(107, 14, COLOR_ORANGE); + drawBar(SCREEN_BAR1_Y, SCREEN_BAR1_H, COLOR_GREEN); + drawBar(SCREEN_BAR2_Y, SCREEN_BAR2_H, COLOR_BLUE); + drawBar(SCREEN_BAR3_Y, SCREEN_BAR3_H, COLOR_ORANGE); - // Center UF2_PRODUCT_NAME and UF2_VERSION_BASE. - int name_x = (DISPLAY_WIDTH - CHAR4_KERNED_WIDTH * (int) strlen(DISPLAY_TITLE)) / 2; - print4(name_x >= 0 ? name_x : 0, 5, COLOR_WHITE, DISPLAY_TITLE); - - int version_x = (DISPLAY_WIDTH - 6 * (int) strlen(UF2_VERSION_BASE)) / 2; - print(version_x >= 0 ? version_x : 0, 40, COLOR_PURPLE, UF2_VERSION_BASE); - - // TODO the reset should be center as well - print(23, 110, 1, BANNER_TEXT); - - int ble_x = (DISPLAY_WIDTH - CHAR4_KERNED_WIDTH * (int) strlen("BLE OTA")) / 2; - print4(ble_x >= 0 ? ble_x : 0, 65, COLOR_WHITE, "BLE OTA"); + // Print title, version, OTA, banner + print_centered(DISPLAY_TITLE_Y, COLOR_WHITE, DISPLAY_TITLE, FONT_SIZE_LARGE); + print_centered(UF2_VERSION_BASE_Y, COLOR_PURPLE, UF2_VERSION_BASE, 1); + print_centered(BLE_OTA_Y, COLOR_WHITE, "BLE OTA", FONT_SIZE_LARGE); + print_centered(BANNER_TEXT_Y, COLOR_WHITE, BANNER_TEXT, 1); draw_screen(frame_buf); }