From 3e6ecf82e6f95490ac6b6d73833cc2ab17ef49a2 Mon Sep 17 00:00:00 2001 From: Sadeep Madurange Date: Sat, 27 Dec 2025 18:58:31 +0800 Subject: E-reader & bumblebee. --- _site/feed.xml | 2 +- _site/index.html | 2 +- _site/log/bumblebee/index.html | 2 +- _site/log/e-reader/index.html | 141 +++++++++++++++++------------------------ _site/log/index.html | 2 +- _site/posts.xml | 2 +- _site/projects/index.html | 4 +- 7 files changed, 65 insertions(+), 90 deletions(-) (limited to '_site') diff --git a/_site/feed.xml b/_site/feed.xml index eee3cb4..2840acb 100644 --- a/_site/feed.xml +++ b/_site/feed.xml @@ -1 +1 @@ -Jekyll2025-12-27T18:35:47+08:00/feed.xmlASCIIMX | LogW. D. Sadeep MadurangeMatrix Rain: 2025 refactor2025-12-21T00:00:00+08:002025-12-21T00:00:00+08:00/log/matrix-digital-rainW. D. Sadeep MadurangeFingerprint door lock (LP)2025-08-18T00:00:00+08:002025-08-18T00:00:00+08:00/log/fpm-door-lock-lpW. D. Sadeep MadurangeHigh-side MOSFET switching2025-06-22T00:00:00+08:002025-06-22T00:00:00+08:00/log/mosfet-switchesW. D. Sadeep MadurangeATmega328P at 3.3V and 5V2025-06-10T00:00:00+08:002025-06-10T00:00:00+08:00/log/arduino-unoW. D. Sadeep MadurangeFingerprint door lock (RF)2025-06-05T00:00:00+08:002025-06-05T00:00:00+08:00/log/fpm-door-lock-rfW. D. Sadeep MadurangeBumblebee: browser automation2025-04-02T00:00:00+08:002025-04-02T00:00:00+08:00/log/bumblebeeW. D. Sadeep MadurangeATSAM3X8E bare-metal programming2024-09-16T00:00:00+08:002024-09-16T00:00:00+08:00/log/arduino-dueW. D. Sadeep MadurangeEtlas: e-paper dashboard2024-09-05T00:00:00+08:002024-09-05T00:00:00+08:00/log/etlasW. D. Sadeep MadurangeExperimental e-reader2023-10-24T00:00:00+08:002023-10-24T00:00:00+08:00/log/e-readerW. D. Sadeep MadurangeNeo4J A* search2018-03-06T00:00:00+08:002018-03-06T00:00:00+08:00/log/neo4j-a-star-searchW. D. Sadeep Madurange \ No newline at end of file +Jekyll2025-12-27T21:02:00+08:00/feed.xmlASCIIMX | LogW. D. Sadeep MadurangeMatrix Rain: 2025 refactor2025-12-21T00:00:00+08:002025-12-21T00:00:00+08:00/log/matrix-digital-rainW. D. Sadeep MadurangeFingerprint door lock (LP)2025-08-18T00:00:00+08:002025-08-18T00:00:00+08:00/log/fpm-door-lock-lpW. D. Sadeep MadurangeHigh-side MOSFET switching2025-06-22T00:00:00+08:002025-06-22T00:00:00+08:00/log/mosfet-switchesW. D. Sadeep MadurangeATmega328P at 3.3V and 5V2025-06-10T00:00:00+08:002025-06-10T00:00:00+08:00/log/arduino-unoW. D. Sadeep MadurangeFingerprint door lock (RF)2025-06-05T00:00:00+08:002025-06-05T00:00:00+08:00/log/fpm-door-lock-rfW. D. Sadeep MadurangeBumblebee: browser automation2025-04-02T00:00:00+08:002025-04-02T00:00:00+08:00/log/bumblebeeW. D. Sadeep MadurangeATSAM3X8E bare-metal programming2024-09-16T00:00:00+08:002024-09-16T00:00:00+08:00/log/arduino-dueW. D. Sadeep MadurangeEtlas: e-paper dashboard2024-09-05T00:00:00+08:002024-09-05T00:00:00+08:00/log/etlasW. D. Sadeep MadurangeESP32 e-reader prototype2023-10-24T00:00:00+08:002023-10-24T00:00:00+08:00/log/e-readerW. D. Sadeep MadurangeNeo4J A* search2018-03-06T00:00:00+08:002018-03-06T00:00:00+08:00/log/neo4j-a-star-searchW. D. Sadeep Madurange \ No newline at end of file diff --git a/_site/index.html b/_site/index.html index b544a60..24e96cf 100644 --- a/_site/index.html +++ b/_site/index.html @@ -160,7 +160,7 @@ - Experimental e-reader + ESP32 e-reader prototype diff --git a/_site/log/bumblebee/index.html b/_site/log/bumblebee/index.html index 2aebc2f..0962a27 100644 --- a/_site/log/bumblebee/index.html +++ b/_site/log/bumblebee/index.html @@ -74,7 +74,7 @@ raised → parsed into a token → insert to list → interpret event → look u instruction from a table → form instruction with event args → insert text to a parallel list → run both lists through optimizer → update Scintilla editor.

-

Problem: manual overriding via Scintilla editor mid-session causes the code +

Limitation: manual overriding via Scintilla editor mid-session causes the code list to go out of sync with the event list. Optimizer can’t handle this yet.

Note to self: need to rethink the event/text list data structures in the diff --git a/_site/log/e-reader/index.html b/_site/log/e-reader/index.html index 3d61417..3eef05d 100644 --- a/_site/log/e-reader/index.html +++ b/_site/log/e-reader/index.html @@ -2,12 +2,12 @@ - Experimental e-reader + ESP32 e-reader prototype - Experimental e-reader + ESP32 e-reader prototype @@ -41,94 +41,69 @@

-

EXPERIMENTAL E-READER

+

ESP32 E-READER PROTOTYPE

24 OCTOBER 2023

-

This project features an experimental e-reader powered by an ESP-WROOM-32 -development board and a 7.5-inch Waveshare -e-paper display built with the intention of learning about e-paper displays.

+

First project with e-paper displays and ESP32.

-

Introduction

- -

The prototype e-reader comprises an ESP32 microcontroller, an e-paper display -HAT, and three buttons: yellow, blue, and white for turning the page backwards, -forwards, and putting the device to sleep, respectively. The prototype does not -store books on the microcontroller. It streams books from a server over HTTP. -The e-reader employs RTC memory to record the reading progress between -sessions.

- -

The most formidable challenge when trying to build an e-reader with an ESP32 is -its limited memory and storage. My ESP-WROOM-32 has a total of 512KB of SRAM -and 4MB of flash memory, which the freeRTOS, ESP-IDF, and the e-reader -application must share. To put things into perspective, a Kindle Paperwhite has -at least 256MB of memory and 8GB of storage. That is 500x more memory than what -I’d have to work with.

- -

Despite its size, as microcontrollers go, ESP32 is a powerful system-on-a-chip -with a 160MHz dual-core processor and integrated WiFi. So, I thought it’d be -amusing to embrace the constraints and build my e-reader using a $5 MCU and the -power of C programming.

- -

The file format

- -

The file format dictates the complexity of the embedded software. So, I’ll -begin there. The e-reader works by downloading and rendering a rasterized -monochrome image of a page (a .ebm file).

- -

The EBM file contains a series of bitmaps, one for each page of the book. The -dimensions of each bitmap are equal to the size of the display. Each byte of -the bitmap encodes information for rendering eight pixels. For my display, -which has a resolution of 480x800, the bitmaps are laid out along 48KB -boundaries. This simple file format lends well to HTTP streaming, which is its -main advantage, as we will soon see.

- -

The pdftoebm.py script enclosed in the tarball at the end of the page converts -PDF documents to EBM files.

- -

How does it work?

- -

As the e-reader has no storage, it can’t store books locally. Instead, it -downloads pages of the EBM file over HTTP from the location pointed to by the -EBM_ARCH_URL setting in the Kconfig.projbuild file on demand. To read a -different book, we have to replace the old file with the new one or change the -EBM_ARCH_URL value. The latter requires us to recompile the embedded -software.

- -

Upon powering up, the e-reader checks the reading progress stored in the RTC -memory. It then downloads three pages (current, previous, and next) to a -circular buffer in DMA-capable memory. When the user turns a page by pressing a -button, one of the microprocessor’s two cores transfers it from the buffer to -the display over a Serial Peripheral Interface (SPI). The other downloads a new -page in the background. I used the ESP-IDF task API to schedule the two tasks -on different cores of the multicore processor to make the reader more -responsive.

- -

I designed the EBM format with HTTP streaming in mind. Since the pages are laid -out in the EBM file along predictable boundaries, the e-reader can request -pages by specifying the offset and the chunk size in the HTTP Range header. Any -web server will process this request without custom logic.

- -

Epilogue

- -

My fascination with e-paper began back in 2017, when I was tasked with -installing a few displays in a car park. Having no idea how they worked, I -remember watching the languid screens refresh like a Muggle witnessing magic. -This project was born out of that enduring curiosity and love of e-paper -technology.

- -

Why did I go to the trouble of building a rudimentary e-reader when I could -easily buy a more capable commercial e-reader? First of all, it’s to prove to -myself that I can. More importantly, there’s a quiet satisfaction to reading on -hardware you built yourself. You are no longer the powerless observer watching -the magic happen from the sidelines. You become the wizard who makes the -invisible particles swirl into form by whispering C to them. There’s only one -way to experience that.

- -

Files: source.tar.gz

+

ESP-WROOM-32, 7.5” Waveshare e-paper display, three buttons (prev/next/sleep).

+ +

No local storage—streams books over HTTP. RTC memory tracks reading progress +between sessions.

+ +

ESP32: 512KB SRAM, 4MB flash (shared with FreeRTOS, ESP-IDF). Not enough to +store books. Stream from webserver instead.

+ +

Custom EBM file format. Rasterized monochrome bitmaps, one per page (480x800). +One byte = 8 pixels. Pages on 48KB boundaries—HTTP Range requests work without +server logic. pdftoebm.py converts PDFs.

+ +

Circular buffer holds 3 pages (prev/current/next)–page table. Single-threaded +approach too slow—user input, SPI, and HTTP on one core causes lag.

+ +

Optimizations: pin the GPIO task (responding to user input and updating +display) to one core, pin the HTTP task to the other core.

+ +

Better, but system unresponsive during screen updates. Made SPI transfer async:

+ +
void epd_draw_async(const uint8_t *buf, size_t n)
+{
+    static spi_transaction_t t[3];
+
+    memset(&t[0], 0, sizeof(t[0])); 
+    t[0].length = 8;
+    t[0].tx_data[0] = 0x13;
+    t[0].user = (void*) 0; 
+    t[0].flags = SPI_TRANS_USE_TXDATA;
+
+    memset(&t[1], 0, sizeof(t[1])); 
+    t[1].length = 8 * n;
+    t[1].tx_buffer = buf;
+    t[1].user = (void*) 1; 
+
+    memset(&t[2], 0, sizeof(t[2])); 
+    t[2].length = 8;
+    t[2].tx_data[0] = 0x12;
+    t[2].user = (void*) 0; 
+    t[2].flags = SPI_TRANS_USE_TXDATA;
+
+    for (int i = 0; i < 3; i++)
+        spi_device_queue_trans(spi, &t[i], portMAX_DELAY);
+}
+
+ +

Much better. Squeeze a few more cycles by moving SPI buffer to DMA.

+ +

Can’t think of anything else.

+ +

Outcome: Works but limited. Led to Etlas.

+ +

Commit: +7f691c4

diff --git a/_site/log/index.html b/_site/log/index.html index 645a982..59582a7 100644 --- a/_site/log/index.html +++ b/_site/log/index.html @@ -150,7 +150,7 @@ - Experimental e-reader + ESP32 e-reader prototype