Boards & Targets

There is no curated board list to install — the catalog is generated from the Zephyr tree you already have, and every board variant in it is a target. Pick one in the config; the build generates a board module that becomes your import of '@typecad/hal'.

reference

the board module

The first build (or typecad-hal board regen) writes .typecad-hal/board.ts — pin map, buses, and capability flags harvested from the board's devicetree. Your project's tsconfig maps '@typecad/hal' onto it, so every import is board-specific by construction.

Example first

typecad-hal.config.ts
import type { TypecadConfig } from '@typecad/hal/config';

const config: TypecadConfig = {
  board: 'xiao_ble/nrf52840',   // a qualified Zephyr board target
};

export default config;
.typecad-hal/
.typecad-hal/
  board.ts               ← what '@typecad/hal' resolves to
  board.json             ← the same facts, machine-readable
  typecad-hal-env.d.ts   ← ambient types (Owned, Shared, Mutable, SafeVariable...)

What's in the module

ExportWhat it is
PinsOne constant per pin — datasheet names, plus silkscreen aliases (D0–D10, A0–A5, SDA/SCL) pointing at the same Pin
LED / BUTTONFrom the Zephyr led0/sw0 devicetree aliases when the board defines them
BusesOne export per wired controller: I2C0, SPI0, UART0, USB0
Gated hardwarePWM, ADC, DAC, Watchdog, Counter, I2CTarget, SPITarget, UART, USBConsole, Keyboard, Mouse, CAN, I2S, Power, Clock, Store, File — exported only when the board supports them
Always presentGPIO, Time, Thread, Sensor, and the core language features
concept

the hardware gateway

The board module is narrowed: it only re-exports hardware the board actually has. Writing code against hardware the target lacks fails at module resolution — before anything is generated, flashed, or debugged on a bench.

Example first

main.ts
import { GPIO, LED, I2C0, PWM } from '@typecad/hal';
// ↑ this specifier resolves to .typecad-hal/board.ts — the board module.
// PWM only exists above if the board's timers support it: importing it on a
// board without PWM fails at module resolution, not on the bench.

Catalog commands

CommandWhat it does
typecad-hal board sync [zephyr-base]Rebuild the catalog from your installed Zephyr tree — run it after west update
typecad-hal board regenForce-regenerate the project board module
automaticEvery build checks the catalog is fresh and regenerates board.ts when needed
pattern

custom pin facts

When the catalog hasn't harvested a routing you need — an ADC channel, a PWM controller — supply the fact and the whole pipeline treats it as its own: same validation, same lowering. Board-wide via typecad-hal.facts.json, per-construction via options.

Example first

typecad-hal.facts.json
{
  "boards": {
    "myboard/mysoc": {
      "adc": {
        "channels": [{ "pin": "PA1", "channel": 9 }]
      },
      "pwm": {
        "specs": [{ "pin": "PB7", "controller": "pwm0", "channel": 2 }]
      }
    }
  }
}
overrides.ts
// per-construction override — facts, not bypasses
let a1 = new ADC(PA0, { channel: 3, device: 'adc1' });
let p1 = new PWM(PB7, { periodNs: 1_000_000, controller: 'pwm0', channel: 2 });

User routes replace the harvested route per pin (the build prints the shadowing), and edits to the facts file regenerate the board module. The final escape hatch is rawCpp() — see The transpiler.

© 2026 typeCAD — code-defined electronics github