Skip to content

Fix the garbage appearing on last line of OLED#10975

Open
tonuonu wants to merge 2 commits intoiNavFlight:maintenance-9.xfrom
tonuonu:tonu
Open

Fix the garbage appearing on last line of OLED#10975
tonuonu wants to merge 2 commits intoiNavFlight:maintenance-9.xfrom
tonuonu:tonu

Conversation

@tonuonu
Copy link

@tonuonu tonuonu commented Jul 19, 2025

User description

Fixes issue #10765 where last line of OLED shown garbage.


PR Type

Bug fix


Description

This description is generated by an AI tool. It may have inaccuracies

  • Fixed OLED display garbage on last line

  • Improved page-by-page clearing method for all 8 pages

  • Added proper address reset after clearing operation


Diagram Walkthrough

flowchart LR
  A["Old Method"] --> B["Single loop 1024 iterations"]
  C["New Method"] --> D["8 pages loop"]
  D --> E["128 columns per page"]
  E --> F["Proper address reset"]
  B --> G["Garbage on last line"]
  F --> H["Clean display"]
Loading

File Walkthrough

Relevant files
Bug fix
display_ug2864hsweg01.c
Fix OLED clear function page addressing                                   

src/main/drivers/display_ug2864hsweg01.c

  • Replaced single 1024-iteration loop with proper 8-page clearing
  • Added page-by-page addressing for complete display coverage
  • Added address reset commands after clearing operation
  • Improved code comments for clarity
+18/-9   

@qodo-code-review
Copy link
Contributor

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
⚡ Recommended focus areas for review

Addressing Mode

The code sets horizontal addressing mode but then uses page addressing commands. This mixed addressing approach may not work correctly on all OLED controllers and could cause display issues.

i2c_OLED_send_cmd(0x20);              // Set Memory Addressing Mode
i2c_OLED_send_cmd(0x00);              // Set Memory Addressing Mode to Horizontal addressing mode

// Clear all 8 pages (0-7)
for (uint8_t page = 0; page < 8; page++) {
    i2c_OLED_send_cmd(0xb0 + page);   // set page address
Missing Command

The original code included display start line register command (0x40) which was removed. This command may be necessary for proper display initialization and its removal could affect display behavior.

void i2c_OLED_clear_display(void)
{
    i2c_OLED_send_cmd(0xa6);              // Set Normal Display
    i2c_OLED_send_cmd(0xae);              // Display OFF
    i2c_OLED_send_cmd(0x20);              // Set Memory Addressing Mode
    i2c_OLED_send_cmd(0x00);              // Set Memory Addressing Mode to Horizontal addressing mode

    // Clear all 8 pages (0-7)
    for (uint8_t page = 0; page < 8; page++) {
        i2c_OLED_send_cmd(0xb0 + page);   // set page address
        i2c_OLED_send_cmd(0x00);          // set low col address to 0
        i2c_OLED_send_cmd(0x10);          // set high col address to 0

        for (uint8_t col = 0; col < 128; col++) {
            i2c_OLED_send_byte(0x00);      // clear
        }
    }

    i2c_OLED_send_cmd(0xb0);              // Reset to page 0
    i2c_OLED_send_cmd(0x00);              // Reset low col address to 0
    i2c_OLED_send_cmd(0x10);              // Reset high col address to 0

    i2c_OLED_send_cmd(0x81);              // Setup CONTRAST CONTROL
    i2c_OLED_send_cmd(200);               // Contrast value
    i2c_OLED_send_cmd(0xaf);              // Display ON
}

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jul 19, 2025

PR Code Suggestions ✨

No code suggestions found for the PR.

@tonuonu
Copy link
Author

tonuonu commented Jul 19, 2025

There is also PR #10760 which in my opinion is not fixing root cause and possibly overwrites something wrong.

- Changed from horizontal (0x00) to page addressing mode (0x02) to match the page-by-page clearing approach
- Restored the display start line command (0x40) that was missing from the previous commit
- This ensures proper OLED initialization and prevents garbage on the last line
@tonuonu
Copy link
Author

tonuonu commented Jul 20, 2025

Fixed @qodo-merge-pro valid concerns.

@sensei-hacker
Copy link
Member

Which displays did you test this with, please?

The SSH1106 needs more data sent to it than the SSD1306. The SSD1306 just gets bytes for the pixels. The SSH1106 has memory for four extra columnsthat are not displayed.

For the SSH1106, we would send two blank columns, then the data you want displayed, then two more blank columns.

Any changes should be tested with both, please.

@b14ckyy b14ckyy added this to the 9.1 milestone Jan 18, 2026
@PCS-Hazak
Copy link

Tested this PR on hardware (SpeedyBee F7V3, SSD1306 128x64). The garbage line fix works — last row is clean. But we found two issues:

Issue 1: i2c_OLED_clear_display_quick() is not updated

This PR changes i2c_OLED_clear_display() to use page addressing mode (0x02) with page-by-page clearing, but i2c_OLED_clear_display_quick() is left unchanged. After init, the display is now in page addressing mode, so the existing flat 1024-byte loop in _quick() no longer works correctly — in page mode, the column pointer wraps within the same page after 128 bytes instead of advancing to the next page. This means _quick() only clears page 0 repeatedly and leaves pages 1-7 dirty.

_quick() is called by dashboardUpdate() on every page transition (welcome → status, disarmed → armed, etc.), so this affects normal operation. It needs the same page-by-page treatment as _clear_display().

Issue 2: DASHBOARD_ARMED_BITMAP broken by addressing mode change

showArmedPage() in dashboard.c calls bitmapDecompressAndShow() which writes 1024 bytes (128x64 RLE bitmap) sequentially using i2c_OLED_send_byte(). This code was written assuming horizontal addressing mode (0x00), where the SSD1306 auto-advances: after column 127 on page N, it moves to column 0 on page N+1.

After this PR, the display is left in page addressing mode (0x02) after clearing. In page mode there is no auto-page-advance — after column 127 the pointer wraps to column 0 on the same page. The bitmap overwrites itself on a single page and displays garbled.

The fix is to either:

  • (a) Set horizontal addressing mode (0x20, 0x00) before bitmap drawing and restore page mode after, or
  • (b) Have the clear functions restore horizontal addressing mode after clearing, since that's what all the existing drawing code expects

We went with (a) in our local build. Tested and confirmed both the garbage line fix AND the armed bitmap work correctly with this approach.

Re: @sensei-hacker's question about SSH1106 — we only have SSD1306 hardware, so can't verify SSH1106 behavior. The page addressing differences between SSD1306 and SSH1106 (132 vs 128 column memory) would be worth testing separately.

Hardware: SpeedyBee F7V3, SSD1306 0.96" 128x64 I2C OLED, iNav 9.0.1.

@sensei-hacker
Copy link
Member

The fix is to either

And also detect which chip is attached and send the right data for that chip. The three chips are not the same, of course.

@sensei-hacker sensei-hacker changed the base branch from master to maintenance-9.x March 7, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants