lora: Improve TX/RX parameters
Match the settings used in the C driver
This commit is contained in:
parent
84240d49ea
commit
60ca5e8479
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user