Auto-detect OLED controller type (SSD1306/SH1106/SH1107/SSD1309) - #11849
Open
sensei-hacker wants to merge 7 commits into
Open
Auto-detect OLED controller type (SSD1306/SH1106/SH1107/SSD1309)#11849sensei-hacker wants to merge 7 commits into
sensei-hacker wants to merge 7 commits into
Conversation
Detect OLED controller type by reading status register 0x00 during initialization. Based on ss_oled library detection algorithm. Detection identifies: - SSD1306: status bits 0x03 or 0x06 (most common 128x64/128x32) - SH1106: status bits 0x08 (132x64, needs +2 pixel X offset) - SH1107: status bits 0x07 or 0x0F (128x128 displays) Adds LOG_ERROR debug messages to show detection results for troubleshooting display issues. Note: Drawing code updates for SH1106 X offset still needed. Reference: https://github.com/bitbank2/ss_oled 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SH1106 controller has 132-column GDDRAM but only 128 are visible; the first 2 columns are hidden. Without the offset, text and graphics render shifted 2 pixels to the left and the rightmost 2 columns are written into the invisible region. Also fixes clearing on SH1106: it only supports page addressing mode and ignores the horizontal addressing mode command (0x20/0x00) used by the previous i2c_OLED_clear_display(). The old code only cleared one page on SH1106 instead of all 8. Changes: - i2c_OLED_set_xy: add +2 pixel column offset for SH1106 - i2c_OLED_set_line: add +2 pixel start column for SH1106 - i2c_OLED_clear_display: switch to page-by-page clear (works on all controllers); apply SH1106 column offset; remove horizontal mode cmd - i2c_OLED_clear_display_quick: same fix - detectOledController: downgrade informational LOG_ERROR to LOG_DEBUG; keep LOG_ERROR only for actual failure paths - ug2864hsweg01InitI2C: remove empty SH1106 init placeholder stub; downgrade status LOG_ERROR messages to LOG_DEBUG
ug2864hsweg01TestPattern() draws a double-outline rectangle: - col 0: outer border, col 1: gap, col 2: inner border - symmetric on the right side - 1-pixel horizontal lines at top (page 0 bit 0) and bottom (page 7 bit 7) Uses i2c_OLED_set_line() so the controller offset is applied transparently — the same code works on SSD1306 (offset 0) and SH1106 (offset 2). How to read it on hardware: Correct offset : outer border flush at screen edge, 1-px gap, inner border Offset off by 1 : one border merges or a gap doubles Offset off by 2 : outer border invisible (off the left edge of the display) Call once after ug2864hsweg01InitI2C() for hardware verification only. Do not call from production code.
Add I2C address probe in detectOledController() that reports which addresses ACK (0x3C and 0x3D) via LOG_DEBUG. Useful when diagnosing hardware issues without an I2C scanner — visible in bootlog after setting log_level=DEBUG and configuring a log serial port. Also: - AOCODARCH7DUAL: add USE_BOOTLOG 4096 for bootlog debugging - ORBITF435: USE_BOOTLOG 4096 already in previous commit - Revert "Bus device found" message back to LOG_DEBUG (was bumped to LOG_ERROR temporarily during hardware debugging session) - Mark ug2864hsweg01TestPattern() call in init as TODO: remove before PR Note: NAND flash (flash_w25n.c) had an unrelated local change that was intentionally excluded from this commit.
Remove the hardware-test-only test pattern call from init (was drawing a diagnostic rectangle on every boot) and the two targets' temporary USE_BOOTLOG additions used only to debug I2C detection on hardware without a scanner. Also note that SH1107 detection is unverified on real 128x128 hardware, since the geometry code still assumes the 128x64/8-page layout used by SSD1306/SH1106.
The prior cleanup commit removed the test-pattern call site but left the 85-line function itself dangling with no callers, plus a debug I2C probe (0x3C/0x3D) that ran on every boot and triggered a real bus reinit on the expected NAK, and several progress-narration log lines with no diagnostic value. Also collapses the four duplicated SH1106 column-offset checks into one helper.
This was referenced Sep 2, 2026
|
RAM / Flash usage vs. base branch — commit
See RAM/flash optimization guide for techniques to reduce usage. |
|
Test firmware build ready — commit Download firmware for PR #11849 247 targets built. Find your board's
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The OLED dashboard driver (
display_ug2864hsweg01.c) probes the connectedcontroller's status register at init and adjusts addressing/geometry to
match — instead of assuming SSD1306 for every board. SH1106 panels (132-wide
GDDRAM, only 128 visible) get the correct +2 pixel column offset applied
throughout, and clearing now uses page-by-page addressing since SH1106
doesn't support the horizontal addressing mode the old code relied on.
Supersedes #10975 and #10760, which worked around the same underlying
SH1106/garbage-on-last-line symptom without detecting the controller type.
Changes
detectOledController(): reads the status register, maps it toSSD1306 / SH1106 / SH1107 / SSD1309, falls back to SSD1306 (previous
behavior) on read failure or an unrecognized value
i2c_OLED_set_xy(),i2c_OLED_set_line(), and both clear functionsi2c_OLED_clear_display()/_quick()switched from a single horizontal-addressing write to page-by-page clearing for all controllers (required
by SH1106; harmless on SSD1306/SSD1309)
common_hardware.c: fixedbusRead()sending a spurious command bytebefore the status-register read (
DEVFLAGS_USE_RAW_REGISTERS)SH1107 detection works, but the geometry code still assumes the
128x64/8-page layout shared by SSD1306/SH1106 (
SCREEN_HEIGHTis fixed at64) — a true 128x128 SH1107 panel would only get its top half addressed.
Flagged in a code comment; untested, since I don't have SH1107 hardware.
Testing
displayed correctly (no offset/garbage issues)
SSD1306, displayed correctly
Code Review
Reviewed with inav-code-review agent; all CRITICAL/IMPORTANT findings
(leftover debug I2C probe with a real bus-reinit side effect, a dead
test-pattern function, duplicated offset logic) addressed before this PR.