summaryrefslogtreecommitdiffstats
path: root/_site
diff options
context:
space:
mode:
Diffstat (limited to '_site')
-rw-r--r--_site/feed.xml2
-rw-r--r--_site/posts.xml2
-rw-r--r--_site/projects/e-reader/index.html94
3 files changed, 51 insertions, 47 deletions
diff --git a/_site/feed.xml b/_site/feed.xml
index 8574cb7..a5979a1 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-08T21:04:23+08:00</updated><id>/feed.xml</id><title type="html">ASCIIMX | Blog</title><author><name>W. D. Sadeep Madurange</name></author><entry><title type="html">How I manage Suckless software packages</title><link href="/blog/suckless-software/" rel="alternate" type="text/html" title="How I manage Suckless software packages" /><published>2025-11-30T00:00:00+08:00</published><updated>2025-11-30T00:00:00+08:00</updated><id>/blog/suckless-software</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Since suckless software requires users to modify the source code and recompile to customize, I need a way to maintain patches over the long term while retaining the ability to upgrade the software as new versions are released.]]></summary></entry><entry><title type="html">Neo4J A* search</title><link href="/blog/neo4j-a-star-search/" rel="alternate" type="text/html" title="Neo4J A* search" /><published>2025-09-14T00:00:00+08:00</published><updated>2025-09-14T00:00:00+08:00</updated><id>/blog/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. Algorithms based on graph theory, such as A* search, provide optimal solutions to such problems. In other words, the set of route points lends itself well to a model based on graphs.]]></summary></entry><entry><title type="html">MOSFETs as electronic switches</title><link href="/blog/mosfet-switches/" rel="alternate" type="text/html" title="MOSFETs as electronic switches" /><published>2025-06-22T00:00:00+08:00</published><updated>2025-06-22T00:00:00+08:00</updated><id>/blog/mosfet-switches</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Recently, I needed a low-power circuit for one of my battery-operated projects. Much of the system’s power savings depended on its ability to electronically switch off components, such as servos, that draw high levels of quiescent currents. My search for a solution led me to MOSFETs, transistors capable of controlling circuits operating at voltages far above their own.]]></summary></entry><entry><title type="html">How to configure ATmega328P microcontrollers to run at 3.3V and 5V</title><link href="/blog/arduino-uno/" rel="alternate" type="text/html" title="How to configure ATmega328P microcontrollers to run at 3.3V and 5V" /><published>2025-04-10T00:00:00+08:00</published><updated>2025-04-10T00:00:00+08:00</updated><id>/blog/arduino-uno</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[This is a quick reference for wiring up ATmega328P ICs to run at 5V and 3.3V. While the 5V configuration is common, the 3.3V configuration can be useful in low-power applications and when interfacing with parts that themselves run at 3.3V. In this guide, the 5V setup is configured with a 16MHz crystal oscillator, while the 3.3V configuration makes use of an 8MHz crystal oscillator.]]></summary></entry><entry><title type="html">How to set up ATSAM3X8E microcontrollers for bare-metal programming in C</title><link href="/blog/arduino-due/" rel="alternate" type="text/html" title="How to set up ATSAM3X8E microcontrollers for bare-metal programming in C" /><published>2024-10-05T00:00:00+08:00</published><updated>2024-10-05T00:00:00+08:00</updated><id>/blog/arduino-due</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[This article is a step-by-step guide for programming bare-metal ATSAM3X8E chips found on Arduino Due boards. It also includes notes on the chip’s memory layout relevant for writing linker scripts. The steps described in this article were tested on an OpenBSD workstation.]]></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-09T23:04:17+08:00</updated><id>/feed.xml</id><title type="html">ASCIIMX | Blog</title><author><name>W. D. Sadeep Madurange</name></author><entry><title type="html">How I manage Suckless software packages</title><link href="/blog/suckless-software/" rel="alternate" type="text/html" title="How I manage Suckless software packages" /><published>2025-11-30T00:00:00+08:00</published><updated>2025-11-30T00:00:00+08:00</updated><id>/blog/suckless-software</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Since suckless software requires users to modify the source code and recompile to customize, I need a way to maintain patches over the long term while retaining the ability to upgrade the software as new versions are released.]]></summary></entry><entry><title type="html">Neo4J A* search</title><link href="/blog/neo4j-a-star-search/" rel="alternate" type="text/html" title="Neo4J A* search" /><published>2025-09-14T00:00:00+08:00</published><updated>2025-09-14T00:00:00+08:00</updated><id>/blog/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. Algorithms based on graph theory, such as A* search, provide optimal solutions to such problems. In other words, the set of route points lends itself well to a model based on graphs.]]></summary></entry><entry><title type="html">MOSFETs as electronic switches</title><link href="/blog/mosfet-switches/" rel="alternate" type="text/html" title="MOSFETs as electronic switches" /><published>2025-06-22T00:00:00+08:00</published><updated>2025-06-22T00:00:00+08:00</updated><id>/blog/mosfet-switches</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Recently, I needed a low-power circuit for one of my battery-operated projects. Much of the system’s power savings depended on its ability to electronically switch off components, such as servos, that draw high levels of quiescent currents. My search for a solution led me to MOSFETs, transistors capable of controlling circuits operating at voltages far above their own.]]></summary></entry><entry><title type="html">How to configure ATmega328P microcontrollers to run at 3.3V and 5V</title><link href="/blog/arduino-uno/" rel="alternate" type="text/html" title="How to configure ATmega328P microcontrollers to run at 3.3V and 5V" /><published>2025-04-10T00:00:00+08:00</published><updated>2025-04-10T00:00:00+08:00</updated><id>/blog/arduino-uno</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[This is a quick reference for wiring up ATmega328P ICs to run at 5V and 3.3V. While the 5V configuration is common, the 3.3V configuration can be useful in low-power applications and when interfacing with parts that themselves run at 3.3V. In this guide, the 5V setup is configured with a 16MHz crystal oscillator, while the 3.3V configuration makes use of an 8MHz crystal oscillator.]]></summary></entry><entry><title type="html">How to set up ATSAM3X8E microcontrollers for bare-metal programming in C</title><link href="/blog/arduino-due/" rel="alternate" type="text/html" title="How to set up ATSAM3X8E microcontrollers for bare-metal programming in C" /><published>2024-10-05T00:00:00+08:00</published><updated>2024-10-05T00:00:00+08:00</updated><id>/blog/arduino-due</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[This article is a step-by-step guide for programming bare-metal ATSAM3X8E chips found on Arduino Due boards. It also includes notes on the chip’s memory layout relevant for writing linker scripts. The steps described in this article were tested on an OpenBSD workstation.]]></summary></entry></feed> \ No newline at end of file
diff --git a/_site/posts.xml b/_site/posts.xml
index 6a3103c..537fbb6 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-08T21:04:23+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-09T23:04:17+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/e-reader/index.html b/_site/projects/e-reader/index.html
index 5a81e2b..5fe3341 100644
--- a/_site/projects/e-reader/index.html
+++ b/_site/projects/e-reader/index.html
@@ -44,20 +44,21 @@
<h2 class="center" id="title">PROTOTYPE E-READER</h2>
<h6 class="center">24 OCTOBER 2023</h5>
<br>
- <div class="twocol justify"><p>This project features a prototype e-reader powered by a 7.5-inch <a href="https://www.waveshare.com/" class="external" target="_blank" rel="noopener noreferrer">Waveshare</a> e-paper display and an
-ESP-WROOM-32 development board.</p>
+ <div class="twocol justify"><p>This project features a prototype 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.</p>
<video style="max-width:100%;" controls="" poster="thumb.png">
<source src="ereader.mp4" type="video/mp4" />
</video>
-<h4 id="overview">Overview</h4>
+<h2 id="overview">Overview</h2>
-<p>In 2017, during a short stint as a project manager, I was tasked with
-installing some e-paper displays in a car park. Not knowing how they worked, I
-remember marveling at their sight like a muggle witnessing magic. As someone
-who enjoys reading, I found e-paper to be a true innovation. This project was
-born out of that enduring curiosity and love of e-paper technology.</p>
+<p>In 2017, I was tasked with installing some e-paper displays in a car park. Not
+knowing how they worked, I remember marveling at their sight like a Muggle
+witnessing magic. As someone who enjoys reading, I found e-paper to be a true
+innovation. This project was born out of that enduring curiosity and love of
+e-paper technology.</p>
<p>The prototype, while far from ready for daily use, has some nifty features that
fellow hobbyists and tinkerers may find interesting. The reader can display
@@ -65,59 +66,62 @@ books of arbitrary sizes by streaming them over HTTP. It employs sleep modes to
minimize power consumption when not in use and records the reading progress in
the chip’s RTC memory.</p>
-<p>The biggest challenge when building an e-reader using an ESP32 board is its low
-memory and lack of storage. My ESP-WROOM-32 board has 512 KB of SRAM and 4 MB
-of flash memory, which the freeRTOS, ESP-IDF, and my own program have to share.
-To put things into perspective, compare that to a Kindle Paperwhite, which has
+<p>The most formidable challenge when trying to build an e-reader with an ESP32
+board is its limited memory and storage. My ESP-WROOM-32 board has 512 KB of
+SRAM and 4 MB 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 256 MB of memory and 8 GB of storage.</p>
-<p>Despite its constraints, as microcontrollers go, ESP32 is a powerful
-system-on-a-chip with a 160 MHz dual-core processor and integrated WiFi. So, I
-thought it’d be amusing to embrace the constraints and build my e-reader using
-just a $5 MCU and the power of C programming.</p>
+<p>Despite its size, as microcontrollers go, ESP32 is a powerful system-on-a-chip
+with a 160 MHz 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>
-<h4 id="the-file-format">The file format</h4>
+<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, where each bitmap corresponds to a
-page of a book sized to fit the e-paper display. Each byte contains information
-for rendering eight pixels. For my display, which has a resolution of 480x800,
-the bitmaps are laid out along 48 KB boundaries. This simple file format lends
-well to HTTP streaming, which is its main advantage, as we will soon see.</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 48 KB
+boundaries. This simple file format lends well to HTTP streaming, which is its
+main advantage, as we will soon see.</p>
-<p>The enclosed pdftoebm.py script in the tarball at the end of the page converts
-PDF documents to an EBM file. I use it to make EBM files before uploading them
-to a web server.</p>
+<p>The pdftoebm.py script enclosed in the tarball at the end of the page converts
+PDF documents to EBM files.</p>
-<h4 id="how-does-it-work">How does it work?</h4>
+<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, I first
-have to upload the EBM file I want to read to a web server. The location of the
-file is configured via the <code class="language-plaintext highlighter-rouge">EBM_ARCH_URL</code> setting in the Kconfig.projbuild
-file. To read a different book, I create an EBM file with the same name and
-upload it to the original location. That way, I don’t have to recompile the
-embedded software.</p>
+have to upload the EBM file I want to read to a web server. The <code class="language-plaintext highlighter-rouge">EBM_ARCH_URL</code>
+setting in the Kconfig.projbuild file points to the URL of the file. To read a
+different book, I create an EBM file with the same name and upload it to the
+original location. That way, I don’t have to modify the <code class="language-plaintext highlighter-rouge">EBM_ARCH_URL</code> value,
+which requires recompiling 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, one of the
-two cores of the MCU transfers it from the buffer to the display over a Serial
-Peripheral Interface (SPI). The other downloads a new page in the background. I
-use the ESP-IDF task API to pin the two routines to each core.</p>
-
-<p>I designed the EBM format with HTTP streaming in mind. To download a page based
-on the current reading progress, the e-reader specifies the page offset and the
-chunk size using the HTTP Range header.</p>
-
-<h4 id="afterword">Afterword</h4>
-
-<p>It’s been six years since the car park and the displays. At the time, I knew
-nothing about embedded systems or display drivers. It took a long time to
-develop the skill set, but now, at last, I know how those displays worked and
-how to build my own.</p>
+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 use the ESP-IDF task API to distribute the two tasks between the
+available cores for maximum parallelism.</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="reflections">Reflections</h2>
+
+<p>It’s been six years since the car park and the displays. I began this project
+hoping to learn the low-level workings of e-paper displays. As a bonus, it led
+me to explore some of ESP32’s most fascinating features: sleep modes, multicore
+processing, DMA, and RTC memory. Embedded systems are magical things: invisible
+particles swirl into form as the programmer whispers C.</p>
<p>Files: <a href="source.tar.gz">source.tar.gz</a></p>
</div>