1#![no_std]
2#![allow(async_fn_in_trait)]
3#![warn(missing_docs)]
4#![cfg_attr(docsrs, feature(doc_cfg))]
5#![doc = include_str!("../README.md")]
6
7#[cfg(feature = "lorawan-radio")]
8#[cfg_attr(docsrs, doc(cfg(feature = "lorawan-radio")))]
9pub mod lorawan_radio;
11
12pub(crate) mod interface;
14pub mod iv;
16pub mod mod_params;
18pub mod mod_traits;
20pub mod sx126x;
22pub mod sx127x;
24
25pub use crate::mod_params::RxMode;
26
27pub use embedded_hal_async::delay::DelayNs;
28use interface::*;
29use mod_params::*;
30use mod_traits::*;
31
32pub struct LoRa<RK, DLY>
34where
35 RK: RadioKind,
36 DLY: DelayNs,
37{
38 radio_kind: RK,
39 delay: DLY,
40 radio_mode: RadioMode,
41 enable_public_network: bool,
42 cold_start: bool,
43 calibrate_image: bool,
44}
45
46impl<RK, DLY> LoRa<RK, DLY>
47where
48 RK: RadioKind,
49 DLY: DelayNs,
50{
51 pub async fn new(radio_kind: RK, enable_public_network: bool, delay: DLY) -> Result<Self, RadioError> {
53 let mut lora = Self {
54 radio_kind,
55 delay,
56 radio_mode: RadioMode::Sleep,
57 enable_public_network,
58 cold_start: true,
59 calibrate_image: true,
60 };
61 lora.init().await?;
62
63 Ok(lora)
64 }
65
66 pub async fn wait_for_irq(&mut self) -> Result<(), RadioError> {
68 self.radio_kind.await_irq().await
69 }
70
71 pub async fn process_irq_event(&mut self) -> Result<Option<IrqState>, RadioError> {
73 self.radio_kind.process_irq_event(self.radio_mode, None, false).await
74 }
75
76 pub fn create_modulation_params(
78 &mut self,
79 spreading_factor: SpreadingFactor,
80 bandwidth: Bandwidth,
81 coding_rate: CodingRate,
82 frequency_in_hz: u32,
83 ) -> Result<ModulationParams, RadioError> {
84 self.radio_kind
85 .create_modulation_params(spreading_factor, bandwidth, coding_rate, frequency_in_hz)
86 }
87
88 pub fn create_tx_packet_params(
90 &mut self,
91 preamble_length: u16,
92 implicit_header: bool,
93 crc_on: bool,
94 iq_inverted: bool,
95 modulation_params: &ModulationParams,
96 ) -> Result<PacketParams, RadioError> {
97 self.radio_kind.create_packet_params(
98 preamble_length,
99 implicit_header,
100 0,
101 crc_on,
102 iq_inverted,
103 modulation_params,
104 )
105 }
106
107 pub fn create_rx_packet_params(
109 &mut self,
110 preamble_length: u16,
111 implicit_header: bool,
112 max_payload_length: u8,
113 crc_on: bool,
114 iq_inverted: bool,
115 modulation_params: &ModulationParams,
116 ) -> Result<PacketParams, RadioError> {
117 self.radio_kind.create_packet_params(
118 preamble_length,
119 implicit_header,
120 max_payload_length,
121 crc_on,
122 iq_inverted,
123 modulation_params,
124 )
125 }
126
127 pub async fn init(&mut self) -> Result<(), RadioError> {
129 self.cold_start = true;
130 self.radio_kind.reset(&mut self.delay).await?;
131 self.radio_kind.ensure_ready(self.radio_mode).await?;
132 self.radio_kind.set_standby().await?;
133 self.radio_mode = RadioMode::Standby;
134 self.do_cold_start().await
135 }
136
137 async fn do_cold_start(&mut self) -> Result<(), RadioError> {
138 self.radio_kind.init_lora(self.enable_public_network).await?;
139 self.radio_kind.set_tx_power_and_ramp_time(0, None, false).await?;
140 self.radio_kind.set_irq_params(Some(self.radio_mode)).await?;
141 self.cold_start = false;
142 self.calibrate_image = true;
143 Ok(())
144 }
145
146 pub async fn enter_standby(&mut self) -> Result<(), RadioError> {
148 self.radio_kind.set_standby().await
149 }
150
151 pub async fn sleep(&mut self, warm_start_if_possible: bool) -> Result<(), RadioError> {
153 if self.radio_mode != RadioMode::Sleep {
154 self.radio_kind.ensure_ready(self.radio_mode).await?;
155 self.radio_kind
156 .set_sleep(warm_start_if_possible, &mut self.delay)
157 .await?;
158 if !warm_start_if_possible {
159 self.cold_start = true;
160 }
161 self.radio_mode = RadioMode::Sleep;
162 }
163 Ok(())
164 }
165
166 pub async fn prepare_for_tx(
168 &mut self,
169 mdltn_params: &ModulationParams,
170 tx_pkt_params: &mut PacketParams,
171 output_power: i32,
172 buffer: &[u8],
173 ) -> Result<(), RadioError> {
174 self.prepare_modem(mdltn_params).await?;
175
176 self.radio_kind.set_modulation_params(mdltn_params).await?;
177 self.radio_kind
178 .set_tx_power_and_ramp_time(output_power, Some(mdltn_params), true)
179 .await?;
180 self.radio_kind.ensure_ready(self.radio_mode).await?;
181 if self.radio_mode != RadioMode::Standby {
182 self.radio_kind.set_standby().await?;
183 self.radio_mode = RadioMode::Standby;
184 }
185
186 tx_pkt_params.set_payload_length(buffer.len())?;
187 self.radio_kind.set_packet_params(tx_pkt_params).await?;
188 self.radio_kind.set_channel(mdltn_params.frequency_in_hz).await?;
189 self.radio_kind.set_payload(buffer).await?;
190 self.radio_mode = RadioMode::Transmit;
191 self.radio_kind.set_irq_params(Some(self.radio_mode)).await?;
192 Ok(())
193 }
194
195 pub async fn tx(&mut self) -> Result<(), RadioError> {
197 if let RadioMode::Transmit = self.radio_mode {
198 self.radio_kind.do_tx().await?;
199 loop {
200 self.wait_for_irq().await?;
201 match self.radio_kind.process_irq_event(self.radio_mode, None, true).await {
202 Ok(Some(IrqState::Done | IrqState::PreambleReceived)) => {
203 self.radio_mode = RadioMode::Standby;
204 return Ok(());
205 }
206 Ok(None) => continue,
207 Err(err) => {
208 self.radio_kind.ensure_ready(self.radio_mode).await?;
209 self.radio_kind.set_standby().await?;
210 self.radio_mode = RadioMode::Standby;
211 return Err(err);
212 }
213 }
214 }
215 } else {
216 Err(RadioError::InvalidRadioMode)
217 }
218 }
219
220 pub async fn prepare_for_rx(
227 &mut self,
228 listen_mode: RxMode,
229 mdltn_params: &ModulationParams,
230 rx_pkt_params: &PacketParams,
231 ) -> Result<(), RadioError> {
232 defmt::trace!("RX mode: {}", listen_mode);
233 self.prepare_modem(mdltn_params).await?;
234
235 self.radio_kind.set_modulation_params(mdltn_params).await?;
236 self.radio_kind.set_packet_params(rx_pkt_params).await?;
237 self.radio_kind.set_channel(mdltn_params.frequency_in_hz).await?;
238 self.radio_mode = listen_mode.into();
239 self.radio_kind.set_irq_params(Some(self.radio_mode)).await?;
240 Ok(())
241 }
242
243 pub async fn rx(
245 &mut self,
246 packet_params: &PacketParams,
247 receiving_buffer: &mut [u8],
248 ) -> Result<(u8, PacketStatus), RadioError> {
249 if let RadioMode::Receive(listen_mode) = self.radio_mode {
250 self.radio_kind.do_rx(listen_mode).await?;
251 loop {
252 self.wait_for_irq().await?;
253 match self.radio_kind.process_irq_event(self.radio_mode, None, true).await {
254 Ok(Some(actual_state)) => match actual_state {
255 IrqState::PreambleReceived => continue,
256 IrqState::Done => {
257 let received_len = self.radio_kind.get_rx_payload(packet_params, receiving_buffer).await?;
258 let rx_pkt_status = self.radio_kind.get_rx_packet_status().await?;
259 return Ok((received_len, rx_pkt_status));
260 }
261 },
262 Ok(None) => continue,
263 Err(err) => {
264 if self.radio_mode != RadioMode::Receive(RxMode::Continuous) {
266 self.radio_kind.ensure_ready(self.radio_mode).await?;
267 self.radio_kind.set_standby().await?;
268 self.radio_mode = RadioMode::Standby;
269 }
270 return Err(err);
271 }
272 }
273 }
274 } else {
275 Err(RadioError::InvalidRadioMode)
276 }
277 }
278
279 pub async fn prepare_for_cad(&mut self, mdltn_params: &ModulationParams) -> Result<(), RadioError> {
281 self.prepare_modem(mdltn_params).await?;
282
283 self.radio_kind.set_modulation_params(mdltn_params).await?;
284 self.radio_kind.set_channel(mdltn_params.frequency_in_hz).await?;
285 self.radio_mode = RadioMode::ChannelActivityDetection;
286 self.radio_kind.set_irq_params(Some(self.radio_mode)).await?;
287 Ok(())
288 }
289
290 pub async fn cad(&mut self, mdltn_params: &ModulationParams) -> Result<bool, RadioError> {
292 if self.radio_mode == RadioMode::ChannelActivityDetection {
293 self.radio_kind.do_cad(mdltn_params).await?;
294 self.wait_for_irq().await?;
295 let mut cad_activity_detected = false;
296 match self
297 .radio_kind
298 .process_irq_event(self.radio_mode, Some(&mut cad_activity_detected), true)
299 .await
300 {
301 Ok(Some(IrqState::Done)) => Ok(cad_activity_detected),
302 Err(err) => {
303 self.radio_kind.ensure_ready(self.radio_mode).await?;
304 self.radio_kind.set_standby().await?;
305 self.radio_mode = RadioMode::Standby;
306 Err(err)
307 }
308 Ok(_) => unreachable!(),
309 }
310 } else {
311 Err(RadioError::InvalidRadioMode)
312 }
313 }
314
315 pub async fn continuous_wave(
321 &mut self,
322 mdltn_params: &ModulationParams,
323 output_power: i32,
324 ) -> Result<(), RadioError> {
325 self.prepare_modem(mdltn_params).await?;
326
327 let tx_pkt_params = self
328 .radio_kind
329 .create_packet_params(0, false, 16, false, false, mdltn_params)?;
330 self.radio_kind.set_packet_params(&tx_pkt_params).await?;
331 self.radio_kind.set_modulation_params(mdltn_params).await?;
332 self.radio_kind
333 .set_tx_power_and_ramp_time(output_power, Some(mdltn_params), true)
334 .await?;
335
336 self.radio_kind.ensure_ready(self.radio_mode).await?;
337 if self.radio_mode != RadioMode::Standby {
338 self.radio_kind.set_standby().await?;
339 self.radio_mode = RadioMode::Standby;
340 }
341 self.radio_kind.set_channel(mdltn_params.frequency_in_hz).await?;
342 self.radio_mode = RadioMode::Transmit;
343 self.radio_kind.set_irq_params(Some(self.radio_mode)).await?;
344 self.radio_kind.set_tx_continuous_wave_mode().await
345 }
346
347 async fn prepare_modem(&mut self, mdltn_params: &ModulationParams) -> Result<(), RadioError> {
348 self.radio_kind.ensure_ready(self.radio_mode).await?;
349 if self.radio_mode != RadioMode::Standby {
350 self.radio_kind.set_standby().await?;
351 self.radio_mode = RadioMode::Standby;
352 }
353
354 if self.cold_start {
355 self.do_cold_start().await?;
356 }
357
358 if self.calibrate_image {
359 self.radio_kind.calibrate_image(mdltn_params.frequency_in_hz).await?;
360 self.calibrate_image = false;
361 }
362
363 Ok(())
364 }
365}