Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setRotation does not work #26

Open
marcmerlin opened this issue May 13, 2019 · 10 comments
Open

setRotation does not work #26

marcmerlin opened this issue May 13, 2019 · 10 comments

Comments

@marcmerlin
Copy link
Contributor

display.setRotation(1) does nothing and after issuing it, fonts get displayed in the same direction than with display.setRotation(0);

Example code:
https://github.com/adafruit/Adafruit-SSD1331-OLED-Driver-Library-for-Arduino/pull/24/files#diff-ef8b6e873f94e375375e7998b2b43ccdR483
yes, the code is a much longer demo but basically rotation just works with other backends this same demo was written on (actually the text scroll code is yours, from a bicolor 8x8 matrix I bought from you eons ago).
Seems that basically setRotation is not implemented at all

https://github.com/sumotoy/SSD_13XX claims to be a much faster fork that was originally started partially to fix the lack of rotation support.

@marcmerlin
Copy link
Contributor Author

To give credit where due, my code was taken from you here:
https://github.com/adafruit/Adafruit_LED_Backpack/blob/master/examples/matrix8x8/matrix8x8.ino#L101

@ladyada
Copy link
Member

ladyada commented May 13, 2019

i dont think we did rotation for this display because it doesnt have any 'smarts' about MADCTL? but you could try adding it manually in some way if you like!

@marcmerlin
Copy link
Contributor Author

Thanks for confirming @ladyada. 3 thoughts

  1. it would be helpful to add a Serial.println("Not supported") in backends that have methods that don't work?
  2. seems supportable as shown in this other driver https://github.com/sumotoy/SSD_13XX/blob/master/SSD_13XX.cpp#L650
  3. I'm currently working on a framebuffer overlay driver that supports RGB24 Neomatrix framebuffers with FastLED primitives and will map back to SSD1331 along with rotation. Will share when it's finished, but obviously this does not help smaller CPUs that lack the RAM to store the full FB.

@ladyada
Copy link
Member

ladyada commented May 13, 2019

wanna try adding support? that would be the best! @makermelissa can also try taking a look later, i think this was one of our first displays so we didn't have rotation support yet

@marcmerlin
Copy link
Contributor Author

marcmerlin commented May 27, 2019

So, I ended up fixing rotation one level higher, in my multi-API library that supports NeoMatrix, RGBPanels, and now SSD1331 offering GFX, FastLED, and LEDMatrix APIs:

Rotation is done between the virtual framebuffer and the SSD1331 when the frame is copied over:

  • FastLED_SPITFT_GFX(fb, 96, 64, 96, 64, ssd1331, 0) for unrotated
  • FastLED_SPITFT_GFX(fb, 64, 96, 96, 64, ssd1331, 1) for a 90 degree rotation

Using my library has a few advantages despite the obvious loss of RAM (i.e. you'll want an ESP8266, ESP32, teensy, etc...):

  1. compatibility with code that needs to re-read from the framebuffer (move pixels, dim pixels, etc)
  2. render pixel by pixel, but copy to the SSD1331 more efficiently by doing quicker SPI line level copies
  3. direct compatibility of your code between TFT SPI screns, FastLED and RGBPanels without any code changes

@PaintYourDragon
Copy link
Contributor

Rotation on non-MADCTL displays is typically brute-forced at the drawPixel() level (see Adafruit_SSD1306 for an example) and would be an appropriate place to handle it here.

@makermelissa
Copy link
Collaborator

It sounds like you got it working for your particular setup @marcmerlin. As @PaintYourDragon mentioned, it will probably need to be done using a brute-force method so that it will work the same as the other displays and play along nicely. It sounds like this feature is something you don't need added, so I will probably go ahead and add it, so I'm going to leave the issue open.

@marcmerlin
Copy link
Contributor Author

marcmerlin commented May 28, 2019

Thanks @makermelissa for the reply. Sorry that I wasn't very clear on what the intent of my reply, was.

@ladyada told me that she'd welcome a PR. I then went to work on my problem which was to extend my triple API support to more backends (GFX + the other 2) and in the process of doing so, realized that it was trivial for me to add rotation when copying from my framebuffer to your device driver.
As a result, I won't be looking at the driver guts on how to do it there, since I have no need for it. That said, having had a quick look, @PaintYourDragon 's suggestion is true for drawpixel, but it's more of a problem when you are using writePixels which expects a line to be a sequence of pixels in the right order. If your display is rotated, I'm no exactly sure how this can be done without having a translation framebuffer, which is what my code is effectively doing.
https://github.com/marcmerlin/FastLED_SPITFT_GFX/blob/5ac4db7cfdb4d185687ed188558a6cbd97ab4db2/FastLED_SPITFT_GFX.cpp#L39

So, as a summary

  1. if this is not really fixable in the core driver due to the writePixels problem, then people finding this issue can look at my framebuffer layer and be set that way
  2. more generally, I wanted to give you and others a pointer to my code since it solves problems than your lower level driver can't (mostly the issue of having a framebuffer you can read from and not just write to) while also offering faster speeds if you're using a lot of pixels as writing them a line at a time is faster than one pixel at a time in the benchmarks I did.
  3. and my abstraction layer takes care of the lower level hardware issues (frame flips like for RGBPanel, poke only vs poke and peek, and things like clear() missing in the SSD1331 due to the slowness it adds as well as the flickering you get if you don't do full frame copies, which my layer does. As a result, you can actually re-run exactly the same code between NeoMatrix, RGBPanel, and SSD1331 without changing a line of code, which sadly isn't as true if you are using the GFX layer only. For instance, when I ported my GFX hello world to SSD1331 ( Ported GFX Demo from NeoMatrix / RGBPanel to SD1331 #24 ), it wasn't very pretty and doesn't really work well without a bigger rewrite for anything that relied on screen clear, but with my layer, it works perfectly without any changes (only downside is the extra memory used for the framebuffer).

But back to this bug, you can decide if it's indeed achievable or not given the writePixels problems and leave it open or close accordingly.
If you're keen on putting a pointer to my layer in your SSD1331 tutorial and/or this project's README.md, I'm happy to send you a PR for that, but also understand if you're not interested.
Cheers.

@marcmerlin
Copy link
Contributor Author

@Patriboom
Copy link

With Arduino, they are 4 possibilities for rotation: 0, 1, 2, 3 with the command display.setRotation(x)
where x is one of

  • 0: 0º
  • 1: 90º
  • 2: 180º (half turn)
  • 3: 270º

You can refere to Adafruit rotating display

example


#Create object
Adafruit_SSD1306 myDisplay(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

setup() {
myDisplay.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
myDisplay.setTextColor(SSD1306_WHITE);
myDisplay.clearDisplay();
myDisplay.setRotation(2);   //Text will rotate by 180º
}

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

No branches or pull requests

5 participants