Skip to content

Releases: jonwaterschoot/TouchPlaited

TouchPlaited v1.9.0 — the kick bank

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 08 Aug 10:43

TouchPlaited v1.9.0:

  • The kick stops being random. Eleven kicks chosen by ear replace the kick pad's engine-and-range pool — deep 808s, sweeping 909s, a stacked 909-over-808, and a few from engines never meant to be drums.
    • Step them with P0 + P10/P11 while the pattern plays; the screen names each one (K05 909 SWEEP).
    • Three knobs become Tone / Punch / Body, bounded per preset so they mean the same thing on every kick and can't be turned out of kick territory.
  • The kick is a priority voice now — protected from being cut for the first 150 ms of every hit.
  • Two voice-pool faults fixed, one of them latent since the drum sequencer shipped: the pool was cutting live drum tails while finished voices sat idle beside them.

https://github.com/jonwaterschoot/TouchPlaited/releases/tag/v1.9.0

Two things to expect when you flash this. Your saved settings reset once — the kick's preset identity is not something a slot's parameters can carry, so the record layout changed and old records are discarded rather than misread. And randomized kits sound different: the kick now draws a named preset instead of rolling an engine and a parameter range.

The full LLM overview of this round of changes:

The LLM overview:

The open question was "can more kicks come from existing engines, or do they need writing?" The answer was yes to the first — nothing was added to the Plaits DSP, and no new engine was needed. What was missing was reachable parameter space, in four places you only find by reading the DSP rather than the knob names.

Twenty candidates were built, auditioned on hardware twice, and eleven kept. What the listening cut was a family and a technique rather than a scatter of numbers.

The part that wasn't on the plan is three voice-pool faults, two of them older than this work. They only surfaced because the kick finally had a tail worth holding a voice for.

Why the old kick was two mediocre choices

The kick pool was two engines wide, and neither entry was reaching the good part of its own engine:

  • Engine 21 renders two different drums — an 808-style analog one on OUT, an "inadvertently 909-ish" synthetic one on AUX — and the Blend fader crossfades them. But the kit randomizer pinned blend at 0.5, so every random kick was the same half-and-half compromise. That was the "very synth sound".
  • Engine 10 plays two octaves below its note. The pool's 36–48 range put the FM kick's fundamental at 16–33 Hz with a modulation index of 0.18 — an inaudible fundamental and almost no harmonics. That was the "low energy" one.
  • Tails were cut twice, by a short pool range and then again by Tightness. The analog resonator's Q is 1500 · 2^(morph·80/12); the long kicks weren't missing, they were unreachable.
  • harmonics on engine 21 is three controls in a row — attack FM, then self-FM, then overdrive on the analog side; sweep depth then sweep length on the synthetic side. Both the grit and the long pitch drops live above 0.5, where the pool's range stopped.

What the auditions cut, and why it's worth knowing

  • All six 2-op FM presets read as regular synth rather than as drums. That's one verdict about engine 10, not six sets of numbers: its only envelope is the LPG in ping mode, so an FM kick has no pitch drop of its own and lands as a bass note with a fast decay. It can be tuned into kick territory; it arrives there sounding like a bass note.
  • Two of three layered presets failed — a noise transient over a deep 808 crackled, an FM snap sat too high — while the one that layers engine 21 with itself survived. A layer has to be the same instrument twice, or it reads as a fault or as a second sound. That one is also the cheapest of the three: one engine, both of its drums, no second render path.
  • One preset was cut in the second pass for a resource reason, and it turned into the most useful finding of the round — see The LPG tail trap below.

All four "outside bet" engines held up, which was not the expected result.

Added

  • The kick bank — eleven fixed, numbered kicks in synth/kick_presets.h, reachable three ways: P0 + P10/P11 steps it from Seq or from Recording on the kick pad; P0 + S35 at full right is a 12th model position (KICK BANK) past the eleven engines, on the kick pad only; and S32 sweeps the whole bank once a preset is loaded. It rails rather than wraps, with the usual limit blink at each end.
  • Tone / Punch / Body on S33 / S34 / S37. These are named for what they do to a kick, not for the engine parameter underneath — they land on the same three fields whatever engine each preset is built from, and each sweeps inside a window chosen for that preset. So one gesture means one thing across all eleven, and no knob can be turned out of kick territory (full-travel harmonics on Additive is a chord; full-travel resonance on VA+VCF is a whistle). Nothing was taken away to make room: S37 in Recording was already the OUT↔AUX blend, which on engine 21 is the 808↔909 control — it only gains bounds and a better name.
  • Kick voices are stolen and shed last, protected for a fixed 150 ms from each strike. That covers the attack and body, which is the part whose loss reads as a dropped downbeat.
  • The screen names what's loaded — on the confirm flash, on S32's own readout, and in the status row while you're recording the kick pad. Held-modifier lists and the P0+P10/P11 callout name it too.

Changed

  • The kick's random pool is the bank. kDrumKick is deleted — its two entries were exactly the two rejected sounds, and for reasons a parameter range can't fix. A randomized kit now gets a kick somebody chose, and one you can name afterwards. The other six slots keep their engine-and-range pools, where the variety is the point.
  • Drive's push on the kick is per preset. It works by opening the kick's timbre, which on the bass drum engine is also its brightness and click — so turning Drive up used to make every deep kick bright. Deep presets take 0.15–0.35 of it now; bright ones keep most.
  • A loaded kick preset is exempt from Tightness. S37 compresses every other morph-decay tail by up to 5×, which is enough to make the deep presets unrecognisable. Per-slot decay (S31 in Recording) is the right way to shorten one kick.
  • Drum one-shots sleep at −60 dBFS instead of −80. A pitched voice is held by a finger and its release tail is worth following to the noise floor; a drum's last 20 dB is inaudible under a kit, while the voice it occupies is not.
  • The settings record layout changed (see the note at the top).

Fixed

  • The voice pool never reused sleeping voices — latent since the background drum sequencer shipped. Drum voices never get a NoteOff, so their slot id stays set forever and the free-slot scan could never see a finished one; the pool went straight to stealing the oldest sounding voice while a silent one sat unused beside it. With six voices shared by seven drums that happens constantly. This was the single biggest cause of drum tails being cut short, and it had nothing to do with the kick.
  • The LPG tail trap. Presets on non-drum engines are the only ones whose tail is Plaits' low-pass gate rather than the engine's own envelope, and the LPG in ping mode ignores the one-shot gate entirely and falls violently slowly. Measured off the envelope code: decay 0.45 holds a voice for 2.5 s, 0.60 for 4.5 s, 0.72 for 7.4 s. One preset was authored at 0.72, so every kick masked the kit with four seconds of 55 Hz sine and permanently cost one of six voices. It's cut; the other two LPG presets are re-authored down to 0.34 / 0.30; and the −60 dBFS sleep threshold above is the net under it.
  • Kick priority, first attempt, reserved rather than prioritised. Keying the protection on "still making sound" held one or two of six voices for most of a bar with the new long kicks, and the other six drums thrashed what was left. It's a 150 ms window from the strike now. (The tell was that a freshly randomized kit sounded right for about a bar first — for that bar the oldest voices still belonged to the previous kit and had already finished, so stealing them was inaudible.)
  • S37's pickup was armed against the wrong value on the P0 release edge while recording a kick preset — the raw blend rather than its position in the Body window. Several presets sit at blend 0.0, so that armed a rail, which catches on any 3% nudge; Body jumped the moment S37 was touched after using P0 for anything, the preset stepper included.
  • Engine 0's harmonics and timbre were swapped in the engine reference table. Harmonics is resonance and timbre is the cutoff, not the other way round. The visualizer always had it right, so the table was the only place the error lived.
  • Four stale claims in MANUAL.md, found by reading it against the source rather than against the notes — including a kick pool that no longer exists, and a voice-cost figure that was true of two presets that had been cut.

Visualizer

The webapp mirrors all of it over protocol v12: a new state byte carries which preset is loaded, so the app names it on the emulated screen, on the P0+P10/P11 and S32 callouts, in the Recording status row, and logs every change by name — the on-device flash is gone in 220 ms, and a curation pass needs to be readable afterwards. Older firmware simply reports no preset; the decoder guards on frame length as it always has.

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

...

Read more

TouchPlaited v1.8.0 — the screen answers back

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 07 Aug 02:03

TouchPlaited v1.8.0:

  • The OLED is a real UI now (status row, hold progress bars, knob-pickup screen, arp pool),
    • e.g. I added info that shows what the modifiers combo's are.
  • two audio bugs that found
TouchPlaited_dynamicvisualizer_v1-8
The full LLM overview of this round of changes:

The LLM overview:

Two rounds in one release. The 128×32 OLED stops being a mirror of the last thing you touched and starts answering questions — what's loaded, what a held combo is about to do, why a knob isn't responding. And building the instrumentation for that turned up two audio faults that had been described as separate mysteries: the output stage was saturating every voice from silence, and four held notes on an expensive engine sat above the load-shedder's threshold with the shedder structurally unable to fire.

Neither of those was on the plan. The screen work is what found them.

Added

  • A status row. ~2 s after you stop touching anything the screen stops showing the last action and says where you are instead — Seq shows genre and transport, Rec shows which pad you're editing and cycles between what's loaded in it and the two ways out, Arp/Mel and Basic Pitch show the sub-state and the loaded model, and Basic Pitch adds the root next to the scale.
  • Held combos show a progress bar, with a note under it saying what crossing the next threshold does, then a flash confirming what changed. The re-randomize holds, the sound-edit toggle and the recording entry all report themselves this way instead of leaving you counting seconds.
  • A held modifier lists what it unlocks. Hold P0, P1 or P2 without pressing anything else and the screen fills with that modifier's combos, scrolling if there are more than four.
  • Knob pickup got its own screen. The value row shows the stored value that's actually in effect, in its own units — a BPM, a note name, a word — and a track underneath carries a tall post at the value the pot has to reach and a block at where the pot is now. Drive the block onto the post and the knob takes over. No arithmetic, and it works the same whatever the value is.
  • Arp/Hold shows the note pool. Seven columns, one per musical pad, each naming its pitch class with a filled marker if it's in the pool and a hollow one if it isn't. It's also the idle home screen while notes are latched, because in Hold you can't look at the pool by pressing a pad — pressing a pad is what takes notes out of it.
  • A live capture indicator. A blinking circle top-right marks the two states you have to leave deliberately: Seq slot editing, and live capture in Arp/Mel Rec. Alongside it, five dots track the recording layers — filled, hollow for muted, and the take being recorded into pulses with the circle.
  • Step chance on S34 in Seq, replacing Punch. Punch was a single global knob feeding only the kick's timbre; S34 now scales every step's own authored chance up or down instead. The screen names the zone rather than showing a percentage, because a raw % reads backwards here: always fire at full left, as authored at center, sparse 2.4x to the right. Steps authored "always" — a four-on-the-floor kick — are never affected. Punch isn't gone: the kick can be any model, so the parameter still exists and now rides Drive (S30) as double duty on the models where it applies.
  • Named density stages on S33: strong · main · ghosts · full, so you can see which weight layers are firing instead of reading a percentage. The range is 1–4 now, so knob-minimum no longer reaches a silent state.
  • S35 names the pattern, and its position in the genre — fourfloor 1/6 rather than a percentage.
  • Recording transport cycles. In Arp/Mel Rec, P2 + P10 now goes capturing → looping (punched out) → stopped, rather than only starting and stopping — punching out stops new capture and leaves the loop running.
  • Drum hits carry the pattern's accents as MIDI velocity on ch 10. Everything you play still leaves at velocity 100 (the pads aren't pressure-sensitive); sequencer steps are the exception.
  • Five new drum patterns, and the pattern editor's round-trip is fixed.

Changed

  • Held-note ceiling is now per engine — 3 on the expensive ones (Six-Op A/B/C, Speech, Particle, String, Modal), 4 elsewhere, replacing v1.7.0's flat 4. Measured on hardware with Six-Op C: idle 16%, then 41 / 58 / 75 / 92% for one to four held voices — so four held already sits at 92-95% against a 90% shed threshold, and gate-held voices are exactly the ones the shedder can never touch. A fifth note briefly makes five awake voices, since the released one's tail keeps rendering; that transient is the crackle, and it's why the fault seemed intermittent.

  • The output limiter has a linear region instead of bending from zero. The old curve was x/(1+|x|), which has no linear region at all: a single quiet voice was already ~3.5 dB down and shaped before anything came near the ceiling, and four voices under a hall tail put 5–6 into the curve for roughly 15 dB of saturation across the whole waveform. That is what "distorts at polyphony 4" actually was — gain staging, not CPU. Below the knee the signal now passes untouched; above it the same curve takes over, rescaled so value and slope match at the crossing.

    Two things to expect when you flash this. The instrument is ~5 dB louder at one voice than it was — check your levels before you play. And one-to-four voices now spans +0.8 dB where the old curve gave +4.1 dB, so chords sound cleaner but add less weight; a bounded output with an unscaled voice sum has to compress somewhere. Both are tunable at kLimitKnee if you build your own.

  • Arp octave range moved to P0 + P10/P11, and undo layer took over P1 + P10. The screen names the octave span it lands on rather than just the direction.

  • OLED redraws cost much less: only changed pages go out to the display, and the shared-bus interlock with the MPR121 touch controller is held per page rather than per frame — which is what makes the 40 ms redraw interval safe. Worth knowing if you're chasing frame rate: the ceiling is audio load, not the bus. At 79% CPU a frame took ~52 ms against ~13 ms of actual I2C traffic. Moving the display to its own faster bus was built, rewired and measured, and changed nothing observable — the flag survives as -DOLED_I2C4 (it costs TRS MIDI), but there's no reason to use it.

  • libDaisy bumped for the SSD1306 128×32 driver fixes (also filed upstream as electro-smith/libDaisy#634) and a UART error-callback fix.

Fixed

  • The genre switch was one position out. SW1's raw reading (0 centre, 1 up, 2 down) was mapped to a panel position before being displayed, but the genre latch indexed the pattern registry with the raw value — so display and audio disagreed by one position: panel-left labelled IDM played Electro, and so on around. Both now go through the same mapping. Boot still lands on Techno.
  • The base octave hit its rail silently. P10/P11 in Basic Pitch clamped at ±3 with no LED blink, while root, arp octave range, the layer stack and undo all blink at their limits. Every rail on the panel answers the same way now.
  • Frame timing used a microsecond counter that wraps every ~21.5 s, so the measurement build reported nonsense roughly three times a minute.
  • Seven documentation bugs found by reading MANUAL.md and README.md against the source rather than against the notes — including a MIDI-out claim the accent work above had made false in the same document, and a voice count that had never been right.

Visualizer

The webapp mirrors all of the above over protocol v11, and then got a pass of its own:

  • The emulated 128×32 screen stopped tracking the drawing below a certain size — it clamped its dot grid and then sized itself from the clamp, so at small zooms it floated clear of the panel entirely.
  • The expanded display sat on the user LED, hiding the limit and state blinks, which read nowhere else on the drawing.
  • Every display setting is now in one settings bar instead of two rows that had each grown their own idiom, and the menu is grouped rather than one flat list.
  • Mobile: the drawing sizes itself to the viewport without pinching (100vh was the viewport with the phone's URL bar hidden, so the bottom of the device sat under the browser chrome), re-fits when you turn the phone, and there's a Keep screen awake toggle — which is the thing that actually breaks a mobile session.

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md

TouchPlaited v1.7.0 — voice cap & fader taper

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 03 Aug 22:57

This release is mostly about playability: fixing a real crackle you can trigger on purpose, and making the volume faders usable at quiet settings. It also adds a boot animation and a couple of doc fixes.

Added

  • 4-voice cap on Basic Pitch. Gate-held voices were never touched by the emergency load-shedder, so a 5th simultaneously-held Basic Pitch note on an expensive Plaits engine could push an audio block over the CPU budget with no way to recover — sustained crackle for as long as the note stayed down, instead of a clean voice steal. A 5th held note now force-releases the oldest one first, matching the confirmed-stable 4-voice ceiling.
  • dB taper on the volume faders (S36). The fader was raw linear gain, so dialing a quiet mix-under-drums level left almost no usable travel at the bottom of the knob. It now maps linearly to dB instead (0 = -50dB, 1 = unity), so the quiet end gets roughly half the fader's travel — knob 25% ≈ 1.3%, 50% ≈ 5.6%, 75% ≈ 23.7%, 100% = unity.
  • OLED boot animation + audio fade-in. TouchPlaited materializes letter by letter (Plaited emphasized one font size up), holds, then disintegrates into scattering particles before settling into a status line reporting whether SettingsJournal restored a prior session. The user LED slow-blinks through loading and flashes once ready, so a unit with no screen attached still shows boot progress. The master output also ramps up from silence over the first 60ms of real audio, so whatever fader position block 0 lands on doesn't hit the DAC as a hard-edged onset.

Fixed

  • Stale SW1 left/right wiring docs in notes.md and a code comment — the actual mapping (per MANUAL.md, the scale/genre tables, and the visualizer) is left=Minor/IDM-Ambient, right=Major/Electro.

Docs

  • Bootloader install instructions.
  • README/MANUAL now cover the boot animation and its LED blink code.

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md

TouchPlaited v1.6.0 — physical OLED screen

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 28 Jul 15:25

TouchPlaited now has an on-board screen: a physical 128×32 OLED that mirrors what the visualizer shows, live, right on the faceplate.

Added

  • Physical OLED (128×32 SSD1306). Shows the last-touched control's label and value using the same three-tier bitmap font stepping (Font_11x18 → Font_7x10 → Font_6x8) and the same control/pad description logic the visualizer uses, so the panel and the physical screen read the same thing from the same telemetry. Seq tempo shows as BPM instead of a raw percentage.
  • Held-combo progress bar + confirm flash. Holding P0+P2 (re-randomize / vary sound), a drum pad (rec entry), P2+pad (layer clear), or the copy gesture now fills a bar toward its threshold and flashes a confirm ("Stage 2", "Recording", "Cleared", "Copied"...) on both the physical screen and the visualizer — matching the LED's own build-up rate and priority order exactly.
  • Two new techno patterns — Minimal and Tropical Sunset — plus fill and groove reworks to Four-on-floor and Rolling.

Fixed

  • A vendored libDaisy SSD1306 driver bug: the 128×32 panel's Update() used the wrong column-start command, wrapping every redraw 32 columns to the right. It also sent one I2C transaction per byte instead of batching a page, cutting a full-screen redraw from ~524 transactions to ~16.

Display / visualizer parity — work in progress

The physical screen and the visualizer's emulated one are still being brought into lockstep. This release includes a crispness fix for the emulator's font rendering (it now blits the firmware's actual bitmap fonts pixel-for-pixel instead of a system font), but a full mode-by-mode wording check against real hardware is still ongoing — expect more polish here over the next few releases.

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md

TouchPlaited v1.5.0 — settings memory

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 23 Jul 01:28

The Simple Touch now remembers where you left it. Power-cycle the device and it comes back with the same sound, kit, and settings — no save button, no SD card, nothing to do.

Added

  • Settings memory. A few seconds after you stop changing things, the current state is written to the Seed's QSPI flash automatically and restored on the next boot: the engine and effective Basic Pitch params, per-mode volumes/drives/blends, FX sends, all seq settings and the genre, octaves and root, the drum kit, the Basic Pitch randomize snapshots, and the arp's and Rec's independent sounds.
  • Restored values follow the same pickup doctrine as everything else: a pot doesn't take over until it crosses the value it's holding, so knobs sitting in arbitrary positions at power-on never stomp the restored sound.
  • Deliberately not saved: whatever a physical switch dictates at boot (SW2 playmode, SW1 scale), transport states, and the note recorder's loop content (that's a take, not a setting). First boot after flashing still starts randomized — it remembers from your first tweak onward, and settings survive firmware reflashes too.

Under the hood

This firmware executes from the same QSPI chip it saves to, which libDaisy's storage helpers refuse outright — so saves go through a small SRAM-resident flash routine and an append-only, CRC-checked journal that never needs a (slow, audible) sector erase while audio runs. Writes cost ~1 ms in a gap the audio interrupt rides out, wear is negligible by construction, and a save torn by a power cut simply falls back to the previous one. Two STM32H7 hardware traps are handled along the way — an MPU guard against speculative-prefetch bus stalls, and a guard band below the top of flash for the QUADSPI prefetch erratum (both documented in the README).

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md

TouchPlaited v1.4.0 — unified Decay, knob rail fix, telemetry v3

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 19 Jul 13:59

Hardware-feedback round on the Arp/Mel playmode, plus a fix that affects every knob: the pots now reach a true 0–100%.

Changed

  • Arp/Mel knob layout: Decay moved to S31 — the unified Decay knob, same position as every other mode. Division/Swing/Density shifted one knob right to S32/S33/S34; Order stays on S35.
  • Six-Op FM joins the unified Decay (engines 2–4): S31 Decay now drives the DX7 envelope time (routed via MORPH — the LPG is bypassed on these engines, so the old Decay knob did nothing there). S34 has no effect on them, like the other morph-decay engines.
  • Drum patterns renamed to unique flavor names, with a deterministic default order per genre (order.json). The pattern editor got a DAW-style grid, a guided workflow, and folder-order tools.

Fixed

  • Pots reach the rails. The hardware tops out around 96–97% of the ADC range, so anything stored at a rail was unreachable — most audibly full arp Density (needs ≥ 98.4%), which always masked one step in 16. The firmware now rescales a fixed guard band ([0.5%, 95%]) to a clamped 0–100%: full Density fills 16/16, and every continuous parameter regains its top few percent.
  • Knobs armed to a rail target (arp Density/Order defaults) also pick up on ~3% of deliberate movement, so they no longer feel dead after a mode change.

Telemetry v3 (visualizer)

STATE frames add the Arp/Mel sound-edit flag and the recording slot; a new KIT frame carries the drum kit (engine/harmonics/timbre/morph/decay/note per slot). The hosted visualizer uses these for its live knob map (with per-engine labels and "no effect on this model" hints), the Seq kit grid, and rec/sound-edit label swaps — plus a new label-overlay cycle (dyn live callouts / S# designators / Aa full faceplate labels). Older firmware still works with the app; it just misses these extras.

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md — now with a Visualizer webapp section.

TouchPlaited v1.3.0 — Arp/Mel playmode

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 16 Jul 02:25

Replaces the Random playmode (SW2 center) with Arp/Mel: an arpeggiator and layered note recorder built around the pads and the existing pitched-mode knob layout. Last Random-mode firmware is preserved on the random-mode tag if you want to go back.

New

  • Arp: note pool with plain add/release or Hold (latch with re-touch toggle), five order modes on S35 (played/up/down/pingpong/random), S31 division against the master 16th clock (1/4–1/32), S32 swing, S33 Euclidean density (steady fill or fill + 75% chance), and octave range expansion on P1+P10/P11. Runs off the internal block clock or external 24 ppqn MIDI ticks.
  • Rec: layered note recording on the pads — 4 layers × 48 events, fixed 2-bar loop from the first note, wrap commits a pass as a new layer, undo pops the open take then the newest layer. Clear gestures: hold P0+P10 ~1.5s clears all layers, P0+pad 1–4 clears just that layer.
  • Independent arp sound: the arp's voice is no longer tied to Basic Pitch — it's seeded from the live BP sound once, on first-ever Arp/Mel entry, and never re-latched, so switching BP's sound afterward doesn't retroactively change a running arp or loop. Arp/loop/MIDI-arp voices carry a new arp_owned flag in the voice pool so BP's live knobs can't reach them.
  • Sound edit sub-mode: hold P0+P1 ~1s to swap the knobs to the BP layout (drive/decay/h/t/m) on the arp's own model, so you can dial in its sound without disturbing Basic Pitch. Auditions on entry, exits on re-toggle, SW1 state change, or mode re-entry (all through knob pickups).

Notes

  • Loop length is fixed at 2 bars for now (confirmed workable on hardware).
  • Not yet in this round: Rec knob morphs, MIDI-in into the arp/loop pool, and arp sub-state (SW1 position, pool contents) in visualizer telemetry.
  • See ARP-MEL-PLAN.md for the full design history and hardware-round notes.

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md

TouchPlaited v1.2.0 — Six-Op FM playability

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 10 Jul 01:38

Makes the three Six-Op FM models (the DX7-compatible engines on P0, models 3–5) actually playable. They were nearly silent over most of their range and fired only on every second pad press — the root cause was a 0.5 ms trigger pulse in the voice wrapper meeting the only Plaits engine with real DX7 key-on/key-off gate semantics. The factory DX7 banks were always on board; they just never got a gate long enough to speak.

New

  • Real gates for Six-Op: pads now hold the DX7 envelopes keyed for the whole press — pads, organs and strings sustain and release on lift, and MORPH's envelope stretching is finally audible. Drum-seq hits and auditions key off on a decay-scaled gate (20–400 ms) instead.
  • Preset browsing feedback: while a Six-Op model is active, the LED blinks once each time S32 steps into one of the 32 DX7 presets.

Fixed / improved

  • Six-Op sounding only on every second press — fixed (the short pulse was landing on the engine's two alternating, render-staggered voices on the wrong parity).
  • Six-Op level padded −14 dB: the engine is registered hotter than anything else in Plaits (unity gain, LPG bypassed), and sustained FM chords saturated the output stage even at low volume.
  • Note-start clicks on Six-Op retriggers/voice steals are masked with a ~3 ms fade window aligned to Plaits' internal trigger delay — DX7 attack character is untouched.
  • Voice stealing now always produces a clean retrigger edge, even when a voice is reused while its gate line is still high.

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md

🤖 Generated with Claude Code

TouchPlaited v1.1.0 — reverb & delay FX

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 09 Jul 23:50

Adds a stereo FX section and a round of SEQ-mode UX and hardware fixes.

New

  • Reverb + delay FX on the P1 knob layer (P1+S30 / P1+S35): center-off knobs — turn left of center for character A (room / slapback), right of center for character B (hall / synced dotted-1/8). The synth and drum groups each have their own send level; the shared character follows the last edit.
  • Per-slot FX send trims in drum recording (P1+S30 / P1+S35), so each recorded drum slot can sit differently in the reverb/delay.
  • FX over MIDI: CC 85–88 address the synth and drum FX sends separately, same center-off encoding as the knobs — automate the drum reverb while playing a pitched mode.

Fixed / improved

  • SW1 is now change-latched per role, so flicking through playmodes no longer jumps scale or genre.
  • Fixed the dead user LED on Seeds with older bootloaders (LED GPIO is now initialized regardless of bootloader version).
  • Better LED patterns in SEQ record mode, and saving no longer immediately re-enters record; the beat pulse is demoted below rec feedback so it stays readable.
  • Removed the particle noise model from the auto drum selector in Seq mode.
  • Reworked the model table and its spread over P0+S35 / P1+S35 (see MANUAL.md).

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md

🤖 Generated with Claude Code

TouchPlaited v1.0.0 — first stable version

Choose a tag to compare

@jonwaterschoot jonwaterschoot released this 07 Jul 23:53

First stable version of TouchPlaited — a Synthux Simple Touch firmware based on Mutable Instruments Plaits.

  • Touch synth: all 24 Plaits models, three playmodes (Basic Pitch / Random / Seq), per-slot sound recording with copy, stereo width + OUT/AUX blend
  • Drum machine: 16-step generative sequencer, three genres (techno / electro / IDM) with selectable patterns and chance steps, runs in the background under the synth modes
  • MIDI in/out on USB and TRS: notes (ch1 pitched / ch10 GM drums), CC20–31, full clock + transport sync (follows external clock, sends its own when master)

Installing

TouchPlaited.bin runs from QSPI flash, so the Daisy bootloader must be on the Seed first (one-time per device — see the README). Then put the Seed in bootloader mode (tap RESET, LED pulses) and upload the .bin with the Daisy Web Programmer, or:

dfu-util -a 0 -s 0x90040000:leave -D TouchPlaited.bin

Full controls reference: MANUAL.md

🤖 Generated with Claude Code