Skip to content

para:spi

import spi from "para:spi";

A small module wrapping the Linux spidev character device (/dev/spidevN.M). Mode / bits-per-word / clock speed configured at open via SPI_IOC_WR_*; transfers via SPI_IOC_MESSAGE for both single full-duplex transfers and multi-segment transactions where chip-select stays asserted across segments.

para:spi is currently Linux-only.

Synchronously enumerates /dev/spidev<bus>.<cs> entries.

spi.devices();
// [
// { path: "/dev/spidev0.0", bus: 0, cs: 0 },
// { path: "/dev/spidev10.0", bus: 10, cs: 0 }, // RPi 5 user header
// ]

On Pi 5 the user-header SPI is at /dev/spidev10.0 (different bus number than Pi 4’s /dev/spidev0.0). The bus / cs fields are parsed from the path — the kernel exposes one device file per (controller, chip-select) pair.

Opens a device, configures mode / bits-per-word / clock speed, and returns a Device.

await using dev = spi.open("/dev/spidev0.0", {
mode: 0, // 0..3 — CPOL/CPHA combinations
bitsPerWord: 8,
speedHz: 1_000_000, // 1 MHz
});

Defaults: mode: 0, bitsPerWord: 8, speedHz: 1_000_000. Device is AsyncDisposable.

Single full-duplex transfer. tx is shifted out; the same number of bytes is shifted in and returned. CS is asserted for the duration.

const rx = await dev.transfer(Uint8Array.of(0x9F, 0, 0, 0));
// rx: Uint8Array(4) — captured during the four-byte tx.

Optional per-call overrides: { speedHz, delayUs }.

Half-duplex write. Same as transfer but discards the rx bytes. For very hot write loops, prefer transactSegments with no rx — that avoids allocating the rx buffer kernel-side too.

Half-duplex read. Sends length zero bytes and returns the captured rx. length must be a positive integer.

Multi-segment transaction with CS held across all segments unless a per-segment csChange: true flips it. Each segment is one of:

  • { tx: Uint8Array } — half-duplex out
  • { rx: number } — half-duplex in (length bytes)
  • { tx: Uint8Array, rx: rx.length } — full-duplex (rx must match tx length)

Plus optional speedHz, delayUs, bitsPerWord, csChange per segment.

// Flash JEDEC ID read: CMD then 3-byte id.
const [, id] = await dev.transactSegments([
{ tx: Uint8Array.of(0x9F) },
{ rx: 3 },
]);
// id: Uint8Array(3) — manufacturer + device + capacity bytes

Returns one slot per segment — tx-only segments yield undefined, rx-bearing segments yield a Uint8Array.

The Pi 5 user header SPI is at /dev/spidev10.0 (bus 10), not /dev/spidev0.0. Enable with dtparam=spi=on in /boot/firmware/config.txt.

  • para:gpio — character-device GPIO on the same Linux SBCs.
  • para:i2c — i2c-dev wrapper.