lr2021/flrc.rs
1//! # API related to FLRC operations
2//!
3//! This module provides an API for configuring and operating the LR2021 chip for Fast Long-Range Communication (FLRC).
4//! FLRC is a Semtech proprietary protocol using GMSK modulation, offering higher sensitivity compared to BLE.
5//! It supports configurable bitrates, coding rates, and filtering on syncwords accepting up to 3 values on 32 bits.
6//!
7//! ## Quick Start
8//!
9//! Here's a typical sequence to initialize the chip for FLRC operations:
10//!
11//! ```rust,no_run
12//! use lr2021::radio::PacketType;
13//! use lr2021::flrc::{FlrcBitrate, FlrcCr, FlrcPacketParams, AgcPblLen, SwLen, SwTx, SwMatch, PktFormat, Crc};
14//! use lr2021::PulseShape;
15//!
16//! // Set packet type to FLRC
17//! lr2021.set_packet_type(PacketType::Flrc).await.expect("Setting packet type");
18//!
19//! // Configure FLRC modulation (2.6Mbps, no coding, BT=1.0 pulse shaping)
20//! lr2021.set_flrc_modulation(FlrcBitrate::Br2600, FlrcCr::None, PulseShape::Bt1p0)
21//! .await.expect("Setting FLRC modulation");
22//!
23//! // Configure syncwords (up to 3 can be configured)
24//! lr2021.set_flrc_syncword(1, 0xCD05CAFE, true).await.expect("Setting syncword 1");
25//! lr2021.set_flrc_syncword(2, 0x12345678, true).await.expect("Setting syncword 2");
26//! lr2021.set_flrc_syncword(3, 0x9ABCDEF0, true).await.expect("Setting syncword 3");
27//!
28//! // Configure packet parameters
29//! let flrc_params = FlrcPacketParams::new(
30//! AgcPblLen::Len16Bits, // 16-bit preamble
31//! SwLen::Sw32b, // 32-bit syncword length
32//! SwTx::Sw1, // Use syncword 1 for TX
33//! SwMatch::Match123, // Match any of the 3 syncwords on RX
34//! PktFormat::Dynamic, // Dynamic packet length
35//! Crc::Crc24, // 24-bit CRC
36//! 255 // Max payload length
37//! );
38//! lr2021.set_flrc_packet(&flrc_params).await.expect("Setting packet parameters");
39//! ```
40//!
41//! ## Available Methods
42//!
43//! - [`set_flrc_modulation`](Lr2021::set_flrc_modulation) - Configure bitrate, coding rate and pulse shaping
44//! - [`set_flrc_packet`](Lr2021::set_flrc_packet) - Set packet parameters (preamble, syncword, CRC, length)
45//! - [`set_flrc_syncword`](Lr2021::set_flrc_syncword) - Configure one of the three possible syncwords
46//! - [`get_flrc_packet_status`](Lr2021::get_flrc_packet_status) - Get status of last received packet
47//! - [`get_flrc_rx_stats`](Lr2021::get_flrc_rx_stats) - Get basic reception statistics
48
49use embedded_hal::digital::OutputPin;
50use embedded_hal_async::spi::SpiBus;
51
52pub use super::cmd::cmd_flrc::*;
53use super::{BusyPin, Lr2021, Lr2021Error, PulseShape};
54
55pub struct FlrcPacketParams {
56 pub agc_pbl_len: AgcPblLen,
57 pub sw_len: SwLen,
58 pub sw_tx: SwTx,
59 pub sw_match: SwMatch,
60 pub hdr_format: PktFormat,
61 pub crc: Crc,
62 pub pld_len: u16
63}
64
65impl FlrcPacketParams {
66 pub fn new(agc_pbl_len: AgcPblLen, sw_len: SwLen, sw_tx: SwTx, sw_match: SwMatch, hdr_format: PktFormat, crc: Crc, pld_len: u16) -> Self {
67 Self{agc_pbl_len, sw_len, sw_tx, sw_match, hdr_format, crc, pld_len}
68 }
69}
70
71impl<O,SPI, M> Lr2021<O,SPI, M> where
72 O: OutputPin, SPI: SpiBus<u8>, M: BusyPin
73{
74
75 /// Set Modulation parameters: raw bitrate, coding rate and pulse shaping
76 pub async fn set_flrc_modulation(&mut self, bitrate: FlrcBitrate, cr: FlrcCr, pulse_shape: PulseShape) -> Result<(), Lr2021Error> {
77 let req = set_flrc_modulation_params_cmd(bitrate, cr, pulse_shape);
78 self.cmd_wr(&req).await
79 }
80
81 /// Set FLRC packet parameters: preamble, syncword, header implicit/explicit, CRC and packet length (max 511)
82 pub async fn set_flrc_packet(&mut self, params: &FlrcPacketParams) -> Result<(), Lr2021Error> {
83 let req = set_flrc_packet_params_cmd(
84 params.agc_pbl_len,
85 params.sw_len,
86 params.sw_tx,
87 params.sw_match,
88 params.hdr_format,
89 params.crc,
90 params.pld_len);
91 self.cmd_wr(&req).await
92 }
93
94 /// Configure one of the three possible syncword
95 pub async fn set_flrc_syncword(&mut self, sw_num: u8, syncword: u32, is_16b: bool) -> Result<(), Lr2021Error> {
96 let sw = if is_16b {syncword << 16} else {syncword};
97 let req = set_flrc_syncword_cmd(sw_num, sw);
98 let req_s = if is_16b {&req[..5]} else {&req};
99 self.cmd_wr(req_s).await
100 }
101
102 /// Return length of last packet received
103 pub async fn get_flrc_packet_status(&mut self) -> Result<FlrcPacketStatusRsp, Lr2021Error> {
104 let req = get_flrc_packet_status_req();
105 let mut rsp = FlrcPacketStatusRsp::new();
106 self.cmd_rd(&req, rsp.as_mut()).await?;
107 Ok(rsp)
108 }
109
110 /// Return basic RX stats
111 pub async fn get_flrc_rx_stats(&mut self) -> Result<FlrcRxStatsRsp, Lr2021Error> {
112 let req = get_flrc_rx_stats_req();
113 let mut rsp = FlrcRxStatsRsp::new();
114 self.cmd_rd(&req, rsp.as_mut()).await?;
115 Ok(rsp)
116 }
117
118}