aboutsummaryrefslogtreecommitdiff
path: root/embassy-lora
diff options
context:
space:
mode:
authorTimo Kröger <[email protected]>2022-06-27 20:52:37 +0200
committerTimo Kröger <[email protected]>2022-08-26 15:44:58 +0200
commit60ca5e8479e951b220299ea32bfc48b1909edd1c (patch)
treee04033bfca37e60a0758233de0ca9d5bb1a95282 /embassy-lora
parent84240d49eaf208691d0785e060ee13a7a14f0671 (diff)
lora: Improve TX/RX parameters
Match the settings used in the C driver
Diffstat (limited to 'embassy-lora')
-rw-r--r--embassy-lora/src/stm32wl/mod.rs82
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
271fn convert_spreading_factor(sf: SpreadingFactor) -> SF { 269fn 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
282fn convert_bandwidth(bw: Bandwidth) -> LoRaBandwidth { 280fn 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,