lora: Improve TX/RX parameters

Match the settings used in the C driver
This commit is contained in:
Timo Kröger 2022-06-27 20:52:37 +02:00
parent 84240d49ea
commit 60ca5e8479

View file

@ -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 /// Perform a transmission with the given parameters and payload. Returns any time adjustements needed form
/// the upcoming RX window start. /// the upcoming RX window start.
async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result<u32, RadioError> { async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result<u32, RadioError> {
trace!("TX Request: {}", config); trace!("TX request: {}", config);
//trace!("TX START");
self.switch.set_tx(); self.switch.set_tx();
self.radio self.radio
@ -87,33 +86,26 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> {
self.radio.set_lora_packet_params(&packet_params)?; self.radio.set_lora_packet_params(&packet_params)?;
let irq_cfg = CfgIrq::new() let irq_cfg = CfgIrq::new().irq_enable_all(Irq::TxDone).irq_enable_all(Irq::Timeout);
.irq_enable_all(Irq::TxDone)
.irq_enable_all(Irq::RxDone)
.irq_enable_all(Irq::Timeout);
self.radio.set_irq_cfg(&irq_cfg)?; self.radio.set_irq_cfg(&irq_cfg)?;
self.radio.set_buffer_base_address(0, 0)?; self.radio.set_buffer_base_address(0, 0)?;
self.radio.write_buffer(0, buf)?; 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 { loop {
let (_status, irq_status) = self.irq_wait().await; let (_status, irq_status) = self.irq_wait().await;
if irq_status & Irq::TxDone.mask() != 0 { if irq_status & Irq::TxDone.mask() != 0 {
let stats = self.radio.lora_stats()?; trace!("TX done");
let (status, error_mask) = self.radio.op_error()?;
trace!(
"TX done. Stats: {:?}. OP error: {:?}, mask {:?}",
stats,
status,
error_mask
);
return Ok(0); return Ok(0);
} else if irq_status & Irq::Timeout.mask() != 0 { }
trace!("TX timeout");
if irq_status & Irq::Timeout.mask() != 0 {
return Err(RadioError); 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> { fn set_lora_mod_params(&mut self, config: RfConfig) -> Result<(), Error> {
let mod_params = LoRaModParams::new() let mod_params = LoRaModParams::new()
.set_sf(convert_spreading_factor(config.spreading_factor)) .set_sf(convert_spreading_factor(&config.spreading_factor))
.set_bw(convert_bandwidth(config.bandwidth)) .set_bw(convert_bandwidth(&config.bandwidth))
.set_cr(CodingRate::Cr45) .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) 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. /// be able to hold a single LoRaWAN packet.
async fn do_rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), RadioError> { async fn do_rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), RadioError> {
assert!(buf.len() >= 255); assert!(buf.len() >= 255);
trace!("RX START"); trace!("RX request: {}", config);
// trace!("Starting RX: {}", config);
self.switch.set_rx(); self.switch.set_rx();
self.radio.set_rf_frequency(&RfFreq::from_frequency(config.frequency))?; 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_preamble_len(8)
.set_header_type(HeaderType::Variable) .set_header_type(HeaderType::Variable)
.set_payload_len(0xFF) .set_payload_len(0xFF)
.set_crc_en(true) .set_crc_en(false)
.set_invert_iq(true); .set_invert_iq(true);
self.radio.set_lora_packet_params(&packet_params)?; self.radio.set_lora_packet_params(&packet_params)?;
let irq_cfg = CfgIrq::new() let irq_cfg = CfgIrq::new()
.irq_enable_all(Irq::RxDone) .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::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_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"); trace!("RX started");
loop { 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 { 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 packet_status = self.radio.lora_packet_status()?;
let rssi = packet_status.rssi_pkt().to_integer(); let rssi = packet_status.rssi_pkt().to_integer();
let snr = packet_status.snr_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.read_buffer(ptr, &mut buf[..len as usize])?;
self.radio.set_standby(StandbyClk::Rc)?; 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))); 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); return Err(RadioError);
} }
} }
@ -194,7 +190,9 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> {
self.radio self.radio
.clear_irq_status(irq_status) .clear_irq_status(irq_status)
.expect("error clearing 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 { if irq_status == 0 {
Poll::Pending Poll::Pending
} else { } else {
@ -268,7 +266,7 @@ pub trait RadioSwitch {
fn set_tx(&mut self); fn set_tx(&mut self);
} }
fn convert_spreading_factor(sf: SpreadingFactor) -> SF { fn convert_spreading_factor(sf: &SpreadingFactor) -> SF {
match sf { match sf {
SpreadingFactor::_7 => SF::Sf7, SpreadingFactor::_7 => SF::Sf7,
SpreadingFactor::_8 => SF::Sf8, 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 { match bw {
Bandwidth::_125KHz => LoRaBandwidth::Bw125, Bandwidth::_125KHz => LoRaBandwidth::Bw125,
Bandwidth::_250KHz => LoRaBandwidth::Bw250, Bandwidth::_250KHz => LoRaBandwidth::Bw250,