Expand description
On-board bus addressing and pin logic for the pamoja SDK.
Before a node reaches any network it has to talk to the chips wired to the board it sits on. Three interfaces cover almost everything cheap hardware uses: I2C for the dense breakout sensors (a BME280, an INA226, an MPU9250, an SSD1306 screen), SPI for displays, SD cards, and LoRa radios, and plain GPIO pins for the relays, valves, buttons, and motion sensors that switch a single line. Each carries a small, exact piece of logic that is pure arithmetic with no hardware attached, and getting it wrong is a classic field bug: the wrong I2C address byte, the wrong SPI clock mode, or an active-low relay driven as if it were active-high.
This crate is that logic, with no pins toggled and no allocation:
i2c- I2C addressing per the NXP I2C-bus specification (UM10204): the 7-bit address byte(address << 1) | r/w, the two-byte11110xxframe for a 10-bit address, and the reserved ranges (0x00..=0x07and0x78..=0x7F) that leave0x08..=0x77for real devices, so a bad address is caught before it reaches the bus.spi- the four SPI clockModes as the(CPOL, CPHA)pair every datasheet quotes, plus bit order, so “mode 3, MSB first” is a checked value rather than two booleans a caller can transpose.pin- the GPIO pin model: physicalLevel, input pull and output drive, the interruptEdge, and an active-high/active-lowPolaritythat maps a logical “asserted” onto the physical level, so an active-low button or relay is handled by the type rather than by remembering to invert.
Everything is exact integer work over Copy values, so the same logic runs on the
smallest microcontroller driving the bus. Clocking the bytes and toggling the lines
themselves is the job of pamoja-hal, whose
embedded-hal traits every board implements. The switch module (the
embedded-hal feature, on by default) puts the two together for the parts that are
a single line: Switch drives a relay, a valve, or a lamp as a
core Actuator, and Contact reads a button, a float switch,
or a motion detector as a core Sensor, each with its Polarity
carried by the type rather than remembered at every call. The linux module (the
linux feature) opens a line on a Linux board through the GPIO character device, so the
same switch runs a real relay on a Raspberry Pi.
§Examples
use pamoja_gpio::i2c::{Address, Direction};
use pamoja_gpio::pin::{Level, Polarity};
use pamoja_gpio::spi::Mode;
// A DS3231 real-time clock answers at 7-bit address 0x68. Its address frame is one
// byte: the address, then the bit that says whether the controller reads or writes.
let rtc = Address::seven_bit(0x68)?;
let read = rtc.frame(Direction::Read);
assert_eq!(read.as_bytes(), [(0x68 << 1) | Direction::Read.rw_bit()]);
// SPI clock mode 0 is the (CPOL, CPHA) pair (false, false), as a datasheet quotes it.
assert_eq!(Mode::Mode0.cpol_cpha(), (false, false));
// An active-low relay is energized by driving its pin low.
assert_eq!(Polarity::ActiveLow.level(true), Level::Low);Modules§
- i2c
- I2C device addressing per the NXP I2C-bus specification (UM10204).
- linux
- Opening a GPIO line on a Linux board.
- pin
- The GPIO pin model: levels, pull and drive configuration, interrupt edges, and active polarity.
- spi
- SPI clock modes and bit order.
- switch
- The parts that are one line: a switch driven, and a contact read, through a pin.
Enums§
- Gpio
Error - What can go wrong forming an I2C address frame.