I'm trying to get a display with CH1115 controller to work using SPI. The current situation is that the display works with my code just fine: I'm able to control it to write and display data. The problem is that for my purposes I need to flip the display both horizontally and vertically. Flipping horizontally works (segment re-map), but vertical does not (scan direction change).

Information on this chip online is fairly scarce - but it is very similar to the popular SSD1306 judging from the datasheets. CH1115 datasheet and SSD1306 datasheet.

According to the CH1115 datasheet (again, pretty much identical to SSD1306), the display can be flipped vertically and horizontally by using the following commands:

    1. Set Segment Re-map: (A0H - A1H) [page 32] -> horizontal flip
    1. Set Common Output Scan Direction: (C0H - C8H) [page 36] -> vertical flip

When I change the segment re-map, the display flips horizontally just fine. However, when I change the output scan direction (to flip it vertically), the display 'breaks': What happens is that the pixels seem to 'bleed' vertically. The lines always go all the way vertically across the entire screen, and have a varying brightness levels, some very dim, some slightly brighter, but all dimmer than full 'on' pixel before the flip.

Note that this is display does not support multiple brightness levels, so this is definitely something other than just 'garbage' being displayed from RAM due to incorrect locations etc.


Below I describe how I tested changing the scan direction - before that, two things from the datasheet which are relevant:

Change scan direction:

the display will have immediate effect once this command is issued. That is, if this command is sent during normal display, the graphic display will be vertically flipped

Turn entire display on:

  1. Set Entire Display OFF/ON: (A4H - A5H) Forcibly turns the entire display on regardless of the contents of the display data RAM.

To make sure that I'm not messing something up when sending the data to the RAM after changing the direction somehow, I first tested with the 'set entire display' command, which should work in every orientation as it bypasses the RAM altogether:

  1. Initialize the display
  2. Turn the entire display on (0xA5)
  3. The display turns fully on.
  4. Change scan direction.
  5. Display goes fully dark
  • If the scan direction is reversed back to normal, the display lights up fully again.

Similarly, I've tried with actual display RAM contents:

  1. Initialize the display
  2. Write data to display
  3. Display graphics show up correctly
  4. Change scan direction.
  5. The display 'breaks' - vertical lines of different intensities.

Finally, I've also tried setting the scan direction during the initialization (before display is on) - it does not work either. `

I'm at a loss here, so any suggestions as to what could be causing this are welcome, if anyone got this far. It seems very odd to me that the display works fine, but breaks after a single command issued exactly as per the datasheet - so I'm curious as to why changing scan direction could be causing such issues.

  • \$\begingroup\$ Which exact command you send from the 8 possible commands 0xC0 to 0xC7? \$\endgroup\$
    – Justme
    Sep 7, 2023 at 19:01
  • \$\begingroup\$ @Justme I send 0xC0 for normal direction and 0xC8 for 'flipped' direction. In datasheet this command is defined as [1100 D***] where D is to be set high or low to change direction, and *'s are "don't cares". So anything between 0xC0 (1100 0000) and 0xC7 (1100 0111) should be normal direction, and anything between 0xC8 (1100 1000) and 0xCF (1100 1111) should be flipped. Just now to test I've sent all 16 possible commands sequentially between 0xC0 and 0xCF: display works for first 8 (normal orientation), and its 'broken' for the remaining 8. \$\endgroup\$ Sep 8, 2023 at 8:33

2 Answers 2


I solved this changing the display offset parameter.

For normal display:

   OLED_SPI_Exchange(OLED_SEGREMAP);           // 0x0A
   OLED_SPI_Exchange(OLED_COMSCANINC);         // 0xC0

For reverse display:

   OLED_SPI_Exchange(OLED_SEGREMAP | 0x01);    // 0x0B
   OLED_SPI_Exchange(OLED_COMSCANINC | 0x08);  // 0xC8

In case someone, someday, somehow has a similar problem: the issue in my case was with the MUX ratio set during initialization of the display. The value which worked in normal scanning direction did not work when the scan direction was flipped.

Increasing the multiplex ratio (A8H command) solved the issue with flipping the image, but introduced some artefacts in form of faint vertical lines. This was fixed by adjusting the display clock/oscillator frequency (D5H command) and increasing the VCOM Deselect Level (DBH command).

The learning here is: just because init parameters work in one direction, does not mean they are correct for the entire display - especially when the display is smaller than the max supported resolution by the controller.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.