Changes since the last Release
Added
-
Real ChucK
MidiInon the bare-metal build (prototype; build-verified, on-hardware wake test pending).libchuck.ais now compiled with ChucK'sMidiIn/MidiOutdevice classes enabled (__DISABLE_MIDI__dropped from all three ChucK define sites —scripts/fetch_chuck.sh, the firmwareMakefile, andpod/Makefile.chuck, kept ABI-consistent), but withmidiio_rtmidi's RtMidi backend stripped: there is no OS MIDI API or callback thread on bare metal, andrtmidi.cpp(166 KB) stays out. A newMidiInManager::inject()feeds bytes straight into ChucK's per-VM MIDI buffer + event-wake path, so a.ckpatch can use the desktop-portableMidiIn min; min.recv(msg);idiom (examples/chuck/midi_in.ck) instead of host-specific globals. The full channel-voice MIDI stream is forwarded (real velocity, NoteOff, CC, pitch-bend, aftertouch, program change) plus system realtime (clock/start/continue/stop): a newIEngine::handle_midi_message(status, d1, d2)virtual (no-op for engines that only usehandle_midi_note) is driven from the UI MIDI poll (core.ui.midi.cpp) for every representable event;ChuckEngineoverrides it to enqueue raw bytes on a lock-free ring (chuck_midi_in.h), andChuckEngine::process()drains it and injects into device 0 on the run() thread, right beforeck->run(), so a shred blocked onmin => nowis woken that block.ChuckEngine::handle_midi_noteis kept only to map channel→deck for the panel gate-in LED. The vendored-ChucK edits live inscripts/patches/midi_daisy.patch, applied idempotently byscripts/fetch_chuck.sh(becausethirdparty/chuckis gitignored and regenerated). The firmware (make engine-chuck) links with matching ABI. Ported from thedaisy-appssibling project; replication guide indocs/dev/chuck-midi-in-porting.md, and the user-facing capabilities + remaining incompatibilities (noMidiOut, single virtual device / no enumeration, 3-byte messages only) are documented indocs/engines/chuck.md. (SysEx / system-common aren't representable in a 3-byteMidiMsgand are not forwarded; on-hardware wake test still pending.) -
mosc engine (
ENGINE=mosc) — a dual macro-oscillator on the Mutable Instruments Plaits DSP, hardware-verified.make engine-moscgives each deck a completeplaits::Voice— the full 24-engine Plaits synthesis voice (virtual analog, waveshaping, FM, wavetable, grain, additive, chord, speech, swarm, noise, particle, string, modal, drums, plus the newer "engine2" models: VA-VCF, phase distortion, 6-op FM, wave terrain, string machine, chiptune) — so the two decks are two independent oscillators. Knobs map Plaits' whole panel: PITCH = note, Alt+PITCH = engine select (24 models), SIZE = harmonics, POS = timbre, ENV = morph, MOD_AMT = LPG decay, MODFREQ = LPG colour, MIX = level. The per-deck Mode switch picks Gate (each trigger strikes the LPG/decay envelope — Play pad / gate-in / MIDI / Seq) vs Drone (LPG bypassed, engine runs open), and the global Routing switch combines the two voices three ways: Stereo (A→L, B→R), DoubleMono (mono sum), and GenerativeStereo (an out/aux spread that uses Plaits' otherwise-discarded auxiliary output for width). The three per-deck CV jacks are wired: V/Oct → note, CV_SIZE_POS → harmonics, CV_MIX → timbre. Like csound/chuck it is aBOOT_QSPIbuild (the 24-engine voice is ~292 KB of code, too big for the 186 KB SRAM_EXEC, so it executes from QSPI flash) — but unlike them it still synthesises from the platform SDRAM arena (a normal arena engine that merely executes from QSPI), so no SD card or external library is needed; the Plaits DSP is vendored in-tree (src/engine/mosc/thirdparty/plaits). Cloned from the reso engine (same author, samestmlib, same PIMPL + arena-placement pattern). User doc:docs/engines/mosc.md; internals, the QSPI build, and the 24-engine order indocs/dev/mosc-impl.md. -
Shared
stmlibfor the Mutable Instruments engines (reso + mosc). Both engines depend on Émilie Gillet'sstmlibsupport library; the two vendored copies were byte-for-byte identical (same upstream, unchanged for years), so they are now a single trimmed copy atsrc/engine/common/thirdparty/stmlib(the union of the Rings and Plaits closures, 19 files), shared via theSTMLIB_TP/STMLIB_INCmake vars. reso's formersrc/engine/reso/thirdparty/stmlibwas removed (its tree is nowringsonly); this is a dedup with no functional change.
Flashing an sk-engines firmware (0.5.1)
Each .bin here is a complete firmware for one engine. Flash exactly one at a time.
Prerequisite
These app binaries are not standalone: they run under the spotykach bootloader, which must
already be installed on the device. Installing the bootloader is a separate, device-level
procedure not covered here.
Step 1: enter bootloader mode
Both methods below need the device in its bootloader (DFU) mode first: hold Reset ~3s until
the bottom pad LEDs breathe white.
Step 2, option A: Daisy Web Programmer (easiest)
Needs a WebUSB browser - Chrome or Edge (Firefox and Safari will not work).
- With the device in bootloader mode, open https://flash.daisy.audio/
- On the "File Upload" tab, choose your engine binary (sk--0.5.1.bin).
- Click FLASH.
Step 2, option B: dfu-util (command line)
dfu-util -a 0 -s 0x90040000:leave -D sk-<engine>-0.5.1.bin -d ,0483:df11
Verify
- Confirm the download is intact:
shasum -a 256 -c SHA256SUMS - Confirm what a binary is:
arm-none-eabi-strings <file>.bin | grep '^spotykach '
(prints e.g.spotykach 0.5.1 engine=reverb)
Note for the csound and chuck and mosc engines
sk-csound-*.bin and sk-chuck-*.bin and sk-mosc-*.bin are QSPI apps: unlike the other engines they execute in place from QSPI flash
(their language runtimes are too big for SRAM), so they are also larger downloads and take longer to
flash. Same address and steps as above, with two caveats:
- They need a bootloader that runs QSPI apps (the spotykach bootloader does); a SRAM-only
bootloader cannot run them. - With
dfu-util, the:leavestep may print a harmlessError 74/ "get_status" message at the
end - the write has already succeeded. Ignore it (the Web Programmer does not show this).