From a942f50b29bb15e91126ec934f7b3bf9af093a43 Mon Sep 17 00:00:00 2001 From: liquidraver <504870+liquidraver@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:44:57 +0100 Subject: [PATCH] M1 fixes --- zephcore/Kconfig | 2 +- zephcore/boards/common/repeater.conf | 5 --- .../nrf52840/thinknode_m1/thinknode_m1.dts | 11 ++++++- zephcore/helpers/ui/display.c | 32 +++++++++++++++---- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/zephcore/Kconfig b/zephcore/Kconfig index 1289d57..fc599f9 100644 --- a/zephcore/Kconfig +++ b/zephcore/Kconfig @@ -442,7 +442,7 @@ config ZEPHCORE_UI_DISPLAY config ZEPHCORE_UI_DISPLAY_AUTO_OFF_MS int "Display auto-off timeout (ms)" - default 15000 + default 10000 depends on ZEPHCORE_UI_DISPLAY help Time in milliseconds before the display turns off diff --git a/zephcore/boards/common/repeater.conf b/zephcore/boards/common/repeater.conf index e31612e..9eb404b 100644 --- a/zephcore/boards/common/repeater.conf +++ b/zephcore/boards/common/repeater.conf @@ -18,11 +18,6 @@ CONFIG_BT=n # for Ed25519 key generation, LoRa random delays, etc. CONFIG_ENTROPY_GENERATOR=y -# ========== Display ========== -# Fast sleep — repeater display is rarely needed, save power. -# Only user button wakes it (no LoRa RX wake, no flashing). -CONFIG_ZEPHCORE_UI_DISPLAY_AUTO_OFF_MS=5000 - # ========== USB CDC ========== # Custom USB init with 1200 baud touch detection for UF2 bootloader (nRF52 only). # ESP32 boards use usb_serial — this setting is ignored there. diff --git a/zephcore/boards/nrf52840/thinknode_m1/thinknode_m1.dts b/zephcore/boards/nrf52840/thinknode_m1/thinknode_m1.dts index 5a6dddf..a56c601 100644 --- a/zephcore/boards/nrf52840/thinknode_m1/thinknode_m1.dts +++ b/zephcore/boards/nrf52840/thinknode_m1/thinknode_m1.dts @@ -210,8 +210,17 @@ width = <200>; height = <200>; rotation = <0>; - gate-inverted; busy-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>; + + /* Use internal temperature sensor for OTP waveform selection. */ + tssv = <0x80>; + + /* OTP waveforms — no explicit LUT needed for SSD1681. + * border-waveform controls the 1-px border during refresh: + * full 0x05 = border follows source (clean full reset) + * partial 0x3c = Hi-Z (border held, no border flash) */ + full { border-waveform = <0x05>; }; + partial { border-waveform = <0x3c>; }; }; }; }; diff --git a/zephcore/helpers/ui/display.c b/zephcore/helpers/ui/display.c index 2cc49ed..9ee19a1 100644 --- a/zephcore/helpers/ui/display.c +++ b/zephcore/helpers/ui/display.c @@ -110,7 +110,17 @@ static int display_early_blank(void) dev = DEVICE_DT_GET_OR_NULL(DT_NODELABEL(ssd1306)); } if (dev && device_is_ready(dev)) { - display_blanking_on(dev); + /* EPD displays are bistable and already show clean white after + * driver init's full refresh. Calling blanking_on here would + * leave blanking_on=true so the subsequent blanking_off in + * mc_display_init() triggers an extra unnecessary full refresh. + * Skip blanking for EPD; OLED still needs it to hide stale VRAM. */ + struct display_capabilities caps; + + display_get_capabilities(dev, &caps); + if (!(caps.screen_info & SCREEN_INFO_EPD)) { + display_blanking_on(dev); + } } return 0; } @@ -150,8 +160,13 @@ int mc_display_init(void) LOG_INF("display: %ux%u%s", disp_width, disp_height, is_epd ? " (e-paper)" : ""); - /* Blank display before CFB init to hide stale VRAM */ - display_blanking_on(disp_dev); + /* OLED: blank before CFB init so stale VRAM isn't visible while we + * build the first frame. EPD: driver init already performed a clean + * full refresh — the panel shows white. Skip blanking to avoid the + * extra full refresh that blanking_off would trigger. */ + if (!is_epd) { + display_blanking_on(disp_dev); + } /* Initialize CFB */ int ret = cfb_framebuffer_init(disp_dev); @@ -191,11 +206,16 @@ int mc_display_init(void) * SSD1306 OLED reports MONO01 by default, which CFB now handles * correctly (white pixels on black background) without manual invert. */ - /* Push a blank frame to clear stale VRAM, then unblank. */ + /* Clear CPU-side framebuffer (zeroes the RAM buffer — no SPI transfer). */ cfb_framebuffer_clear(disp_dev, false); - cfb_framebuffer_finalize(disp_dev); - display_blanking_off(disp_dev); + /* OLED: push the blank frame to hardware and unblank. + * EPD: skip — the first ui_pages_render() will push real content via + * partial refresh (fast, no visible flash). */ + if (!is_epd) { + cfb_framebuffer_finalize(disp_dev); + display_blanking_off(disp_dev); + } backlight_set(true); disp_on = true; disp_initialized = true;