Flipping an OLED display

Hey everyone, in my project I’m using the SparkFun Flexible OLED and their provided library

I’m trying to rotate my display by 180°, so flip it horizontally and vertically. I’ve found that the library provides both a flipHorizontal and a flipVertical function, but I either don’t understand their intended behaviour or they don’t quite work. Instead of flipping / mirroring the content, the display just clears with flipVertical. flipHorizontal does nothing at all.
Here’s an example sketch (run from an Arduino Uno) and a gif of the output (my display already took some beating…). flipvertical
(I didn’t attach the graphics.h, as it just contains the macaque image as byte array, storing it in PROGMEM)

// Includes 
// ------------------------------------------------
// ------------------------------------------------
#include <SSD1320_OLED.h>
#include "graphics.h"       // stores all bitmap graphics

// pgmspace
#if (defined(__AVR__))
  #include <avr/pgmspace.h>
#else
  #include <pgmspace.h>
#endif


// Pins
// ------------------------------------------------
// ------------------------------------------------
#define OLED_CS 10          // Chip Select, OLED
#define OLED_RES 9          // Reset, OLED


// OLED Display Instance
SSD1320 flexibleOLED(OLED_CS, OLED_RES);

// Setup
// ------------------------------------------------
// ------------------------------------------------
void setup() {
    // Begin Serial for Debug
    Serial.begin(115200);

    pinMode(OLED_CS,OUTPUT);

    // Init OLED Display (Display is 160 wide, 32 high)
    flexibleOLED.begin(160, 32);

    // Load Graphic
    loadImage(macaque,sizeof(macaque));
}

// Main Loop 
// ------------------------------------------------  
// ------------------------------------------------
void loop() {
      delay(2000);
      flexibleOLED.flipVertical(true);
      delay(2000);
      flexibleOLED.flipVertical(false);
}

void loadImage(const unsigned char *image, int imageSize){
    flexibleOLED.setRowAddress(0);
    flexibleOLED.setColumnAddress(0);
    //Send the bytes from program memory to OLED display
    for (int i = 0 ; i < imageSize ; i++)
    {
      byte theByte = pgm_read_byte(image + i);
    
      flexibleOLED.data(theByte); //Write byte directly to display
    }
}

I don't know that library or screen, but in others it's pretty common that only sets how, what you draw to the screen, is actually printed. Aka, first you flip, then you draw.

Here are the functions in the library. I think you need to do some research into what those commands actually mean.

//** \brief Vertical flip.
  Flip the graphics on the OLED vertically.
*/
void SSD1320::flipVertical(boolean flip)
{
  if (flip)
  {
    command(COMSCANINC);
  }
  else
  {
    command(COMSCANDEC);
  }
}


/** \brief Horizontal flip.
    Flip the graphics on the OLED horizontally.
*/
void SSD1320::flipHorizontal(boolean flip)
{
  if (flip)
  {
    command(SETSEGREMAP | 0x01); //Set the bit
  }
  else
  {
    command(SETSEGREMAP & ~0x01); //Clear the bit
  }
}

septillion:
I don't know that library or screen, but in others it's pretty common that only sets how, what you draw to the screen, is actually printed. Aka, first you flip, then you draw.

That's a good tip. Adapting my code in the main loop to

void loop() {
    delay(2000);
    flexibleOLED.flipHorizontal(true);
    loadImage(macaque,sizeof(macaque));
    delay(2000);
    flexibleOLED.flipHorizontal(false);
    loadImage(macaque,sizeof(macaque));
}

flips the image as expected. flipVertical tho still doesn't work.

johnwasser:
Here are the functions in the library. I think you need to do some research into what those commands actually mean.

Yes, I've already looked at that. As far as I understand, these functions send command bytes via SPI to the display, where COMSCANINC is 0xC0 for example. Those are defined in the .h file...

What that means or does is beyond me tho. I have no experience with such low level hardware programming, coming from a web dev perspective.

Maybe COMSCANDEC changes the order in which the lines are filled. Perhaps if you have the screen 'flipped' you have to start writing at the last line instead of the first. That would require letting loadImage() know that flexibleOLED.setRowAddress(); should be called with the address of the last row. Maybe add a startRowAddress to loadImage():

void loadImage(const unsigned char *image, int imageSize, int startRowAdress){
    flexibleOLED.setRowAddress(startRowAddress);

johnwasser:
Maybe COMSCANDEC changes the order in which the lines are filled. Perhaps if you have the screen 'flipped' you have to start writing at the last line instead of the first. That would require letting loadImage() know that flexibleOLED.setRowAddress(); should be called with the address of the last row. Maybe add a startRowAddress to loadImage():

I've tried that, with different rows: 0 / 16 / 32 / 48 / -16... (the display has 32 rows). It did not change. Digging through the data sheet I only found this:

.

For others with similar displays like the SSD1306 it seems to work just fine, no further work required. I'm still lost what might be the problem here.

anselmpaul:
I've tried that, with different rows: 0 / 16 / 32 / 48 / -16... (the display has 32 rows). It did not change. Digging through the data sheet I only found this:

For others with similar displays like the SSD1306 it seems to work just fine, no further work required. I'm still lost what might be the problem here.

According to that datasheet, it should have just worked.

1.1.15 Set COM Output Scan Direction (C0h/C8h) This command sets the scan direction of the COM output, allowing layout flexibility in the OLED module design. Additionally, the display will show once this command is issued. For example, if this command is sent during normal display then the graphic display will be vertically flipped immediately.