1mod radio_kind_params;
2
3use defmt::debug;
4use embedded_hal_async::delay::DelayNs;
5use embedded_hal_async::spi::*;
6pub use radio_kind_params::TcxoCtrlVoltage;
7use radio_kind_params::*;
8
9use crate::mod_params::*;
10use crate::mod_traits::IrqState;
11use crate::{InterfaceVariant, RadioKind, SpiInterface};
12mod variant;
13pub use variant::*;
14
15const LORA_MAC_PUBLIC_SYNCWORD: u16 = 0x3444; const LORA_MAC_PRIVATE_SYNCWORD: u16 = 0x1424; const MAX_NUMBER_REGS_IN_RETENTION: u8 = 4;
21
22const SX126X_XTAL_FREQ: u32 = 32000000;
24
25const SX126X_PLL_STEP_SHIFT_AMOUNT: u32 = 14;
27
28const SX126X_PLL_STEP_SCALED: u32 = SX126X_XTAL_FREQ >> (25 - SX126X_PLL_STEP_SHIFT_AMOUNT);
30
31const SX126X_MAX_LORA_SYMB_NUM_TIMEOUT: u8 = 248;
33
34const BRD_TCXO_WAKEUP_TIME: u32 = 10;
36
37const RX_CONTINUOUS_TIMEOUT: u32 = 0xffffff;
39
40#[repr(u8)]
42pub enum DeviceSel {
43 LowPowerPA = 1,
45 HighPowerPA = 0,
47}
48
49pub struct Config<C: Sx126xVariant + Sized> {
51 pub chip: C,
53 pub tcxo_ctrl: Option<TcxoCtrlVoltage>,
55 pub use_dcdc: bool,
57 pub rx_boost: bool,
59}
60
61pub struct Sx126x<SPI, IV, C: Sx126xVariant + Sized> {
63 intf: SpiInterface<SPI, IV>,
64 config: Config<C>,
65}
66
67impl<SPI, IV, C> Sx126x<SPI, IV, C>
68where
69 SPI: SpiDevice<u8>,
70 IV: InterfaceVariant,
71 C: Sx126xVariant,
72{
73 pub fn new(spi: SPI, iv: IV, config: Config<C>) -> Self {
75 let intf = SpiInterface::new(spi, iv);
76 Self { intf, config }
77 }
78
79 async fn add_register_to_retention_list(&mut self, register: Register) -> Result<(), RadioError> {
81 let mut buffer = [0x00u8; (1 + (2 * MAX_NUMBER_REGS_IN_RETENTION)) as usize];
82
83 self.intf
85 .read(
86 &[
87 OpCode::ReadRegister.value(),
88 Register::RetentionList.addr1(),
89 Register::RetentionList.addr2(),
90 0x00u8,
91 ],
92 &mut buffer,
93 )
94 .await?;
95
96 let number_of_registers = buffer[0];
97 for i in 0..number_of_registers {
98 if register.addr1() == buffer[(1 + (2 * i)) as usize] && register.addr2() == buffer[(2 + (2 * i)) as usize]
99 {
100 return Ok(()); }
102 }
103
104 if number_of_registers < MAX_NUMBER_REGS_IN_RETENTION {
105 buffer[0] += 1; buffer[(1 + (2 * number_of_registers)) as usize] = register.addr1();
108 buffer[(2 + (2 * number_of_registers)) as usize] = register.addr2();
109
110 let register = [
111 OpCode::WriteRegister.value(),
112 Register::RetentionList.addr1(),
113 Register::RetentionList.addr2(),
114 ];
115 self.intf.write_with_payload(®ister, &buffer, false).await
116 } else {
117 Err(RadioError::InvalidConfiguration)
118 }
119 }
120
121 async fn update_retention_list(&mut self) -> Result<(), RadioError> {
122 self.add_register_to_retention_list(Register::RxGain).await?;
123 self.add_register_to_retention_list(Register::TxModulation).await
124 }
125
126 async fn set_lora_symbol_num_timeout(&mut self, symbol_num: u16) -> Result<(), RadioError> {
128 let mut exp = 0u8;
129 let mut mant = ((symbol_num.min(SX126X_MAX_LORA_SYMB_NUM_TIMEOUT.into()) + 1) >> 1) as u8;
130 while mant > 31 {
131 mant = (mant + 3) >> 2;
132 exp += 1;
133 }
134 let val: u8 = mant << ((2 * exp) + 1);
135 self.intf
136 .write(&[OpCode::SetLoRaSymbTimeout.value(), val], false)
137 .await?;
138
139 if symbol_num > 0 {
140 let val = exp + (mant << 3);
141 let buf = [
142 OpCode::WriteRegister.value(),
143 Register::SynchTimeout.addr1(),
144 Register::SynchTimeout.addr2(),
145 val,
146 ];
147 self.intf.write(&buf, false).await?;
148 }
149 Ok(())
150 }
151
152 async fn set_pa_config(&mut self, pa_duty_cycle: u8, hp_max: u8, device_sel: DeviceSel) -> Result<(), RadioError> {
153 const PA_LUT_RESERVED: u8 = 0x01;
154 let op_code_and_pa_config = [
155 OpCode::SetPAConfig.value(),
156 pa_duty_cycle,
157 hp_max,
158 device_sel as u8,
159 PA_LUT_RESERVED,
160 ];
161 self.intf.write(&op_code_and_pa_config, false).await
162 }
163
164 fn timeout_1(timeout: u32) -> u8 {
165 ((timeout >> 16) & 0xFF) as u8
166 }
167 fn timeout_2(timeout: u32) -> u8 {
168 ((timeout >> 8) & 0xFF) as u8
169 }
170 fn timeout_3(timeout: u32) -> u8 {
171 (timeout & 0xFF) as u8
172 }
173
174 fn convert_freq_in_hz_to_pll_step(freq_in_hz: u32) -> u32 {
175 let steps_int = freq_in_hz / SX126X_PLL_STEP_SCALED;
177 let steps_frac = freq_in_hz - (steps_int * SX126X_PLL_STEP_SCALED);
178
179 (steps_int << SX126X_PLL_STEP_SHIFT_AMOUNT)
180 + (((steps_frac << SX126X_PLL_STEP_SHIFT_AMOUNT) + (SX126X_PLL_STEP_SCALED >> 1)) / SX126X_PLL_STEP_SCALED)
181 }
182}
183
184impl<SPI, IV, C> RadioKind for Sx126x<SPI, IV, C>
185where
186 SPI: SpiDevice<u8>,
187 IV: InterfaceVariant,
188 C: Sx126xVariant,
189{
190 async fn init_lora(&mut self, is_public_network: bool) -> Result<(), RadioError> {
191 if self.config.use_dcdc {
193 let reg_data = [OpCode::SetRegulatorMode.value(), RegulatorMode::UseDCDC.value()];
194 self.intf.write(®_data, false).await?;
195 }
196 if self.config.chip.use_dio2_as_rfswitch() {
198 let cmd = [
199 OpCode::SetDIO2AsRfSwitchCtrl.value(),
200 self.config.chip.use_dio2_as_rfswitch() as u8,
201 ];
202 self.intf.write(&cmd, false).await?;
203 }
204
205 if let Some(voltage) = self.config.tcxo_ctrl {
207 let mut buf = [0u8; 2];
212 let _ = self
213 .intf
214 .read_with_status(&[OpCode::ClearDeviceErrors.value()], &mut buf)
215 .await?;
216
217 let timeout = BRD_TCXO_WAKEUP_TIME << 6;
219 let op_code_and_tcxo_control = [
220 OpCode::SetTCXOMode.value(),
221 voltage.value() & 0x07,
222 Self::timeout_1(timeout),
223 Self::timeout_2(timeout),
224 Self::timeout_3(timeout),
225 ];
226 self.intf.write(&op_code_and_tcxo_control, false).await?;
227 self.intf
229 .write(&[OpCode::Calibrate.value(), 0b0111_1111], false)
230 .await?;
231 self.intf.iv.wait_on_busy().await?;
232 }
233
234 self.intf
236 .write(&[OpCode::SetPacketType.value(), PacketType::LoRa.value()], false)
237 .await?;
238 let word = match is_public_network {
239 true => u16::to_be_bytes(LORA_MAC_PUBLIC_SYNCWORD),
240 false => u16::to_be_bytes(LORA_MAC_PRIVATE_SYNCWORD),
241 };
242 let lora_syncword_set = [
244 OpCode::WriteRegister.value(),
245 Register::LoRaSyncword.addr1(),
246 Register::LoRaSyncword.addr2(),
247 word[0],
248 word[1],
249 ];
250 self.intf.write(&lora_syncword_set, false).await?;
251
252 self.set_tx_rx_buffer_base_address(0, 0).await?;
253 self.update_retention_list().await?;
255 Ok(())
256 }
257
258 fn create_modulation_params(
259 &self,
260 spreading_factor: SpreadingFactor,
261 bandwidth: Bandwidth,
262 coding_rate: CodingRate,
263 frequency_in_hz: u32,
264 ) -> Result<ModulationParams, RadioError> {
265 spreading_factor_value(spreading_factor)?;
267 bandwidth_value(bandwidth)?;
268 coding_rate_value(coding_rate)?;
269 if ((bandwidth == Bandwidth::_250KHz) || (bandwidth == Bandwidth::_500KHz)) && (frequency_in_hz < 400_000_000) {
270 return Err(RadioError::InvalidBandwidthForFrequency);
271 }
272
273 let mut low_data_rate_optimize = 0x00u8;
274 if (((spreading_factor == SpreadingFactor::_11) || (spreading_factor == SpreadingFactor::_12))
275 && (bandwidth == Bandwidth::_125KHz))
276 || ((spreading_factor == SpreadingFactor::_12) && (bandwidth == Bandwidth::_250KHz))
277 {
278 low_data_rate_optimize = 0x01u8;
279 }
280 Ok(ModulationParams {
281 spreading_factor,
282 bandwidth,
283 coding_rate,
284 low_data_rate_optimize,
285 frequency_in_hz,
286 })
287 }
288
289 fn create_packet_params(
290 &self,
291 mut preamble_length: u16,
292 implicit_header: bool,
293 payload_length: u8,
294 crc_on: bool,
295 iq_inverted: bool,
296 modulation_params: &ModulationParams,
297 ) -> Result<PacketParams, RadioError> {
298 if ((modulation_params.spreading_factor == SpreadingFactor::_5)
299 || (modulation_params.spreading_factor == SpreadingFactor::_6))
300 && (preamble_length < 12)
301 {
302 preamble_length = 12;
303 }
304
305 Ok(PacketParams {
306 preamble_length,
307 implicit_header,
308 payload_length,
309 crc_on,
310 iq_inverted,
311 })
312 }
313
314 async fn reset(&mut self, delay: &mut impl DelayNs) -> Result<(), RadioError> {
315 self.intf.iv.reset(delay).await
316 }
317
318 async fn ensure_ready(&mut self, mode: RadioMode) -> Result<(), RadioError> {
320 match mode {
321 RadioMode::Sleep | RadioMode::Receive(RxMode::DutyCycle(_)) => {
322 let op_code_and_null = [OpCode::GetStatus.value(), 0x00u8];
323 self.intf.write(&op_code_and_null, false).await?;
324 }
325 _ => self.intf.iv.wait_on_busy().await?,
326 }
327 Ok(())
328 }
329
330 async fn set_standby(&mut self) -> Result<(), RadioError> {
332 let op_code_and_standby_mode = [OpCode::SetStandby.value(), StandbyMode::RC.value()];
333 self.intf.write(&op_code_and_standby_mode, false).await?;
334 self.intf.iv.disable_rf_switch().await
335 }
336
337 async fn set_sleep(&mut self, warm_start_if_possible: bool, delay: &mut impl DelayNs) -> Result<(), RadioError> {
338 self.intf.iv.disable_rf_switch().await?;
339 let sleep_params = SleepParams {
340 wakeup_rtc: false,
341 reset: false,
342 warm_start: warm_start_if_possible,
343 };
344 let op_code_and_sleep_params = [OpCode::SetSleep.value(), sleep_params.value()];
345 self.intf.write(&op_code_and_sleep_params, true).await?;
346 delay.delay_ms(2).await;
347
348 Ok(())
349 }
350
351 async fn set_tx_rx_buffer_base_address(
352 &mut self,
353 tx_base_addr: usize,
354 rx_base_addr: usize,
355 ) -> Result<(), RadioError> {
356 if tx_base_addr > 255 || rx_base_addr > 255 {
357 return Err(RadioError::InvalidBaseAddress(tx_base_addr, rx_base_addr));
358 }
359 let op_code_and_base_addrs = [
360 OpCode::SetBufferBaseAddress.value(),
361 tx_base_addr as u8,
362 rx_base_addr as u8,
363 ];
364 self.intf.write(&op_code_and_base_addrs, false).await
365 }
366
367 async fn set_tx_power_and_ramp_time(
373 &mut self,
374 output_power: i32,
375 mdltn_params: Option<&ModulationParams>,
376 is_tx_prep: bool,
377 ) -> Result<(), RadioError> {
378 let tx_params_power;
379 let ramp_time = match is_tx_prep {
380 true => RampTime::Ramp40Us, false => RampTime::Ramp200Us, };
383
384 match self.config.chip.get_device_sel() {
385 DeviceSel::LowPowerPA => {
386 const LOW_POWER_MIN: i32 = -17;
387 const LOW_POWER_MAX: i32 = 15;
388 let txp = output_power.clamp(LOW_POWER_MIN, LOW_POWER_MAX);
390
391 if txp == 15 {
392 if let Some(m_p) = mdltn_params {
393 if m_p.frequency_in_hz < 400_000_000 {
394 return Err(RadioError::InvalidOutputPowerForFrequency);
395 }
396 }
397 }
398
399 match txp {
404 LOW_POWER_MAX => {
405 self.set_pa_config(0x06, 0x00, DeviceSel::LowPowerPA).await?;
406 tx_params_power = 14;
407 }
408 11..=14 => {
409 self.set_pa_config(0x04, 0x00, DeviceSel::LowPowerPA).await?;
410 tx_params_power = txp as u8;
411 }
412 LOW_POWER_MIN..=10 => {
414 self.set_pa_config(0x01, 0x00, DeviceSel::LowPowerPA).await?;
415 tx_params_power = txp as u8 + 3;
417 }
418 _ => unreachable!("Invalid output power value for low power PA!"),
419 }
420 }
421 DeviceSel::HighPowerPA => {
422 const HIGH_POWER_MIN: i32 = -9;
423 const HIGH_POWER_MAX: i32 = 22;
424 let txp = output_power.clamp(HIGH_POWER_MIN, HIGH_POWER_MAX);
426 let mut tx_clamp_cfg = [0x00u8];
428 self.intf
429 .read(
430 &[
431 OpCode::ReadRegister.value(),
432 Register::TxClampCfg.addr1(),
433 Register::TxClampCfg.addr2(),
434 0x00u8,
435 ],
436 &mut tx_clamp_cfg,
437 )
438 .await?;
439 tx_clamp_cfg[0] |= 0x0F << 1;
440 let register_and_tx_clamp_cfg = [
441 OpCode::WriteRegister.value(),
442 Register::TxClampCfg.addr1(),
443 Register::TxClampCfg.addr2(),
444 tx_clamp_cfg[0],
445 ];
446 self.intf.write(®ister_and_tx_clamp_cfg, false).await?;
447
448 match txp {
450 21..=HIGH_POWER_MAX => {
451 self.set_pa_config(0x04, 0x07, DeviceSel::HighPowerPA).await?;
452 tx_params_power = 22;
453 }
454 18..=20 => {
455 self.set_pa_config(0x03, 0x05, DeviceSel::HighPowerPA).await?;
456 tx_params_power = txp as u8 + 2;
458 }
459 15..=17 => {
460 self.set_pa_config(0x02, 0x03, DeviceSel::HighPowerPA).await?;
461 tx_params_power = txp as u8 + 5;
463 }
464 HIGH_POWER_MIN..=14 => {
465 self.set_pa_config(0x02, 0x02, DeviceSel::HighPowerPA).await?;
466 tx_params_power = txp as u8 + 8;
468 }
469 _ => {
470 unreachable!("Invalid output power value for high power PA!")
471 }
472 }
473 }
474 }
475 let op_code_and_tx_params = [OpCode::SetTxParams.value(), tx_params_power, ramp_time.value()];
476 self.intf.write(&op_code_and_tx_params, false).await
477 }
478
479 async fn set_modulation_params(&mut self, mdltn_params: &ModulationParams) -> Result<(), RadioError> {
480 let spreading_factor_val = spreading_factor_value(mdltn_params.spreading_factor)?;
481 let bandwidth_val = bandwidth_value(mdltn_params.bandwidth)?;
482 let coding_rate_val = coding_rate_value(mdltn_params.coding_rate)?;
483 debug!(
484 "sf = {}, bw = {}, cr = {}",
485 spreading_factor_val, bandwidth_val, coding_rate_val
486 );
487 let op_code_and_mod_params = [
488 OpCode::SetModulationParams.value(),
489 spreading_factor_val,
490 bandwidth_val,
491 coding_rate_val,
492 mdltn_params.low_data_rate_optimize,
493 ];
494 self.intf.write(&op_code_and_mod_params, false).await?;
495
496 let mut tx_mod = [0x00u8];
498 self.intf
499 .read(
500 &[
501 OpCode::ReadRegister.value(),
502 Register::TxModulation.addr1(),
503 Register::TxModulation.addr2(),
504 0x00u8,
505 ],
506 &mut tx_mod,
507 )
508 .await?;
509 if mdltn_params.bandwidth == Bandwidth::_500KHz {
510 let register_and_tx_mod_update = [
511 OpCode::WriteRegister.value(),
512 Register::TxModulation.addr1(),
513 Register::TxModulation.addr2(),
514 tx_mod[0] & (!(1 << 2)),
515 ];
516 self.intf.write(®ister_and_tx_mod_update, false).await
517 } else {
518 let register_and_tx_mod_update = [
519 OpCode::WriteRegister.value(),
520 Register::TxModulation.addr1(),
521 Register::TxModulation.addr2(),
522 tx_mod[0] | (1 << 2),
523 ];
524 self.intf.write(®ister_and_tx_mod_update, false).await
525 }
526 }
527
528 async fn set_packet_params(&mut self, pkt_params: &PacketParams) -> Result<(), RadioError> {
529 let op_code_and_pkt_params = [
530 OpCode::SetPacketParams.value(),
531 ((pkt_params.preamble_length >> 8) & 0xFF) as u8,
532 (pkt_params.preamble_length & 0xFF) as u8,
533 pkt_params.implicit_header as u8,
534 pkt_params.payload_length,
535 pkt_params.crc_on as u8,
536 pkt_params.iq_inverted as u8,
537 ];
538 self.intf.write(&op_code_and_pkt_params, false).await?;
539
540 let mut iq_polarity = [0x00u8];
542 self.intf
543 .read(
544 &[
545 OpCode::ReadRegister.value(),
546 Register::IQPolarity.addr1(),
547 Register::IQPolarity.addr2(),
548 0x00u8,
549 ],
550 &mut iq_polarity,
551 )
552 .await?;
553
554 let reg = if pkt_params.iq_inverted {
555 iq_polarity[0] & (!(1 << 2))
556 } else {
557 iq_polarity[0] | (1 << 2)
558 };
559
560 let op = [
561 OpCode::WriteRegister.value(),
562 Register::IQPolarity.addr1(),
563 Register::IQPolarity.addr2(),
564 reg,
565 ];
566 self.intf.write(&op, false).await?;
567 Ok(())
568 }
569
570 async fn calibrate_image(&mut self, frequency_in_hz: u32) -> Result<(), RadioError> {
572 let mut cal_freq = [0x00u8, 0x00u8];
573
574 if frequency_in_hz > 900000000 {
575 cal_freq[0] = 0xE1;
576 cal_freq[1] = 0xE9;
577 } else if frequency_in_hz > 850000000 {
578 cal_freq[0] = 0xD7;
579 cal_freq[1] = 0xDB;
580 } else if frequency_in_hz > 770000000 {
581 cal_freq[0] = 0xC1;
582 cal_freq[1] = 0xC5;
583 } else if frequency_in_hz > 460000000 {
584 cal_freq[0] = 0x75;
585 cal_freq[1] = 0x81;
586 } else if frequency_in_hz > 425000000 {
587 cal_freq[0] = 0x6B;
588 cal_freq[1] = 0x6F;
589 }
590
591 let op_code_and_cal_freq = [OpCode::CalibrateImage.value(), cal_freq[0], cal_freq[1]];
592 self.intf.write(&op_code_and_cal_freq, false).await
593 }
594
595 async fn set_channel(&mut self, frequency_in_hz: u32) -> Result<(), RadioError> {
596 debug!("channel = {}", frequency_in_hz);
597 let freq_in_pll_steps = Self::convert_freq_in_hz_to_pll_step(frequency_in_hz);
598 let op_code_and_pll_steps = [
599 OpCode::SetRFFrequency.value(),
600 ((freq_in_pll_steps >> 24) & 0xFF) as u8,
601 ((freq_in_pll_steps >> 16) & 0xFF) as u8,
602 ((freq_in_pll_steps >> 8) & 0xFF) as u8,
603 (freq_in_pll_steps & 0xFF) as u8,
604 ];
605 self.intf.write(&op_code_and_pll_steps, false).await
606 }
607
608 async fn set_payload(&mut self, payload: &[u8]) -> Result<(), RadioError> {
609 let op_code_and_offset = [OpCode::WriteBuffer.value(), 0x00u8];
610 self.intf.write_with_payload(&op_code_and_offset, payload, false).await
611 }
612
613 async fn do_tx(&mut self) -> Result<(), RadioError> {
614 self.intf.iv.enable_rf_switch_tx().await?;
615
616 let cmd = [
618 OpCode::SetTx.value(),
619 Self::timeout_1(0),
620 Self::timeout_2(0),
621 Self::timeout_3(0),
622 ];
623 self.intf.write(&cmd, false).await
624 }
625
626 async fn do_rx(&mut self, rx_mode: RxMode) -> Result<(), RadioError> {
627 self.intf.iv.enable_rf_switch_rx().await?;
628
629 let op_code_and_true_flag = [OpCode::SetStopRxTimerOnPreamble.value(), 0x01u8];
631 self.intf.write(&op_code_and_true_flag, false).await?;
632
633 let num_symbols = match rx_mode {
634 RxMode::DutyCycle(_) | RxMode::Continuous => 0,
635 RxMode::Single(n) => n,
636 };
637 self.set_lora_symbol_num_timeout(num_symbols).await?;
638
639 let rx_gain = if self.config.rx_boost { 0x96 } else { 0x94 };
640 let register_and_rx_gain = [
641 OpCode::WriteRegister.value(),
642 Register::RxGain.addr1(),
643 Register::RxGain.addr2(),
644 rx_gain,
645 ];
646 self.intf.write(®ister_and_rx_gain, false).await?;
647
648 match rx_mode {
649 RxMode::DutyCycle(args) => {
650 let op = [
651 OpCode::SetRxDutyCycle.value(),
652 Self::timeout_1(args.rx_time),
653 Self::timeout_2(args.rx_time),
654 Self::timeout_3(args.rx_time),
655 Self::timeout_1(args.sleep_time),
656 Self::timeout_2(args.sleep_time),
657 Self::timeout_3(args.sleep_time),
658 ];
659 self.intf.write(&op, false).await
660 }
661 RxMode::Single(_) => {
662 let op = [
663 OpCode::SetRx.value(),
664 Self::timeout_1(0),
665 Self::timeout_2(0),
666 Self::timeout_3(0),
667 ];
668 self.intf.write(&op, false).await
669 }
670 RxMode::Continuous => {
671 let op = [
672 OpCode::SetRx.value(),
673 Self::timeout_1(RX_CONTINUOUS_TIMEOUT),
674 Self::timeout_2(RX_CONTINUOUS_TIMEOUT),
675 Self::timeout_3(RX_CONTINUOUS_TIMEOUT),
676 ];
677 self.intf.write(&op, false).await
678 }
679 }
680 }
681
682 async fn get_rx_payload(
683 &mut self,
684 rx_pkt_params: &PacketParams,
685 receiving_buffer: &mut [u8],
686 ) -> Result<u8, RadioError> {
687 let op_code = [OpCode::GetRxBufferStatus.value()];
688 let mut rx_buffer_status = [0x00u8; 2];
689 let read_status = self.intf.read_with_status(&op_code, &mut rx_buffer_status).await?;
690 if OpStatusErrorMask::is_error(read_status) {
691 return Err(RadioError::OpError(read_status));
692 }
693
694 let mut payload_length_buffer = [0x00u8];
695 if rx_pkt_params.implicit_header {
696 self.intf
697 .read(
698 &[
699 OpCode::ReadRegister.value(),
700 Register::PayloadLength.addr1(),
701 Register::PayloadLength.addr2(),
702 0x00u8,
703 ],
704 &mut payload_length_buffer,
705 )
706 .await?;
707 } else {
708 payload_length_buffer[0] = rx_buffer_status[0];
709 }
710
711 let payload_length = payload_length_buffer[0];
712 let offset = rx_buffer_status[1];
713
714 if (payload_length as usize) > receiving_buffer.len() {
715 Err(RadioError::PayloadSizeMismatch(
716 payload_length as usize,
717 receiving_buffer.len(),
718 ))
719 } else {
720 self.intf
721 .read(
722 &[OpCode::ReadBuffer.value(), offset, 0x00u8],
723 &mut receiving_buffer[..payload_length as usize],
724 )
725 .await?;
726 Ok(payload_length)
727 }
728 }
729
730 async fn get_rx_packet_status(&mut self) -> Result<PacketStatus, RadioError> {
731 let op_code = [OpCode::GetPacketStatus.value()];
732 let mut pkt_status = [0x00u8; 3];
733 let read_status = self.intf.read_with_status(&op_code, &mut pkt_status).await?;
734 if OpStatusErrorMask::is_error(read_status) {
735 return Err(RadioError::OpError(read_status));
736 }
737 let rssi = ((-(pkt_status[0] as i32)) >> 1) as i16;
739 let snr = (((pkt_status[1] as i8) + 2) >> 2) as i16;
740 let _signal_rssi = ((-(pkt_status[2] as i32)) >> 1) as i16; Ok(PacketStatus { rssi, snr })
743 }
744
745 async fn do_cad(&mut self, mdltn_params: &ModulationParams) -> Result<(), RadioError> {
746 self.intf.iv.enable_rf_switch_rx().await?;
747
748 let mut rx_gain_final = 0x94u8;
749 if self.config.rx_boost {
751 rx_gain_final = 0x96u8;
752 }
753
754 let register_and_rx_gain = [
755 OpCode::WriteRegister.value(),
756 Register::RxGain.addr1(),
757 Register::RxGain.addr2(),
758 rx_gain_final,
759 ];
760 self.intf.write(®ister_and_rx_gain, false).await?;
761
762 let spreading_factor_val = spreading_factor_value(mdltn_params.spreading_factor)?;
766 let op_code_and_cad_params = [
767 OpCode::SetCADParams.value(),
768 CADSymbols::_8.value(), spreading_factor_val + 13u8, 10u8, 0x00u8, 0x00u8, 0x00u8,
774 0x00u8,
775 ];
776 self.intf.write(&op_code_and_cad_params, false).await?;
777
778 let op_code_for_set_cad = [OpCode::SetCAD.value()];
779 self.intf.write(&op_code_for_set_cad, false).await
780 }
781
782 async fn set_irq_params(&mut self, radio_mode: Option<RadioMode>) -> Result<(), RadioError> {
784 let mut irq_mask: u16 = IrqMask::None.value();
785 let mut dio1_mask: u16 = IrqMask::None.value();
786 let dio2_mask: u16 = IrqMask::None.value();
787 let dio3_mask: u16 = IrqMask::None.value();
788
789 match radio_mode {
790 Some(RadioMode::Standby) => {
791 irq_mask = IrqMask::All.value();
792 dio1_mask = IrqMask::All.value();
793 }
794 Some(RadioMode::Transmit) => {
795 irq_mask = IrqMask::TxDone.value() | IrqMask::RxTxTimeout.value();
796 dio1_mask = IrqMask::TxDone.value() | IrqMask::RxTxTimeout.value();
797 }
798 Some(RadioMode::Receive(_)) => {
799 irq_mask = IrqMask::All.value();
800 dio1_mask = IrqMask::All.value();
801 }
802 Some(RadioMode::ChannelActivityDetection) => {
803 irq_mask = IrqMask::CADDone.value() | IrqMask::CADActivityDetected.value();
804 dio1_mask = IrqMask::CADDone.value() | IrqMask::CADActivityDetected.value();
805 }
806 _ => {}
807 }
808
809 let op_code_and_masks = [
810 OpCode::CfgDIOIrq.value(),
811 ((irq_mask >> 8) & 0x00FF) as u8,
812 (irq_mask & 0x00FF) as u8,
813 ((dio1_mask >> 8) & 0x00FF) as u8,
814 (dio1_mask & 0x00FF) as u8,
815 ((dio2_mask >> 8) & 0x00FF) as u8,
816 (dio2_mask & 0x00FF) as u8,
817 ((dio3_mask >> 8) & 0x00FF) as u8,
818 (dio3_mask & 0x00FF) as u8,
819 ];
820 self.intf.write(&op_code_and_masks, false).await
821 }
822
823 async fn set_tx_continuous_wave_mode(&mut self) -> Result<(), RadioError> {
824 self.intf.iv.enable_rf_switch_tx().await?;
825
826 let op_code = [OpCode::SetTxContinuousWave.value()];
827 self.intf.write(&op_code, false).await
828 }
829
830 async fn await_irq(&mut self) -> Result<(), RadioError> {
831 self.intf.iv.await_irq().await
832 }
833
834 async fn process_irq_event(
840 &mut self,
841 radio_mode: RadioMode,
842 cad_activity_detected: Option<&mut bool>,
843 clear_interrupts: bool,
844 ) -> Result<Option<IrqState>, RadioError> {
845 let op_code = [OpCode::GetIrqStatus.value()];
846 let mut irq_status = [0x00u8, 0x00u8];
847 let read_status = self.intf.read_with_status(&op_code, &mut irq_status).await?;
849 let irq_flags = ((irq_status[0] as u16) << 8) | (irq_status[1] as u16);
850
851 if clear_interrupts && irq_flags != 0 {
852 let op_code_and_irq_status = [OpCode::ClrIrqStatus.value(), irq_status[0], irq_status[1]];
853 self.intf.write(&op_code_and_irq_status, false).await?;
854 }
855
856 if OpStatusErrorMask::is_error(read_status) {
857 debug!(
858 "process_irq read status error = 0x{:x} in radio mode {}",
859 read_status, radio_mode
860 );
861 }
862
863 debug!(
864 "process_irq satisfied: irq_flags = 0x{:x} in radio mode {}",
865 irq_flags, radio_mode
866 );
867
868 if (irq_flags & IrqMask::HeaderValid.value()) == IrqMask::HeaderValid.value() {
869 debug!("HeaderValid in radio mode {}", radio_mode);
870 }
871 if (irq_flags & IrqMask::PreambleDetected.value()) == IrqMask::PreambleDetected.value() {
872 debug!("PreambleDetected in radio mode {}", radio_mode);
873 }
874 if (irq_flags & IrqMask::SyncwordValid.value()) == IrqMask::SyncwordValid.value() {
875 debug!("SyncwordValid in radio mode {}", radio_mode);
876 }
877
878 match radio_mode {
879 RadioMode::Transmit => {
880 if (irq_flags & IrqMask::TxDone.value()) == IrqMask::TxDone.value() {
881 return Ok(Some(IrqState::Done));
882 }
883 if (irq_flags & IrqMask::RxTxTimeout.value()) == IrqMask::RxTxTimeout.value() {
884 return Err(RadioError::TransmitTimeout);
885 }
886 }
887 RadioMode::Receive(rx_mode) => {
888 if (irq_flags & IrqMask::HeaderError.value()) == IrqMask::HeaderError.value() {
889 debug!("HeaderError in radio mode {}", radio_mode);
890 }
891 if (irq_flags & IrqMask::CRCError.value()) == IrqMask::CRCError.value() {
892 debug!("CRCError in radio mode {}", radio_mode);
893 }
894 if (irq_flags & IrqMask::RxDone.value()) == IrqMask::RxDone.value() {
895 debug!("RxDone in radio mode {}", radio_mode);
896 if rx_mode != RxMode::Continuous {
897 let register_and_clear = [
899 OpCode::WriteRegister.value(),
900 Register::RTCCtrl.addr1(),
901 Register::RTCCtrl.addr2(),
902 0x00u8,
903 ];
904 self.intf.write(®ister_and_clear, false).await?;
905
906 let mut evt_clr = [0x00u8];
907 self.intf
908 .read(
909 &[
910 OpCode::ReadRegister.value(),
911 Register::EvtClr.addr1(),
912 Register::EvtClr.addr2(),
913 0x00u8,
914 ],
915 &mut evt_clr,
916 )
917 .await?;
918 evt_clr[0] |= 1 << 1;
919 let register_and_evt_clear = [
920 OpCode::WriteRegister.value(),
921 Register::EvtClr.addr1(),
922 Register::EvtClr.addr2(),
923 evt_clr[0],
924 ];
925 self.intf.write(®ister_and_evt_clear, false).await?;
926 }
927 return Ok(Some(IrqState::Done));
928 }
929 if IrqMask::PreambleDetected.is_set_in(irq_flags) || IrqMask::HeaderValid.is_set_in(irq_flags) {
930 return Ok(Some(IrqState::PreambleReceived));
931 }
932 if (irq_flags & IrqMask::RxTxTimeout.value()) == IrqMask::RxTxTimeout.value() {
933 return Err(RadioError::ReceiveTimeout);
934 }
935 }
936 RadioMode::ChannelActivityDetection => {
937 if (irq_flags & IrqMask::CADDone.value()) == IrqMask::CADDone.value() {
938 if let Some(detected) = cad_activity_detected {
939 *detected =
940 (irq_flags & IrqMask::CADActivityDetected.value()) == IrqMask::CADActivityDetected.value();
941 }
942 return Ok(Some(IrqState::Done));
943 }
944 }
945 RadioMode::Sleep | RadioMode::Standby => {
946 defmt::warn!("IRQ during sleep/standby?");
947 }
948 RadioMode::FrequencySynthesis => todo!(),
949 }
950
951 Ok(None)
953 }
954}
955
956#[cfg(test)]
957mod tests {
958 #[test]
961 fn power_level_negative_value_conversion() {
964 let mut i32_val: i32 = -17;
965 assert_eq!(i32_val as u8, 0xefu8);
966 i32_val = -9;
967 assert_eq!(i32_val as u8, 0xf7u8);
968 }
969}