Displays with driver subclassed from framebuf

Discuss development of drivers for external hardware and components, such as LCD screens, sensors, motor drivers, etc.
Target audience: Users and developers of drivers.
User avatar
mcauser
Posts: 507
Joined: Mon Jun 15, 2015 8:03 am

Re: Seeking display with driver subclassed from framebuf

Post by mcauser » Thu Aug 23, 2018 6:41 am

Have you seen @deshipu 's driver for the SSD1331 display?
It doesn't extend the framebuf, but may provide some inspiration.
https://bitbucket.org/thesheep/micropyt ... c/default/

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

SSD1331 driver: background

Post by pythoncoder » Thu Aug 23, 2018 8:04 am

I hadn't spotted that one. I based mine on Adafruit's driver. Porting it to MicroPython was straightforward.

My Writer class for displaying arbitrary fonts was originally a proof of concept for SSD1306 only, but sufficient people were using it as-is (and reporting its limitations) that I decided to make it a practical solution. One aim is that it should "just work" with any display driver, monochrome or colour, which is
  • Subclassed from framebuf.
  • Provides height and width bound variables.
Having done this, I wanted to test it. The following have tested fine:
  • Official SSD1306 monochrome driver.
  • Your PCD8544 (Nokia) monochrome driver pcd8544_fb.py.
  • My SSD1331 colour driver.
Peter Hinch
Index to my micropython libraries.

User avatar
mcauser
Posts: 507
Joined: Mon Jun 15, 2015 8:03 am

Re: Seeking display with driver subclassed from framebuf

Post by mcauser » Thu Aug 23, 2018 11:28 pm

Another set of display drivers in my collection are the Waveshare epaper displays.
https://github.com/mcauser/micropython- ... ld/test.py
https://github.com/mcauser/micropython- ... ld/test.py

I'm not subclassing the FrameBuffer, instead using one in the examples. I could add a Framebuf subclassed version, however, I only own 2 of the displays, so I can't test the other displays without help from others. Most of the panels feature 2 memory areas which you can write to, so would need extra logic in the show() method to know which to draw to.

The repo includes drivers for each of the 14 Waveshare displays, currently with a lot of code duplication as so far I've only simply ported the Waveshare Raspi Python examples to MicroPython so they could run on my STM32 boards. Later I'll restructure them with common ancestors and clean it all up.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

A colour display driver in ~35 lines

Post by pythoncoder » Fri Aug 24, 2018 7:36 am

You've written a lot more MicroPython display drivers than me ;)

The recent ability to subclass framebuf strikes me as powerful, at least for small displays and for those which don't have their own frame buffer (like many EPD's). My SSD1331 driver provides graphics primitives courtesy of framebuf. It can render text in arbitrary fonts in colour via the CWriter class. It does this in ~35 lines of code. The fact that we can now do this strikes me as remarkable.

The SSD1331 has its own frame buffer so we could write a better driver than this one, which merely updates the framebuf then chucks the whole thing at the device. To save RAM it uses 8-bit colour. An improved driver would use less RAM, offer 16-bit colour and be much faster. However to provide the same functionality using the device's frame buffer would need considerably (10x?) more code, and for basic information displays I doubt the speed gain would be noticeable.
Peter Hinch
Index to my micropython libraries.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Colour OLED display drivers

Post by pythoncoder » Fri Sep 07, 2018 9:46 am

I've posted drivers for SSD1331 displays (Adafruit 0.96 inch OLED) and SSD1351 (Adafruit 1.27 inch and 1.5 inch) colour OLED's). These are based on framebuf and use 8-bit colour to minimise the buffer size. Buffer sizes are 6144, 12288 and 16384 bytes respectively. These are large but manageable on a Pyboard. Display update time for the largest display is 41ms.

On SSD1351 units colours are mapped to 16-bit on the fly as the chip lacks native support for 8-bit colour. This is done in assembler. Using the standard bytecode emitter an update takes 270ms because of the overhead of this mapping. A portable driver is offered, but expect rather languid performance.

The drivers may be found in this repo.

If anyone has the 1.27 inch display and is interested in driver design there is a piece of code commented as "daft". I'd very much like to know how to set the RAM address rather than incrementing it, but all my attempts failed. It wouldn't improve performance much, but it would set my mind at rest. ;)
Peter Hinch
Index to my micropython libraries.

zieglef1
Posts: 1
Joined: Fri Jul 26, 2019 12:55 pm

Re: Displays with driver subclassed from framebuf

Post by zieglef1 » Fri Jul 26, 2019 1:28 pm

I recently purchased an 1.5" OLED with 128*128 pixels. The driver IC is a SSD1351 with SPI interface. Looking for an appropriate micropython driver I found pythoncoders driver within his nano-gui project. Astonishingly this worked immediately together with an ESP32 module. The behaviour looked a bit strange when updating the display content, so I had a closer look at the code and at the SSD1351 data sheet. I wanted to play with the parameters of the SET_REMAP command and recognised, that none of my changes had any effect on the display. Then I found a small notice on top of the command list, that with multibyte commands only the first byte has to be sent to the driver with the command/data line set to LOW. The subsequent bytes, if any, have to be sent with the command/data line set to HIGH. After changing the code to accomplish this, the display still worked fine and I was able to change parameters and watch the effects. Since the display itself is different from the Adafruit one, and by the way it is much cheaper, I was able to change the colour sequence, contrast levels. Especially the data transfer to the display RAM is now much simpler because of its straight forward pin mapping.

User avatar
mcauser
Posts: 507
Joined: Mon Jun 15, 2015 8:03 am

Re: Displays with driver subclassed from framebuf

Post by mcauser » Fri Aug 23, 2019 9:59 am

With all this talk of creating display drivers in C...
Can one written in C subclass the Framebuf?

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Displays with driver subclassed from framebuf

Post by jimmo » Fri Aug 23, 2019 1:54 pm

mcauser wrote:
Fri Aug 23, 2019 9:59 am
With all this talk of creating display drivers in C...
Can one written in C subclass the Framebuf?
Yes.

When you create a type, you specify its base type. Most use `mp_type_type` as their base, but you could use `mp_type_framebuf`.

This is currently "private" (i.e. static) to modframebuf.c, but could be moved to (a hypothetical) modframebuf.h.

User avatar
mattyt
Posts: 410
Joined: Mon Jan 23, 2017 6:39 am

Re: Displays with driver subclassed from framebuf

Post by mattyt » Sat Aug 24, 2019 1:58 pm

The purist in me has always found the derivation from framebuf a bit...awkward.

Wouldn't it be better if the driver contained a framebuf? It's less tightly coupled and describes the relationship more correctly. Doesn't it? What are the benefits of inheritance here?

User avatar
jimmo
Posts: 2754
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia
Contact:

Re: Displays with driver subclassed from framebuf

Post by jimmo » Sun Aug 25, 2019 4:45 am

mattyt wrote:
Sat Aug 24, 2019 1:58 pm
The purist in me has always found the derivation from framebuf a bit...awkward.
Yeah I agree, does feel like a violation of the LSP.
mattyt wrote:
Sat Aug 24, 2019 1:58 pm
Wouldn't it be better if the driver contained a framebuf? It's less tightly coupled and describes the relationship more correctly. Doesn't it? What are the benefits of inheritance here?
I imagine the initial reason was that they wanted all the methods of framebuf to be methods on display without the cost of writing a bunch of helpers. (iirc, before the inheriting-from-builtins worked correctly, it used to manually set up those forwards)?

Or possibly it was also to make it look like the existing supported displays (e.g. LCD160CR) that have built-in framebuffers.

I'd be inclined to suggest that the display should be completely decoupled from the framebuf altogether. Displays are just things that know how to render framebufs. And this simplifies things like allowing different framebufs on each frame (haha just kidding who has that kind of RAM to burn). But I'm not quite sure how to map that back to the LCD160CR.

Having taught this stuff to high school kids, I have found that it is nice to be able to forget that the framebuf exists -- you create a display and call `fill_rect` on the display. But then they get confused why they have to call disp.show() after making modifications to the framebuf. By separating the two it's really clear that modifying the framebuf doesn't modify the display, you call display.show(fb) when you've finished making the framebuf ready.

Post Reply