summaryrefslogtreecommitdiffstats
path: root/_log
diff options
context:
space:
mode:
authorSadeep Madurange <sadeep@asciimx.com>2026-01-08 22:28:37 +0800
committerSadeep Madurange <sadeep@asciimx.com>2026-01-08 22:28:37 +0800
commite836c4b9e78cc3892cdebf8126cb650f1b91ed37 (patch)
tree4e52155aef0105cc9b888a42b3e760455a2bcb36 /_log
parent57ff09d2eefefa2462a2af0175e3e8164c7bc828 (diff)
downloadwww-e836c4b9e78cc3892cdebf8126cb650f1b91ed37.tar.gz
Tighten prose.
Diffstat (limited to '_log')
-rw-r--r--_log/bumblebee.md29
-rw-r--r--_log/e-reader.md33
-rw-r--r--_log/etlas.md33
-rw-r--r--_log/fpm-door-lock-lp.md17
-rw-r--r--_log/fpm-door-lock-rf.md42
-rw-r--r--_log/neo4j-a-star-search.md6
-rw-r--r--_log/site-search.md63
7 files changed, 113 insertions, 110 deletions
diff --git a/_log/bumblebee.md b/_log/bumblebee.md
index 25f08e4..6ef46b3 100644
--- a/_log/bumblebee.md
+++ b/_log/bumblebee.md
@@ -6,34 +6,27 @@ project: true
thumbnail: thumb_sm.png
---
-Work project. Browser session-to-code conversion.
+Browser session-to-code conversion. For work. Pre-LLM.
<video style="max-width:100%; margin-bottom: 10px" controls="" poster="poster.png">
<source src="bee.mp4" type="video/mp4">
</video>
-Architecture: C# WinForms host, embedded browser, code editor. Browser
-extension rejected due to security policy and shallow event control.
+Quality of scripts are pitiful.
-Tool evaluation:
+Created tool to generate them real-time (as the user browses the web).
- - CefSharp: Discarded. API lacked elegance.
- - WebView2: Selected. Better WinForms integration. Hard dependency on
- Microsoft Edge--acceptable for corporate Windows environments.
+Architecture: C# WinForms host, embedded WebView2 browser, Scintilla.NET
+editor.
Implementation:
- 1. Interception: Injected JS hooks; internal browser event monitoring
- (pop-ups/downloads).
- 2. Transformation: Event → Token → Instruction Table → String.
- 3. Optimization: Parallel event/text lists processing; rendered
- in <a href="https://github.com/desjarlais/Scintilla.NET" class="external"
- target="_blank" rel="noopener noreferrer">Scintilla.NET</a>
+ - Interception: Injected JS hooks + internal browser events.
+ - Transformation: Event → Token → Instruction table → String.
+ - Optimization: Parallel event/text lists.
+ - Two-way binding of code to Scintilla editor.
-Bug: Manual mid-session overrides desync code/event lists, bypassing optimizer.
-Linear lists inadequate for state synchronization. Need to rethink data
-structures; look to compiler Abstract Syntax Trees (AST) for intermediate
-representation.
+NOTE: Abstract syntax trees.
-Verdict: Serves its purpose.
+Script generation: minutes/hours → seconds.
diff --git a/_log/e-reader.md b/_log/e-reader.md
index 69b1e96..45363f7 100644
--- a/_log/e-reader.md
+++ b/_log/e-reader.md
@@ -1,12 +1,12 @@
---
-title: 512 KB e-reader
+title: 512KB e-reader
date: 2023-10-24
layout: post
project: true
thumbnail: thumb_sm.png
---
-First project with e-paper displays and ESP32.
+First project with e-paper.
<video style="max-width:100%;" controls="" poster="poster.png">
<source src="ereader.mp4" type="video/mp4">
@@ -15,13 +15,13 @@ First project with e-paper displays and ESP32.
ESP-WROOM-32, 7.5" Waveshare e-paper display, three-button interface
(prev/next/sleep).
-Memory: 512KB SRAM + 4MB flash. Internal 4 MB flash unsuitable for storing
-books due to P/E cycle limits. HTTP Range requests for on-demand bitmap
-streaming. Progress saved to RTC memory to survive deep sleep without flash
-wear.
+Memory: 512KB SRAM + 4MB flash. Internal flash unsuitable for storing books due
+to P/E cycle limit. Used HTTP Range requests to stream them on-demand.
+Progress saved to RTC memory to survive deep sleep without flash wear.
-EBM format: Raw bitmap sequence. 1 byte = 8 pixels, 1 page = 48 KB (display
-resolution), headerless. Optimized for HTTP Range requests:
+PDFs are rasterized and stored as sequences of bitmaps on a server. 1 byte = 8
+pixels, 1 page = 48KB (display resolution), headerless. Optimized for Range
+requests without server-side logic:
```
int r0 = ((page_n - 1) * PAGE_SIZE);
@@ -35,8 +35,9 @@ esp_http_client_set_header(http_client, "Range", buf);
esp_http_client_perform(http_client);
```
-Page buffer: Three pages (prev/current/next) in RAM—maximum possible. On
-request: cycles buffer, updates screen, prefetches next page.
+Three pages (prev/current/next) held in a buffer—maximum possible. Upon
+request, embedded software cycles the buffer, updates the screen, prefetches
+the next page.
```
c_page_num++;
@@ -50,12 +51,14 @@ epd_draw_async(pages[c_page_num % PAGE_LEN], PAGE_SIZE);
epd_draw_await();
```
-Responsiveness: inadequate. Scheduling GPIO, SPI, and HTTP tasks on a single
-thread causes input lag. Pinned GPIO/SPI tasks to one core and the HTTP task to
-the other.
+System isn't as responsive as I'd hoped. Scheduling GPIO, SPI, and HTTP tasks
+on a single thread causes input lag. Pinned GPIO/SPI tasks to one core and the
+HTTP task to the other.
-Better, but screen updates block user input. Moved SPI buffers to DMA and made
-transfers async. Few more cycles saved.
+Better, but screen updates block user input.
+
+Moved the SPI buffers to DMA and made the transfers async. Few more cycles
+saved.
Can't think of anything else.
diff --git a/_log/etlas.md b/_log/etlas.md
index 7c50c72..a2458d5 100644
--- a/_log/etlas.md
+++ b/_log/etlas.md
@@ -6,9 +6,9 @@ project: true
thumbnail: thumb_sm.jpg
---
-Repurposed [e-reader prototype](../e-reader/) into something for regular use.
-News, stocks, weather dashboard. ESP32 NodeMCU D1 + 7.5" Waveshare e-paper +
-DHT22 sensor.
+Repurposed the [e-reader](../e-reader/) into something for regular use. News,
+stocks, weather dashboard. ESP32 NodeMCU D1 + 7.5" Waveshare e-paper + DHT22
+sensor.
<table style="border: none;">
<tr style="border: none;">
@@ -20,18 +20,21 @@ DHT22 sensor.
</tr>
</table>
-Stocks: Two weeks EOD prices from Polygon.io (max possible). Flask app on VPS
-relays feed; manages watchlist. Backend: httpd + htpasswd + FastCGI + Flask.
+Stocks: Two weeks EOD data from Polygon.io (max possible). Flask app on VPS
+manages watchlist, relays the feed. Backend: httpd + htpasswd + slowcgi +
+Flask.
-gui_plot_stocks() triggers watchdog; vTaskDelay() required. Stepped graph was
-easier to implement (under memory constraints), but the logic is hideous. Note
-to self: Refactor with Bresenham’s?
+gui_plot_stocks() plots a stepped graph; was easier to implement, but the code
+is hideous; triggers watchdog. vTaskDelay() prevents that.
-News: Channel NewsAsia RSS. MCU parses XML directly. Character glyphs stored as
-bitmaps in header files.
+NOTE: Refactor. Bresenham’s?
+
+News: Channel NewsAsia RSS. MCU does the parsing. Didn't plan to have a backend
+at the time. Now that I have one for stocks, should relay the feed for
+flexibility.
Weather: DHT22 single-wire protocol. 26µs/50µs/70µs pulses are too fast for
-standard ESP32 APIs. Bit-banged relative pulse widths: (Ported from <a
+standard ESP32 APIs. Bit-banged relative pulse widths (ported from <a
href="https://github.com/Fonger/ESP8266-RTOS-DHT" class="external"
target="_blank" rel="noopener noreferrer">ESP8266</a>):
@@ -91,10 +94,10 @@ static inline int dht_get_raw_data(unsigned char buf[BUFLEN])
}
```
-Ghost in the machine: epd_init() stalls intermittently on first refresh() after
-flash. Toggling delay values in refresh() resolves it. If first refresh
-succeeds, it remains stable. Root cause unknown--suspected power supply issues
-from powering display via MCU.
+epd_init() stalls intermittently on first refresh() after flash. Toggling delay
+values in refresh() resolves it. If the first refresh succeeds, it remains
+stable. Root cause unknown--suspect noisy power supply due to powering display
+via MCU.
Uptime: August 2024 - January 2026
diff --git a/_log/fpm-door-lock-lp.md b/_log/fpm-door-lock-lp.md
index 1be2b76..d63131e 100644
--- a/_log/fpm-door-lock-lp.md
+++ b/_log/fpm-door-lock-lp.md
@@ -14,10 +14,9 @@ idle. Linear regulators were a disaster. Battery didn't last 24 hours.
<source src="video.mp4" type="video/mp4">
</video>
-Redesigned the PCB completely. Tossed the RF modules and the second MCU.
-Connected R503 sensor directly to the ATmega328P. Sensor now mounts on door
-exterior, servo attaches to interior knob, MCU stays on the back to prevent
-tampering.
+Redesigned the PCB completely. Tossed RF modules and the second MCU. Connected
+R503 directly to the ATmega328P. Sensor now mounts on door exterior, servo
+attaches to interior knob, MCU stays on the back to prevent tampering.
<table style="border: none; width: 100%">
<tr style="border: none;">
@@ -42,14 +41,14 @@ Solved idle power draw with MOSFETs. 2N7000 and NDP6020P cut power to sensor
and servo before deep sleep. Through-hole MOSFETs that switch at 3.3V are
getting harder to find. NDP6020P already obsolete.
-Replaced linear regulators with MP1584EN DC-DC buck converters. No RF, noise
-isn't a big concern. Buck's pin breakout not great--wouldn't fit most
-commercial dev boards.
+Replaced linear regulators with MP1584EN DC-DC buck converters. No RFM--noise
+isn't a big concern. Buck's pin breakout not great--wouldn't fit commercial dev
+boards.
-Squeezed more power savings from the MCU by running it at 3.3V/8MHz. Combined
+Squeezed more power savings by underclocking MCU to 8MHz/3.3V. Combined
with buck converters: 56% total power savings.
-Wake sequence: MCU activates sensor MOSFET, unlocks sensor over UART, scans and
+Wake sequence: MCU activates FPM MOSFET, unlocks FPM over UART, scans and
matches fingerprint. Match triggers blue LED, servo MOSFET, PWM signal to
unlock. No match triggers red LED. MOSFETs off, back to sleep.
diff --git a/_log/fpm-door-lock-rf.md b/_log/fpm-door-lock-rf.md
index 76f64d7..87dc6b4 100644
--- a/_log/fpm-door-lock-rf.md
+++ b/_log/fpm-door-lock-rf.md
@@ -12,21 +12,25 @@ Wanted to unlock door with fingerprint, wirelessly to avoid drilling.
lines of the transceivers to UART RXD/TXD of an ATmega328P.
Unreliable--constant packet loss.
-2025-01: Switched to RFM69 modules. A complete ball-ache. Followed the
-datasheet to the letter, audited code more than 10 times, cross-checked with
-RadioHead and RFM69 OSS drivers. No luck. ATmega328P runs at 5V, RFM69 3.3V. I
-suspect the problem is with the logic-level converter (LLC). Not enough swing.
+2025-01: Switched to RFM69 modules. Complete ball-ache. Followed datasheet to
+the letter, audited code many times, cross-checked with RadioHead and RFM69
+open-source drivers. No luck.
-2025-04: Ditched RFM69s. Switched to NRF24L01+ modules--5V tolerant, no LLC
-required. Spent six weekends writing driver from scratch--clean-room, using
-datasheet. Works perfectly.
+Datasheet riddled with ambiguity.
-2025-05: Wrote FPM sensor drivers for R503 and FPM10A. UART RX sequence was
-tricky--took multiple attempts to get handshake working. R503 has built-in LEDs
-and better form factor--will use it for the lock.
+ATmega328P runs at 5V; RFM69 3.3V. Suspect logic-level converter (LLC)
+issues. High resistance. Not enough swing.
-2025-06: First PCB design. Two boards: fingerprint sensor (front), servo
-controller (back). Encrypted RF link between them.
+2025-04: Ditched RFM69s. Switched to NRF24L01+ modules-- data pins 5V tolerant,
+no LLC required. Spent six weekends writing driver from scratch--clean-room.
+Works like a charm.
+
+2025-05: Wrote FPM drivers for R503 and FPM10A. UART RX sequence was
+tricky--adopted Adafruit C++ FOSS implementation to C. R503 has built-in LEDs
+and better form factor. Chose it for the lock.
+
+2025-06: Two PCB boards for FPM (front) and servo (back) controllers. Encrypted
+RF link between them.
<table style="border: none; width: 100%">
<tr style="border: none;">
@@ -52,19 +56,17 @@ controller (back). Encrypted RF link between them.
</table>
PCB specs: 2-layer, 1oz copper, 0.3mm traces (0.5mm for power). Ground plane.
-Both subsystems worked—could control servo from sensor over RF.
-2025-06: NRF24L01+ on the back controller stopped working after mounting on
-PCB. RFM is too close to PWM line. Fixed by soldering a large 47uF (16V)
-electrolytic capacitor between VCC and ground.
+2025-06: NRF24L01+ on the back stopped working after mounting on PCB. Too close
+to servo's PWM line. Soldering a large 47uF (16V) electrolytic capacitor
+between VCC and ground fixed it.
Power problems became clear. Linear regulators dissipated too much heat. Sensor
-and servo drew 13.8mA and 4.6mA quiescent—unacceptable for battery. Servo
-inrush current can exceed 1A. Trace width (0.3mm), especially for servo and
-power, cutting it close.
+and servo drew 13.8mA and 4.6mA quiescent currents--unacceptable for battery.
+Servo inrush current exceeds 1A. 0.3mm tracks cuts it too close.
Verdict: Functional but not practical. Battery dead in under 24 hours. Led to
-[complete redesign](../fpm-door-lock-lp/) with proper power management.
+[redesign](../fpm-door-lock-lp/) with proper power management.
Commit:
[f4b0b73](https://git.asciimx.com/smart-home/commit/?id=f4b0b734a595919cf451ab9448b06274c8e609a4)
diff --git a/_log/neo4j-a-star-search.md b/_log/neo4j-a-star-search.md
index de0ef25..db74444 100644
--- a/_log/neo4j-a-star-search.md
+++ b/_log/neo4j-a-star-search.md
@@ -4,8 +4,8 @@ date: 2018-03-06
layout: post
---
-Work project. Marine vessel tracking with Neo4J hit a limit. Need to store
-13,000 route points; Dijkstra's shortest path search slows after 4,000.
+Work. Vessel tracking with Neo4J hit a limit. Need to analyze 13,000 route
+points; Dijkstra's shortest path search slows after 4,000.
Replaced Dijkstra's algorithm with A* search using haversine function as
heuristic:
@@ -48,7 +48,7 @@ private void updateCosts(
}
```
-Outcome: 300x speedup. Scaled to 13,000 route points.
+300x speedup. Scaled to 13,000 route points.
Upstreamed changes: <a
href="https://github.com/neo4j-contrib/neo4j-graph-algorithms/releases/tag/3.4.0.0"
diff --git a/_log/site-search.md b/_log/site-search.md
index d178d07..0cfbf99 100644
--- a/_log/site-search.md
+++ b/_log/site-search.md
@@ -1,33 +1,34 @@
---
-title: Search engine (Perl + FastCGI + SA)
+title: Site search with suffix array
date: 2026-01-03
layout: post
---
-Article count on the website is growing. Need a way to search.
+Article count is growing. Need a way to search.
Requirements: matches substrings, case-insensitive, fast, secure. No
JavaScript.
Architecture: browser → httpd → slowcgi → Perl CGI script.
-httpd, slowcgi, Perl are in the OpenBSD base system. No dependencies. Access
-governed by file system permissions--no secrets to manage. Secure by default.
+Perl, httpd, slowcgi are in the OpenBSD base system. Instead of secrets, file
+system permissions govern access.
-2025-12-30: Regex search. Wrote a 140-line Perl script that searches HTML files
-using Regex. Script slurps 500 files (16 KB each) in 40 milliseconds. Fast
-enough. Start to feel the O(N) pull at higher file counts.
+2025-12-30: Regex search.
-Regex and the site crawl introduce ReDoS and symlink attack vectors. Both can
-be mitigated. Tempted to stop here.
+140-line Perl script searches 500 files in 40ms. Fast enough; O(N) pull felt at
+higher file counts.
-2026-01-03: Suffix array (SA) based index lookup.
+Introduces ReDoS and symlink attack vectors. Both can be mitigated. Tempted to
+stop here.
-Inefficiency of scanning every file on each request troubles me. Regex search
-depends almost entirely on hardware for speed.
+2026-01-03: Suffix Array (SA) based index lookup.
-Built SA index comprising three files: corpus.bin (articles), sa.bin (sorted
-byte offsets), file_map.dat (metadata). Index created with the site:
+Slurping files on every request bothers me. Regex search depends almost
+entirely on hardware for speed.
+
+Implemented SA index with three files: corpus.bin, sa.bin, file_map.dat. Index
+built with site:
```
$ JEKYLL_ENV=production bundle exec jekyll build
@@ -35,10 +36,9 @@ $ cd cgi-bin/
$ perl indexer.pl
```
-Indexer extracts HTML, lowercases, encodes text as UTF-8 binary sequences, and
-saves to corpus.bin. Null byte sentinel marks the document boundaries. Suffix
-array stores offsets of all suffixes as 32-bit unsigned integers, sorted by the
-lexicographical order:
+Indexer extracts HTML, lowercases, encodes into UTF-8 binary sequences. Null
+byte sentinel for document boundaries. sa.bin stores suffix offsets as
+32-bit unsigned integers, sorted by lexicographical order:
```
my @sa = 0 .. (length($corpus) - 1);
@@ -67,11 +67,11 @@ SORTED SUFFIXES:
[7] x
```
-Algorithmic complexity: O(L⋅N log N). Fast path caps L at 64 bytes (length of a
-cache line), reducing complexity to O(N log N).
+Time complexity: O(L⋅N log N). Fast path caps L at 64 bytes (length of cache
+line), reducing complexity to O(N log N).
-Search: Textbook range query with two binary searches. Random access to offsets
-and the text is possible via the fixed-width offsets:
+Search: Textbook range query with twin binary searches. Random access to
+suffixes and the text made possible by the fixed-width offsets:
```
seek($fh_sa, $mid * 4, 0);
@@ -81,8 +81,9 @@ seek($fh_cp, $off, 0);
read($fh_cp, my $text, $query_len);
```
-Small seek/reads are fast on modern SSDs. Keeps memory usage low, and was easy
-to implement. Note to self: mmap.
+Small seek/reads are fast on modern SSDs. Keeps memory usage low.
+
+NOTE: mmap.
Benchmarks on T490 (i7-10510U, OpenBSD 7.8, article size: 16 KB).
@@ -110,14 +111,16 @@ Benchmarks on T490 (i7-10510U, OpenBSD 7.8, article size: 16 KB).
- Search (SA): 0.0161 s
- Search (Regex): 0.9120 s
-Security: Much of it comes from its architectural simplicity. No dependencies
-to manage, no secrets to hide, no assets for lateral movement. Runs in chroot.
+Security: Derived from architectural simplicity. Zero dependencies to manage,
+no secrets to hide, no targets for lateral movement.
+
+Runs in chroot.
-Resource exhaustion and XSS attacks are inherent. The former is mitigated by
-limiting concurrent searches via lock-file semaphores and capping query length
-(64B) and result sets (20). All output is HTML-escaped to prevent XSS.
+Resource exhaustion and XSS attacks are inherent. Former mitigated by limiting
+concurrent searches via lock-file semaphores. Query length (64B) and result set
+(20) capped. All output is HTML-escaped to prevent XSS.
-Verdict: Fast SA lookup; Works on every conceivable web browser.
+Secure by default. Fast. Durable.
Commit:
[6da102d](https://git.asciimx.com/www/commit/?h=term&id=6da102d6e0494a3eac3f05fa3b2cdcc25ba2754e)