Repository navigation
v0.8.0: storage and PRST presets (#49, #50) - #53
Merged
Merged
Conversation
Storage for PRST (presets), off by default: the release image is
unchanged at 427 772 B.
- CONFIG_SP1_STORAGE: the eMMC driver (sp1_emmc.c, 1-bit, bit-banged;
protocol from sp1-tape-looper and SP-1-dev), FatFs through Zephyr's
fs layer, and a storage thread at K_PRIO_PREEMPT(5) -- below audio,
main and USB, so it only uses idle CPU. It never feeds the watchdog.
Commands sent: 0 1 2 3 7 8 13 16 17 24 only; nothing writes EXT_CSD,
erases or partitions. Reads are CRC16-checked; writes need the card's
"accepted" token and are retried.
- CONFIG_SP1_FRESH (wakes-sp1-fresh): formats the card on its first
ON -- one MBR partition, FAT32 at block 8192 (the 4 MB erase group),
32 KB clusters, 2 FATs, block 0 cleared first and the MBR written
last -- and stamps WAKES/FRESH.ID with its build ID; it formats again
only when that stamp is missing or names another build (Adara: option
A). The format holds ON entry with a progress bar on T1-T4, then two
0-100 % flickers and a quick fade into the page. Only the 30 s "••"
backstop powers off meanwhile; it runs every tick, first and
unconditionally, and stops the format via sp1_quiesce_peripherals.
- Only the fresh image can format, by construction: a normal image has
no f_mkfs, every mount is NO_FORMAT, our Kconfig defaults
FS_FATFS_MOUNT_MKFS to n (Zephyr's y would format any unmountable
card), and check_image.py fails an image that breaks either rule.
- CONFIG_SP1_STORAGE_TEST: the card report ("EMMC" lines) and a file
test ("STORE" lines) on every ON.
- west.yml: the fatfs module (Adara). FatFs R0.16 in NOTICE and
LICENSES/FatFs.txt.
On hardware (logs/sp1-20261007-173828/-174058/-174227): format 11.0 s,
FAT32 as above; second ON did not format; a normal image mounted the
card with no format and the ON counter went 1, 2, 3; 64 KB written,
read back identical; 0 retries, CRC errors, rejects or timeouts; write
busy <= 7.1 ms; storage stack <= 1168 of 4096 B; SYSTEM_OFF reached.
The format's write estimate now counts the WAKES folder's cluster
(2035 writes measured against 1966 estimated).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The tape-looper's method, with a slow path behind every fast step: - 512-byte payloads and their CRC16 ride SPIM3 + EasyDMA at 16 MHz (inside the card's 26 MHz default-speed limit); the start-bit hunt, the CRC-status token, the busy and every command stay bit-banged. SPIM3 is otherwise unused in Wakes. - Commands at register speed once the card is identified; the first four tries are fast, the rest at the 1 us identification clock. - CMD18 / CMD25 bursts with CMD12 (R1b waited after writes). A burst that fails part-way finishes block by block; a block is retried bit-banged, then at 1 us. The device's last block never ends a CMD18. - Table-driven CRC16, checked against "123456789" = 0x31C3 at init. - Anomaly 195 workaround on power-down; anomaly 198 (SPIM3 TX) is caught by the card's own CRC check and retried. - spim_xfer re-reads EVENTS_END after its 5 ms bound: the storage thread is the lowest priority there is, and a preemption between the two reads made finished transfers look timed out (38 in 512 KB on hardware, each dropping a burst to the slow path). - Timeouts are counted by cause (data / busy / spim); the report counts burst blocks and fallbacks. - The storage test moves 512 KB in 16 KB chunks (32-block bursts). On hardware (logs/sp1-20261007-194750.log), audio running at ~62 %: 512 KB written at 294-297 KB/s and read at 315-321 KB/s, identical; 2048 blocks in bursts, 0 fallbacks; retries, CRC errors, rejects and timeouts all 0; write busy <= 6.3 ms. Bit-banged was 25/28 KB/s. Audio fail 0 / rst 0. Release image unchanged (427 772 B). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drive mode (CONFIG_SP1_DRIVE, off by default):
- In STANDBY with a host attached (not a charger) the eMMC is a USB
drive, automatically; turning ON takes it back after the transfer
in flight. The mass-storage interface is always in the descriptor and
reads "no medium" while ON, so STANDBY <-> ON never re-enumerates.
It is registered last, so CDC/MIDI/audio interface numbers do not
move; bcdDevice 0x0500 with the drive (SP1_USB_BCD_DEVICE), 0x0403
without, as every release so far.
- Zephyr's usbd_msc thread starts cooperative, above audio: moved to
PREEMPT(main + 1).
- Two disks over one card ("EMMC" for Wakes, "DRIVE" for the host) and
an owner under a lock every transfer holds. A card with no
filesystem is not offered (a host would offer to format it).
- STANDBY: the T2/T3 plugged/charging lights are gone in every build
(the play-row bar still breathes while charging); host reads and
writes chase T1, T3, T2, T4 from 50 %.
- Measured: with a host attached and ON, usbd_msc 0.0 % CPU.
Burst READS are closed-ended (CMD23 + CMD18):
- Open-ended CMD18 stopped by CMD12 made this card return, as the
SECOND block of a later burst, its internal buffer with a valid CRC.
Reproduced on the device: 4 ON entries x 3 rounds of FAT scan + 512 KB
read, open-ended 5 bad blocks (all at position 1), closed-ended 0.
Writes were never affected (~10 000 verified, 0 wrong) and stay
CMD25 ... CMD12.
Formatted check (Adara): every ON looks for a FAT volume. Without one
Wakes boots with PRST off ("STORE PRST off"); sp1_store_volume() is the
check every PRST feature and key combo must pass, and UNKNOWN counts as
no. Only wakes-sp1-fresh formats.
Long file names on (presets will be "<name>.prst", ini inside); the
fresh format labels the volume "SP-1", which is what a host shows.
Diagnostics, test builds only: CONFIG_SP1_EMMC_VERIFY (read every write
back), host-activity counters per STANDBY visit, the mismatch report,
and the open- vs closed-ended reproduction in the storage test.
Release image 427 844 B (+72: bcdDevice set explicitly, STANDBY).
Test image m6-8 (drive + diagnostics) 459 312 B; 0 warnings,
check_image PASS. The fix image is not yet confirmed on hardware.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Drive mode: in plugged-in STANDBY, every block the computer reads or writes restarts the power-on fill, so ON needs 1 s without a transfer with "••" held. No time limit (Adara). Power-off and the 30 s backstop are untouched. - Closed-ended burst reads are the only read path: the open-ended switch, the stress comparison and the host-activity counters are removed. SP1_STORAGE_TEST and SP1_EMMC_VERIFY stay, off by default. - SP1_STORAGE and SP1_DRIVE default on in Plaits builds: the plain build is the release wakes-sp1.bin, which never formats. - CI builds wakes-sp1, wakes-sp1-fresh (renamed, never a plain-named copy) and the fallback recovery image (no storage), and checks each image's .config against its name. Releases attach the fresh image and explain what it erases. - Manual updated (Adara). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- sp1_prst.{c,h}: a PRST slot as ini text -- write, read, and a field
check. A field holding an impossible value (NaN, infinity, out of
range, an exponent, an unknown token, a destination off its output's
ring, a scale not included) loads THAT parameter's ROTC default and the
rest of the file still loads; a bad BASE fader takes the neutral value
of the engine that was loaded. Unknown engine -> slot 1. A missing or
unknown format version loads the whole slot from defaults.
- tools/gen_prst.py: the one field list (46 fields, choice tokens mapped
to enum names) and the format versions. The build fails if the list
changes without a new version, and prints the line to add.
- The rips are now "rip patch, then put" in both UIs, so the ROTC values
have one source; PRST's defaults come from it. sp1_pui/mui_get/put
sanitise. main.c's output / burst / drive defaults are SP1_PRST_DEF_*.
- prsttest (host + CI): round trips, every corrupt field, hand-edited
text, writer bounds, ~23 000 truncated / damaged / random files.
Not called yet: nothing user-visible changes. Image 450 028 B.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…50) - Load: the ON job reads WAKES/PRST/SLOT and the four slot folders (the first .prst of each, case-insensitive) into RAM after the volume check. A folder with no .prst is that slot at the ROTC defaults; no card, no filesystem or a read error turns PRST off for the session. main waits for it before audio starts, at most 10 s, with the 30 s backstop live, then applies the current slot (Wakes comes up in PLAITS). With PRST off the patch in memory is kept. - Save: only when the ordinary shutdown animation completes (sp1_power_set_save_hook; never from the 30 s backstop): LEDs off, audio stopped, the slot written to SAVE.TMP then renamed over the loaded file (or N.prst), then SLOT. Limit 4 s, watchdog fed. - Field check: a quantizer together with a V/Oct route -> quantizer off (the M4b interlock). - ROTC on MARBLES now routes t2 -> TRIG and X2 -> V/Oct (Adara); the rip calls voct_took_over(). Docs and both test suites updated. - wakes-sp1-fresh writes WAKES/PRST/1..4/N.prst (the ROTC patch) and SLOT = 1 after its format, before the stamp. Image 458 060 B (fresh 462 920 B), 0 warnings. Not yet tested on hardware. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PLAY pressed with "••" held shows the current slot: its face LED (T1..T4) ramps 100 % -> 0 at 10 Hz for 1.6 s, the other three face LEDs black, the play row as normal; then the page fades back. - PLAY pressed again while it shows, in the same "••" hold: the next slot (4 -> 1), loaded at once from RAM -- the old slot's unsaved changes dropped, faders picked up, module and page kept. Saved at shutdown. - PLAY held from a press that did not change slot: ROTC, still 3 s -- glyph 1.6 s, black 0.25 s, rise to full 0.4 s, the Unpatch animation 0.75 s, then the wipe (BUILD_ASSERT on the sum). Let go past the glyph: cancelled, back to the SHIFT screen. No ROTC after a slot change until "••" is released. - Every PRST part checks prst_available(): the volume is OK and this ON session loaded a slot. - docs/UI-PAGES.md, docs/UI-SPEC.md updated. Smoke-tested on hardware (Adara). Image 458 664 B, fresh 463 524 B. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With no PRST (no filesystem, or no slot loaded this session) there is no slot glyph, so the first 1.6 s of a "••" + PLAY hold fade the face LEDs slowly from the SHIFT screen to black (Adara); then the same black, rise and Unpatch animation, and the wipe at 3 s. Letting go during the fade cancels back to the SHIFT screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he browser (#50) - Engines not in config/engines.csv: every build contains all of Plaits' engines, so a PRST slot may name one that is not listed and it plays. A selection is a list position or SP1_PUI_OFFLIST + its Plaits index; engine facts come from a new all-engine table (gen_engines.py). No glyph of its own: its flash is all four face LEDs ramping 70 % -> 0 every 64 ms for 0.7 s. T3 from it -> the first listed engine, T2 -> the last; MIDI's MODEL CC counts from list position 1. A name no engine of the build has -> list position 1. Fixes sp1_pui_slot_leds() reading past the table for a selection that is not a list position. - The save at OFF verifies WAKES, PRST and the slot's folder: a folder is used, a missing one is created (logged), a FILE in its place fails the save and is left alone. - Letting go of SHFT leaves the PRST browser at once: the glyph ends, PLAY no longer changes slot, the page fades back in. - Tests: prsttest section 9 and miditest's MODEL-from-off-list; all ten host suites pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Storage (#49) and PRST presets (#50): the eMMC as a FAT32 volume and a USB drive in STANDBY; four preset slots in WAKES/PRST/1..4 loaded at ON and saved at a normal power-off; the slot browser and the new ROTC animation on SHFT + PLAY. A minor version: ROTC on Marbles now leaves t2 -> TRIG and X2 -> V/Oct, and first-time users need wakes-sp1-fresh.bin, which formats the eMMC. Manual updated (Adara). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Closed
10 tasks
PRST contents (no DJVU), the WAKES/PRST folders and file names, 30 s emergency shutdowns skip saving, backups, fresh formats the card, ENG and SCL buttons the right way round, ROTC's routing on Marbles. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.8.0: storage and PRST presets
Storage (#49, done) and PRST (#50) in one PR, as agreed when #51 was closed. For #50 rather than
Closes: some of its hardware checks are still open (below), and the manual note about unsaved sessions is still to come.Storage (#49)
SP-1). In STANDBY with a computer attached it is a USB drive; turning ON takes it back after the transfer in flight, and the power-on hold waits while the computer is reading or writing.wakes-sp1-fresh.binformats. A normal image contains no formatter (check_image.pyenforces it). CI buildswakes-sp1,wakes-sp1-freshand the fallback, and checks each image's config against its name.PRST (#50)
WAKES/PRST/1…4, one.prst(ini text) per folder, with any file name. If a folder holds more than one, the first in alphabetical order is used.WAKES/PRST/SLOTholds the last-loaded slot.tools/gen_prst.py).engines.csvload from a preset and play. Their flash is all four face LEDs ramping 70 % → 0 at 15.6 Hz. T3 goes to the first listed engine and T2 to the last; MIDI MODEL counts from list position 1.wakes-sp1-freshwrites the four default slots andSLOT= 1 after it formats.Cost
0x20000,check_image.pypasses. Fresh 464 612 B, fallback 86 640 B.Tests
prsttest(new, in CI): round trips; every kind of corrupt field one at a time; hand-edited text; writer bounds; ~23 000 cut-off, damaged or random files, all giving a safe patch; engines off the list.uitestandmiditestwere updated for the new ROTC routing and for MODEL from an off-list engine.main.cblock tick by tick.On hardware (Adara)
🤖 Generated with Claude Code