[sdiy] Organisation of tasks in synth's main uP

Olivier Gillet ol.gillet at gmail.com
Mon Nov 22 18:12:51 CET 2010


Hi Tom,

It's probably best illustrated by code
(https://github.com/pichenettes/shruthi-1/blob/master/hardware/shruthi/shruthi.cc),
but I can summarize here what I did for the Shruthi:

ISR land:

* Incoming MIDI data is pushed onto a ring buffer whenever the UART RX
interrupt is raised.
* There's a 39kHz timer interrupt which does the following:
 - pop samples from a ring buffer and write them to the audio output.
The path from the interrupt prolog to the actual write is
constant-time to avoid jitter.
 - every 16th clock tick (2.5 kHz):
    - send a nibble from a ring-buffer to the LCD (The LCD is thus
never polled - we are sure a write is complete because there's a
guarantee delay between calls).
    - step through the switches/encoder debouncing routine
    - flush bytes from a ring-buffer to the MIDI out
 - every 32th clock tick, update a ms system clock which is used in a
few places.


mainland:

Besides that, everything is in non-blocking, rate-independent,
cooperative "tasks". The core of the program is a loop that calls the
tasks in sequence, with some tasks being called more often than
others. All the tasks are polling something, so they return
immediately if there's nothing for them to do:
- poll debounced switches values.
- poll the ADC's end of conversion flag to read pots values / CV inputs.
- poll the MIDI input buffer and parse MIDI.
- poll the text buffer to detect changes on the LCD text and push
bytes to LCD commands ring buffer.
- poll the output buffer and if empty, render 32 samples of audio + 1
sample of modulations.

All the tasks do small chunks of processing which take less than the
allowed 32 buffered samples. At one exception, none of those tasks
have a heavy state, so there's not much cost switching from one task
to another. The "context-switch" is simply a function
prelude/postlude. I find the following idiom particularly useful:
http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html

Indeed, there's only one bit in the code which is blocking: writes to
eeprom when saving patches - I block during the 5ms or so of write
time between each eeprom block.

I did not consider a RTOS but will do when switching to a platform on
which I can tolerate the overhead.

Olivier



More information about the Synth-diy mailing list