adafruit / Adafruit-SSD1331-OLED-Driver-Library-for-Arduino

For 0.96" OLEDs in the Adafruit shop
http://www.adafruit.com/products/684
Other
100 stars 67 forks source link

setRotation does not work #26

Open marcmerlin opened 5 years ago

marcmerlin commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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:

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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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 ( https://github.com/adafruit/Adafruit-SSD1331-OLED-Driver-Library-for-Arduino/pull/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 commented 3 years ago

I just switched to https://github.com/moononournation/Arduino_GFX

and it seems that SSD1331 supports rotation. See https://github.com/moononournation/Arduino_GFX/blob/d3572d287e70395057e69f8c8be716e3ccec16c9/src/display/Arduino_SSD1331.cpp#L96

Patriboom commented 1 year ago

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

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º
}