1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
use embedded_hal_async::delay::DelayUs;
use crate::mod_params::*;
/// Functions implemented for an embedded framework for an MCU/LoRa chip combination
/// to allow this crate to control the LoRa chip.
pub trait InterfaceVariant {
/// Set the LoRa board type
fn set_board_type(&mut self, board_type: BoardType);
/// Select the LoRa chip for an operation
async fn set_nss_low(&mut self) -> Result<(), RadioError>;
/// De-select the LoRa chip after an operation
async fn set_nss_high(&mut self) -> Result<(), RadioError>;
/// Reset the LoRa chip
async fn reset(&mut self, delay: &mut impl DelayUs) -> Result<(), RadioError>;
/// Wait for the LoRa chip to become available for an operation
async fn wait_on_busy(&mut self) -> Result<(), RadioError>;
/// Wait for the LoRa chip to indicate an event has occurred
async fn await_irq(&mut self) -> Result<(), RadioError>;
/// Enable an antenna used for receive operations, disabling other antennas
async fn enable_rf_switch_rx(&mut self) -> Result<(), RadioError>;
/// Enable an antenna used for send operations, disabling other antennas
async fn enable_rf_switch_tx(&mut self) -> Result<(), RadioError>;
/// Disable all antennas
async fn disable_rf_switch(&mut self) -> Result<(), RadioError>;
}
/// Functions implemented for a specific kind of LoRa chip, called internally by the outward facing
/// LoRa physical layer API
pub trait RadioKind {
/// Get the specific type of the LoRa board (for example, Stm32wlSx1262)
fn get_board_type(&self) -> BoardType;
/// Reset the loRa chip
async fn reset(&mut self, delay: &mut impl DelayUs) -> Result<(), RadioError>;
/// Ensure the LoRa chip is in the appropriate state to allow operation requests
async fn ensure_ready(&mut self, mode: RadioMode) -> Result<(), RadioError>;
/// Perform any necessary antenna initialization
async fn init_rf_switch(&mut self) -> Result<(), RadioError>;
/// Place the LoRa chip in standby mode
async fn set_standby(&mut self) -> Result<(), RadioError>;
/// Place the LoRa chip in power-saving mode
async fn set_sleep(&mut self, delay: &mut impl DelayUs) -> Result<bool, RadioError>;
/// Perform operations to set a multi-protocol chip as a LoRa chip
async fn set_lora_modem(&mut self, enable_public_network: bool) -> Result<(), RadioError>;
/// Perform operations to set the LoRa chip oscillator
async fn set_oscillator(&mut self) -> Result<(), RadioError>;
/// Set the LoRa chip voltage regulator mode
async fn set_regulator_mode(&mut self) -> Result<(), RadioError>;
/// Set the LoRa chip send and receive buffer base addresses
async fn set_tx_rx_buffer_base_address(
&mut self,
tx_base_addr: usize,
rx_base_addr: usize,
) -> Result<(), RadioError>;
/// Perform any necessary LoRa chip power setup prior to a send operation
async fn set_tx_power_and_ramp_time(
&mut self,
output_power: i32,
mdltn_params: Option<&ModulationParams>,
tx_boosted_if_possible: bool,
is_tx_prep: bool,
) -> Result<(), RadioError>;
/// Update the LoRa chip retention list to support warm starts from sleep
async fn update_retention_list(&mut self) -> Result<(), RadioError>;
/// Set the LoRa chip modulation parameters prior to using a communication channel
async fn set_modulation_params(&mut self, mdltn_params: &ModulationParams) -> Result<(), RadioError>;
/// Set the LoRa chip packet parameters prior to sending or receiving packets
async fn set_packet_params(&mut self, pkt_params: &PacketParams) -> Result<(), RadioError>;
/// Set the LoRa chip to support a given communication channel frequency
async fn calibrate_image(&mut self, frequency_in_hz: u32) -> Result<(), RadioError>;
/// Set the frequency for a communication channel
async fn set_channel(&mut self, frequency_in_hz: u32) -> Result<(), RadioError>;
/// Set a payload for a subsequent send operation
async fn set_payload(&mut self, payload: &[u8]) -> Result<(), RadioError>;
/// Perform a send operation
async fn do_tx(&mut self, timeout_in_ms: u32) -> Result<(), RadioError>;
/// Set up to perform a receive operation (single-shot, continuous, or duty cycle)
async fn do_rx(
&mut self,
rx_pkt_params: &PacketParams,
duty_cycle_params: Option<&DutyCycleParams>,
rx_continuous: bool,
rx_boosted_if_supported: bool,
symbol_timeout: u16,
rx_timeout_in_ms: u32,
) -> Result<(), RadioError>;
/// Get an available packet made available as the result of a receive operation
async fn get_rx_payload(
&mut self,
rx_pkt_params: &PacketParams,
receiving_buffer: &mut [u8],
) -> Result<u8, RadioError>;
/// Get the RSSI and SNR for the packet made available as the result of a receive operation
async fn get_rx_packet_status(&mut self) -> Result<PacketStatus, RadioError>;
/// Perform a channel activity detection operation
async fn do_cad(
&mut self,
mdltn_params: &ModulationParams,
rx_boosted_if_supported: bool,
) -> Result<(), RadioError>;
/// Set the LoRa chip to provide notification of specific events based on radio state
async fn set_irq_params(&mut self, radio_mode: Option<RadioMode>) -> Result<(), RadioError>;
/// Process LoRa chip notifications of events
async fn process_irq(
&mut self,
radio_mode: RadioMode,
rx_continuous: bool,
cad_activity_detected: Option<&mut bool>,
) -> Result<(), RadioError>;
}
/// Internal trait for specifying that a [`RadioKind`] object has RNG capability.
pub(crate) trait RngRadio: RadioKind {
async fn get_random_number(&mut self) -> Result<u32, RadioError>;
}
/// If the LoRa chip supports it, provides an async implementation of the onboard RNG. This trait makes no guarantees
/// with regards to the distribution of the generated random numbers (ie, uniform or Gaussian). If uniformity is
/// needed, apply necessary software processing.
pub trait AsyncRng {
/// Generate a 32 bit random value.
///
/// # Warning
///
/// `prepare_for_xxx()` MUST be called after this operation to set modulation and packet parameters (for
/// example: xxx = tx, rx, cad).
/// Do not set modulation and packet parameters, do a random number generation, then initiate Tx, Rx, or CAD.
async fn get_random_number(&mut self) -> Result<u32, RadioError>;
}