Firmware¶
The firmware uses platformio and the Arduino framework.
The common dependencies are
Additionally, the LoPy4 platform uses Jan Mrázek’s SmartLeds library to control the WS2812 LED.
Board support¶
The include/board.h header is used to pull in the appropriate
board-specific definitions. The board definition is setup in
the platformio.ini configuration file. The current board definitions
are
__feather__for the Feather M0 with RFM95 radio. The board-specific code is insrc/feather.cpp.__lopy4__for the LoPy4. The board-specific code is insrc/lopy4.cpp.
EEPROM¶
The eeprom library provides support for 24LCxxx I2C EEPROMs; in the future, this may expand to the 25LCxxx SPI EEPROMs. Boards are expected to have a single EEPROM at the default address (EEPROM_BASE_ADDRESS), and a single instance of this class is instantiated in the main code. It provides the following methods:
bool write(uint16_t addr, uint8_t *data, uint8_t len)attempts to writelenbytes ofdatastarting ataddr. The maximum length of data that can be written this way is governed by the EEPROM’s size; a 24LC256 can write up to 64 bytes of data at a time.bool wait()blocks until the EEPROM has finished writing. This is referred as ACK polling in the datasheet; essentially, after writing a block of data, the EEPROM needs to take some time to write the data. It will be unavailable for other operations until it has completed its write cycle. This really only needs to be called shortly after writing if more writes are needed (e.g. when writing a large buffer of data).bool read(uint16_t addr, uint8_t *data, uint8_t len)attempts to readlenbytes ofdatafromaddr; the maximum read size is the same as the maximum write size.
EEPROM support is included with the include/eeprom.h header, and
the source is in src/eeprom.cpp.
Generally, the EEPROM is only needed at boot up to read the node’s identity, but it is available for future uses as needed, subject to the memory layout described below.
The EEPROM’s memory layout is
- $0000 - $0003: Node ID, a uint32
- $0004 - $0023: Identity key, a 32-byte Ed25519 private key
- $0024 - $002C: The RNG seed
- $002D - $0032: The node’s provisioning datetime
At a high level, the following blocks are used:
- $0000 - $0032: node’s identity
Identity¶
Central to this project is the notion of a node’s identity. The
Identity docs give an overview of this. The identity header
defines a node’s identity in the Identity structure, and provides
the following functions:
bool load_identity(EEPROM_24LC &eeprom)tries to read the node’s identity information from the eeprom and performs the necessary setup like deriving the public key. If this fails, startup must fail.bool zeroise_identity(EEPROM_24LC &eeprom)erases the node’s identity. This information is no longer recoverable from the node.
It also makes the node’s identity available via the identity variable.
Radio¶
This provides support for the LoRa radio; it may eventually encompass support for other radios. It requires the following definitions to be present, which should be done in the relevant board header:
RF95_CSRF95_RSTRF95_INT
These are required by the RadioHead library to set up the radio driver.
The header file, include/radio.h, provides the following definitions
as well:
RF_FREQ(which defaults to 915.0 MHz) sets the centre frequency for the radio.RF_INIT_TXPWR(which defaults to 20) sets the initial power when the radio is enabled.
The following functions are provided (and implemented in src/radio.cpp):
bool enable_lora()enables and activates the radio, placing it into an idle state.void disable_lora()disables the radio by putting it into sleep mode and driving the RST pin low.void lora_tx_power(int8_t power)sets the transmitter power for the radio.