Firmware for the Hermetic Modular Alchemy Lab V2 · mi-alchemy v0.2.0

Plaits24 synthesis models behind four knobs, on the Alchemy Lab

Mutable Instruments' macro-oscillator, unmodified, running at its native 48 kHz. Pick a model, set the pitch, and shape it with HARMONICS, TIMBRE and MORPH. A trigger hands the sound to Plaits' low-pass gate and decay envelope.

Built and native-tested · not yet flashed or heard
Orange: Plaits 1.2 models · green: the classics · red: noise, physical models, drumsTap a model to open it on the ring below
The PLAY page as the firmware draws it, with MODEL on its first-boot model, Virtual analog.

What it does

This is Plaits, Emilie Gillet's macro-oscillator for Mutable Instruments, compiled for the Alchemy Lab. All 24 models are here: the eight added in Plaits 1.2, the eight pitched classics, and the eight noise, physical-model and drum models. The DSP is plaits::Voice from the eurorack repository, byte for byte. The firmware around it does what Plaits' own ui.cc and settings.cc did, on six pots, three buttons and ten jacks.

Untriggered, the model drones. Once a trigger arrives, on J3 or from B1, Plaits' low-pass gate closes between hits and its internal decay envelope runs, shaped by DECAY and LPG COLOUR.

The original has four big knobs, three attenuverters, two model buttons and a set of hidden settings reached by holding a button and turning a knob. Here the performance controls sit on the PLAY page. The attenuverters and the hidden settings move to a SETUP page you hold B3 to see. A single MODEL selector replaces the two model buttons, and B2 jumps between banks.

Out on J9, the model's auxiliary output on J10. The inputs J1 and J2 are unused: they are AC-coupled, and Plaits' FM input needs DC.

The panel

Pick a page, then hover or tap any pot, button or jack. The rings are drawn the way the firmware draws them: selectors as dots, levels as arcs, bipolar controls fanning out from a white centre.

Select a control

The panel

6 pots × 2 pages · 3 buttons · 10 jacks
Front view, left to right and top to bottom: P1, B1, P2 on the first row; P3, B2, P4; P5, B3, P6. Below them the USB-C port and the ten jacks, inputs on the left and outputs on the right.

Buttons

B1 · STRIKE. A press is a trigger, and holding it holds the gate, just as a gate on J3 would. It strikes the drums and physical models, clocks the Chiptune arpeggiator, and opens the low-pass gate. It is ORed with J3.

B2 · BANK. A tap jumps MODEL to the same position in the next bank: model 9 goes to 17, 17 to 1, 1 to 9. The stored value moves, so the ring follows and the change is saved, and the MODEL pot has to catch its new value before it takes over again.

B3 · SETUP. Hold it to show the SETUP page on the pots. Let go and you're back on PLAY. B2 stands down while B3 is held, so the Settings chord (B2 + B3 for two seconds) never jumps a bank on the way in.

The model ring

CLASSIC · MODEL 9 OF 24
Virtual analog

Twenty-four models share one pot, and the ring's lit arc is 13 LEDs, so MODEL moves one model about every 4 % of travel and most LEDs cover two models. The firmware draws the ring itself, from the model that is playing:

  • Every LED is dim in the colour of the bank its models belong to: orange for 1.2, green for the classics, red for noise and drums. The three banks always show as three stretches of the arc.
  • One LED is bright: the model that is sounding, in its bank's colour, at LED floor((model + 0.5) × 13 / 24). It is drawn from the engine itself, not from the pot, so the ring and the sound always agree.
  • B2's colour repeats the bank. Model names are in the web programmer and in the table below.

The 24 models

What HARMONICS, TIMBRE and MORPH do on each model, from how each engine in the vendored source uses them. Models marked own envelope render their own amplitude envelope, so Plaits skips the low-pass gate on them. That flag is set in voice.cc.

ZoneModelHARMONICSTIMBREMORPH

Pitch

FREQUENCY sets the pitch, over the range picked by OCTAVE on the SETUP page, and J5 adds 1 V per octave. The formulas are Plaits' own ui.cc, except FINE, below. Try them:

note
C4

Plaits' pitch maths assumes its original codec rate, 47,872.34 Hz (dsp.h). The Lab runs at 48 kHz, which would put every note 4.6 cents sharp, so the firmware subtracts 12·log2(48000 / 47872.34) = 0.046 semitones and notes land in tune. What remains is libDaisy's clock, which runs the codec about 250 ppm fast: roughly 0.4 cents sharp, not corrected.

OCTAVEWhat FREQUENCY does
LFOSub-audio: note −48.4 at the left to +11.6 at the right. The whole sweep is 60 semitones.
C0 … C7Fixes the octave. FREQUENCY spans ±7 semitones around it.
OctavesFREQUENCY steps in octaves, 9 steps with hysteresis, centred on C4.
FreeThe factory default: an 8-octave sweep, note 12 to 108, with C4 at noon.

FINE is not upstream's. On a real Plaits, fine tune (hold FREQUENCY and turn) only works in the Octaves range and spans ±7 semitones. Here FINE is a ±1 semitone trim that works in every range. Octaves mode uses fine tune's centre.

Triggers and the low-pass gate

A real Plaits sends a probe signal through its normalled jacks to tell a patched cable from an empty jack. The Alchemy Lab has no probe, so the firmware decides each "patched" flag another way.

TRIGGER is a Settings switch (Settings 1, P2):

  • Auto (default): drones until the first trigger on J3 or B1 since power-up, then stays gated until the next power-up.
  • Drone: never gated.
  • Triggered: always gated, silent between hits.

A timeout back to drone was considered and rejected, because the gate would then open by itself after a quiet spell.

LEVEL CV (Settings 1, P5, off by default). When on, J4 drives the low-pass gate directly, replacing the internal envelope: an envelope, or a VCA CV. 0 V on J4 is then silence, which is why it defaults to off.

TIMBRE and MORPH (J6, J7) count as patched while more than 50 mV has been seen there in the last two seconds. The flag only chooses what the attenuverter scales: the CV when patched, the internal envelope when not. A wrong guess is audible but harmless.

FM is never patched: this port has no FM jack. So once the module is triggered, the FM attenuverter sets how far the internal envelope sweeps the pitch. On the Speech model it sets the prosody.

Jacks and CV

Every CV jack is read directly in the audio callback, with Plaits' own default calibration scaled to the Lab's ±5 V inputs. None of them goes through the SDK's CV matrix, so they cannot be re-routed from the web programmer.

JackDoesScaling and reading
J1, J2UnusedAC-coupled codec inputs. Plaits' FM input needs DC, so they stay free.
J3TRIGGERGate on above 1.5 V, off below 0.5 V, read every 24-frame block (0.5 ms). Plaits adds its own 1 ms trigger delay.
J4LEVEL0.2 per volt, 0 to 1. Only with Settings LEVEL CV on.
J5V/Oct12 semitones per volt from the calibrated jack, smoothed as ui.cc smooths it.
J6TIMBRE CV0.32 per volt, times the TIMBRE attenuverter.
J7MORPH CV0.32 per volt, times the MORPH attenuverter.
J8HARMONICS CV0.2 per volt, added directly. Plaits has no attenuverter here either.
J9OUTThe model's main output.
J10AUXThe model's auxiliary output: a variant, a sub, or a raw signal, depending on the model.

Reading the lights

MODEL ring. The three banks as dim stretches of colour, with the playing model's LED bright, as described above.

Other rings. The SDK draws them from the knobs. FREQUENCY, FINE and the attenuverters are bipolar and fan out from a white centre dot, so noon is off. OCTAVE is an 11-dot selector.

B1 is white while the trigger (J3 or B1) is high. Otherwise it glows dim, brighter as the output gets louder.

B2 shows the active bank: orange, green or red. It turns red when the audio callback averages over 80 % CPU.

B3 has a dim Setup tint while you're on PLAY.

P1 at boot. For 2.5 s after power-up, the P1 ring shows the previous session's worst audio-block load. Green is under 75 %, amber is under 90 %, and red is 90 % or more. A single dim blue dot means there is no data yet, as on the first boot after a flash. CPU is the main thing to watch on this build.

Firmware on the card

Download v0.2.0 · built and tested on a computer, not yet run on a module

plaits_alchemy.binSD card zip · all seven

The zip holds all seven firmwares and the Elements samples, laid out for the card: unzip it onto the card's top level and the .bin files land in /alchemy, elements.smp in /mi. Release notes and SHA-256 checksums.

The image is plaits_alchemy.bin. Put it in the /alchemy folder on the Lab's SD card, beside any other Alchemy firmware, and pick it from Settings page 2 (the Firmware page):

  • P1 FILE picks the file.
  • P2 FLASH writes it: turn it below 85 %, then past 95 %. It checks the file, writes it, verifies it and reboots.
  • P3 DFU is the same gesture, and reboots into the bootloader instead.

The same picker is in Clouds, Elements and Marbles for Alchemy Lab, and in Mark, Belt and Smack.

Where it saves. Plaits keeps its working state in its own file on the card, /alchemy/state/plaits.st, and saves about five seconds after the last change, when no button is held. Switching to another firmware and back leaves Plaits as you left it. On return, each pot has to catch its saved value before it takes over.

Up to v0.1.0 it used preset slot 11; the first boot of v0.2.0 copies that onto the card. The other Lab firmwares keep their own slots, 1–5 and 12–15, so 6–11 are free for presets you save by hand.

First boot after a flash: Plaits' factory state. MODEL is on Virtual analog, OCTAVE on Free, decay at noon, LPG colour fully VCFA, attenuverters off.

Settings at a glance

Page · potControlChoices and default
1 · P1BRIGHTNESS5–100 %, default 30 %, applied as you turn
1 · P2TRIGGERAuto · Drone · Triggered, default Auto
1 · P3PRESET SLOT16 slots, 0–15. Picks the slot for P4.
1 · P4PRESET ACTIONFully left saves, fully right loads
1 · P5LEVEL CVOff · On, default Off
1 · P6nothing
2 · P1–P3FILE · FLASH · DFUThe SD firmware picker

Hold B2 + B3 for two seconds to open Settings. B1 steps to the next page, and a press of B2 or B3 leaves.

Status

What is proven

  • The firmware builds: a 451 KB image, 93 % of the SRAM region. The engine is compiled for size (-Os) to fit. At -O2 it fits too, but leaves only about 13 KB.
  • A native test renders all 24 models for one second each, drone and triggered: none is silent and none sits at the rails.
  • The slowest model, Particle, took about 2 µs per 12-frame call on a desktop CPU under sanitizers, against a 250 µs budget. That only bounds the problem; it is not a measurement on the Lab.

Not yet tested on the module

  • Nothing has been flashed or heard.
  • CPU on the Lab's Cortex-M7 at -Os. Watch B2 and the P1 boot readout, especially on the 6-op FM models, Particle and Inharmonic string.
  • Output level against a real Plaits. Full scale maps to the codec's full scale, which may be hot or quiet.
  • The CV scaling on J4 and J6–J8, taken from Plaits' default calibration.
  • Finding models by ear with 24 zones on one pot.

Left out

  • User wavetables and DX7 banks sent as audio. The 6-op models use their built-in patches, as on a fresh Plaits.
  • The FM jack, the MODEL CV, and Plaits' own calibration procedure. The Lab's factory CV calibration is used instead.
  • The Launchpad, USB-audio and controller modes of the other Alchemy firmwares. This build is HostLink only. It never writes the card's USB setting, so the other firmwares keep theirs.