Skip to main content

Sx127x

Struct Sx127x 

Source
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>

Source

pub fn new(spi: SPI, reset: RESET, delay: D, board: Board) -> Self

Wraps a chip’s SPI device and NRESET line. Nothing is sent until init.

§Arguments
  • spi - the SPI device, with NSS as its chip select.
  • reset - the NRESET line, as an output.
  • delay - a delay for the reset pulse and the polling.
  • board - how the module wires the chip.
§Returns

The driver.

Source

pub fn board(&self) -> Board

Returns how the module wires the chip.

§Returns

The board.

Source

pub fn config(&self) -> Option<&RadioConfig>

Returns the configuration the chip was last tuned to.

§Returns

The configuration, or None before configure or after a reset.

Source

pub fn tx_power(&self, output_dbm: i8) -> TxPower

Returns the power settings for an output power on this board’s amplifier output.

§Arguments
  • output_dbm - the output power wanted at the antenna port.
§Returns

The amplifier settings.

Source

pub fn release(self) -> (SPI, RESET, D)

Gives back the SPI device, the line, and the delay.

§Returns

The SPI device, NRESET, and the delay.

Source§

impl<SPI, RESET, D> Sx127x<SPI, RESET, D>
where SPI: SpiDevice, RESET: OutputPin, D: DelayNs,

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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, BUSY, RESET, D> From<Sx127x<SPI, RESET, D>> for Radio<SPI, BUSY, RESET, D>

Source§

fn from(radio: Sx127x<SPI, RESET, D>) -> Self

Converts to this type from the input type.
Source§

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>

What the radio reports when it or the bus under it fails.
Returns the link settings frames go out with, which the duty cycle’s arithmetic needs. Read more
Source§

fn start_transmit(&mut self, frame: &[u8]) -> Result<u64, Self::Error>

Starts sending one frame, without waiting for it to leave. Read more
Source§

fn finish_transmit(&mut self) -> Result<bool, Self::Error>

Reports whether the frame start_transmit began has left. Read more
Source§

fn listen(&mut self) -> Result<(), Self::Error>

Starts listening, and keeps listening frame after frame. Read more
Source§

fn take_frame( &mut self, buffer: &mut [u8], ) -> Result<Option<usize>, Self::Error>

Takes a frame the radio has received since the last call, dropping one whose CRC failed. Read more

Auto Trait Implementations§

§

impl<SPI, RESET, D> Freeze for Sx127x<SPI, RESET, D>
where SPI: Freeze, RESET: Freeze, D: Freeze,

§

impl<SPI, RESET, D> RefUnwindSafe for Sx127x<SPI, RESET, D>
where SPI: RefUnwindSafe, RESET: RefUnwindSafe, D: RefUnwindSafe,

§

impl<SPI, RESET, D> Send for Sx127x<SPI, RESET, D>
where SPI: Send, RESET: Send, D: Send,

§

impl<SPI, RESET, D> Sync for Sx127x<SPI, RESET, D>
where SPI: Sync, RESET: Sync, D: Sync,

§

impl<SPI, RESET, D> Unpin for Sx127x<SPI, RESET, D>
where SPI: Unpin, RESET: Unpin, D: Unpin,

§

impl<SPI, RESET, D> UnsafeUnpin for Sx127x<SPI, RESET, D>
where SPI: UnsafeUnpin, RESET: UnsafeUnpin, D: UnsafeUnpin,

§

impl<SPI, RESET, D> UnwindSafe for Sx127x<SPI, RESET, D>
where SPI: UnwindSafe, RESET: UnwindSafe, D: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.