diff --git a/App/board.c b/App/board.c index b1b94efd..e6c62f9b 100644 --- a/App/board.c +++ b/App/board.c @@ -71,9 +71,18 @@ void BOARD_GPIO_Init(void) LL_GPIO_InitTypeDef InitStruct; LL_GPIO_StructInit(&InitStruct); InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - InitStruct.Pull = LL_GPIO_PULL_UP; InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH; + /* Keep the backlight dark from the first possible GPIO write. Its pin can + * otherwise float while the rest of the board GPIOs are being configured. */ + LL_GPIO_ResetOutputPin(GPIOF, LL_GPIO_PIN_8); + InitStruct.Mode = LL_GPIO_MODE_OUTPUT; + InitStruct.Pull = LL_GPIO_PULL_NO; + InitStruct.Pin = LL_GPIO_PIN_8; + LL_GPIO_Init(GPIOF, &InitStruct); + + InitStruct.Pull = LL_GPIO_PULL_UP; + // --------------------- // Input pins @@ -123,9 +132,8 @@ void BOARD_GPIO_Init(void) LL_GPIO_Init(GPIOF, &InitStruct); #endif - // Backlight: PF8 // BK4819 CS: PF9 - InitStruct.Pin = LL_GPIO_PIN_9 | LL_GPIO_PIN_8 ; + InitStruct.Pin = LL_GPIO_PIN_9; LL_GPIO_Init(GPIOF, &InitStruct); #ifndef ENABLE_SWD @@ -177,13 +185,14 @@ void BOARD_ADC_GetBatteryInfo(uint16_t *pVoltage, uint16_t *pCurrent) void BOARD_Init(void) { BOARD_GPIO_Init(); + /* Blank and initialise the LCD as soon as its GPIOs are available. */ + ST7565_Init(); BACKLIGHT_InitHardware(); BOARD_ADC_Init(); #ifdef ENABLE_VOICE VOICE_Init(); #endif PY25Q16_Init(); - ST7565_Init(); #ifdef ENABLE_FMRADIO BK1080_Init0(); #endif diff --git a/App/driver/st7565.c b/App/driver/st7565.c index 23d93e48..0736f43c 100644 --- a/App/driver/st7565.c +++ b/App/driver/st7565.c @@ -204,9 +204,11 @@ void ST7565_DrawLine(const unsigned int Column, const unsigned int Line, const u void ST7565_FillScreen(uint8_t value) { CS_Assert(); - for (unsigned i = 0; i < 8; i++) { - // TODO: This is wrong - DrawLine(0, i, NULL, value); + for (uint8_t line = 0; line < 8u; line++) { + ST7565_SelectColumnAndLine(4u, line); + A0_Set(); + for (uint8_t column = 0; column < LCD_WIDTH; column++) + SPI_WriteByte(value); } CS_Release(); } @@ -333,6 +335,10 @@ void ST7565_Init(void) SPI_Init(); ST7565_HardwareReset(); CS_Assert(); + + /* Hide the controller RAM immediately. On K1 there is no usable hardware + * reset pin, so its power-on contents can otherwise briefly reach the LCD. */ + ST7565_WriteByte(ST7565_CMD_DISPLAY_ON_OFF | 0); ST7565_WriteByte(ST7565_CMD_SOFTWARE_RESET); // software reset SYSTEM_DelayMs(120); @@ -354,13 +360,16 @@ void ST7565_Init(void) ST7565_WriteByte(ST7565_CMD_POWER_CIRCUIT | 0b111); // VB=1 VR=1 VF=1 SYSTEM_DelayMs(40); - - ST7565_WriteByte(ST7565_CMD_SET_START_LINE | 0); // line 0 - ST7565_WriteByte(ST7565_CMD_DISPLAY_ON_OFF | 1); // D=1 + ST7565_WriteByte(ST7565_CMD_SET_START_LINE | 0); // line 0 CS_Release(); + /* Clear all eight LCD RAM pages while the display is still disabled. */ ST7565_FillScreen(0x00); + + CS_Assert(); + ST7565_WriteByte(ST7565_CMD_DISPLAY_ON_OFF | 1); // D=1 + CS_Release(); } #ifdef ENABLE_FEAT_F4HWN_SLEEP diff --git a/App/ui/multiboot.c b/App/ui/multiboot.c index 4f14f7d8..9a733de7 100644 --- a/App/ui/multiboot.c +++ b/App/ui/multiboot.c @@ -229,9 +229,18 @@ static void mb_render_slots(uint8_t selected, ST7565_BlitFullScreen(); } -/* Both restore and initial Main backup use the exact same progress frame. - * Keep it out-of-line: each caller has different text, but duplicating the - * framebuffer setup and the two LCD blits only wastes MCU flash. */ +static void mb_draw_progress_outline(void) +{ + /* Same rounded outline and hatch pattern as the scan progress gauge. */ + gFrameBuffer[6][3] = 0x0Cu; + gFrameBuffer[6][4] = 0x12u; + gFrameBuffer[6][123] = 0x12u; + gFrameBuffer[6][124] = 0x0Cu; + for (uint8_t x = 5; x < 123u; x++) + gFrameBuffer[6][x] = 0x21u; +} + +/* Full progress frame used while restoring a firmware slot. */ __attribute__((noinline)) static void mb_prepare_progress_screen(const char *title, const char *detail) { @@ -240,14 +249,7 @@ __attribute__((noinline)) static void mb_prepare_progress_screen(const char *tit UI_PrintStringSmallNormal(title, 2, 126, 1); UI_PrintStringSmallNormal("DO NOT POWER OFF", 2, 126, 3); UI_PrintStringSmallNormal(detail, 2, 126, 5); - - /* Same rounded outline and hatch pattern as the scan progress gauge. */ - gFrameBuffer[6][3] = 0x0Cu; - gFrameBuffer[6][4] = 0x12u; - gFrameBuffer[6][123] = 0x12u; - gFrameBuffer[6][124] = 0x0Cu; - for (uint8_t x = 5; x < 123u; x++) - gFrameBuffer[6][x] = 0x21u; + mb_draw_progress_outline(); ST7565_BlitStatusLine(); ST7565_BlitFullScreen(); } @@ -265,7 +267,13 @@ static void mb_prepare_progress(uint8_t slot) * Flash-Firmware install, while the running firmware is copied into slot 0. */ static void mb_backup_prepare(void) { - mb_prepare_progress_screen("Saving Main", "Slot Main"); + UI_DisplayClear(); + UI_StatusClear(); + UI_PrintStringSmallNormal("Init Main", 2, 126, 1); + UI_PrintStringSmallNormal("DO NOT POWER OFF", 2, 126, 3); + mb_draw_progress_outline(); + ST7565_BlitStatusLine(); + ST7565_BlitFullScreen(); } static void mb_backup_progress(uint32_t done, uint32_t total) @@ -398,8 +406,8 @@ void UI_MultibootSelector(void) * multiboot (fresh radio, or a plain Flash-Firmware). */ static uint8_t mb_adopt_internal_as_main(void) { - BACKLIGHT_TurnOn(); mb_backup_prepare(); + BACKLIGHT_TurnOn(); if (MB_BackupInternalToSlot0(mb_backup_progress) == MB_OK) (void)MB_SetActiveProfile(MB_SLOT_BACKUP); return MB_SLOT_BACKUP;