Mutable Instruments Marbles · for the Hermetic Modular Alchemy Lab V2

Marblesfor Alchemy Lab

A random sampler. Three streams of gates, four of voltages, drawn from distributions you shape with the knobs, and a loop that can make chance repeat itself.

Built, tested on a computer, not yet flashed or heard. Version 0.1.0 compiles and its native test suite passes. No module has run it. The status section lists what to check first.
Each marble is one X value: a uniform random number bent by SPREAD and BIAS.SPREAD 50% · BIAS 50%

What it does

01 · The same generators as the Eurorack module

Marbles makes decisions for a patch. Its T section is a clock and two coin-flippers: T2 ticks, and on each tick T1 or T3 (or both, or neither) fire, depending on the mode and the bias. Its X section draws three voltages, X1–X3, each time its clock ticks, from a distribution SPREAD and BIAS shape, optionally quantized to a scale. Y is a fourth, slower voltage. DEJA VU decides how often a value is new and how often it is one of the last LENGTH values again.

Engine

Unmodified TGenerator and XYGenerator

Emilie Gillet's generator code, byte-identical to pichenettes/eurorack at 08460a6, at the original's 32 kHz. This firmware maps the Alchemy Lab's pots, buttons and jacks onto it, using the scaling from Marbles' own cv_reader.cc.

On this panel

A CV and gate module

No audio. Seven of the ten jacks are outputs: X1–X3 and Y on J3–J6, the T gates on J7, J9 and J10. J1 and J2 take clocks, and J8 is the one CV input.

Controls

Six pots on two pages

PLAY holds the eleven-knob module's six most-used knobs. Hold B3 for SETUP: steps, length and the modes Marbles set with buttons. Three Settings pages hold the hidden options, the Y section among them.

The panel

02 · Drawn to scale from the SDK's KiCad template · click any control

Every hole is where it sits on an Alchemy Lab. The coordinates come from the SDK's own front-panel template, and the drawing is generated from them. Pick a page, then click a pot, a button or a jack.

Select a control

The panel

6 pots × 2 pages + 3 Settings pages · 3 buttons · 10 jacks
Click anything on the drawing. The rings show example values, drawn as the firmware draws them.
plate 60.96 × 128.5 mm · 12 HP
rings 16 LEDs, 13 in the arc
The six middle jacks are numbered in reading order (J3 J4 J5 above, J6 J7 J8 below). The template doesn't state the order, so check against the numbers printed on your panel.

The jacks

03 · Seven outputs, three inputs · fast paths for the gates

The Alchemy Lab has three ways to put a voltage on a jack. Marbles uses all three and gives the fastest to the T gates: the codec's DC-coupled outputs run per sample. The X voltages go through the slower I²C converter, where a millisecond does no harm to a stepped voltage.

JackRolePathTiming
J1t CLOCK in: T follows this clockcodec input, AC-couplededge per sample, on above +1.0 V, off below +0.5 V
J2X CLOCK in: X steps on this clockcodec input, AC-coupledsame
J3 · J4 · J5X1 · X2 · X3MCP4728 DAC over I²Cstaged when a value moves ≥ 2.4 mV, one flush per 1 ms poll (~0.45 ms of bus)
J6YMCP4728 DAC over I²Csame
J7T3STM32 DAConce per 16-sample block (0.5 ms)
J8CV in, default RATE at 1 V/octADConce per block
J9T1codec output, DC-coupledper sample
J10T2, the master clockcodec output, DC-coupledper sample
Why T2 on J10

The clock gets the clean path

T2 is Marbles' steady master clock, the output most likely to clock other modules, so it rides the only sample-accurate path. T1 sits next to it on the codec pair; T3 takes the STM32 DAC with 0.5 ms of jitter, which gates don't notice.

X first, then T

Gates leave 2 ms late

X reaches its jack up to ~2 ms after it is computed. The T gates are held back 64 samples (2 ms) so a sample-and-hold or envelope fired by T1 sees the new X1, as on the original. The original held them back 2 samples. Relative to J1's clock, T is 2 ms late.

Is a cable in?

Edges instead of switches

Marbles knew a cable was in J1/J2 from the jack's switch. The Lab can't tell, so a clock input counts as patched while edges arrive (the last within 3 s). Settings can force the internal clock or pick X's clock explicitly.

Check X against a tuner before playing melodies

The SDK rates J3–J8 at about ±50 mV in output mode, because their calibration was measured with the output switch open. At 1 V per octave that is about ±60 cents: fine for modulation, possibly out of tune into an oscillator. J1 and J2 are AC-coupled, so a long held gate sags and releases early; clocks and triggers are fine. Gates on J9/J10 are written as 0 V and +4.995 V; their real levels haven't been measured.

The loop, live

04 · Marbles' random-sequence code, running in this page

Turn DEJA VU to noon and lock a button: the gates and the voltages repeat exactly every LENGTH steps. Turn it left for new values, right to shuffle the loop. The random sequence, the coin-toss, independent, three-state and drum models, the jitter and the quantizer are ported line for line from the vendored C++; the notes below list the one simplification.

T2 2.00 Hz t deja vu 0.00 X deja vu 0.00 LENGTH 8 X1 —
X1's deja vu buffer: 16 values. The outlined cells are the last LENGTH; white is the value just played.
Lock both deja vu buttons to check the repeat.

Buttons · tap on / off, hold 2 s to lock

Play page

Setup page

What is ported, and the one simplification

Ported: RandomSequence::NextValue and NextVector (the 16-value loop, p = (2·deja vu − 1)², new values at or below noon, random jumps above it, locked = 0.5 so p = 0); the four T models' bitmask code and drum patterns; the jitter (JITTER⁴ × 36 semitones, with the phase-difference pull back to the straight clock); the firmware's RATE curve and deja vu deadband; the loop-length table; the X modes' spread and bias per channel; the degenerate and Bernoulli ends of SPREAD; and the quantizer's weight thresholds with the six factory scales. X1, X2 and X3 each step on T1, T2 and T3, the default X CLOCK.

Simplified: the X distribution. Marbles reads a precomputed inverse-CDF table; this page draws from a beta curve set by SPREAD and BIAS, so shapes are close, not identical. Left of noon, X STEPS eases to each value instead of running Marbles' lag processor. Clusters and Divider aren't simulated. The page uses the browser's random numbers; the module uses the STM32's hardware generator. The firmware and its native tests run the real code; this page is for getting a feel for it.

Buttons and lights

05 · Marbles' deja vu gesture, decided on release
ButtonDoesLEDs
B1 · t DEJA VUFrom off: tap for on, hold 2 s for locked. From on: tap for off, hold 2 s for locked. From locked: any press returns to on. dark: off · green: on, breathing while DEJA VU sits in its noon lock band · amber: locked
B2 · X DEJA VUThe same gesture for the X section. B2 stands down while B3 is held, because B2 + B3 for 2 s opens Settings. as B1 · red when the audio callback averages over 80 % CPU
B3 · SETUPHold to show the SETUP page. Pots catch their stored values on the way in and out, so nothing jumps. flashes white on each T2 tick
RATE ring

Three gate pips

Over RATE's level arc, three pips light while T1, T2 and T3 are high, so the clock is visible without a patch cable.

DEJA VU ring

Bipolar from noon

Left of noon: new values more often. Noon: a small deadband that locks the loop. Right: the loop's values in shuffled order.

At boot

Last session's CPU

For 2.5 s the P1 ring shows the previous session's worst audio-block load: green, amber above 75 %, red above 90 %. One dim dot means no data yet.

Settings

06 · Hold B2 + B3 for two seconds · B1 steps through the pages

The options Marbles hid behind button combinations, including the whole Y section. Changes are saved with the rest of the state.

PageP1P2P3P4P5P6
MainBrightnesst RANGE: ×¼, ×1, ×4Preset slotPreset actionJ1 CLOCK: Auto, IgnoreX CLOCK: Auto, T1+T2+T3, T1, T2, T3, J2
FirmwareFILEFLASHDFUJ8 CV TO: Rate, t Bias, t Jitter, Deja vu, X Spread, X Bias, X Steps, LengthEXTERNAL X: Off, OnGATE LENGTH
YY SPREADY BIASY STEPSY DIVIDER: 1/64 … 1/1 (default 1/8)Y RANGE: +2 V, +5 V, ±5 VGATE JITTER
  • J8 CV TO. RATE takes exact 1 V/oct (12 semitones per volt, as Marbles' rate input). Any other destination moves its knob's whole travel over 10 V.
  • EXTERNAL X. Marbles' external processing: X samples the voltage on J8 on each X clock and quantizes it to the scale. J8 then has no other destination.
  • X CLOCK Auto uses J2 while edges arrive, otherwise T1 clocks X1, T2 clocks X2 and T3 clocks X3. J1 CLOCK Ignore keeps T on the internal clock whatever J1 receives.
  • Y DIVIDER sets how many X steps pass before Y takes a new value.
  • The firmware page's FILE, FLASH and DFU are the SD card picker.

On the card

07 · One of several firmwares, switched from the panel

Marbles carries the same SD card firmware picker as Mark, Belt, Smack and the other Mutable ports, so any of them can hand the module to any other without a computer.

Prepare the card

FAT32, a folder named alchemy

Put marbles_alchemy.bin in /alchemy with the other firmwares. On a Mac, run dot_clean on the card before ejecting so resource forks don't show up as files.

Switch

Settings, firmware page

P1 FILE picks the file. On P2 FLASH, turn below 85 % and then all the way up: it compares, erases, writes, verifies and reboots. If that firmware is already loaded it writes nothing and just shows solid green.

Its own memory

A file on the card

Marbles keeps its working state in /alchemy/state/marbles.st and saves it 5 s after the last change, once your hands are off the buttons. Switch away and back, and it returns as you left it. Up to v0.1.0 it used slot 10; 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.

Build and install

08 · From source · Alchemy Lab V2 only

Download the firmware, or build it from the repository, which holds all seven ports, then put it on the card or flash it over the front USB-C.

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

marbles_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.

git clone https://github.com/timncox/mi-alchemy
cd mi-alchemy
git submodule update --init
git -C lib/libDaisy submodule update --init --recursive
make libdaisy        # once
make FW=marbles      # build-marbles/marbles_alchemy.bin, ~399 KB
make test            # the native suites for all four engines
From the card

The picker

Copy the .bin to /alchemy and flash it from any firmware in the family, as above.

First time

Hold B3 at power-on

The bootloader serves DFU on the front USB-C. Flash with Hermetic's web programmer or dfu-util, pinned to your module with -S.

USB

HostLink only in 0.1

The front USB-C talks to the web programmer. This version has no Launchpad or USB-audio mode, and it never changes the card's shared USB setting.

Custom firmware

Hermetic Modular and Mutable Instruments didn't write or test this port and can't support it. Please don't contact them about it; open an issue on the repository instead.

How it is built

09 · The layer between Marbles' code and the Alchemy SDK
PieceWhat it is
The enginemarbles::TGenerator, XYGenerator, the ramp extractor and the lookup tables, byte-identical to pichenettes/eurorack @ 08460a6, at 32 kHz in 16-sample blocks.
marbles_engine.hWhat marbles.cc's Process() did, without the hardware: clock edge detection, the parameter scaling from cv_reader.cc, the deja vu deadband, the loop-length quantizer, the X clock source and the 2 ms T delay. The native test runs this exact code.
Parameter scalingRATE = pot × 120 − 60 semitones around 2 Hz; t BIAS × 1.05 − 0.025; X SPREAD and BIAS × 1.02 − 0.01; STEPS × 1.04 − 0.02; LENGTH through Marbles' 1–16 table. A one-pole filter smooths the knob values.
ScalesThe six factory scales copied from settings.cc, which can't be compiled here because it includes the STM32F4 flash driver.
Random numbersThe STM32's hardware generator feeds Marbles' random stream from the 1 ms poll, as its own RNG driver did.
Working state/alchemy/state/marbles.st (slot 10 up to v0.1.0): both pages, the Settings, the deja vu buttons and last session's CPU peak, schema-tagged so another firmware's state is never read as this one's.
Budget398,844 B image: SRAM 82.75 % of 480 KB, DTCM 83,880 B, D2 only the LED window. CPU on the module is unmeasured; Marbles ran on a 168 MHz STM32F405 with its whole UI.

Left out

  • Scale recording and per-note scale edits: the six factory scales only.
  • Explicit reset mode, the self-patching detector (pick T1, T2 or T3 as X CLOCK instead), factory calibration and output-test modes, and the colour-blind LED scheme.
  • The Markov T model, which the original firmware also keeps out of reach.
  • CV on every knob: there is one CV input, J8, so that Y could keep its jack.

Status

10 · Built and tested on a computer · not flashed · not heard

The native test suite runs marbles_engine.h over the vendored generators at 32 kHz with address and undefined-behaviour sanitizers. All of it passes. Nothing below has been checked on a module.

Passed on the computer

Clocks and loops

RATE at noon gives 2.000 Hz, +12 semitones 4.000 Hz, J8 at +1 V 4.000 Hz. A 3 Hz clock on J1 gives 3.000 Hz at 1/1 and 12.000 Hz at ×4. Deja vu locked at LENGTH 2, 5 and 16 repeats X and T with no mismatches.

Passed on the computer

Voltages

X stays inside and fills the +2 V, +5 V and ±5 V ranges. Quantized X lands on the scale for all six scales. EXTERNAL X: +2 V on J8 gives 2.000 V on X1.

To check on a module, in order

  1. It boots from the picker, the P1 ring shows the CPU readout, B3 flashes with T2.
  2. T1 on J9, T2 on J10, T3 on J7; RATE at noon is 2 Hz.
  3. A clock into J1 takes over T; X CLOCK Auto follows a clock into J2.
  4. X1–X3 and Y on J3–J6, measured against a tuner or meter (the ±50 mV question).
  5. J8 into RATE at 1 V/oct.
  6. Whether the panel feels slow with smooth X (STEPS left of noon), which flushes the I²C DAC every millisecond and uses about half of the control loop.
  7. Settings survive switching to another firmware and back.