Skip to content

Timing and latency

paradajz edited this page Apr 21, 2026 · 1 revision

This page summarizes the firmware-side timing that affects switch, encoder, analog input, MIDI, and OSC response latency in OpenDeck.

Latency is not a single fixed number. The total time from a physical action to a MIDI message depends on:

  • when the action happens relative to the next firmware scan
  • the input topology used by the target
  • switch debouncing or analog filtering
  • scheduler timing and other active work
  • the selected MIDI or network transport
  • host operating system, USB/BLE/network stack, DAW, control software, and audio buffer settings

The values below describe OpenDeck firmware timing. They do not include host-side MIDI, network, control software, or audio latency.

Firmware timing constants

Item Value Notes
Digital scan loop sleep 1 ms Applies to switches and encoders.
Analog scan loop sleep 1 ms Applies to analog inputs.
I2C loop sleep 1 ms Applies to I2C display/peripheral processing.
Zephyr timeslice 10 ms Used when multiple same-priority preemptive threads are ready.
MIDI thread priority 0 Higher priority than the I/O scan threads.
Digital, analog, output, I2C, touchscreen, and system work priority 1 Lower priority than MIDI processing.
Switch debounce depth 8 samples A switch must be stable for 8 consecutive digital scans.
BLE MIDI connection interval request 7.5 ms BLE timing also depends on the central device accepting/maintaining the interval.

Scan terms

Term Meaning Used by
Digital frame One complete read of every physical digital input on the target. Switches and encoders are processed after the frame is complete. Switches, encoders
Digital frame acquisition The time needed to read one complete digital frame. Switches, encoders
Digital scan interval Digital frame acquisition time plus the 1 ms digital scan loop sleep. Switches, encoders
Analog frame One complete analog scan pass for the currently enabled physical analog inputs. Each scanned input is sampled twice and the first sample is discarded. Disabled analog inputs are skipped. Analog inputs
Analog frame acquisition The time needed to read one complete analog frame. Analog inputs
Analog scan interval Analog frame acquisition time plus the 1 ms analog scan loop sleep. Analog inputs

Switch latency

Switches are sampled by the digital scan thread and must pass the debounce filter before a state change is accepted.

Stage Contribution Notes
Digital frame acquisition One complete digital frame read Native GPIO is very quick; shift-register and matrix topologies add clock/read time.
Debounce 8 stable digital frames Native GPIO targets are close to 8 ms; larger digital topologies add their frame acquisition time to each debounce sample.
Processing and routing Small, workload-dependent Runs after the debounced state is accepted.
MIDI/OSC transport Transport-dependent USB, DIN, BLE, network, and the host each add their own timing.

Approximate firmware-side latency: ~8 ms on native GPIO targets before routing and MIDI/OSC transport.

Native GPIO switches have very little frame acquisition overhead, so their firmware-side debounce time is close to 8 ms plus up to one extra scan interval. Shift-register and matrix topologies add the time needed to clock/read one full digital frame to each debounce sample, so large digital topologies have proportionally higher switch latency.

Encoder latency

Encoders use the same digital scan thread as switches, but they do not use the switch debounce filter.

Stage Contribution Notes
Digital frame acquisition One completed digital frame read Encoder state is processed from the completed digital frame.
Processing and routing Workload-dependent Also depends on encoder pulse rate, message type, limits, and acceleration settings.
MIDI transport Transport-dependent USB, DIN, BLE, and the host each add their own timing.

Approximate firmware-side latency: about one completed digital frame acquisition before routing and MIDI transport.

Native GPIO targets are usually close to the 1 ms digital scan interval. Shift-register and matrix topologies add the time needed to clock/read one full digital frame.

Analog latency

Analog inputs are scanned by the analog scan thread.

Stage Contribution Notes
Analog frame acquisition Enabled physical analog inputs times 2 ADC conversions, plus mux GPIO overhead Each conversion uses the ADC acquisition setting from the target devicetree. The first sample after selecting an input is discarded for settling.
Filtering and change detection Configuration-dependent Deadband, limits, and message type can delay or suppress outgoing messages.
Processing and routing Workload-dependent Runs after the analog value is accepted as changed.
MIDI transport Transport-dependent USB, DIN, BLE, and the host each add their own timing.

Approximate firmware-side latency: target-specific; roughly one analog scan interval before routing and MIDI transport.

Small native ADC targets have short frame acquisition. Large mux targets take longer when many analog inputs are enabled because each enabled physical input adds two ADC conversions to the analog frame. Disabled analog inputs do not add ADC conversion time.

The table below is extrapolated from the target devicetree topology. It shows worst-case analog workload with all analog inputs enabled and ADC timing, not a measured wall-clock time. Tick-based STM32 and SAMD51 settings are converted to time using the ADC clock from the generated devicetree clock tree and ADC prescaler. RP2040/RP2350 timing is converted from the ADC clock divider in devicetree.

Target Analog topology ADC conversions if all inputs are enabled ADC time per conversion Minimum ADC time if all inputs are enabled
arduino_nano_33_ble native 12 5 us 60 us
bergamot mux 32 5.33 us 171 us
blackpill411 native 16 4.67 us 75 us
discovery_f407g native 14 5.33 us 75 us
dubfocus16t mux 160 5.33 us 853 us
grand_central_m4 native 32 5.0 us 160 us
metro_rp2040 native 6 4.0 us 24 us
nrf52840dk native 16 5 us 80 us
nrf5340dk native 12 5 us 60 us
nucleo_f767zi native 34 4.15 us 141 us
nucleo_h753zi native 38 4.33 us 165 us
opendeck2 mux 64 5.33 us 341 us
opendeck21 mux 64 5.33 us 341 us
opendeck22 mux 64 4.0 us 256 us
opendeck31 mux-on-mux 128 4.0 us 512 us
pico native 6 4.0 us 24 us
pico2 native 6 4.0 us 24 us
rooibos mux 64 5.33 us 341 us
teensy4 native 20 5.6 us 112 us
teensy41 native 32 5.6 us 179 us
ws_core405r native 32 5.33 us 171 us

The minimum ADC time is only the listed per-conversion time multiplied by the number of conversions. Full analog frame acquisition also includes mux GPIO switching and driver overhead. The analog scan interval then adds the 1 ms analog loop sleep.

For a partial configuration, approximate the ADC part of the frame as:

enabled analog inputs * 2 * ADC time per conversion

For example, on opendeck31, one enabled analog input is about 8 us of ADC conversion time (1 * 2 * 4 us) before mux GPIO overhead and the 1 ms analog loop sleep. With all 64 analog inputs enabled, the worst-case ADC conversion time is about 512 us.

Analog filtering runs after the frame has been acquired. These filters do not change the ADC acquisition time in the table above; they decide whether the newly scanned value is stable or meaningful enough to publish.

Filter behavior Applies to Timing effect
ADC deadband Potentiometers and continuous FSR values Small ADC movement inside the current deadband is suppressed until the value moves far enough. This reduces jitter, but tiny movements may not emit immediately.
Direction-change confirmation Potentiometers and continuous FSR values Small opposite-direction movement may need another accepted scan before it is treated as real motion. This prevents brief bounce around the current value.
EMA smoothing Potentiometers and continuous FSR values Accepted ADC values are blended with the previous filtered value. This does not add a fixed wait, but fast physical movement can be reflected over several scans instead of one abrupt jump.
Endpoint assist Potentiometers and continuous FSR values Near the configured minimum or maximum, the filter can snap to the endpoint instead of slowly approaching it. This can reduce visible latency at the edges.
Idle drift confirmation Potentiometers and continuous FSR values After motion has been idle for about 100 ms, a new low-level drift value may need one repeated sample before it is published. Active movement bypasses this path.
Hysteresis Analog inputs configured as switches Analog switch mode bypasses the continuous-value filter and uses on/off thresholds with hysteresis. It avoids analog smoothing delay, but values inside the hysteresis band are ignored until they cross a threshold.

MIDI transport timing

After OpenDeck decides to send a MIDI message, transport latency is added on top of the input latency:

Transport Firmware-side expectation Notes
USB MIDI Usually the lowest-latency OpenDeck transport Host USB stack and receiving software still matter.
DIN MIDI Fixed serial line time A 3-byte MIDI message takes about 0.96 ms on the wire at the MIDI baud rate.
BLE MIDI Depends heavily on the active BLE connection interval Also depends on central-device behavior and radio conditions.

Clone this wiki locally