From 60ca5e8479e951b220299ea32bfc48b1909edd1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timo=20Kr=C3=B6ger?= Date: Mon, 27 Jun 2022 20:52:37 +0200 Subject: [PATCH] lora: Improve TX/RX parameters Match the settings used in the C driver --- embassy-lora/src/stm32wl/mod.rs | 82 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 42 deletions(-) diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 5170b261..c142353b 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -69,8 +69,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { /// Perform a transmission with the given parameters and payload. Returns any time adjustements needed form /// the upcoming RX window start. async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result { - trace!("TX Request: {}", config); - //trace!("TX START"); + trace!("TX request: {}", config); self.switch.set_tx(); self.radio @@ -87,33 +86,26 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { self.radio.set_lora_packet_params(&packet_params)?; - let irq_cfg = CfgIrq::new() - .irq_enable_all(Irq::TxDone) - .irq_enable_all(Irq::RxDone) - .irq_enable_all(Irq::Timeout); + let irq_cfg = CfgIrq::new().irq_enable_all(Irq::TxDone).irq_enable_all(Irq::Timeout); self.radio.set_irq_cfg(&irq_cfg)?; self.radio.set_buffer_base_address(0, 0)?; self.radio.write_buffer(0, buf)?; - self.radio.set_tx(Timeout::DISABLED)?; + // The maximum airtime for any LoRaWAN package is 2793.5ms. + // The value of 4000ms is copied from C driver and gives us a good safety margin. + self.radio.set_tx(Timeout::from_millis_sat(4000))?; + trace!("TX started"); loop { let (_status, irq_status) = self.irq_wait().await; if irq_status & Irq::TxDone.mask() != 0 { - let stats = self.radio.lora_stats()?; - let (status, error_mask) = self.radio.op_error()?; - trace!( - "TX done. Stats: {:?}. OP error: {:?}, mask {:?}", - stats, - status, - error_mask - ); - + trace!("TX done"); return Ok(0); - } else if irq_status & Irq::Timeout.mask() != 0 { - trace!("TX timeout"); + } + + if irq_status & Irq::Timeout.mask() != 0 { return Err(RadioError); } } @@ -121,10 +113,15 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { fn set_lora_mod_params(&mut self, config: RfConfig) -> Result<(), Error> { let mod_params = LoRaModParams::new() - .set_sf(convert_spreading_factor(config.spreading_factor)) - .set_bw(convert_bandwidth(config.bandwidth)) + .set_sf(convert_spreading_factor(&config.spreading_factor)) + .set_bw(convert_bandwidth(&config.bandwidth)) .set_cr(CodingRate::Cr45) - .set_ldro_en(true); + .set_ldro_en(matches!( + (config.spreading_factor, config.bandwidth), + (SpreadingFactor::_12, Bandwidth::_125KHz) + | (SpreadingFactor::_12, Bandwidth::_250KHz) + | (SpreadingFactor::_11, Bandwidth::_125KHz) + )); self.radio.set_lora_mod_params(&mod_params) } @@ -132,8 +129,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { /// be able to hold a single LoRaWAN packet. async fn do_rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), RadioError> { assert!(buf.len() >= 255); - trace!("RX START"); - // trace!("Starting RX: {}", config); + trace!("RX request: {}", config); self.switch.set_rx(); self.radio.set_rf_frequency(&RfFreq::from_frequency(config.frequency))?; @@ -144,41 +140,41 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { .set_preamble_len(8) .set_header_type(HeaderType::Variable) .set_payload_len(0xFF) - .set_crc_en(true) + .set_crc_en(false) .set_invert_iq(true); self.radio.set_lora_packet_params(&packet_params)?; let irq_cfg = CfgIrq::new() .irq_enable_all(Irq::RxDone) - //.irq_enable_all(Irq::PreambleDetected) + .irq_enable_all(Irq::PreambleDetected) + .irq_enable_all(Irq::HeaderValid) .irq_enable_all(Irq::HeaderErr) - .irq_enable_all(Irq::Timeout) - .irq_enable_all(Irq::Err); + .irq_enable_all(Irq::Err) + .irq_enable_all(Irq::Timeout); self.radio.set_irq_cfg(&irq_cfg)?; - self.radio.set_rx(Timeout::DISABLED)?; + self.radio.set_buffer_base_address(0, 0)?; + + self.radio + .set_rx(Timeout::from_millis_sat(self.get_rx_window_duration_ms()))?; trace!("RX started"); loop { - let (status, irq_status) = self.irq_wait().await; + let (_status, irq_status) = self.irq_wait().await; - trace!("RX IRQ {:?}, {:?}", status, irq_status); if irq_status & Irq::RxDone.mask() != 0 { - let (status, len, ptr) = self.radio.rx_buffer_status()?; - + let (_status, len, ptr) = self.radio.rx_buffer_status()?; let packet_status = self.radio.lora_packet_status()?; let rssi = packet_status.rssi_pkt().to_integer(); let snr = packet_status.snr_pkt().to_integer(); - trace!( - "RX done. Received {} bytes. RX status: {:?}. Pkt status: {:?}", - len, - status.cmd(), - packet_status, - ); self.radio.read_buffer(ptr, &mut buf[..len as usize])?; self.radio.set_standby(StandbyClk::Rc)?; + + trace!("RX done: {=[u8]:#02X}", &mut buf[..len as usize]); return Ok((len as usize, RxQuality::new(rssi, snr as i8))); - } else if irq_status & (Irq::Timeout.mask() | Irq::TxDone.mask()) != 0 { + } + + if irq_status & Irq::Timeout.mask() != 0 { return Err(RadioError); } } @@ -194,7 +190,9 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { self.radio .clear_irq_status(irq_status) .expect("error clearing irq status"); - trace!("IRQ status: {=u16:b}", irq_status); + + trace!("SUGHZ IRQ 0b{=u16:b}, {:?}", irq_status, status); + if irq_status == 0 { Poll::Pending } else { @@ -268,7 +266,7 @@ pub trait RadioSwitch { fn set_tx(&mut self); } -fn convert_spreading_factor(sf: SpreadingFactor) -> SF { +fn convert_spreading_factor(sf: &SpreadingFactor) -> SF { match sf { SpreadingFactor::_7 => SF::Sf7, SpreadingFactor::_8 => SF::Sf8, @@ -279,7 +277,7 @@ fn convert_spreading_factor(sf: SpreadingFactor) -> SF { } } -fn convert_bandwidth(bw: Bandwidth) -> LoRaBandwidth { +fn convert_bandwidth(bw: &Bandwidth) -> LoRaBandwidth { match bw { Bandwidth::_125KHz => LoRaBandwidth::Bw125, Bandwidth::_250KHz => LoRaBandwidth::Bw250,