📖 What Pearson does
Chapter 13 builds circuits that lock the frequency of one oscillator to a multiple or fraction of another. The big chip is the 4046 PLL (phase-locked loop). Sub-projects:
- The 4046 VCO. A voltage-controlled oscillator.
- Portamento, glide, and glissando. Slowly sliding between two pitches.
- VCO switching. Switching between multiple VCOs.
- Sample and hold. Freezing a changing control voltage to a constant.
- LFO multiplication. Using a PLL to make a slow LFO.
- Audio-frequency multiplication. Using a PLL to make a fast oscillator.
🎓 Background: PLLs in software
PLLs are analog circuits that lock an oscillator’s phase to a reference signal. They are how analog synths tune their oscillators to other instruments or to a master clock. In software, a PLL is just a frequency-locked loop — a control algorithm that adjusts an oscillator’s frequency until its phase matches a reference.
Our firmware does not implement PLLs explicitly. The closest analog is the jam-sync feature (F-031): when sync-in is enabled, the sequencer advances on each incoming sync pulse, which keeps it phase-locked to the master device. There is no “fractional” sync — one pulse is one step. Pearson’s PLL multipliers and dividers are not implemented.
Portamento (smoothly sliding between two pitches) is approximated
by AMY’s slew_time field, which can be set on a per-event
basis. We have not wired this to a UART verb.
🔧 Try it on the device
Exercise 1: jam-sync as a simple PLL.
If you have another PO-33 (real or otherwise) running, connect a cable from its sync OUT to our device’s sync IN. Long-press FX for 2 seconds to enable sync-in listening:
> sync_in_toggle
Now when you press play on our device, it will wait for sync pulses from the master. Each pulse advances one step. That is a PLL with multiplier 1.
Exercise 2: pitch glide via FX.
The PO-33 has a punch-in effect called PORTAMENTO (when fully implemented). Set it:
> fx PORTAMENTO
> note 9 60
> note 9 72
The note should slide from C4 to C5 rather than jumping. (As of
v0.6, the PORTAMENTO case in apply_fx() is a no-op.)
🛠 Code reference
- Sync-in listener —
main/system/sync.c.sync_in_task(). Blocked on a semaphore; wakes per pulse; callssequencer_tick(). - Sync-in toggle —
main/ui/input.c, end-of-drain polling block. Long-press FX for 2 seconds togglessequencer_set_sync_in_active().
🚫 What we can’t simulate
- The 4046 PLL chip. No analog here. PLL math in software is trivial (an integer-N counter), but the analog version has subtle behaviour (lock range, capture range, hold range) that no digital emulator captures without effort.
- VCO switching. No equivalent.
- Sample and hold. Could be done in software but is not.