diff options
| -rw-r--r-- | embassy-lora/src/stm32wl/mod.rs | 82 |
1 files changed, 40 insertions, 42 deletions
diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 5170b261a..c142353b6 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> { | |||
| 69 | /// Perform a transmission with the given parameters and payload. Returns any time adjustements needed form | 69 | /// Perform a transmission with the given parameters and payload. Returns any time adjustements needed form |
| 70 | /// the upcoming RX window start. | 70 | /// the upcoming RX window start. |
| 71 | async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result<u32, RadioError> { | 71 | async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result<u32, RadioError> { |
| 72 | trace!("TX Request: {}", config); | 72 | trace!("TX request: {}", config); |
| 73 | //trace!("TX START"); | ||
| 74 | self.switch.set_tx(); | 73 | self.switch.set_tx(); |
| 75 | 74 | ||
| 76 | self.radio | 75 | self.radio |
| @@ -87,33 +86,26 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { | |||
| 87 | 86 | ||
| 88 | self.radio.set_lora_packet_params(&packet_params)?; | 87 | self.radio.set_lora_packet_params(&packet_params)?; |
| 89 | 88 | ||
| 90 | let irq_cfg = CfgIrq::new() | 89 | let irq_cfg = CfgIrq::new().irq_enable_all(Irq::TxDone).irq_enable_all(Irq::Timeout); |
| 91 | .irq_enable_all(Irq::TxDone) | ||
| 92 | .irq_enable_all(Irq::RxDone) | ||
| 93 | .irq_enable_all(Irq::Timeout); | ||
| 94 | self.radio.set_irq_cfg(&irq_cfg)?; | 90 | self.radio.set_irq_cfg(&irq_cfg)?; |
| 95 | 91 | ||
| 96 | self.radio.set_buffer_base_address(0, 0)?; | 92 | self.radio.set_buffer_base_address(0, 0)?; |
| 97 | self.radio.write_buffer(0, buf)?; | 93 | self.radio.write_buffer(0, buf)?; |
| 98 | 94 | ||
| 99 | self.radio.set_tx(Timeout::DISABLED)?; | 95 | // The maximum airtime for any LoRaWAN package is 2793.5ms. |
| 96 | // The value of 4000ms is copied from C driver and gives us a good safety margin. | ||
| 97 | self.radio.set_tx(Timeout::from_millis_sat(4000))?; | ||
| 98 | trace!("TX started"); | ||
| 100 | 99 | ||
| 101 | loop { | 100 | loop { |
| 102 | let (_status, irq_status) = self.irq_wait().await; | 101 | let (_status, irq_status) = self.irq_wait().await; |
| 103 | 102 | ||
| 104 | if irq_status & Irq::TxDone.mask() != 0 { | 103 | if irq_status & Irq::TxDone.mask() != 0 { |
| 105 | let stats = self.radio.lora_stats()?; | 104 | trace!("TX done"); |
| 106 | let (status, error_mask) = self.radio.op_error()?; | ||
| 107 | trace!( | ||
| 108 | "TX done. Stats: {:?}. OP error: {:?}, mask {:?}", | ||
| 109 | stats, | ||
| 110 | status, | ||
| 111 | error_mask | ||
| 112 | ); | ||
| 113 | |||
| 114 | return Ok(0); | 105 | return Ok(0); |
| 115 | } else if irq_status & Irq::Timeout.mask() != 0 { | 106 | } |
| 116 | trace!("TX timeout"); | 107 | |
| 108 | if irq_status & Irq::Timeout.mask() != 0 { | ||
| 117 | return Err(RadioError); | 109 | return Err(RadioError); |
| 118 | } | 110 | } |
| 119 | } | 111 | } |
| @@ -121,10 +113,15 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { | |||
| 121 | 113 | ||
| 122 | fn set_lora_mod_params(&mut self, config: RfConfig) -> Result<(), Error> { | 114 | fn set_lora_mod_params(&mut self, config: RfConfig) -> Result<(), Error> { |
| 123 | let mod_params = LoRaModParams::new() | 115 | let mod_params = LoRaModParams::new() |
| 124 | .set_sf(convert_spreading_factor(config.spreading_factor)) | 116 | .set_sf(convert_spreading_factor(&config.spreading_factor)) |
| 125 | .set_bw(convert_bandwidth(config.bandwidth)) | 117 | .set_bw(convert_bandwidth(&config.bandwidth)) |
| 126 | .set_cr(CodingRate::Cr45) | 118 | .set_cr(CodingRate::Cr45) |
| 127 | .set_ldro_en(true); | 119 | .set_ldro_en(matches!( |
| 120 | (config.spreading_factor, config.bandwidth), | ||
| 121 | (SpreadingFactor::_12, Bandwidth::_125KHz) | ||
| 122 | | (SpreadingFactor::_12, Bandwidth::_250KHz) | ||
| 123 | | (SpreadingFactor::_11, Bandwidth::_125KHz) | ||
| 124 | )); | ||
| 128 | self.radio.set_lora_mod_params(&mod_params) | 125 | self.radio.set_lora_mod_params(&mod_params) |
| 129 | } | 126 | } |
| 130 | 127 | ||
| @@ -132,8 +129,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { | |||
| 132 | /// be able to hold a single LoRaWAN packet. | 129 | /// be able to hold a single LoRaWAN packet. |
| 133 | async fn do_rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), RadioError> { | 130 | async fn do_rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), RadioError> { |
| 134 | assert!(buf.len() >= 255); | 131 | assert!(buf.len() >= 255); |
| 135 | trace!("RX START"); | 132 | trace!("RX request: {}", config); |
| 136 | // trace!("Starting RX: {}", config); | ||
| 137 | self.switch.set_rx(); | 133 | self.switch.set_rx(); |
| 138 | 134 | ||
| 139 | self.radio.set_rf_frequency(&RfFreq::from_frequency(config.frequency))?; | 135 | self.radio.set_rf_frequency(&RfFreq::from_frequency(config.frequency))?; |
| @@ -144,41 +140,41 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { | |||
| 144 | .set_preamble_len(8) | 140 | .set_preamble_len(8) |
| 145 | .set_header_type(HeaderType::Variable) | 141 | .set_header_type(HeaderType::Variable) |
| 146 | .set_payload_len(0xFF) | 142 | .set_payload_len(0xFF) |
| 147 | .set_crc_en(true) | 143 | .set_crc_en(false) |
| 148 | .set_invert_iq(true); | 144 | .set_invert_iq(true); |
| 149 | self.radio.set_lora_packet_params(&packet_params)?; | 145 | self.radio.set_lora_packet_params(&packet_params)?; |
| 150 | 146 | ||
| 151 | let irq_cfg = CfgIrq::new() | 147 | let irq_cfg = CfgIrq::new() |
| 152 | .irq_enable_all(Irq::RxDone) | 148 | .irq_enable_all(Irq::RxDone) |
| 153 | //.irq_enable_all(Irq::PreambleDetected) | 149 | .irq_enable_all(Irq::PreambleDetected) |
| 150 | .irq_enable_all(Irq::HeaderValid) | ||
| 154 | .irq_enable_all(Irq::HeaderErr) | 151 | .irq_enable_all(Irq::HeaderErr) |
| 155 | .irq_enable_all(Irq::Timeout) | 152 | .irq_enable_all(Irq::Err) |
| 156 | .irq_enable_all(Irq::Err); | 153 | .irq_enable_all(Irq::Timeout); |
| 157 | self.radio.set_irq_cfg(&irq_cfg)?; | 154 | self.radio.set_irq_cfg(&irq_cfg)?; |
| 158 | 155 | ||
| 159 | self.radio.set_rx(Timeout::DISABLED)?; | 156 | self.radio.set_buffer_base_address(0, 0)?; |
| 157 | |||
| 158 | self.radio | ||
| 159 | .set_rx(Timeout::from_millis_sat(self.get_rx_window_duration_ms()))?; | ||
| 160 | trace!("RX started"); | 160 | trace!("RX started"); |
| 161 | 161 | ||
| 162 | loop { | 162 | loop { |
| 163 | let (status, irq_status) = self.irq_wait().await; | 163 | let (_status, irq_status) = self.irq_wait().await; |
| 164 | 164 | ||
| 165 | trace!("RX IRQ {:?}, {:?}", status, irq_status); | ||
| 166 | if irq_status & Irq::RxDone.mask() != 0 { | 165 | if irq_status & Irq::RxDone.mask() != 0 { |
| 167 | let (status, len, ptr) = self.radio.rx_buffer_status()?; | 166 | let (_status, len, ptr) = self.radio.rx_buffer_status()?; |
| 168 | |||
| 169 | let packet_status = self.radio.lora_packet_status()?; | 167 | let packet_status = self.radio.lora_packet_status()?; |
| 170 | let rssi = packet_status.rssi_pkt().to_integer(); | 168 | let rssi = packet_status.rssi_pkt().to_integer(); |
| 171 | let snr = packet_status.snr_pkt().to_integer(); | 169 | let snr = packet_status.snr_pkt().to_integer(); |
| 172 | trace!( | ||
| 173 | "RX done. Received {} bytes. RX status: {:?}. Pkt status: {:?}", | ||
| 174 | len, | ||
| 175 | status.cmd(), | ||
| 176 | packet_status, | ||
| 177 | ); | ||
| 178 | self.radio.read_buffer(ptr, &mut buf[..len as usize])?; | 170 | self.radio.read_buffer(ptr, &mut buf[..len as usize])?; |
| 179 | self.radio.set_standby(StandbyClk::Rc)?; | 171 | self.radio.set_standby(StandbyClk::Rc)?; |
| 172 | |||
| 173 | trace!("RX done: {=[u8]:#02X}", &mut buf[..len as usize]); | ||
| 180 | return Ok((len as usize, RxQuality::new(rssi, snr as i8))); | 174 | return Ok((len as usize, RxQuality::new(rssi, snr as i8))); |
| 181 | } else if irq_status & (Irq::Timeout.mask() | Irq::TxDone.mask()) != 0 { | 175 | } |
| 176 | |||
| 177 | if irq_status & Irq::Timeout.mask() != 0 { | ||
| 182 | return Err(RadioError); | 178 | return Err(RadioError); |
| 183 | } | 179 | } |
| 184 | } | 180 | } |
| @@ -194,7 +190,9 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> { | |||
| 194 | self.radio | 190 | self.radio |
| 195 | .clear_irq_status(irq_status) | 191 | .clear_irq_status(irq_status) |
| 196 | .expect("error clearing irq status"); | 192 | .expect("error clearing irq status"); |
| 197 | trace!("IRQ status: {=u16:b}", irq_status); | 193 | |
| 194 | trace!("SUGHZ IRQ 0b{=u16:b}, {:?}", irq_status, status); | ||
| 195 | |||
| 198 | if irq_status == 0 { | 196 | if irq_status == 0 { |
| 199 | Poll::Pending | 197 | Poll::Pending |
| 200 | } else { | 198 | } else { |
| @@ -268,7 +266,7 @@ pub trait RadioSwitch { | |||
| 268 | fn set_tx(&mut self); | 266 | fn set_tx(&mut self); |
| 269 | } | 267 | } |
| 270 | 268 | ||
| 271 | fn convert_spreading_factor(sf: SpreadingFactor) -> SF { | 269 | fn convert_spreading_factor(sf: &SpreadingFactor) -> SF { |
| 272 | match sf { | 270 | match sf { |
| 273 | SpreadingFactor::_7 => SF::Sf7, | 271 | SpreadingFactor::_7 => SF::Sf7, |
| 274 | SpreadingFactor::_8 => SF::Sf8, | 272 | SpreadingFactor::_8 => SF::Sf8, |
| @@ -279,7 +277,7 @@ fn convert_spreading_factor(sf: SpreadingFactor) -> SF { | |||
| 279 | } | 277 | } |
| 280 | } | 278 | } |
| 281 | 279 | ||
| 282 | fn convert_bandwidth(bw: Bandwidth) -> LoRaBandwidth { | 280 | fn convert_bandwidth(bw: &Bandwidth) -> LoRaBandwidth { |
| 283 | match bw { | 281 | match bw { |
| 284 | Bandwidth::_125KHz => LoRaBandwidth::Bw125, | 282 | Bandwidth::_125KHz => LoRaBandwidth::Bw125, |
| 285 | Bandwidth::_250KHz => LoRaBandwidth::Bw250, | 283 | Bandwidth::_250KHz => LoRaBandwidth::Bw250, |
