Skip to content
All guides

systems

Firmware: a control loop

Start with the LED happy path (electronics):

use std.led.{on, off, wait}

fn main() {
    while true {
        on()
        wait(200)
        off()
        wait(200)
    }
}

buraaq run on the host. buraaq flash on a Pico W in BOOTSEL.

When you outgrow the LED, the same language shapes a sensor loop: read, decide, write a pin.

struct Sample {
    pub millivolts: int
    pub tick: int
}

fn should_trip(window: ref List[Sample], limit: int) -> bool {
    mut i = 0
    mut sum = 0
    n = window.len()
    while i < n {
        s = window.get(i)
        sum = sum + s.millivolts
        i = i + 1
    }
    if n == 0 {
        return false
    }
    return (sum / n) > limit
}

fn tick(window: ref mut List[Sample], mv: int, t: int, limit: int) -> bool {
    window.push(Sample { millivolts: mv, tick: t })
    while window.len() > 16 {
        window.remove_at(0)
    }
    return should_trip(window, limit)
}

What you just reused from Learn

  • struct for a sample
  • List as a sliding window
  • while + index (no hidden iterator protocol)
  • ref / ref mut so the window is not moved every tick

That is the philosophy: the same language from a ledger CLI to a trip-curve. Python-shaped. Native drop. No GC in the 1 ms budget.

Bring-up checklist

  1. Prefer std.led / board packs via buraaq flash
  2. Drop to extern c only for vendor HAL you do not wrap yet
  3. Keep heap optional: a [Sample; 16] array is even more honest on tiny RAM
mut ring: [Sample; 16] = ...
mut head = 0

Fixed arrays when the size is the type. Lists when the host can malloc.

Honest status

Hosted buraaq build / buraaq run is the daily driver. buraaq flash --board pico_w ships a UF2 for the activity LED. Linking your Buraaq main as the on-device entry (thumb object + board HAL) is the next tighten of the loop: the source shape does not change.