diff options
| author | Sadeep Madurange <sadeep@asciimx.com> | 2025-12-27 18:58:31 +0800 |
|---|---|---|
| committer | Sadeep Madurange <sadeep@asciimx.com> | 2025-12-27 21:02:36 +0800 |
| commit | 3e6ecf82e6f95490ac6b6d73833cc2ab17ef49a2 (patch) | |
| tree | 9bf5d5284c4c88c94c20f37dcc2892a18db4d405 /_site | |
| parent | 15ab870972f3fbeeec24ae70f1eb2ad19bc0be11 (diff) | |
| download | www-3e6ecf82e6f95490ac6b6d73833cc2ab17ef49a2.tar.gz | |
E-reader & bumblebee.
Diffstat (limited to '_site')
| -rw-r--r-- | _site/feed.xml | 2 | ||||
| -rw-r--r-- | _site/index.html | 2 | ||||
| -rw-r--r-- | _site/log/bumblebee/index.html | 2 | ||||
| -rw-r--r-- | _site/log/e-reader/index.html | 141 | ||||
| -rw-r--r-- | _site/log/index.html | 2 | ||||
| -rw-r--r-- | _site/posts.xml | 2 | ||||
| -rw-r--r-- | _site/projects/index.html | 4 |
7 files changed, 65 insertions, 90 deletions
diff --git a/_site/feed.xml b/_site/feed.xml index eee3cb4..2840acb 100644 --- a/_site/feed.xml +++ b/_site/feed.xml @@ -1 +1 @@ -<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-12-27T18:35:47+08:00</updated><id>/feed.xml</id><title type="html">ASCIIMX | Log</title><author><name>W. D. Sadeep Madurange</name></author><entry><title type="html">Matrix Rain: 2025 refactor</title><link href="/log/matrix-digital-rain/" rel="alternate" type="text/html" title="Matrix Rain: 2025 refactor" /><published>2025-12-21T00:00:00+08:00</published><updated>2025-12-21T00:00:00+08:00</updated><id>/log/matrix-digital-rain</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[The 2022 version worked but had some loose ends. Unicode support was inflexible–couldn’t mix ASCII with Katakana; Phosphor decay was stored in a separate array when it should’ve been packed with RGB; Code was harder to read than it needed to be.]]></summary></entry><entry><title type="html">Fingerprint door lock (LP)</title><link href="/log/fpm-door-lock-lp/" rel="alternate" type="text/html" title="Fingerprint door lock (LP)" /><published>2025-08-18T00:00:00+08:00</published><updated>2025-08-18T00:00:00+08:00</updated><id>/log/fpm-door-lock-lp</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Second iteration of the RF door lock. Old version worked but drew too much quiescent current. Sensor and servo pulled 13.8mA and 4.6mA idle. Linear regulators were a disaster. Battery didn’t last 24 hours.]]></summary></entry><entry><title type="html">High-side MOSFET switching</title><link href="/log/mosfet-switches/" rel="alternate" type="text/html" title="High-side MOSFET switching" /><published>2025-06-22T00:00:00+08:00</published><updated>2025-06-22T00:00:00+08:00</updated><id>/log/mosfet-switches</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Needed low-power switching for the fingerprint door lock. Servo and FPM draw high quiescent current–had to cut power electronically during sleep. MOSFETs can do this.]]></summary></entry><entry><title type="html">ATmega328P at 3.3V and 5V</title><link href="/log/arduino-uno/" rel="alternate" type="text/html" title="ATmega328P at 3.3V and 5V" /><published>2025-06-10T00:00:00+08:00</published><updated>2025-06-10T00:00:00+08:00</updated><id>/log/arduino-uno</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Quick reference for wiring ATmega328P ICs at 5V and 3.3V. 5V uses 16MHz crystal, 3.3V uses 8MHz.]]></summary></entry><entry><title type="html">Fingerprint door lock (RF)</title><link href="/log/fpm-door-lock-rf/" rel="alternate" type="text/html" title="Fingerprint door lock (RF)" /><published>2025-06-05T00:00:00+08:00</published><updated>2025-06-05T00:00:00+08:00</updated><id>/log/fpm-door-lock-rf</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Wanted to unlock door with fingerprint, wirelessly to avoid drilling.]]></summary></entry><entry><title type="html">Bumblebee: browser automation</title><link href="/log/bumblebee/" rel="alternate" type="text/html" title="Bumblebee: browser automation" /><published>2025-04-02T00:00:00+08:00</published><updated>2025-04-02T00:00:00+08:00</updated><id>/log/bumblebee</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Built with Andy Zhang for an employer. Tool to automate web scraping script generation.]]></summary></entry><entry><title type="html">ATSAM3X8E bare-metal programming</title><link href="/log/arduino-due/" rel="alternate" type="text/html" title="ATSAM3X8E bare-metal programming" /><published>2024-09-16T00:00:00+08:00</published><updated>2024-09-16T00:00:00+08:00</updated><id>/log/arduino-due</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Notes on programming ATSAM3X8E chips (Arduino Due) without bootloader. Tested on OpenBSD.]]></summary></entry><entry><title type="html">Etlas: e-paper dashboard</title><link href="/log/etlas/" rel="alternate" type="text/html" title="Etlas: e-paper dashboard" /><published>2024-09-05T00:00:00+08:00</published><updated>2024-09-05T00:00:00+08:00</updated><id>/log/etlas</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Etlas is a news, stock market, and weather tracker powered by an ESP32 NodeMCU D1, featuring a 7.5-inch Waveshare e-paper display and a DHT22 sensor module.]]></summary></entry><entry><title type="html">Experimental e-reader</title><link href="/log/e-reader/" rel="alternate" type="text/html" title="Experimental e-reader" /><published>2023-10-24T00:00:00+08:00</published><updated>2023-10-24T00:00:00+08:00</updated><id>/log/e-reader</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[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.]]></summary></entry><entry><title type="html">Neo4J A* search</title><link href="/log/neo4j-a-star-search/" rel="alternate" type="text/html" title="Neo4J A* search" /><published>2018-03-06T00:00:00+08:00</published><updated>2018-03-06T00:00:00+08:00</updated><id>/log/neo4j-a-star-search</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Back in 2018, we used Neo4J graph database to track the movement of marine vessels. We were interested in the shortest path a ship could take through a network of about 13,000 route points. Graph theoretic algorithms provide optimal solutions to such problems, and the set of route points lends itself well to graph-based modelling.]]></summary></entry></feed>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-12-27T21:02:00+08:00</updated><id>/feed.xml</id><title type="html">ASCIIMX | Log</title><author><name>W. D. Sadeep Madurange</name></author><entry><title type="html">Matrix Rain: 2025 refactor</title><link href="/log/matrix-digital-rain/" rel="alternate" type="text/html" title="Matrix Rain: 2025 refactor" /><published>2025-12-21T00:00:00+08:00</published><updated>2025-12-21T00:00:00+08:00</updated><id>/log/matrix-digital-rain</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[The 2022 version worked but had some loose ends. Unicode support was inflexible–couldn’t mix ASCII with Katakana; Phosphor decay was stored in a separate array when it should’ve been packed with RGB; Code was harder to read than it needed to be.]]></summary></entry><entry><title type="html">Fingerprint door lock (LP)</title><link href="/log/fpm-door-lock-lp/" rel="alternate" type="text/html" title="Fingerprint door lock (LP)" /><published>2025-08-18T00:00:00+08:00</published><updated>2025-08-18T00:00:00+08:00</updated><id>/log/fpm-door-lock-lp</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Second iteration of the RF door lock. Old version worked but drew too much quiescent current. Sensor and servo pulled 13.8mA and 4.6mA idle. Linear regulators were a disaster. Battery didn’t last 24 hours.]]></summary></entry><entry><title type="html">High-side MOSFET switching</title><link href="/log/mosfet-switches/" rel="alternate" type="text/html" title="High-side MOSFET switching" /><published>2025-06-22T00:00:00+08:00</published><updated>2025-06-22T00:00:00+08:00</updated><id>/log/mosfet-switches</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Needed low-power switching for the fingerprint door lock. Servo and FPM draw high quiescent current–had to cut power electronically during sleep. MOSFETs can do this.]]></summary></entry><entry><title type="html">ATmega328P at 3.3V and 5V</title><link href="/log/arduino-uno/" rel="alternate" type="text/html" title="ATmega328P at 3.3V and 5V" /><published>2025-06-10T00:00:00+08:00</published><updated>2025-06-10T00:00:00+08:00</updated><id>/log/arduino-uno</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Quick reference for wiring ATmega328P ICs at 5V and 3.3V. 5V uses 16MHz crystal, 3.3V uses 8MHz.]]></summary></entry><entry><title type="html">Fingerprint door lock (RF)</title><link href="/log/fpm-door-lock-rf/" rel="alternate" type="text/html" title="Fingerprint door lock (RF)" /><published>2025-06-05T00:00:00+08:00</published><updated>2025-06-05T00:00:00+08:00</updated><id>/log/fpm-door-lock-rf</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Wanted to unlock door with fingerprint, wirelessly to avoid drilling.]]></summary></entry><entry><title type="html">Bumblebee: browser automation</title><link href="/log/bumblebee/" rel="alternate" type="text/html" title="Bumblebee: browser automation" /><published>2025-04-02T00:00:00+08:00</published><updated>2025-04-02T00:00:00+08:00</updated><id>/log/bumblebee</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Built with Andy Zhang for an employer. Tool to automate web scraping script generation.]]></summary></entry><entry><title type="html">ATSAM3X8E bare-metal programming</title><link href="/log/arduino-due/" rel="alternate" type="text/html" title="ATSAM3X8E bare-metal programming" /><published>2024-09-16T00:00:00+08:00</published><updated>2024-09-16T00:00:00+08:00</updated><id>/log/arduino-due</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Notes on programming ATSAM3X8E chips (Arduino Due) without bootloader. Tested on OpenBSD.]]></summary></entry><entry><title type="html">Etlas: e-paper dashboard</title><link href="/log/etlas/" rel="alternate" type="text/html" title="Etlas: e-paper dashboard" /><published>2024-09-05T00:00:00+08:00</published><updated>2024-09-05T00:00:00+08:00</updated><id>/log/etlas</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Etlas is a news, stock market, and weather tracker powered by an ESP32 NodeMCU D1, featuring a 7.5-inch Waveshare e-paper display and a DHT22 sensor module.]]></summary></entry><entry><title type="html">ESP32 e-reader prototype</title><link href="/log/e-reader/" rel="alternate" type="text/html" title="ESP32 e-reader prototype" /><published>2023-10-24T00:00:00+08:00</published><updated>2023-10-24T00:00:00+08:00</updated><id>/log/e-reader</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[First project with e-paper displays and ESP32.]]></summary></entry><entry><title type="html">Neo4J A* search</title><link href="/log/neo4j-a-star-search/" rel="alternate" type="text/html" title="Neo4J A* search" /><published>2018-03-06T00:00:00+08:00</published><updated>2018-03-06T00:00:00+08:00</updated><id>/log/neo4j-a-star-search</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Back in 2018, we used Neo4J graph database to track the movement of marine vessels. We were interested in the shortest path a ship could take through a network of about 13,000 route points. Graph theoretic algorithms provide optimal solutions to such problems, and the set of route points lends itself well to graph-based modelling.]]></summary></entry></feed>
\ 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 @@ <tr> <td class="posts-td posts-td-link"> - <a href="/log/e-reader/" class="link-decor-none">Experimental e-reader</a> + <a href="/log/e-reader/" class="link-decor-none">ESP32 e-reader prototype</a> </td> <td class="posts-td posts-td-time"> <span class="post-meta"> 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.</p> -<p>Problem: manual overriding via Scintilla editor mid-session causes the code +<p>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.</p> <p>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 @@ <html> <head> <meta charset="utf-8"> - <title>Experimental e-reader</title> + <title>ESP32 e-reader prototype</title> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Experimental e-reader</title> + <title>ESP32 e-reader prototype</title> <link rel="stylesheet" href="/assets/css/main.css"> <link rel="stylesheet" href="/assets/css/skeleton.css"> </head> @@ -41,94 +41,69 @@ <main> <div class="container"> <div class="container-2"> - <h2 class="center" id="title">EXPERIMENTAL E-READER</h2> + <h2 class="center" id="title">ESP32 E-READER PROTOTYPE</h2> <h6 class="center">24 OCTOBER 2023</h5> <br> - <div class="twocol justify"><p>This project features an experimental e-reader powered by an ESP-WROOM-32 -development board and a 7.5-inch <a href="https://www.waveshare.com/" class="external" target="_blank" rel="noopener noreferrer">Waveshare</a> -e-paper display built with the intention of learning about e-paper displays.</p> + <div class="twocol justify"><p>First project with e-paper displays and ESP32.</p> <video style="max-width:100%;" controls="" poster="poster.png"> <source src="ereader.mp4" type="video/mp4" /> </video> -<h2 id="introduction">Introduction</h2> - -<p>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.</p> - -<p>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.</p> - -<p>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.</p> - -<h2 id="the-file-format">The file format</h2> - -<p>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).</p> - -<p>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.</p> - -<p>The pdftoebm.py script enclosed in the tarball at the end of the page converts -PDF documents to EBM files.</p> - -<h2 id="how-does-it-work">How does it work?</h2> - -<p>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 -<code class="language-plaintext highlighter-rouge">EBM_ARCH_URL</code> 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 -<code class="language-plaintext highlighter-rouge">EBM_ARCH_URL</code> value. The latter requires us to recompile the embedded -software.</p> - -<p>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.</p> - -<p>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.</p> - -<h2 id="epilogue">Epilogue</h2> - -<p>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.</p> - -<p>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.</p> - -<p>Files: <a href="source.tar.gz">source.tar.gz</a></p> +<p>ESP-WROOM-32, 7.5” Waveshare e-paper display, three buttons (prev/next/sleep).</p> + +<p>No local storage—streams books over HTTP. RTC memory tracks reading progress +between sessions.</p> + +<p>ESP32: 512KB SRAM, 4MB flash (shared with FreeRTOS, ESP-IDF). Not enough to +store books. Stream from webserver instead.</p> + +<p>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.</p> + +<p>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.</p> + +<p>Optimizations: pin the GPIO task (responding to user input and updating +display) to one core, pin the HTTP task to the other core.</p> + +<p>Better, but system unresponsive during screen updates. Made SPI transfer async:</p> + +<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>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); +} +</code></pre></div></div> + +<p>Much better. Squeeze a few more cycles by moving SPI buffer to DMA.</p> + +<p>Can’t think of anything else.</p> + +<p>Outcome: Works but limited. Led to <a href="../etlas/">Etlas</a>.</p> + +<p>Commit: +<a href="https://git.asciimx.com/esp32-e-reader/commit/?id=7f691c46093933b67aab466c0ca582ace8ab73d4">7f691c4</a></p> </div> <p class="post-author right">by W. D. Sadeep Madurange</p> </div> 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 @@ <tr> <td class="posts-td posts-td-link"> - <a href="/log/e-reader/" class="link-decor-none">Experimental e-reader</a> + <a href="/log/e-reader/" class="link-decor-none">ESP32 e-reader prototype</a> </td> <td class="posts-td posts-td-time"> <span class="post-meta"> diff --git a/_site/posts.xml b/_site/posts.xml index c92221f..38aac29 100644 --- a/_site/posts.xml +++ b/_site/posts.xml @@ -1 +1 @@ -<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/posts.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-12-27T18:35:47+08:00</updated><id>/posts.xml</id><title type="html">ASCIIMX</title><author><name>W. D. Sadeep Madurange</name></author></feed>
\ No newline at end of file +<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/posts.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-12-27T21:02:00+08:00</updated><id>/posts.xml</id><title type="html">ASCIIMX</title><author><name>W. D. Sadeep Madurange</name></author></feed>
\ No newline at end of file diff --git a/_site/projects/index.html b/_site/projects/index.html index 8891836..71a41e6 100644 --- a/_site/projects/index.html +++ b/_site/projects/index.html @@ -93,8 +93,8 @@ <td class="project-item"> <a href="../log/e-reader" class="link-decor-none"> - <img src="../log/e-reader/thumb_sm.png" alt="Experimental e-reader"> - <h5>Experimental e-reader</h5> + <img src="../log/e-reader/thumb_sm.png" alt="ESP32 e-reader prototype"> + <h5>ESP32 e-reader prototype</h5> </a> </td> |
