Hardware Events
Attach a handler to a pin with an edge or level token, and it fires when the pin changes — the way hardware interrupts always have, without the setup ceremony.
For sequential "wait for a signal" logic, interrupts are the wrong tool — poll inside an async function with Time.sleep and let the task yield between checks.
onInterrupt / offInterrupt
Attach and detach a GPIO interrupt with an edge or level token — a misspelled token is an editor error; an invalid mode is a build error naming the valid spellings.
Example first
import { GPIO, LED, BUTTON } from '@typecad/hal';
const led = new GPIO(LED, GPIO.OUTPUT);
const button = new GPIO(BUTTON, GPIO.INPUT | GPIO.PULL_UP);
button.onInterrupt(GPIO.INT_EDGE_FALLING, () => {
led.toggle();
});Mode tokens
| Token | Fires when |
|---|---|
| GPIO.INT_EDGE_RISING | the pin goes low → high |
| GPIO.INT_EDGE_FALLING | the pin goes high → low |
| GPIO.INT_EDGE_BOTH | either transition |
| GPIO.INT_LEVEL_LOW | the pin is held low |
| GPIO.INT_LEVEL_HIGH | the pin is held high |
offInterrupt offInterrupt(): void
button.offInterrupt(); // disable and remove the callbackISR safety
The handler runs in interrupt context. Setting variables and driving pins in the handler is fine, but calls that would block — delays, bus transactions, UART writes — are flagged at build time with the offending call named. The pattern that always works: set a flag in the handler, act on it in the main flow.
let pressed = false;
button.onInterrupt(GPIO.INT_EDGE_FALLING, () => { pressed = true; });
while (true) {
if (pressed) {
pressed = false;
UART0.writeLine('pressed'); // safe here
}
Time.sleep(10);
}Interrupts or polling?
| Interrupt | Poll in an async task | |
|---|---|---|
| Latency | microseconds | the poll period (typically milliseconds) |
| Context | ISR constraints apply | none — ordinary code |
| Best at | events that must not be missed | sequential logic, debouncing |
| Many inputs | one callback per pin | one task can watch many conditions |
Debouncing is the classic deciding case: an interrupt fires on every bounce, while a polling task
reads a settled level. while (button.get()) { await Time.sleep(20); } debounces by construction.