Skip to content

Fix ssd1306 start line - #586

Merged
gatk555 merged 1 commit into
buserror:masterfrom
fefedefe-frog:fix-ssd1306-start-line
Aug 9, 2026
Merged

Fix ssd1306 start line#586
gatk555 merged 1 commit into
buserror:masterfrom
fefedefe-frog:fix-ssd1306-start-line

Conversation

@fefedefe-frog

@fefedefe-frog fefedefe-frog commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Fix SSD1306 start-line command decoding and full VRAM reset

While using simavr to simulate an ATmega32U4 project with an SSD1306 display driven by the U8g2 library over hardware SPI, I encountered two issues in the virtual SSD1306 part:

  1. Set Display Start Line commands in the 0x40..0x7F range were treated as multi-byte commands.
  2. The reset hook cleared only half of the VRAM buffer for a 128×64 display.

This two issue together caused the display to show its content incorrectly causing to shift horizzontally the content, and disallign half of it vertically:

Before the fix

Reproduction

A minimal reproduction can be created by setting up a PlatformIO or Arduino project using the U8g2 library with an SSD1306 128×64 display:

  • create a new Arduino/PlatformIO project;
  • add the U8g2 library;
  • configure it for an SSD1306 display over 4-wire SPI;
  • use a simple page-buffer rendering example that sends basic drawing commands.
  • simavr host program that loads the generated firmware, connects the virtual SSD1306 part, and displays its framebuffer

If you want to test faster, here the code(
reproduction_files.zip
) that i used as example for investigating and resolving this issues, the zip contain:

  • src/main.cpp: the source code made using Arduino IDE or PlatformIO
  • simulator/atmega32u4_test.c: source code used by simavr for emulating the atmega32u4
  • platformio.ini: configuration file if you want to use PlatformioIO
  • compiled_firmware/: folder that contain the the compiled firmware for the ATmega33U4 from the src/source main.cpp

Fix

Issue 1: incorrect Set Display Start Line decoding

According to the SSD1306 datasheet the Set Display Start Line command is encoded as a single byte. Fixed with:

  • Handle the complete 0x40..0x7F range as single-byte commands.
  • Remove SSD1306_VIRT_SET_LINE from the multi-byte command handling.

Issue 2: incomplete VRAM clearing on reset

The framebuffer is 1024 bytes for a 128×64 display, but the previous reset logic only cleared half of it.
Fix:

Clear the complete framebuffer using its actual size:

memset(part->vram, 0, sizeof(part->vram));

@gatk555

gatk555 commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator

The code changes look plausible, but you posted over 11 screens of bot drivel to support a three-line change! Please post a description and reproduction instructions that will not waste a reviewer's time.

@fefedefe-frog

Copy link
Copy Markdown
Contributor Author

Sorry, never done a pull request, so i asked wrongly an ai if it was good to put all that stuff, hope that now its better

@gatk555

gatk555 commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Thank you, that is better, but the link to the ZIP is also gone. Can you restore it, and include the AVR binary, as I do not use PlatformIO?

The change does improve the code, but in a way that does not seem useful. The incorrect parsing of that command is gone but the command still does nothing, so the only way it can really fix anything is if the command is used only to restate the default. Otherwise it just changes one bug to another.

Also, the data sheet does not mention resetting the VRAM. It might be better to fill with a pattern on reset so that display of uninitialised memory is clearly visible.

@fefedefe-frog

Copy link
Copy Markdown
Contributor Author

ok, i've added back the link to te zip file, i've also included the firmware.elf and firmware.hex files inside of it, if you intended that for "AVR binary"(btw the main.cpp file included is compatible with arduino ide, or any other ide like arduino, not only with platformIO).


The change does improve the code, but in a way that does not seem useful. The incorrect parsing of that command is gone but the command still does nothing, so the only way it can really fix anything is if the command is used only to restate the default. Otherwise it just changes one bug to another.

Yes, I understand that this change does not implement the effect of the Set Display Start Line command, the purpuse of the fix from my issue is only for correctly interpreter the command length as a single byte command(as the datasheet says), so the next command after "0x40..." will be readed correcly, i know that now(as before) the command is readed but not implemented at all, but my fix is only intended to fix the correct reading of the command after "0x40.."

Also, the data sheet does not mention resetting the VRAM. It might be better to fill with a pattern on reset so that display of uninitialised memory is clearly visible.

Just for specification, i've tested the vram fix only after solving the first problem, and initially i didn't know that the issue of the vertical shift, only on half of the display, was caused by the VRAM.

After some different try and error, the complete VRAM array initializzation removed that remaining artifact so i opted for using this solution.
I have not yet determined why the partially initialized buffer produced a vertical displacement affecting only one half of the display, and neither found why this bug occurred only if using the U8g2 lib (and not the example code of the SSD1306 of this repo), but, after testing this fix, saw that worked, and didn't affect the original example code present in the simavr repo (the test for the SSD1306) i opted to use the complete VRAM initialization as fix for the "half display vertical shift".
I agree that clearing the buffer to zero is only one possible modeling choice, since even the datasheet does not appear to define how the VRAM is initialized or setted after a reset, but the use of a patter can be another solution, probably the only important thing is that all the VRAM is filled, if is a pattern, or initialized to zero, i really don't know.

In the end:

  • I found this two issues only using the U8g2 lib (i'm gonna specify better this in the request above).
  • The example code of the SSD1306 present in the simavr repo worked both before and after the fixes (I tested the SSD1306 emulation only with that example code).
    So maybe U8g2 is pretty strict(or simply, send commands that are correct for the real hardware, but not for how they are implemented in the emulator), but i'm not really an expert in this, so take this last sentence as my personal ipothesis

@gatk555

gatk555 commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

That seems odd to me, but it is an improvement, so I can merge it. Can you squash it to one change, with at most a two-line description? Alternatively, I can do a squash merge, but that will put my name on your submission.

@fefedefe-frog
fefedefe-frog force-pushed the fix-ssd1306-start-line branch from 6984b06 to a2635cf Compare August 8, 2026 22:58
@fefedefe-frog

Copy link
Copy Markdown
Contributor Author

ok, I've squashed the changes to one, I hope that's correct, I've never made one before

@gatk555

gatk555 commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

It looks fine. Thanks, G.

@gatk555
gatk555 merged commit 9985961 into buserror:master Aug 9, 2026
8 checks passed
@fefedefe-frog
fefedefe-frog deleted the fix-ssd1306-start-line branch August 9, 2026 17:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants