pub struct Sx127x<SPI, RESET, D> { /* private fields */ }Expand description
A Semtech SX1276, SX1277, SX1278, or SX1279 on an SPI bus, with its NRESET line.
init resets the chip and puts it in LoRa mode,
configure calibrates its receiver and tunes it to a
RadioConfig, and transmit and receive
send and wait for one frame each. For anything those do not cover, the register and data
buffer methods reach the chip directly.
§Examples
The chip’s side of initialization, scripted: an RFM95W that answers RegVersion with 0x12.
use pamoja_hal::digital::PinState;
use pamoja_hal::script::{DelayLog, PinScript, SpiScript, SpiStep};
use pamoja_radios::sx127x::config::PaOutput;
use pamoja_radios::sx127x::{Board, Sx127x};
let spi = SpiScript::new([
SpiStep::write([0x42]),
SpiStep::read([0x12]),
SpiStep::write([0x81]),
SpiStep::write([0x08]),
SpiStep::write([0x81]),
SpiStep::write([0x88]),
SpiStep::write([0x81]),
SpiStep::write([0x89]),
SpiStep::write([0x8C]),
SpiStep::write([0x23]),
]);
let board = Board::new(PaOutput::PaBoost);
let mut radio = Sx127x::new(spi, PinScript::new([]), DelayLog::new(), board);
radio.init().expect("the scripted RFM95W answers");
let (spi, reset, _) = radio.release();
assert!(spi.done());
assert_eq!(reset.driven(), [PinState::Low, PinState::High]);Implementations§
Source§impl<SPI, RESET, D> Sx127x<SPI, RESET, D>
impl<SPI, RESET, D> Sx127x<SPI, RESET, D>
Source§impl<SPI, RESET, D> Sx127x<SPI, RESET, D>where
SPI: SpiDevice,
RESET: OutputPin,
D: DelayNs,
impl<SPI, RESET, D> Sx127x<SPI, RESET, D>where
SPI: SpiDevice,
RESET: OutputPin,
D: DelayNs,
Sourcepub fn init(&mut self) -> Result<(), RadioError<SPI::Error>>
pub fn init(&mut self) -> Result<(), RadioError<SPI::Error>>
Resets the chip and puts it in LoRa mode.
NRESET is pulsed low and RegVersion read. The chip, which comes out of reset as an FSK radio in standby, is put to sleep, clocked from a TCXO if the board has one, and switched to LoRa, which it only allows in sleep. It then goes to standby with the LNA at LoRaMac-node’s setting.
§Errors
Returns RadioError::Absent if RegVersion is not 0x12, and RadioError::Spi or
RadioError::Pin if the bus or the line fails.
Sourcepub fn configure(
&mut self,
config: RadioConfig,
) -> Result<(), RadioError<SPI::Error>>
pub fn configure( &mut self, config: RadioConfig, ) -> Result<(), RadioError<SPI::Error>>
Tunes the chip to a configuration.
The first time a carrier on each RF port is configured, the receiver’s image and RSSI calibration runs there, as the datasheet’s Image and RSSI Calibration section advises, since the calibration at reset only covers the low frequency port at 434 MHz. The chip then takes the frequency, the amplifier, the modem settings, the preamble, the SF6 detection settings, the 500 kHz erratum, the longest payload, and the sync word.
§Arguments
config- the configuration.
§Errors
Returns RadioError::Modulation if the link does not fit the chip at the carrier,
RadioError::Output if the power settings are for the other output,
RadioError::Calibration if the calibration does not finish, and the bus errors of
write_register.
Sourcepub fn transmit(
&mut self,
payload: &[u8],
) -> Result<u64, RadioError<SPI::Error>>
pub fn transmit( &mut self, payload: &[u8], ) -> Result<u64, RadioError<SPI::Error>>
Sends one frame and waits for it to leave.
This is start_transmit, a wait for the frame’s airtime,
and finish_transmit read every IRQ_POLL_US until the
chip reports the frame sent.
§Arguments
payload- the frame’s payload, 1 to 255 bytes.
§Returns
The frame’s airtime in microseconds, for a DutyCycle to
count.
§Errors
Returns the errors of start_transmit, and
RadioError::NoInterrupt if TxDone does not arrive within the airtime and
TIMEOUT_MARGIN_US twice over.
Sourcepub fn start_transmit(
&mut self,
payload: &[u8],
) -> Result<u64, RadioError<SPI::Error>>
pub fn start_transmit( &mut self, payload: &[u8], ) -> Result<u64, RadioError<SPI::Error>>
Starts sending one frame and returns once the chip is transmitting.
The steps are the datasheet’s transmit sequence: standby, the IQ polarity, the payload length, the data buffer pointer at the transmit base, the payload into RegFifo, TxDone on DIO0, the interrupt flags cleared, and TX mode, after which the chip returns to standby by itself.
§Arguments
payload- the frame’s payload, 1 to 255 bytes.
§Returns
The frame’s airtime in microseconds.
§Errors
Returns RadioError::NotConfigured before configure,
RadioError::PayloadLength for an empty payload or one past 255 bytes, and the bus
errors of write_register.
Sourcepub fn finish_transmit(&mut self) -> Result<bool, RadioError<SPI::Error>>
pub fn finish_transmit(&mut self) -> Result<bool, RadioError<SPI::Error>>
Reports whether the frame start_transmit began has left.
RegIrqFlags is read once, and on TxDone that flag is cleared.
§Returns
true once the frame has been sent, false while it is still going out.
§Errors
Returns the bus errors of write_register.
Sourcepub fn receive(
&mut self,
buffer: &mut [u8],
timeout_us: u64,
) -> Result<Reception, RadioError<SPI::Error>>
pub fn receive( &mut self, buffer: &mut [u8], timeout_us: u64, ) -> Result<Reception, RadioError<SPI::Error>>
Listens for one frame in RXSINGLE mode.
The receiver is prepared as for listen, the symbol timeout is set
from timeout_us, and RegIrqFlags is read until RxDone or RxTimeout. The chip returns
to standby by itself either way.
§Arguments
buffer- where the payload goes.timeout_us- how long to listen for a preamble, in microseconds, which the chip counts in symbols from 4 to 1023; a longer timeout ends at 1023 symbols.
§Returns
The frame’s length and levels, or that the timeout passed or the frame was corrupt.
§Errors
Returns RadioError::NotConfigured before configure,
RadioError::BufferTooSmall if the payload does not fit, RadioError::NoInterrupt
if the chip never answers, and the bus errors of
write_register.
Sourcepub fn listen(&mut self) -> Result<(), RadioError<SPI::Error>>
pub fn listen(&mut self) -> Result<(), RadioError<SPI::Error>>
Starts listening in RXCONTINUOUS mode, so the chip receives frame after frame until another mode is set.
The steps are the datasheet’s receive sequence with erratum 2.3 applied: standby, the
IQ polarity, the IF and the carrier offset of the erratum, the data buffer pointer at
the receive base, RxDone on DIO0, the interrupt flags cleared, and RXCONTINUOUS. Each
frame is read with take_frame.
§Errors
Returns RadioError::NotConfigured before configure, and the
bus errors of write_register.
Sourcepub fn take_frame(
&mut self,
buffer: &mut [u8],
) -> Result<Option<Reception>, RadioError<SPI::Error>>
pub fn take_frame( &mut self, buffer: &mut [u8], ) -> Result<Option<Reception>, RadioError<SPI::Error>>
Takes the frame a listen has received, if one has arrived.
RegIrqFlags is read once. On RxDone the reception flags are cleared, and a frame whose CRC checked is copied out of the data buffer from its start address with its signal levels while the chip goes on listening.
§Arguments
buffer- where the payload goes.
§Returns
The frame, a corrupt frame, or None when nothing has arrived.
§Errors
Returns RadioError::NotConfigured before configure,
RadioError::BufferTooSmall if the payload does not fit, and the bus errors of
write_register.
Sourcepub fn standby(&mut self) -> Result<(), RadioError<SPI::Error>>
pub fn standby(&mut self) -> Result<(), RadioError<SPI::Error>>
Puts the chip in standby, which stops a transmission or a reception.
§Errors
Returns the bus errors of write_register.
Sourcepub fn sleep(&mut self) -> Result<(), RadioError<SPI::Error>>
pub fn sleep(&mut self) -> Result<(), RadioError<SPI::Error>>
Puts the chip to sleep, where it keeps its registers but loses the data buffer.
The configuration survives sleep, so the next transmission or reception wakes the chip by setting its mode.
§Errors
Returns the bus errors of write_register.
Sourcepub fn version(&mut self) -> Result<u8, RadioError<SPI::Error>>
pub fn version(&mut self) -> Result<u8, RadioError<SPI::Error>>
Reads RegVersion.
§Returns
The silicon revision, 0x12 for the SX1276 family.
§Errors
Returns RadioError::Spi if the SPI device fails.
Sourcepub fn irq_flags(&mut self) -> Result<IrqFlags, RadioError<SPI::Error>>
pub fn irq_flags(&mut self) -> Result<IrqFlags, RadioError<SPI::Error>>
Reads the raised interrupts.
§Returns
RegIrqFlags.
§Errors
Returns RadioError::Spi if the SPI device fails.
Sourcepub fn modem_status(&mut self) -> Result<ModemStatus, RadioError<SPI::Error>>
pub fn modem_status(&mut self) -> Result<ModemStatus, RadioError<SPI::Error>>
Reads the live state of the LoRa modem.
§Returns
RegModemStat, decoded.
§Errors
Returns RadioError::Spi if the SPI device fails.
Sourcepub fn rssi(&mut self) -> Result<Decibels, RadioError<SPI::Error>>
pub fn rssi(&mut self) -> Result<Decibels, RadioError<SPI::Error>>
Reads the signal power the receiver hears right now, while it listens.
§Returns
The RSSI in dBm, with the offset of the port the configured carrier uses.
§Errors
Returns RadioError::NotConfigured before configure, and
RadioError::Spi if the SPI device fails.
Sourcepub fn read_register(
&mut self,
address: u8,
) -> Result<u8, RadioError<SPI::Error>>
pub fn read_register( &mut self, address: u8, ) -> Result<u8, RadioError<SPI::Error>>
Reads one register.
§Arguments
address- the register address.
§Returns
The register value.
§Errors
Returns RadioError::Spi if the SPI device fails.
Sourcepub fn write_register(
&mut self,
address: u8,
value: u8,
) -> Result<(), RadioError<SPI::Error>>
pub fn write_register( &mut self, address: u8, value: u8, ) -> Result<(), RadioError<SPI::Error>>
Writes one register.
§Arguments
address- the register address.value- the value.
§Errors
Returns RadioError::Spi if the SPI device fails.
Sourcepub fn read_registers(
&mut self,
address: u8,
values: &mut [u8],
) -> Result<(), RadioError<SPI::Error>>
pub fn read_registers( &mut self, address: u8, values: &mut [u8], ) -> Result<(), RadioError<SPI::Error>>
Reads consecutive registers in one transaction, or bytes out of the data buffer when
address is register::FIFO.
§Arguments
address- the first register’s address.values- where the values go.
§Errors
Returns RadioError::Spi if the SPI device fails.
Sourcepub fn write_registers(
&mut self,
address: u8,
values: &[u8],
) -> Result<(), RadioError<SPI::Error>>
pub fn write_registers( &mut self, address: u8, values: &[u8], ) -> Result<(), RadioError<SPI::Error>>
Writes consecutive registers in one transaction, or bytes into the data buffer when
address is register::FIFO.
§Arguments
address- the first register’s address.values- the values.
§Errors
Returns RadioError::Spi if the SPI device fails.
Trait Implementations§
Source§impl<SPI, RESET, D> LoraRadio for Sx127x<SPI, RESET, D>where
SPI: SpiDevice,
RESET: OutputPin,
D: DelayNs,
impl<SPI, RESET, D> LoraRadio for Sx127x<SPI, RESET, D>where
SPI: SpiDevice,
RESET: OutputPin,
D: DelayNs,
Source§type Error = RadioError<<SPI as ErrorType>::Error>
type Error = RadioError<<SPI as ErrorType>::Error>
Source§fn link(&self) -> Option<LinkSettings>
fn link(&self) -> Option<LinkSettings>
Source§fn start_transmit(&mut self, frame: &[u8]) -> Result<u64, Self::Error>
fn start_transmit(&mut self, frame: &[u8]) -> Result<u64, Self::Error>
Source§fn finish_transmit(&mut self) -> Result<bool, Self::Error>
fn finish_transmit(&mut self) -> Result<bool, Self::Error>
start_transmit began has
left. Read more