SPI Helpers
Drive a SPI bus (native Linux spidev node or a CH347 USB bridge) from Lua. Each helper builds a request message and
sends it on the configured SPI connection. All helpers return true once the request is queued, or raise a Lua runtime
error on invalid parameters.
The contract is identical for both backends. The cs (chip-select) argument is a 0-based line index for the CH347
bridge; it is ignored by the native spidev backend, where the chip-select is fixed by the device node. All helpers
accept an optional trailing connection_id (default: 0) selecting the target connection, followed by an optional
delay_ms that schedules the request delay_ms milliseconds in the future instead of sending it immediately
(default: 0 — send now). This is handy for inserting settling time between bus operations.
Request Functions
spi_write(cs, data, connection_id, delay_ms) → boolean
Clock data out on the given chip-select, discarding anything read back.
cs(number, optional) - Chip-select line index (default:0)data(string) - Payload bytes to write (required, must be non-empty)connection_id(number, optional) - Target connection (default:0)delay_ms(number, optional) - Delay delivery by this many milliseconds (default:0)
spi_read(cs, data, length, connection_id, delay_ms) → boolean
Clock out an optional data preamble (e.g. a command/address), then clock in length bytes.
cs(number, optional) - Chip-select line index (default:0)data(string) - Preamble bytes written before the read (can be empty)length(number) - Number of bytes to clock in (required, must be> 0)connection_id(number, optional) - Target connection (default:0)delay_ms(number, optional) - Delay delivery by this many milliseconds (default:0)
spi_transfer(cs, data, connection_id, delay_ms) → boolean
Full-duplex transfer: clock data out while simultaneously clocking the same number of bytes in.
cs(number, optional) - Chip-select line index (default:0)data(string) - Payload bytes to transfer (required, must be non-empty)connection_id(number, optional) - Target connection (default:0)delay_ms(number, optional) - Delay delivery by this many milliseconds (default:0)
Handling Responses
Read and transfer results arrive as ordinary RX messages in on_receive(). Use message:get_metadata("spi_op") to
identify the result type. Write confirmations and errors are emitted as engine events, not RX messages.
spi_op metadata | Message kind | Payload |
|---|---|---|
read_response | RX | The bytes clocked in; spi_cs in metadata |
transfer_response | RX | The bytes read back during the duplex transfer; spi_cs |
write_response | event | spi_write event with spi_cs metadata |
error | event | spi_error event; the error value holds the message |
Example: read a register over SPI
local READ_CMD = 0x80 -- many SPI sensors OR the register with 0x80 to read
local WHO_AM_I = 0x0F
function on_start()
-- Send {0x80 | reg} as preamble, then clock in 1 byte
spi_read(0, string.char(READ_CMD | WHO_AM_I), 1, 0)
end
function on_receive()
if message:get_metadata("spi_op") ~= "read_response" then return false end
local id = read_u8(message.payload, 1)
log("info", string.format("WHO_AM_I = 0x%02X", id))
message:add_int_value("who_am_i", id)
return true
end
Example: full-duplex transfer
function on_timer(now_ms)
-- Clock out two command bytes; the device returns two bytes in the same frame
spi_transfer(0, string.char(0x9F, 0x00), 0)
end
function on_receive()
if message:get_metadata("spi_op") ~= "transfer_response" then return false end
local status = read_u8(message.payload, 2) -- 2nd byte read back
message:add_int_value("status", status)
return true
end