summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--_log/arduino-due.md5
-rw-r--r--_log/e-reader.md6
-rw-r--r--_log/etlas.md6
-rw-r--r--_log/fpm-door-lock-lp.md7
-rw-r--r--_log/fpm-door-lock-rf.md55
-rw-r--r--_log/matrix-digital-rain.md39
-rw-r--r--_log/neo4j-a-star-search.md10
-rw-r--r--_log/site-search.md23
-rw-r--r--about.html16
-rw-r--r--assets/css/main.css46
-rw-r--r--assets/css/skeleton.css24
-rw-r--r--assets/fonts/Nouveau_IBM_Stretch.ttfbin0 -> 72180 bytes
12 files changed, 163 insertions, 74 deletions
diff --git a/_log/arduino-due.md b/_log/arduino-due.md
index e24666c..8176b3b 100644
--- a/_log/arduino-due.md
+++ b/_log/arduino-due.md
@@ -56,6 +56,7 @@ $ arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -T script.ld \
$ openocd -f openocd-due.cfg -c "program a.elf verify reset exit"
```
-Commit:
-[3184969](https://git.asciimx.com/bare-metal-arduino-due/commit/?id=318496925ca76668dd9d63c3d060376f489276f8)
+Commit: <a
+href="https://git.asciimx.com/bare-metal-arduino-due/commit/?id=318496925ca76668dd9d63c3d060376f489276f8"
+class="external" target="_blank" rel="noopener noreferrer">3184969</a>.
diff --git a/_log/e-reader.md b/_log/e-reader.md
index 45363f7..66c262b 100644
--- a/_log/e-reader.md
+++ b/_log/e-reader.md
@@ -64,5 +64,7 @@ Can't think of anything else.
Verdict: Functional but limited. Led to [Etlas](../etlas/).
-Commit:
-[7f691c4](https://git.asciimx.com/esp32-e-reader/commit/?id=7f691c46093933b67aab466c0ca582ace8ab73d4)
+Commit: <a
+href="https://git.asciimx.com/esp32-e-reader/commit/?id=7f691c46093933b67aab466c0ca582ace8ab73d4"
+class="external" target="_blank" rel="noopener noreferrer">7f691c4</a>.
+
diff --git a/_log/etlas.md b/_log/etlas.md
index a2458d5..6d5bd4e 100644
--- a/_log/etlas.md
+++ b/_log/etlas.md
@@ -101,5 +101,7 @@ via MCU.
Uptime: August 2024 - January 2026
-Commit:
-[a92c86a](https://git.asciimx.com/etlas/commit/?id=a92c86ac1592c2137d3d1fec1668eacc2d0ca581)
+Commit: <a
+href="https://git.asciimx.com/etlas/commit/?id=a92c86ac1592c2137d3d1fec1668eacc2d0ca581"
+class="external" target="_blank" rel="noopener noreferrer">a92c86a</a>.
+
diff --git a/_log/fpm-door-lock-lp.md b/_log/fpm-door-lock-lp.md
index d63131e..aed991e 100644
--- a/_log/fpm-door-lock-lp.md
+++ b/_log/fpm-door-lock-lp.md
@@ -54,6 +54,7 @@ unlock. No match triggers red LED. MOSFETs off, back to sleep.
Total power savings: 99.9% (30.6mA → 2.9μA). Verdict: Fixed.
-Commit:
-[7529094](https://git.asciimx.com/fpm-door-lock/commit/?id=75290945b2fd84b3bc108fd46419ee478eaac3ca)
-| Gerber: [gerber.zip](gerber.zip)
+Commit: <a
+href="https://git.asciimx.com/fpm-door-lock/commit/?id=75290945b2fd84b3bc108fd46419ee478eaac3ca"
+class="external" target="_blank" rel="noopener noreferrer">7529094</a> | Gerber: [gerber.zip](gerber.zip)
+
diff --git a/_log/fpm-door-lock-rf.md b/_log/fpm-door-lock-rf.md
index 87dc6b4..d8822f9 100644
--- a/_log/fpm-door-lock-rf.md
+++ b/_log/fpm-door-lock-rf.md
@@ -16,21 +16,54 @@ Unreliable--constant packet loss.
the letter, audited code many times, cross-checked with RadioHead and RFM69
open-source drivers. No luck.
-Datasheet riddled with ambiguity.
-
ATmega328P runs at 5V; RFM69 3.3V. Suspect logic-level converter (LLC)
issues. High resistance. Not enough swing.
-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-04: Ditched RFM69s. Switched to NRF24L01+ modules--data pins 5V tolerant,
+no LLC required. Spent six weekends writing a clean-room driver from scratch.
+Works like a charm.
+
+Basic security via xor cipher–good enough for a door behind a guard post and
+gate:
+
+```
+void xor(const char *k, const char *s, char *d, uint8_t n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ d[i] = s[i] ^ k[i];
+}
+```
+
+Resists replay attacks by cycling the key:
+
+```
+static inline void keygen(char *buf, uint8_t n)
+{
+ int i, imax;
+ uint8_t sreg;
+ uint16_t seed;
+
+ sreg = SREG;
+ cli();
+ seed = TCNT1;
+ SREG = sreg;
+
+ for (i = 0, imax = n - 1; i < imax; i++, seed++)
+ buf[i] = tab[(seed % tablen)];
+ buf[imax] = '\0';
+}
+```
+
+Protocol: FPM sends SYN. Servo responds with session key. Both xor-ed with
+static key. Session key used thereafter. Private command set authenticates
+endpoints.
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.
+2025-06: Two PCBs for FPM (front) and servo (back) controllers.
<table style="border: none; width: 100%">
<tr style="border: none;">
@@ -68,7 +101,9 @@ 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
[redesign](../fpm-door-lock-lp/) with proper power management.
-Commit:
-[f4b0b73](https://git.asciimx.com/smart-home/commit/?id=f4b0b734a595919cf451ab9448b06274c8e609a4)
-| Gerber: [gerber_back.zip](gerber_back.zip),
+Commit: <a
+href="https://git.asciimx.com/smart-home/commit/?id=f4b0b734a595919cf451ab9448b06274c8e609a4"
+class="external" target="_blank" rel="noopener noreferrer">f4b0b73</a> |
+Gerber: [gerber_back.zip](gerber_back.zip),
[gerber_front.zip](gerber_front.zip)
+
diff --git a/_log/matrix-digital-rain.md b/_log/matrix-digital-rain.md
index 78fe623..2edc7e7 100644
--- a/_log/matrix-digital-rain.md
+++ b/_log/matrix-digital-rain.md
@@ -7,7 +7,7 @@ thumbnail: thumb_sm.png
---
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
+incomplete--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.
@@ -39,17 +39,48 @@ static inline void insert_code(matrix *mat,
uint64_t blk;
uint32_t min, max;
- blk = glyphs[(rand() % glyphlen)];
+ blk = glyphs[(xor() % glyphlen)];
min = (uint32_t)blk;
max = (uint32_t)(blk >> 32);
- mat->code[index(mat, row, col)] = rand() % (max - min) + min;
+ mat->code[index(mat, row, col)] = xor() % (max - min) + min;
}
```
Full-width Katakana breaks column alignment. Stick to half-width
(U+FF61-U+FF9F) range. Compile with -DNOKANA to disable Katakana altogether.
-blend() is still good. Leaving it alone.
+blend() for screen decay is still good:
+
+```
+static inline void blend(matrix *mat,
+ size_t row, size_t col)
+{
+ unsigned char *color;
+
+ color = mat->rgb[index(mat, row, col)].color;
+ color[R] = color[R] - (color[R] - RGB_BG_RED) / DECAY_MPLIER;
+ color[G] = color[G] - (color[G] - RGB_BG_GRN) / DECAY_MPLIER;
+ color[B] = color[B] - (color[B] - RGB_BG_BLU) / DECAY_MPLIER;
+}
+```
+
+Left it alone.
+
+Optimized RNG--xorshift instead of rand():
+
+```
+static inline uint32_t xor(void)
+{
+ /* Xorshift RNGs, George Marsaglia, Florida State University. */
+ static uint32_t y = 2463534242;
+
+ y ^= (y << 13);
+ y = (y >> 17);
+ return (y ^= (y << 5));
+}
+```
+
+NOTE: Non-linear variations (xorshitr+) for more speed.
Tossed license and automake cruft. Just `cc -O3 main.c -o matrix` now. Don't
need the ceremony.
diff --git a/_log/neo4j-a-star-search.md b/_log/neo4j-a-star-search.md
index db74444..017a33e 100644
--- a/_log/neo4j-a-star-search.md
+++ b/_log/neo4j-a-star-search.md
@@ -28,7 +28,6 @@ private double computeHeuristic(
* Math.sin(lonDistance / 2);
final double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
-
return earthRadius * c * kmToNM;
}
```
@@ -50,8 +49,13 @@ private void updateCosts(
300x speedup. Scaled to 13,000 route points.
+Despite impressive speedup, performance horizon visible. Unlikely to scale past
+16,000 points.
+
Upstreamed changes: <a
href="https://github.com/neo4j-contrib/neo4j-graph-algorithms/releases/tag/3.4.0.0"
class="external" target="_blank" rel="noopener noreferrer">Neo4J v3.4.0</a> |
-[Full
-source](https://github.com/neo4j-contrib/neo4j-graph-algorithms/blob/bd9732d9a690319552e134708692acb5a0d6b37c/algo/src/main/java/org/neo4j/graphalgo/impl/ShortestPathAStar.java)
+<a
+href="https://github.com/neo4j-contrib/neo4j-graph-algorithms/blob/bd9732d9a690319552e134708692acb5a0d6b37c/algo/src/main/java/org/neo4j/graphalgo/impl/ShortestPathAStar.java"
+class="external" target="_blank" rel="noopener noreferrer">Full source</a>.
+
diff --git a/_log/site-search.md b/_log/site-search.md
index dab5133..4ccae3c 100644
--- a/_log/site-search.md
+++ b/_log/site-search.md
@@ -4,7 +4,7 @@ date: 2026-01-03
layout: post
---
-Article count is growing. Need a way to search.
+Article count is growing. Need search.
Requirements: matches substrings, case-insensitive, fast, secure. No
JavaScript.
@@ -14,7 +14,7 @@ Architecture: browser → httpd → slowcgi → Perl CGI script.
Perl, httpd, slowcgi are in the OpenBSD base system. Instead of secrets, file
system permissions govern access.
-2025-12-30: Regex search.
+2025-12-30: Regex.
140-line Perl script searches 500 files in 40ms. Fast enough; O(N) pull felt at
higher file counts.
@@ -22,7 +22,7 @@ higher file counts.
Introduces ReDoS and symlink attack vectors. Both can be mitigated. Tempted to
stop here.
-2026-01-03: Suffix Array (SA) based index lookup.
+2026-01-03: Suffix array (SA) based index lookup.
Slurping files on every request bothers me. Regex search depends almost
entirely on hardware for speed.
@@ -36,8 +36,8 @@ $ cd cgi-bin/
$ perl indexer.pl
```
-Indexer extracts HTML, lowercases, encodes into UTF-8 binary sequences. Null
-byte sentinel for document boundaries. sa.bin stores suffix offsets as
+Indexer extracts HTML, lowercases, and 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:
```
@@ -120,9 +120,12 @@ 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.
-Secure by default. Fast. Durable.
+Verdict: Fast. Durable. Secure by default.
+
+Commit: <a
+href="https://git.asciimx.com/www/commit/?h=term&id=6da102d6e0494a3eac3f05fa3b2cdcc25ba2754e"
+class="external" target="_blank" rel="noopener noreferrer">6da102d</a> |
+Benchmarks: <a
+href="https://git.asciimx.com/site-search-bm/commit/?id=8a4da6809cf9368cd6a5dd7351181ea4256453f9"
+class="external" target="_blank" rel="noopener noreferrer">8a4da68</a>
-Commit:
-[6da102d](https://git.asciimx.com/www/commit/?h=term&id=6da102d6e0494a3eac3f05fa3b2cdcc25ba2754e)
-| Benchmarks:
-[8a4da68](https://git.asciimx.com/site-search-bm/commit/?id=8a4da6809cf9368cd6a5dd7351181ea4256453f9)
diff --git a/about.html b/about.html
index ce515a1..f14905b 100644
--- a/about.html
+++ b/about.html
@@ -21,19 +21,23 @@ title: About
<li>hme: Latest articles.</li>
<li>poc: Projects.</li>
<li>abt: Site information.</li>
- <li>lup: Look up articles.</li>
+ <li>lup: Article lookup.</li>
<li>rss: RSS (Atom) feed.</li>
</ul>
<h4>Site credits</h4>
<p>
- The site's CSS is derived from <a href="http://getskeleton.com/"
- class="external" target="_blank" rel="noopener noreferrer">Skeleton</a> by Dave
- Gamache (<a href="/assets/lic/skeleton.txt" target="_blank">license</a>) and <a
+ Font: Arto Hatanpää's Nouveau IBM Stretch.
+ </p>
+
+ <p>
+ CSS: Dave Gamache's <a href="http://getskeleton.com/" class="external"
+ target="_blank" rel="noopener noreferrer">Skeleton</a> (<a
+ href="/assets/lic/skeleton.txt" target="_blank">license</a>) / John Coene's <a
href="https://github.com/JohnCoene/marat" class="external" target="_blank"
- rel="noopener noreferrer">Marat</a> by John Coene (<a
- href="/assets/lic/marat.txt" target="_blank">license</a>).
+ rel="noopener noreferrer">Marat</a> (<a href="/assets/lic/marat.txt"
+ target="_blank">license</a>).
</p>
</div>
diff --git a/assets/css/main.css b/assets/css/main.css
index 1b4341b..c46729c 100644
--- a/assets/css/main.css
+++ b/assets/css/main.css
@@ -1,6 +1,13 @@
+@font-face {
+ font-family: 'Nouveau IBM Stretch';
+ src: url('/assets/fonts/Nouveau_IBM_Stretch.ttf') format('truetype');
+}
+
:root {
--main-bg-color: #202020;
--main-fg-color: #00B140;
+ --font-family: 'Nouveau IBM Stretch', 'Roboto Mono', monospace;
+ --text-shadow: 0 0 1px var(--main-fg-color), 0 0 6px var(--main-fg-color);
}
*,
@@ -16,21 +23,21 @@ body {
text-decoration-skip: ink;
color: var(--main-fg-color);
padding-top: 10px;
- font-family: 'Roboto Mono', monospace;
+ font-family: var(--font-family);
background-color: var(--main-bg-color);
background-size: 2px 2px;
- text-shadow: 0 0 1px var(--main-fg-color), 0 0 6px var(--main-fg-color);
+ /* text-shadow: var(--text-shadow); */
}
::selection {
- color: var(--main-bg-color);
- background: var(--main-fg-color);
- text-shadow: 0 0 1px var(--main-bg-color), 0 0 6px var(--main-bg-color);
+ color: var(--main-bg-color);
+ background: var(--main-fg-color);
+ /* text-shadow: var(--text-shadow); */
}
::-moz-selection {
- color: var(--main-bg-color);
- background: var(--main-fg-color);
- text-shadow: 0 0 1px var(--main-bg-color), 0 0 6px var(--main-bg-color);
+ color: var(--main-bg-color);
+ background: var(--main-fg-color);
+ /* text-shadow: var(--text-shadow); */
}
.footer {
@@ -39,7 +46,7 @@ body {
width: 100%;
padding-top: 10px;
padding-bottom: 10px;
- color: rgba(47, 47, 47, 0.6)
+ color: var(--main-fg-color);
}
a {
@@ -196,6 +203,15 @@ pre::-webkit-scrollbar {
display: none;
}
+code {
+ line-height: 2.4rem;
+ font-family: var(--font-family);
+}
+
+input {
+ font-family: var(--font-family);
+}
+
.typewriter-1 {
overflow: hidden;
white-space: nowrap;
@@ -221,12 +237,12 @@ pre::-webkit-scrollbar {
.typewriter-2::after {
filter: brightness(0.9);
background-color: var(--main-fg-color);
- box-shadow: 0 0 1px var(--main-fg-color), 0 0 6px var(--main-fg-color);
+ /* box-shadow: var(--text-shadow); */
content: '';
display: inline-block;
- width: 1.3rem;
- height: 1.9rem;
- margin-left: -8px;
+ width: 0.9rem;
+ height: 1.45rem;
+ margin-left: -6px;
animation: cursor-blink 1s steps(1, start) infinite;
animation-delay: 3.5s;
}
@@ -242,7 +258,7 @@ pre::-webkit-scrollbar {
border-color: var(--main-fg-color);
color: var(--main-fg-color) !important;
background-color: var(--main-bg-color);
- text-shadow: 0 0 1px var(--main-fg-color), 0 0 6px var(--main-fg-color);
+ /* text-shadow: 0 0 1px var(--main-fg-color), 0 0 6px var(--main-fg-color); */
}
#search-btn {
@@ -250,5 +266,5 @@ pre::-webkit-scrollbar {
border-color: var(--main-fg-color);
color: var(--main-fg-color);
background-color: var(--main-bg-color);
- text-shadow: 0 0 1px var(--main-fg-color), 0 0 6px var(--main-fg-color);
+ /* text-shadow: 0 0 1px var(--main-fg-color), 0 0 6px var(--main-fg-color); */
}
diff --git a/assets/css/skeleton.css b/assets/css/skeleton.css
index 87b0050..0354b60 100644
--- a/assets/css/skeleton.css
+++ b/assets/css/skeleton.css
@@ -120,8 +120,8 @@ are based on 10px sizing. So basically 1.5rem = 15px :) */
html {
font-size: 62.5%; }
body {
- font-size: 1.8em; /* currently ems cause chrome bug misinterpreting rems on body element */
- line-height: 1.4;
+ font-size: 2.0em; /* currently ems cause chrome bug misinterpreting rems on body element */
+ line-height: 1.2;
}
h1, h2, h3, h4, h5, h6 {
@@ -131,21 +131,11 @@ h1, h2, h3, h4, h5, h6 {
}
h1 { font-size: 4.0rem; line-height: 1.2; letter-spacing: -.1rem;}
-h2 { font-size: 3.6rem; line-height: 1.25; letter-spacing: -.1rem; }
+h2 { font-size: 3.6rem; line-height: 1.2; letter-spacing: -.1rem; }
h3 { font-size: 3.0rem; line-height: 1.3; letter-spacing: -.1rem; }
h4 { font-size: 2.4rem; line-height: 1.35; letter-spacing: -.08rem; }
-h5 { font-size: 1.8rem; line-height: 1.5; letter-spacing: -.05rem; }
-h6 { font-size: 1.5rem; line-height: 1.6; letter-spacing: 0; }
-
-/* Larger than phablet */
-@media (min-width: 550px) {
- h1 { font-size: 5.0rem; }
- h2 { font-size: 3.4rem; }
- h3 { font-size: 3.0rem; }
- h4 { font-size: 2.6rem; }
- h5 { font-size: 2.4rem; }
- h6 { font-size: 1.5rem; }
-}
+h5 { font-size: 2.0rem; line-height: 1.5; letter-spacing: -.05rem; }
+h6 { font-size: 1.8rem; line-height: 1.6; letter-spacing: 0; }
p {
margin-top: 0; }
@@ -289,7 +279,7 @@ ol ul {
margin: 1.5rem 0 1.5rem 3rem;
font-size: 90%; }
li {
- margin-bottom: 0.6rem; }
+ margin-bottom: 0.1rem; }
ol {
margin-left: 1.8em; }
@@ -299,7 +289,7 @@ ol {
code {
padding: .2rem .5rem;
margin: 0 .2rem;
- font-size: 95%;
+ /* font-size: 95%; */
white-space: nowrap;
border-radius: 4px; }
diff --git a/assets/fonts/Nouveau_IBM_Stretch.ttf b/assets/fonts/Nouveau_IBM_Stretch.ttf
new file mode 100644
index 0000000..71279ba
--- /dev/null
+++ b/assets/fonts/Nouveau_IBM_Stretch.ttf
Binary files differ