Bufferless e-paper

Introduction

E-paper displays come in many forms, both in terms of size and how the pixels are controlled. For this article I'm going to focus on the less expensive serial interface type (SPI bus) which have a built-in controller (COG = controller on glass) and come with their own framebuffer memory. Since the panel itself has the necessary memory to hold all of the pixels it displays, it's possible to do quite a lot without needing any RAM on the MCU side. For those familiar with OLED displays like the popular 128x64 SSD1306, the memory of these e-paper panels can be managed in a similar way.

Bufferless Limitations

Working without a local copy of the graphics presents some challenges. You can define a memory window (a smaller rectangle of the display) of any number of bytes (not pixels). This means that in one direction, you only have access to 8 pixels at a time, since the memory planes are each 1-bit per pixel, packed 8 to a byte. Some e-paper controllers allow you to read the contents of the framebuffer, but doing so is usually not possible due to the way the SPI interface works (the MOSI signal would need to be bidirectional) and is certainly impractical because for each change, you need to send multi-byte command sequences to define the memory window and plane number. Here's a more detailed example of why I say that it's impractical - suppose you want to draw a diagonal line one pixel wide. In order to not disturb the other 7 pixels that occupy each byte you'll need to send commands to define single byte memory windows for both reading and writing of each byte. This will slow access to a crawl. If time and power aren't an issue, then this can work. So, for practical purposes, without a local copy of the graphics, the e-paper memory is effectively "write-only". This means that for small MCUs with very little internal memory, it takes some planning to make good looking displays out of text and graphics primitives. Below is a photo of thin diagonal lines drawn in "write-only" mode. Where they touch the same bytes, they clobber each other.

Working against the grain?

The memory layout of the e-paper determines how you have to format and write your pixels. For the more popular controllers, the bytes are arranged parallel to the edge of the display with the controller chip (the white rubbery material which covers the controller). Most controllers allow you to flip the display 180 degrees and reverse the bit direction (from MSB on the left to MSB on the right), but not swap the x/y axes. Many color LCD controllers like the ILI9341 allow you to swap the x and y. Since you can't change the basic direction of the bytes, you're stuck arranging your data that way. In the case when you want to rotate your image 90 degrees, you have the option of looping over the lines of your source image and capturing one line of rotated pixels at a time to transmit to the e-paper. Again, this is certainly possible to do, but may exceed the time and energy of your project if you have to do it at run time. For my own e-paper projects, I pre-rotate fonts and images to match the memory direction when working in "bufferless" mode. Here's what happens when you don't rotate the graphics - in the photo below, the e-paper's memory is arranged with byte 0,0 in the upper right corner and byte 15,0 in the lower right corner. The Y=0 row is on the right and Y=295 row is on the left. To make the letters look correct for a landscape reading orientation, the font images need to be rotated 90 or 270 degrees. You could of course rotate the letters at run-time, but that requires memory and the whole point of working this way it to avoid needing local RAM.


Why work with one hand tied behind your back?

The motivation for this project was a search for cost and power reduction. I've created many epaper projects with the ESP32 (various). The ESP32 family of MCUs is powerful and impressive for the cost, and very capable of doing a wide range of tasks with e-paper. It has plenty of RAM, fast CPU(s) and wireless (WiFi/BLE) capabilities. One downside to those MCUs is that they're not optimized for really low power applications. It's possible to get the current consumption low in deep sleep if waking from an internal timer, but upon wakeup there is a huge current spike and even on their newest, most efficient model, a small task takes a significant amount of energy. Super low power MCUs have been in existence for many years, but they usually come in two flavors: super expensive (e.g. NXP's various "L" series) or are so simple that they're too 'wimpy' and programming them is pure frustration (e.g. 8051 based models). I wanted to test running "more interesting" e-paper projects on 'wimpy' MCUs.

ESP32 ULP?

The ESP32 has been including a ULP (ultra low power CPU) inside most of its MCUs for a couple of years now. Part of this e-paper idea was to see if I could run a complete project from the ESP32's ULP. Different ESP32s have different ULPs, but the latest generation is a full RISC-V CPU. The newest and most capable one is found in the ESP32-C6. It's a 20MHz RISC-V with 16K of RAM (the RTC RAM shared by the ESP32 main CPU). My test project is an e-paper clock/calender which updates the time every minute. When run on the ESP32-C6 main CPU and taking care to sleep during idle periods (and when the e-paper is updating), I couldn't get the average power below 2mA. The ULP in the C6 doing the same job averages about 150uA. That doesn't sound half bad until you learn that the nearly 30 year old ATMega MCU can do the same job in 41uA. Here's the clock running on the ATMega328 (Arduino Pro Mini). It's running from a CR2450 coil cell and should last more than a year.
This is part of the reason I'm working on an e-paper library for MCUs with nearly no RAM. In the project above, the panel is a 4.2" 400x300 (15K framebuffer) being controlled by the AVR. With less than 1K of RAM used for stack, structures, variables and temporary buffers, it's able to use 2 font sizes (78pt and 38pt) and do partial (non-flashing) updates on the panel every minute.

So now that you know the why and how, you're probably wondering about the 'where can I get it?' part...I'm still testing and documenting this code. It will be ready in the near future and if you're reading this, you'll know when I release it.

Comments

Popular posts from this blog

Surprise! ESP32-S3 has (a few) SIMD instructions

How much current do OLED displays use?

Fast SSD1306 OLED drawing with I2C bit banging