Conversation
A second transport for the MIDI feature: plug the panel into a computer with the cable it is flashed over and it is a class-compliant MIDI device named "Patternflow" - no driver, no session, no Wi-Fi in the path. Same map as RTP-MIDI (CC 20-23 hold, 24-27 nudge, notes 60-63 press, program change picks a pattern; encoders out as CC 24-27), both transports up at once. The transport (features/midi/core_midi_usb.h) is part of the midi feature, not a feature of its own: the boundary checker's rule is that features do not know each other, and a transport that needs the map is not a peer of the map. It compiles in only when the build's USB port is the OTG stack (ARDUINO_USB_MODE=0); everywhere else it is three empty functions. That flag is the Arduino core's, decided per env, so the edition needs its own PlatformIO env - `env`, the third file a bundle may now carry, read by build.sh and shelf.sh (bundles/midi/env -> firmware_midi). The S3 has one USB PHY; OTG presents CDC (still Serial: Improv and the log survive) plus MIDI, and the ROM's download mode is untouched. No worker and no queue on this transport, unlike RTP: USB has flow control, so a full FIFO makes the host wait rather than losing data, and the frame task reads the class FIFO itself, one batch per frame. Verified on board .119 (Windows 11): enumerates as a composite - CDC on COM18 and a MEDIA-class "Patternflow" with the in-box driver; CC 20 sweeps 0..127 track params 0..1000; relative CC 24 counted; program change both ways (host picks a module, the panel echoes the change); Improv answers over the TinyUSB CDC; `build.sh all` builds all five compositions and the marker scan holds (the audio image carries no USB marker). Cost: ~28 KB of internal RAM against the default image (45 KB free after services, largest 32 KB; a 22 KB module still loads), so the edition is for a panel that is a MIDI port first. In the tree and built by CI, not on the shelf: the EDITIONS tuples in release.py/check_versions.py, the cards and the AGENTS.md version line stay as they are until it is published. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Some encoders count the other way round, some give two edges per detent
instead of four. Both are properties of the part soldered in, and until
now the only answer was INVERT_ENCODER in config.h and a rebuild - which
is also the answer builders keep asking for. Now each knob has a direction
and an edges-per-click setting (4, 2 or 1), stored in NVS ("pf_knobs"),
with INVERT_ENCODER remaining the compile-time default a fresh device
starts from.
- core_encoders.h: getClicks() counts from a per-knob base, so a saved
change does not move the knob - the click count carries on from where it
was, in the new direction and at the new size. Settings are applied on
the frame task (PFLoopSync from the handler) because the frame reads the
same counters.
- core_knobs_http.h + console/knobs.html: GET/POST /api/knobs and the page,
with a live position and edge readout to check a knob against. A Setup
row on the home console.
- console_serve.py mocks /api/knobs so the page can be worked on without a
panel; console_pages.py knows the page.
- docs: rest-api.md (the endpoint, 1.5), console/README.md, BUILD_GUIDE.md
(the direction advice points here), CHANGELOG.
- director-midi.md: the one Live setting that made a wired or wireless
MIDI knob pin itself and tick - Remote on the port's Output row sends
every mapped value straight back, and the panel reads a position as a
relative turn. Found on the first USB test; documented for both.
Verified on board .119: GET/POST, invalid input refused, clicks unchanged
across a save, settings survive a reboot; build.sh all compiles every
composition; boundary, source and version checks pass; the page renders
in the console preview and on the panel.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n its own; CI builds compositions in parallel.
The structure was starting to multiply: a feature became an edition
because that was the only way onto a panel, and every edition brought a
card, a release, a build and a board to test. The shelf is now what its
maintainer stands behind and nothing else.
- The Clock edition leaves the shelf. The clock stays a feature and
bundles/clock stays in the tree as a composition CI keeps compiling;
its last image, clock-v0.1.5, stays on the v3.10.2 tag. EDITIONS in
release.py and check_versions.py is ("audio", "performance"); the card
and the AGENTS.md clause go with it.
- `release.py edition <name> vA.B.C`: one edition on its own - bump its
PF_VARIANT_VERSION and AGENTS.md clause, shelf.sh, point its card,
commit - with no core release, no tag, no changelog section. It is how
an edition's maintainer ships from a pull request; the core's
maintainer merges and does nothing else (docs/RELEASING.md). cut's
helpers are split so both commands share them.
- build.sh gains `one <composition>`: build one and scan its image,
with the marker tables and the scan factored out of `all`. The CI
workflow runs the five compositions as a matrix, one job each, so the
wall clock is one build instead of five in a row, and each job pins
its own static RAM (check_footprint.py --only).
- check_footprint.py pins midi (154,000 / 71,667) and re-pins the rest
after the knobs page: default +344 B DRAM / +156 B IRAM, audio +864 /
+156, performance +88 / +0, clock +352 / +156 - the knob settings and
the /knobs handler, all well inside tolerance.
- Docs say which bundles are published: EDITIONS.md, bundles/README.md,
RELEASING.md, AGENTS.md, CHANGELOG.
Verified: check_versions agrees with the shelf as it now is; the docs
link checker passes; the web typecheck passes with three cards;
`release.py edition performance v0.2.8 --no-build --no-commit` edits the
three files it should; `build.sh one clock` builds and scans.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
/features is the catalogue the shelf never was. The shelf answers "which firmware do I install"; this answers the question under it: what can a panel do, one feature at a time, what does each one need, and which firmware carries it. Features are the unit somebody develops, proposes and maintains, so they get a page rather than a bullet list on a card. Five groups, each with the reel that goes round on Instagram beside its cards: the panel itself (knobs, console, a pattern arriving from the community site); sound, one reel for the microphone, the browser extension and OSC, with a caption that says OSC into a DAW is not in it and works the same way; MIDI over Wi-Fi in Live, with the USB route named as the midi composition in the tree; the clock, now a feature with a recipe rather than a firmware on the shelf; and Simone's performance set - MQTT with its reel, sequences and the weather without one, and saying so. Features in the tree but in no firmware are listed at the end so nobody starts them twice. Reels are Instagram's own embed pages by permalink, in lazy iframes: no script of theirs on the site, nothing fetched until scrolled to, and the permalink under each for when an embed is blocked. The page shares the shelf's document shape and card (its CSS module is imported), and adds the one thing the shelf lacks: a sticky reel column that goes single-column with the reel first on a phone. Also: the sitemap, the shelf's lede, README's editions row, ARCHITECTURE's route table, AGENTS.md and the changelog name the page. Verified in the dev server: renders, five embeds load, no console errors, no horizontal overflow at 375px, typecheck and lint clean on the new files. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ys so. The catalogue's last section described Improv-BLE as something for whoever finishes it. It was tried, it did not work (the phone never listed the panel), and it was left in the tree as it was; the copy now says exactly that. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…rest. The first cut grouped the rows under headings that were the firmwares in disguise - "Sound", "MIDI", "Performance" - which put the shelf back one level up and lost the reason features and firmwares are separate things. It also needed a screen of scrolling per group. Now: one flat list, one line per feature - name, a one-liner, and a tag saying where it lives (every firmware, in Audio, in Performance, a recipe in the tree, did not work) - so the ten rows fit on a screen. A row is a native <details>: open it for the paragraph, what it needs, which firmware carries it (a fact on the row, never a category over it), the links and the reel. Reels stay Instagram embeds and load only when a row is opened; self-hosting was considered and rejected for the server's sake. Copy that changed with the shape: the clock's row says it is joining the Performance firmware and is a recipe until then; the sequences and weather rows have no reel and say so; the Bluetooth row says the attempt did not work. The shared sound reel says, on each of its three rows, which of them it shows. Verified in the dev server: rows are single-line on a desktop (46 px, the list 505 px for ten), name + tag over the line on a phone with no horizontal overflow, typecheck and lint clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
New post (ko+en): a vivid dream about a snake, the first artist edition going out signed with a certificate Hyunji designed, and a few low days before that. The certificate's front (recipient name already blurred) and its Patternflow-shaped back are joined into one image beside the paragraph about it, also the cover. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
… the panel slims down. Each Inside entry now has a title and one primary category, with a filter in the store and in the panel heading (with counts); a shared URL or Back that lands on a pin outside the filter widens it to All rather than losing it. The panel loses its second layer: contact links, the filtered list, a note asking for links and photos, journal and map links. The mobile viewer CTA and its styles go. CONTRIBUTING.md says how to add an entry and how to classify it (the subject, not its surroundings); the Inside subtitle now reads 'Builds, projects, and places where Patternflow comes to life.' Work from another session, committed here to ride the same dev -> main merge. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
engmung
added a commit
that referenced
this pull request
Sep 16, 2026
Dev: the Inside filter's files, missing from #434
This branch had an error being deployed
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.
What changed
New journal post —
a-strange-dream(ko + en), published 2026-09-16: a vivid dream about a snake, the first artist edition going out signed with a certificate Hyunji designed, and a few low days before it.One image, placed beside the certificate paragraph and used as the cover: the certificate's front (recipient name already blurred in the source photo) and its Patternflow-shaped back, joined side by side (2416×1600 JPEG, 430 KB).
Also on
devand carried by this PR (already committed there, not new work for this post):firmware:MIDI edition — the DevKit's USB port as a MIDI devicefirmware:knob direction and click size as settings, on a /knobs pagefirmware:the shelf is Core, Audio and Performance; an edition cuts on its own; CI builds compositions in parallelweb:the features page, one row per feature with a reel each, including the note on the failed Bluetooth attemptNotes
highlightset.dev(CONTRIBUTING.md, inside page, globe card) are not part of this PR.🤖 Generated with Claude Code