From b2ea27f506446bd2f6ce59e163a7591e624e1712 Mon Sep 17 00:00:00 2001 From: Me Here Date: Sun, 31 May 2026 22:28:44 -0500 Subject: [PATCH] pm-kit: minimal 0xB6 (no unlock) bracketed by DISP off/on for line count The 0xF0 extension unlock (gates gamma/power) was the likely blanker; 0xB6 is a basic command and needs no unlock. Strip to just DISPOFF -> 0xB6(480 lines) -> DISPON, the one change vs mipidsi's working-but-1/4 baseline. Co-Authored-By: Claude Opus 4.8 (1M context) --- rust/pm-kit/src/main.rs | 33 +++++++-------------------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/rust/pm-kit/src/main.rs b/rust/pm-kit/src/main.rs index b4894b0..773aa4f 100644 --- a/rust/pm-kit/src/main.rs +++ b/rust/pm-kit/src/main.rs @@ -79,37 +79,18 @@ fn main() -> ! { .init(&mut timer) .unwrap(); - // mipidsi's ST7796 model uses the ST7789 init (SLPOUT, MADCTL=0x48, INVON, COLMOD, NORON, - // DISPON — confirmed via the host initdump). It omits the ST7796 extension setup, and doing - // it *after* mipidsi's DISPON (on a live panel) blanks the screen. So replay the full, - // known-good CircuitPython st7796_init here, ending in its own DISPON. MADCTL stays 0x48, - // which is exactly what mipidsi's drawing already assumes — so draws map correctly. + // Minimal: mipidsi's plain init already lit the panel (milestone 2 showed content, just in a + // sub-region because the gate scan wasn't set to 480 lines). 0xB6 (Display Function Control) + // fixes the line count and is a BASIC command — it does NOT need the 0xF0 extension unlock + // (the unlock gates gamma/power, and was the likely blanker). Bracket it with DISP off/on so + // the scan is reconfigured while the display is off, the way CircuitPython does it. { let di = unsafe { display.dcs() }; - di.send_command(0x01, &[]).unwrap(); // SWRESET - timer.delay_ms(120); - di.send_command(0x11, &[]).unwrap(); // SLPOUT - timer.delay_ms(120); - di.send_command(0xF0, &[0xC3]).unwrap(); // unlock extension command set - di.send_command(0xF0, &[0x96]).unwrap(); - di.send_command(0x36, &[0x48]).unwrap(); // MADCTL (matches mipidsi orientation) - di.send_command(0x3A, &[0x55]).unwrap(); // COLMOD 16bpp - di.send_command(0xB4, &[0x01]).unwrap(); + di.send_command(0x28, &[]).unwrap(); // DISPOFF di.send_command(0xB6, &[0x80, 0x02, 0x3B]).unwrap(); // display function control: 480 lines - di.send_command(0xE8, &[0x40, 0x8A, 0x00, 0x00, 0x29, 0x19, 0xA5, 0x33]).unwrap(); - di.send_command(0xC1, &[0x06]).unwrap(); - di.send_command(0xC2, &[0xA7]).unwrap(); - di.send_command(0xC5, &[0x18]).unwrap(); - timer.delay_ms(120); - di.send_command(0xE0, &[0xF0, 0x09, 0x0B, 0x06, 0x04, 0x15, 0x2F, 0x54, 0x42, 0x3C, 0x17, 0x14, 0x18, 0x1B]).unwrap(); - di.send_command(0xE1, &[0xE0, 0x09, 0x0B, 0x06, 0x04, 0x03, 0x2B, 0x43, 0x42, 0x3B, 0x16, 0x14, 0x17, 0x1B]).unwrap(); - di.send_command(0xF0, &[0x3C]).unwrap(); // lock - di.send_command(0xF0, &[0x69]).unwrap(); - timer.delay_ms(120); - di.send_command(0x21, &[]).unwrap(); // INVON (INVERT_COLORS = true) di.send_command(0x29, &[]).unwrap(); // DISPON - timer.delay_ms(50); } + timer.delay_ms(50); // Same UI code the host simulator renders (rust/uisim → PNG). If this is wrong, the sim // shows it without the bench; if the sim is right but the panel is wrong, it's a controller