-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
extmod/modframebuf: add 24bit RGB support (RGB888) #3551
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
Conversation
770fa54
to
64cd93e
Compare
Thanks for the contribution. I think that such a format is a useful addition to have.
Did you have this in mind when writing the code, or was the main use of RGB888 for an LCD/OLED display?
Yes I agree it's best to keep these simple and common formats as fast as possible. One thing to discuss: RGB888 will introduce a similar issue re endianess as pointed out in #3536. The patch here has it as little endian, which at the very least should be documented. Is there a case for bigendian? Note that it would be equivalent to a little endian BGR888, and then what about all the other cases: RBG, GRB, GBR, BRG? |
As for the comment of the endianess of the 565 format: the framebuffer module should support one format, and re-ordering of the bytes can be done beforehand, if needed. If done in Python, performance may be bad however. At least, on ESP8266 and STM32 viper code can be used for that. |
The main use I saw was for neopixel based displays, such as the Pimoroni Unicorn HAT. But since I've done some work on the SenseHAT - that would be a good fit too. I haven't looked into LCD/OLED type displays. Now as for the Pimoroni HAT I've concluded that Neopixel based display may need in fact another framebuffer mapping - they are likely wired in a "meander" way instead of a grid:
So the odd number of rows are in reversed order then the even ones. This wiring makes also sense if someone decides to make a display out of neopixel strips (it avoids cabling running from the end-of row to the beginning of the next row). The SenseHAT is wired differently - the framebuffers contents can be transferred using I2C to a memory mapped address. That should be ok.
Since the framebuffer does not know about colours, "RGB" is meaningless. The WS2812B ("neopixel") based LEDs for example are GRB mapped. From that point of view a naming like "two-byte-per-pixel" and "three-byte-per-pixel" might be cleaner than RGB888, RGB565, and independant of the endianess. It wouldn't imply a color mapping. RBG, GRB, BRG mappings essentially lead to the same C-code (with the existing framebuffer approach - all are 3 byte mapping). Endianess can be handled by several means, depending on the application:
In the long term I'd very much like to see a standardized way of displaying text/color on different uPy applications, independant of the HW. But I see that this is a big challenge.
I can't see one - but of course I may have overlooked something. BTW i can provide a PR for the mapping for the "meander" type wiring - if anyone is interested in it :) |
Thanks @hoihu for the reply. It would be good to see some use-case for this for an LCD/OLED, but displays made of many RGB pixels would already justify to have such a format. As for the meandering pixel order: I think supporting that is out of scope because it's too niche, and it opens the door to needing to support heaps of other, similar formats. It could be supported by some fast conversion code written in assembler. |
ok no problem. Makes sense to set the number of variants as low as possible
that would be interesting to implement - however bound to a specific platform...
I'll try to check some of the display driver chips (SSDxxxx) for this. FYI reagarding neopixel displays & wiring: Adafruit mentions this "meandering" problem in their "neopixel Uberguide" https://cdn-learn.adafruit.com/downloads/pdf/adafruit-neopixel-uberguide.pdf p47 and ff. They call the wiring options "zickzack" (for meandering) and "progressive". I checked some of their products and it seems that newer products like the feather 4x8 neopixel shield https://www.adafruit.com/product/2945 are "progressive" style, e.g. would work with the current implementation. Whereas some of big flex matrix style displays are "zickzack" style, like https://www.adafruit.com/product/2294 Regarding colors: They mention that color rendering is sufficient with 16bit (565 mapping). As far as I understood, their GFX library is fixed to 16 bit, 565 color mapping. They then do a conversion to lift those values to a 888 mapping for 24 bit neopixels https://github.com/adafruit/Adafruit_NeoMatrix/blob/master/Adafruit_NeoMatrix.cpp#L64 . Probably not very efficient but seems to do the job. |
Here is a gist that demonstrates mirroring of framebuffer row data in viper notation: it works on a pimoroni unicorn HAT (which is wired in "zickzack" manner as described above). One thing to consider: Relative framebuf operations such as |
ec7165b
to
4b92136
Compare
4b92136
to
b6fd0a0
Compare
sorry for the noise on the build server.. it's not my git day it seems :) I've rebased to the current master and added a small note on endianness used. If anything is missing please let me know. |
I think this is a worthwhile feature for, e.g. APA102 and RGBW WS2812 LED strips. See #7253 for discussion about adding more modes to modframebuf. |
This adds support for 24bit RGB to the framebuf module, called RGB888 (following the naming convention of RGB565). This may be useful for neopixel based displays.
On the ESP8266 port it adds 340 Bytes of flash which is a lot.
Streamlining rgb888, rgb565 and gs8 support into generic functions would actually save flash. I've done this as an exercise on a separate branch and it reduced the size by 20 Bytes or 360 Bytes compared to this version.
But I believe the performance penalty for rgb565 and gs8 was probably too high so I stayed with the existing design pattern.