aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcirakg <cirakg@cirakg.xyz>2026-10-20 12:16:59 +0200
committercirakg <cirakg@cirakg.xyz>2026-10-20 12:16:59 +0200
commit25910f3a7a7fb28c4a58367b6e56dd2468b60933 (patch)
tree4201b020700547fe921f30a571c42bd42206da05
parent1ebc828f30698c1661055e17483e8d50a139ed45 (diff)
docs: record M6 (all 12 symbologies) results; bump to 0.6.0v0.6.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
-rw-r--r--CHANGELOG.md11
-rw-r--r--README.md10
-rw-r--r--docs/PERFORMANCE.md13
-rw-r--r--docs/TESTING.md11
4 files changed, 38 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 31b6ce8..5e3882e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,7 +11,10 @@ All notable changes to this project are documented here. The format follows
## [Unreleased]
-Milestone M6 in progress (released as 0.6.0 when all four parts are done).
+## [0.6.0] - 2026-10-20
+
+Milestone M6: barcodes. Code entries now show their barcode: all 12
+symbologies of README 12.1, encoded on the watch.
### Added
@@ -49,6 +52,12 @@ Milestone M6 in progress (released as 0.6.0 when all four parts are done).
screens, deferred cache saving and 8-at-a-time packing.
- Dev image: pdf417gen, ppf-datamatrix and aztec-code-generator as reference
encoders (pure Python, MIT).
+- M6d, Aztec (`Aztec.mc`):
+ - Compact 1-4 and full range 1-32 layers, error correction of 10, 23, 36
+ or 50 %, Upper, Lower and Digit modes with Binary Shift.
+ - The geometry is ported from aztec_code_generator, and symbols match it
+ for single-class text.
+ - Decoded with zxing-cpp, also from a screenshot.
## [0.5.0] - 2026-10-20
diff --git a/README.md b/README.md
index b9a119b..ffe2f91 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,11 @@
A Garmin Connect IQ watch app that shows one-time passwords (TOTP, HOTP, and optional Steam Guard codes) and stores barcodes and QR codes (loyalty cards, tickets) to show at a scanner. Everything lives encrypted on the watch. There is no cloud, no backend and no analytics, and the app requests no permissions, so it cannot use the network.
-> **Status: M6a-M6c (linear barcodes, QR, Data Matrix, PDF417) done; M6d (Aztec) next; M1 (settings spike) ready for your phone test.** The plan below was approved on 2026-10-18. M0 built the Docker toolchain and pipeline, M2 the crypto and OTP core, M3 the encrypted vault ([docs/SECURITY.md](docs/SECURITY.md)), M4 the screens and M5 import (`otpauth://` and Aegis JSON via the phone settings). M6 added the code screen and, so far, 11 of the 12 symbologies, encoded on the watch:
+> **Status: M6 (barcodes) done; next is M7, the phone settings forms; M1 (settings spike) ready for your phone test.** The plan below was approved on 2026-10-18. M0 built the Docker toolchain and pipeline, M2 the crypto and OTP core, M3 the encrypted vault ([docs/SECURITY.md](docs/SECURITY.md)), M4 the screens and M5 import (`otpauth://` and Aegis JSON via the phone settings). M6 added the code screen and all 12 symbologies, encoded on the watch:
>
> - **Linear codes** are encoded directly.
-> - **2D codes** are encoded as resumable jobs and cached encrypted.
-> - **Checks:** each is compared with a reference encoder (zxing-cpp, segno, ppf.datamatrix, pdf417gen) and decoded with zxing-cpp, and screenshots of four kinds of code decode on seven simulated watches.
+> - **QR, Data Matrix, PDF417 and Aztec** are encoded as resumable jobs and cached encrypted.
+> - **Checks:** each is compared with a reference encoder (zxing-cpp, segno, ppf.datamatrix, pdf417gen, aztec_code_generator) and decoded with zxing-cpp. Screenshots of five kinds of code decode on seven simulated watches.
>
> The settings spike (`make spike`, [docs/SETTINGS_SPIKE.md](docs/SETTINGS_SPIKE.md)) waits for your test. The Phase 0 research, with sources, is in [docs/FEASIBILITY.md](docs/FEASIBILITY.md); the daily workflow is in [docs/DEVELOPER_GUIDE.md](docs/DEVELOPER_GUIDE.md).
@@ -597,12 +597,12 @@ Linear: EAN-13 needs 113 modules, which means 1 px per module on a 218 px screen
- **Padding.** segno adds a whole zero byte when the bit stream already ends on a codeword boundary (always the case in byte mode). ISO/IEC 18004 7.4.10 adds no padding there, and the watch follows the standard. The exact references therefore use payloads that segno pads correctly.
- **Segmentation.** segno encodes one mode per symbol, while the watch segments optimally. The exact references use single-mode payloads, and mixed content is covered by decoding.
- Data Matrix is compared with ppf.datamatrix in ASCII mode. ppf turns a pad codeword of exactly 254 into 0 (`(R + 130) % 254`), while ISO/IEC 16022 5.2.3 keeps 254, so the references avoid payloads whose padding hits that value. PDF417 is compared with pdf417gen at fixed columns and level. The watch mirrors pdf417gen's compaction rules, so its rows match exactly.
+ Data Matrix is compared with ppf.datamatrix in ASCII mode. ppf turns a pad codeword of exactly 254 into 0 (`(R + 130) % 254`), while ISO/IEC 16022 5.2.3 keeps 254, so the references avoid payloads whose padding hits that value. PDF417 is compared with pdf417gen at fixed columns and level. The watch mirrors pdf417gen's compaction rules, so its rows match exactly. Aztec is compared with aztec_code_generator for payloads of one character class (capitals, small letters or digits, with spaces). For those, the reference's optimal mode sequence and the watch's simpler encodation give the same bits, and the symbols match exactly, from compact to full range with reference grids. Mixed content is checked by decoding.
2. **Decoding**: the simulator tests dump every encoder output. It's rendered at each device's module size and decoded with zxing-cpp, which reads all 12 symbologies. The decoded text must equal the input, for hundreds of seeded random payloads per symbology.
3. **Screenshots**: simulator screenshots of the code screen on Forerunner 255S, Venu Sq 2 and Forerunner 965 must decode with zxing-cpp.
4. **Real world** (manual checklist): your phone's camera, plus any real shop scanner you can try, indoors and outdoors, on MIP and AMOLED.
-A symbology counts as implemented only when checks 1 to 3 pass. Otherwise it's listed as deferred, with the reason, in this README and the changelog.
+A symbology counts as implemented only when checks 1 to 3 pass. Otherwise it's listed as deferred, with the reason, in this README and the changelog. **M6 result: all 12 are implemented**, with the comparison limits described above. The real-world check is your phone and scanners (manual checklist).
## 13. UX design
diff --git a/docs/PERFORMANCE.md b/docs/PERFORMANCE.md
index 9c9a31a..0fbb2f0 100644
--- a/docs/PERFORMANCE.md
+++ b/docs/PERFORMANCE.md
@@ -28,7 +28,7 @@ The targets are in [README section 18](../README.md#18-performance-budgets). Thi
### M6, 2026-10-20 (barcodes, in 0.6.0)
- **Linear codes** encode in milliseconds while the screen opens; nothing is cached.
-- **QR is encoded as a job** in steps sized for the Forerunner 255S's watchdog: at most 2,500 modules to place, 500 to score as rows, 1,000 as columns, or one Reed-Solomon block. Simulator compute time and steps:
+- **2D codes are encoded as jobs.** QR works in steps sized for the Forerunner 255S's watchdog: at most 2,500 modules to place, 500 to score as rows, 1,000 as columns, or one Reed-Solomon block. Simulator compute time and steps:
| QR | Compute | Steps | At 50 ms per step on a watch |
| --- | --- | --- | --- |
@@ -36,6 +36,17 @@ The targets are in [README section 18](../README.md#18-performance-budgets). Thi
| Version 10 (57 x 57) | 312 ms | 105 | at least 5.3 s |
| Version 26 (121 x 121) | 1.4 s | 407 | at least 20 s |
+- **First-time encoding in the simulated watches** (the UI flow's demo cards, `make screenshots` prints these times):
+
+ | Code | Size | Time |
+ | --- | --- | --- |
+ | QR (version 6) | 41 x 41 | 2.8 s |
+ | Data Matrix | 18 x 18 | 0.2 s |
+ | PDF417 | 86 x 29 rows (round watches), 103 x 15 (rectangular) | 0.35 to 0.55 s |
+ | Aztec (compact) | 23 x 23 | 0.15 s |
+
+ These times are mostly the 50 ms pauses between steps. QR is the slow one, because of its eight mask evaluations.
+
Version 10 is over README 18's 3 s target. Most of the time is the pauses between steps, and mask scoring (eight masks, every module) is most of the steps. The cache makes every later opening instant. M8 can cut the steps, for example by scoring masks on packed rows. The demo card (version 6) encodes in 2.8 s in the simulated watches (`make screenshots` prints it).
### M5, 2026-10-20 (version 0.5.0, import)
diff --git a/docs/TESTING.md b/docs/TESTING.md
index cf9bee0..d8302af 100644
--- a/docs/TESTING.md
+++ b/docs/TESTING.md
@@ -26,6 +26,16 @@ Test devices (`TEST_DEVICES`): Forerunner 255S (weakest: 218 px round MIP, butto
## Results
+### M6d, 2026-10-20 (Aztec; M6 complete, version 0.6.0)
+
+Monkey C unit tests: 120 per device.
+
+1. **Reference comparison.** 24 Aztec symbols are identical to aztec_code_generator: compact (15 x 15 up) and full range, including sizes with reference grids, and error correction of 10, 23, 36 and 50 %. The payloads are of one character class each, for which both encoders produce the same bits; README 12.4 explains why mixed content can't be compared exactly.
+2. **Decoding.** 8 Aztec codes are decoded with zxing-cpp: mixed case with digits and punctuation (Binary Shift and mode latches), UTF-8, a URL, and a long payload.
+3. **Screenshots.** The UI flow opens an Aztec card after the PDF417 card, and its screenshot decodes on all seven watches.
+
+With that, all 12 symbologies of README 12.1 pass checks 1 to 3. The UI flow shows 16 screens per watch (15 on touch-only watches), five of them barcodes that must decode.
+
### M6c, 2026-10-20 (Data Matrix and PDF417, in 0.6.0)
Monkey C unit tests: 117 per device.
@@ -186,3 +196,4 @@ Things the simulator can't verify, done by you on the Forerunner 70. The checkli
- [ ] M6a: with "Debug: demo entries", open "Gym card" (an EAN-13). Scan it with your phone's camera, or a shop scanner if you can, indoors and outdoors. Tell me whether it reads.
- [ ] M6b: open "Member QR" (a demo entry) and scan it with your phone's camera. The first opening encodes it; note roughly how long that takes. The second opening should be instant (cache).
- [ ] M6c: scan the "Parcel" (Data Matrix) and "Ticket" (PDF417) demo cards with a phone app that reads them, for example the zxing-based "Barcode Scanner".
+- [ ] M6d: scan the "Rail pass" (Aztec) demo card with a phone app that reads Aztec.