ThingPulse / esp8266-oled-ssd1306

Driver for the SSD1306 and SH1106 based 128x64, 128x32, 64x48 pixel OLED display running on ESP8266/ESP32
https://thingpulse.com
Other
2.03k stars 643 forks source link

how to flip the display between normal and flipvertical and back to normal during runtime? #129

Closed tofrnr closed 4 years ago

tofrnr commented 7 years ago

how is it possible to flip the display between normal orientation and flipvertical and back to normal? e.g., sth like the following, inserted at the top line of loop() ?

if (digitalRead(D2)==LOW) { display.flipScreenVertically(); } // by a permanent jumper or switch
else
if (digitalRead(D2)==HIGH) { display.defaultOrientation(); }

e.g., for ILI9341 TFTs there are functions like tft.rotate(x) or tft.setorientation(x) available, for x=0,1,2,3 to set TFT orientation.

CelliesProjects commented 7 years ago

I am running into the same issue here.

Maybe this thread is a step in the right direction? https://digistump.com/board/index.php?topic=1669.0

For now I made something like this:

...
bool OLEDflipped = false;  // false = OLED displays normally - true = OLED displays upside down
...
...
  OLED.init();
  OLED.clear();
  if ( OLEDflipped) {
    OLED.flipScreenVertically();
  }
...
...
webServer.on( "/api/flipoled", []() {
    OLEDflipped = !OLEDflipped;
    if ( !OLEDflipped ) {
      OLED.init();
    } else {
      OLED.flipScreenVertically();
    }
    webServer.send( 200, FPSTR( textplainHEADER ), OLEDflipped ? "OLED flipped" : "OLED normal" );
  });

Which would be for your piece of code

if (digitalRead(D2)==LOW) { display.flipScreenVertically(); } // by a permanent jumper or switch
else { display.init(); }

You can skip the second compare, because if D2 is not LOW then it can only be HIGH.

tofrnr commented 7 years ago

no, does not work:

if (digitalRead(D1)==LOW && !OLED_FLIPPED) { display.flipScreenVertically(); OLED_FLIPPED = true; }
  else {display.init(); OLED_FLIPPED = false; }

leads to perpetual MCU reset. So there should exist a function to flip there and back on the fly.

CelliesProjects commented 7 years ago

Maybe this will work

bool OLEDflipped = false;

setup(){
  display.init();
}

loop(){
  static bool PINstate = digitalRead(D1);
  if ( PINstate != OLEDflipped ){
    OLEDflipped = PINstate;
    OLEDflipped ? display.flipScreenVertically() : display.init();
  }
}
CelliesProjects commented 7 years ago

But I agree a function to flip the display from the lib would be preferable.

tofrnr commented 7 years ago

doesn't work as well

RudyFiero commented 7 years ago

The code below does the vertical flips. I am using a switch input here but on my target device I have an orientation sensor. (switch was easier to use for testing) I call the routine from in loop().

` void switchOrientation() {

switch5State = digitalRead(switch5);

if (switch5State != Orientation) { Orientation = switch5State; digitalWrite(led15, Orientation);

if (switch5State == 1)
{
  //COMSCANDEC 0xC8    SEGREMAP   0xA1          // Normal display
  Wire.beginTransmission(I2C_DISPLAY_ADDRESS);
  Wire.write(0x80);
  Wire.write(0xC8);
  Wire.endTransmission();

  Wire.beginTransmission(I2C_DISPLAY_ADDRESS);
  Wire.write(0x80);
  Wire.write(0xA1);
  Wire.endTransmission();

  ui.nextFrame();
}
else
{
  //Flipped
  //COMSCANINC 0xC0   SEGREMAP   0xA0
  Wire.beginTransmission(I2C_DISPLAY_ADDRESS);
  Wire.write(0x80);
  Wire.write(0xC0);
  Wire.endTransmission();

  Wire.beginTransmission(I2C_DISPLAY_ADDRESS);
  Wire.write(0x80);
  Wire.write(0xA0);
  Wire.endTransmission();

  ui.nextFrame();
}

} } ` This is a brute force method. I do ui.nextFrame(); to refresh the buffer. The overlay does not get updated until the end of the forced transition so it is a bit messy, but only for a brief time

I would have like to determine the current frame and then force a re-write of it but I couldn't find what the current frame was. And it looks like there is logic to prevent re-writing to the current frame, but I'm not certain about that.

The device I have is a small remote control that is battery operated. I wanted the display to reflect the orientation of the device.

espsmall

R0binBl00d commented 6 years ago

Had the same problem and found something great :-)

http://nerdclub-uk.blogspot.com/2016/03/adding-flip-function-to-adafruits.html

so now I can flip the display anytime at runtime with a simple click of a button:

display.clear();

  if(digitalRead(Button) == 1)
  {
    flip = !flip;
  }

  display.drawString(0, 0, text);

  if(flip)
  {
    display.flip();
  }
  // write the buffer to the display
  display.display();

(/Users/myself/Documents/Arduino/libraries/ESP8266_and_ESP32_Oled_Driver_for_SSD1306_display) In the OLEDDisplay.h file I added the single line (just below flipScreenVertically):

void flip();

And in the OLEDDisplay.cpp file, added the function: Since I am not using Adafruit Librarys, but ESP8266 Oled, I had to change the code a bit:

void OLEDDisplay::flip(void){ 
      // loop through every byte in the buffer and flip it vertically. 
      // Since the display draws 8 vertical bits (per byte) we can just flip each byte 
      // from MSB to LSB first 
      uint8_t t; 
      uint8_t p; 
      int byteCount=((DISPLAY_WIDTH*DISPLAY_HEIGHT/8)/2)-1;
      int bufferEnd = (DISPLAY_WIDTH*DISPLAY_HEIGHT/8)-1;
      for (uint16_t i=0; i<=byteCount; i++) { 
            p=0; 
            t=buffer[i]; 
            for(int j=0; j<=7; j++){ 
                  p=p << 1; 
                  if((t & 0x01)>0){ p=p|1;} 
                  t=t >> 1; 
            } 

            t=buffer[bufferEnd-i]; 
            buffer[bufferEnd-i]=p; 

            p=0; 
            for(int j=0; j<=7; j++){ 
                  p=p << 1; 
                  if((t & 0x01)>0){ p=p|1;} 
                  t=t >> 1; 
            } 
            buffer[i]=p; 
      } 
}
stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.