Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/boblio-max/origin/llms.txt

Use this file to discover all available pages before exploring further.

Beyond GPIO and servo control, Origin provides first-class syntax for the three serial protocols that are standard on every Raspberry Pi: I2C, SPI, and UART. These protocol primitives follow the same parenthesis-free, English-like style as all Origin statements. Write i2c.read 0x40, 0x00 and Origin generates the correct smbus2 call under the hood — no imports, no bus setup, and no teardown required in your script.

Parenthesis-Free Syntax

All three protocol namespaces use dot-method syntax with space- or comma-separated arguments — the same convention as set pin and set servo.angle. Arguments follow the method name directly, and parentheses are optional:
i2c.read <addr>, <reg>
i2c.read <addr>, <reg>, <size>
i2c.write <addr>, <reg>, <data>
spi.read <n>
spi.write <data>
uart.read <n>
uart.write <data>
The parser recognizes i2c, spi, and uart as hardware primitive namespaces and produces a HardwarePrimitiveNode in the AST. The interpreter then emits a call to the corresponding _execute_<namespace>_<method>(...) Python runtime function — for example, i2c.read 0x40, 0x00 becomes _execute_i2c_read(64, 0).

I2C

I2C (Inter-Integrated Circuit) is a two-wire serial bus. On the Raspberry Pi, I2C1 uses BCM GPIO 2 (SDA, physical pin 3) and BCM GPIO 3 (SCL, physical pin 5). Most sensors, display drivers, and PWM controllers (like the PCA9685) communicate over I2C. Origin’s I2C primitives are backed by the smbus2 library. Each call opens bus 1, performs the read or write, and returns. The underlying smbus2 calls are:
  • i2c.read <addr>, <reg>bus.read_byte_data(addr, reg) — reads one byte from register reg
  • i2c.read <addr>, <reg>, <size>bus.read_i2c_block_data(addr, reg, size) — reads size bytes starting at reg
  • i2c.write <addr>, <reg>, <data>bus.write_byte_data(addr, reg, data) (integer) or bus.write_i2c_block_data(addr, reg, data) (list)

Read

i2c.read <addr>, <reg>
i2c.read <addr>, <reg>, <size>
  • addr — the 7-bit I2C device address (e.g. 0x40)
  • reg — the register address to read from (e.g. 0x00)
  • size — optional number of bytes to read; defaults to 1
Returns a single byte integer when size is 1, or a list of bytes when size is greater than 1. Example — read one byte from register 0x00 of an I2C temperature sensor at address 0x48:
let temp_raw: int = i2c.read 0x48, 0x00
print temp_raw
Example — read 4 bytes starting at register 0x00 from a device at 0x40:
let data: int = i2c.read 0x40, 0x00, 4
print data

Write

i2c.write <addr>, <reg>, <data>
  • addr — the 7-bit I2C device address
  • reg — the register address to write to
  • data — an integer byte value or a list of bytes
Example — write configuration byte 0x01 to register 0x00 of a sensor at 0x48:
i2c.write 0x48, 0x00, 0x01
Example — write a multi-byte sequence to register 0x00 of a device at 0x40:
i2c.write 0x40, 0x00, [0x11, 0x22]

Hexadecimal Addresses

Origin’s lexer handles hexadecimal literals natively. Addresses like 0x40, 0x48, 0x68, and 0x76 are parsed as integers — no conversion or prefix stripping needed:
let reading: int = i2c.read 0x76, 0xF7, 3
i2c.write 0x68, 0x6B, 0x00
I2C requires the interface to be enabled on your Raspberry Pi. Run sudo raspi-config, go to Interface Options → I2C, and enable it. You may need to reboot. The smbus2 library must also be installed: pip install smbus2. When smbus2 is not installed, i2c.read silently returns 0 and i2c.write does nothing.

SPI

SPI (Serial Peripheral Interface) is a four-wire synchronous bus commonly used for high-speed devices such as ADCs, DACs, displays, and SD card controllers. The Raspberry Pi exposes SPI0 on BCM pins 10 (MOSI), 9 (MISO), 11 (SCLK), and 8 (CE0). Origin’s SPI primitives generate calls to _execute_spi_read(n) and _execute_spi_write(data) in the translated Python output.

Read

spi.read <n>
Reads n bytes from the SPI bus. Example — read 2 bytes from a connected SPI ADC:
let raw: int = spi.read 2
print raw

Write

spi.write <data>
Writes data to the SPI bus. Example — send a command byte to an SPI device:
spi.write 0x01
Example — send a start-bit and channel selection byte to an MCP3008 ADC, then read the result:
spi.write 0x01
spi.write 0x80
let result: int = spi.read 2
Enable SPI in raspi-config under Interface Options → SPI before using spi.read or spi.write. SPI requires the target device to be correctly wired to the Pi’s SPI0 header.

UART

UART (Universal Asynchronous Receiver-Transmitter) provides serial communication over two wires: TX (transmit) and RX (receive). On the Raspberry Pi, the primary UART is available on BCM GPIO 14 (TX, physical pin 8) and BCM GPIO 15 (RX, physical pin 10). Origin’s UART primitives generate calls to _execute_uart_read(n) and _execute_uart_write(data) in the translated Python output.

Read

uart.read <n>
Reads n bytes from the UART serial port. Example — read a single byte from a UART-connected device:
let byte: int = uart.read 1
print byte

Write

uart.write <data>
Writes data to the UART serial port. Example — send a command byte to a UART peripheral:
uart.write 0xFF
Example — send a numeric value:
uart.write 42
Enable UART in raspi-config under Interface Options → Serial Port. Disable the serial console but enable the serial hardware interface when prompted. On some Pi models the default UART is shared with Bluetooth; consult the official Raspberry Pi documentation for your specific board to redirect the primary UART if needed.

Complete Example: Reading an I2C Sensor in a Loop

This script reads a single-byte measurement from register 0x00 of an I2C sensor at address 0x48 every second and prints the raw value, repeating twenty times.
import time

let sensor_addr: int = 0x48
let sensor_reg: int = 0x00
let count: int = 0
let reading: int = 0

print "Starting sensor read loop..."

while count < 20 {
    reading = i2c.read sensor_addr, sensor_reg
    print reading
    time.sleep(1)
    count += 1
}

print "Read loop complete."
1

Wire the I2C sensor

Connect the sensor’s SDA to physical pin 3 (BCM 2) and SCL to physical pin 5 (BCM 3). Connect VCC and GND to appropriate 3.3 V and GND pins.
2

Confirm the device address

Run i2cdetect -y 1 on your Pi. Your sensor should appear at 0x48 in the output grid. If it appears at a different address, update sensor_addr in the script accordingly.
3

Enable I2C and install smbus2

Enable I2C in raspi-config if not already done, then run pip install smbus2.
4

Run the script

Save the script as sensor_loop.or and execute origin sensor_loop.or. Raw byte readings will print to the terminal once per second.

Build docs developers (and LLMs) love