From 1a48e465b9bdc801841b5802f82cd3f56468a530 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Thu, 2 Nov 2023 17:30:37 +0200 Subject: [PATCH 1/2] sx127x: Use match for radio_mode in process_irq Also dropped one additional debug message about HeaderValid flag. --- src/sx1276_7_8_9/mod.rs | 62 +++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/sx1276_7_8_9/mod.rs b/src/sx1276_7_8_9/mod.rs index 5b82793..3831821 100644 --- a/src/sx1276_7_8_9/mod.rs +++ b/src/sx1276_7_8_9/mod.rs @@ -582,40 +582,42 @@ where irq_flags, radio_mode ); - if (irq_flags & IrqMask::HeaderValid.value()) == IrqMask::HeaderValid.value() { - debug!("HeaderValid in radio mode {}", radio_mode); - } - - if radio_mode == RadioMode::Transmit { - if (irq_flags & IrqMask::TxDone.value()) == IrqMask::TxDone.value() { - debug!("TxDone in radio mode {}", radio_mode); - return Ok(TargetIrqState::Done); - } - } else if radio_mode == RadioMode::Receive { - if (irq_flags & IrqMask::CRCError.value()) == IrqMask::CRCError.value() { - debug!("CRCError in radio mode {}", radio_mode); - } - if (irq_flags & IrqMask::RxDone.value()) == IrqMask::RxDone.value() { - debug!("RxDone in radio mode {}", radio_mode); - return Ok(TargetIrqState::Done); + match radio_mode { + RadioMode::Transmit => { + if (irq_flags & IrqMask::TxDone.value()) == IrqMask::TxDone.value() { + debug!("TxDone in radio mode {}", radio_mode); + return Ok(TargetIrqState::Done); + } } - if target_rx_state == TargetIrqState::PreambleReceived && IrqMask::HeaderValid.is_set_in(irq_flags) { - debug!("HeaderValid in radio mode {}", radio_mode); - return Ok(TargetIrqState::PreambleReceived); + RadioMode::Receive => { + if target_rx_state == TargetIrqState::PreambleReceived && IrqMask::HeaderValid.is_set_in(irq_flags) + { + debug!("HeaderValid in radio mode {}", radio_mode); + return Ok(TargetIrqState::PreambleReceived); + } + if (irq_flags & IrqMask::RxDone.value()) == IrqMask::RxDone.value() { + debug!("RxDone in radio mode {}", radio_mode); + return Ok(TargetIrqState::Done); + } + if (irq_flags & IrqMask::RxTimeout.value()) == IrqMask::RxTimeout.value() { + debug!("RxTimeout in radio mode {}", radio_mode); + return Err(RadioError::ReceiveTimeout); + } } - if (irq_flags & IrqMask::RxTimeout.value()) == IrqMask::RxTimeout.value() { - debug!("RxTimeout in radio mode {}", radio_mode); - return Err(RadioError::ReceiveTimeout); + RadioMode::ChannelActivityDetection => { + if (irq_flags & IrqMask::CADDone.value()) == IrqMask::CADDone.value() { + debug!("CADDone in radio mode {}", radio_mode); + if cad_activity_detected.is_some() { + *(cad_activity_detected.unwrap()) = (irq_flags & IrqMask::CADActivityDetected.value()) + == IrqMask::CADActivityDetected.value(); + } + return Ok(TargetIrqState::Done); + } } - } else if radio_mode == RadioMode::ChannelActivityDetection - && (irq_flags & IrqMask::CADDone.value()) == IrqMask::CADDone.value() - { - debug!("CADDone in radio mode {}", radio_mode); - if cad_activity_detected.is_some() { - *(cad_activity_detected.unwrap()) = - (irq_flags & IrqMask::CADActivityDetected.value()) == IrqMask::CADActivityDetected.value(); + RadioMode::Sleep | RadioMode::Standby => { + defmt::warn!("IRQ during sleep/standby?"); } - return Ok(TargetIrqState::Done); + RadioMode::FrequencySynthesis | RadioMode::ReceiveDutyCycle => todo!(), } // if an interrupt occurred for other than an error or operation completion, loop to wait again From c8c6af72c695b058d9ee400ab57fa9588c25c5f9 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Tue, 7 Nov 2023 13:23:28 +0200 Subject: [PATCH 2/2] sx127x: Add IRQ's for DIO1 and DIO3 and use it for ValidHeader irq --- src/sx1276_7_8_9/mod.rs | 23 ++++++++++----- src/sx1276_7_8_9/radio_kind_params.rs | 40 ++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/src/sx1276_7_8_9/mod.rs b/src/sx1276_7_8_9/mod.rs index 3831821..2e23f0e 100644 --- a/src/sx1276_7_8_9/mod.rs +++ b/src/sx1276_7_8_9/mod.rs @@ -478,7 +478,9 @@ where .await } - // Set the IRQ mask to disable unwanted interrupts, enable interrupts on DIO0 (the IRQ pin), and allow interrupts. + // Set the IRQ mask to disable unwanted interrupts, + // enable interrupts on DIO pins (sx127x has multiple), + // and allow interrupts. async fn set_irq_params(&mut self, radio_mode: Option) -> Result<(), RadioError> { match radio_mode { Some(RadioMode::Transmit) => { @@ -500,15 +502,22 @@ where self.write_register( Register::RegIrqFlagsMask, IrqMask::All.value() - ^ (IrqMask::RxDone.value() | IrqMask::RxTimeout.value() | IrqMask::CRCError.value()), + ^ (IrqMask::RxDone.value() + | IrqMask::RxTimeout.value() + | IrqMask::CRCError.value() + | IrqMask::HeaderValid.value()), false, ) .await?; - let mut dio_mapping_1 = self.read_register(Register::RegDioMapping1).await?; - dio_mapping_1 = (dio_mapping_1 & DioMapping1Dio0::Mask.value()) | DioMapping1Dio0::RxDone.value(); - self.write_register(Register::RegDioMapping1, dio_mapping_1, false) - .await?; + // HeaderValid and CRCError are mutually exclusive when attempting to + // trigger DIO-based interrupt, so our approach is to trigger HeaderValid + // as this is required for preamble detection. + // TODO: RxTimeout should be configured on DIO1 + let dio_mapping_1 = self.read_register(Register::RegDioMapping1).await?; + let val = (dio_mapping_1 & DioMapping1Dio0::Mask.value() & DioMapping1Dio3::Mask.value()) + | (DioMapping1Dio0::RxDone.value() | DioMapping1Dio3::ValidHeader.value()); + self.write_register(Register::RegDioMapping1, val, false).await?; self.write_register(Register::RegIrqFlags, 0x00u8, false).await?; } @@ -578,7 +587,7 @@ where self.write_register(Register::RegIrqFlags, 0xffu8, false).await?; // clear all interrupts debug!( - "process_irq satisfied: irq_flags = 0x{:x} in radio mode {}", + "process_irq: irq_flags = 0b{:08b} in radio mode {}", irq_flags, radio_mode ); diff --git a/src/sx1276_7_8_9/radio_kind_params.rs b/src/sx1276_7_8_9/radio_kind_params.rs index 8ae9505..7f8cc42 100644 --- a/src/sx1276_7_8_9/radio_kind_params.rs +++ b/src/sx1276_7_8_9/radio_kind_params.rs @@ -18,7 +18,14 @@ impl LoRaMode { } } -#[derive(Clone, Copy)] +// IRQ mapping for sx127x chips: +// DIO0 - RxDone, TxDone, CadDone +// DIO1 - RxTimeout, FhssChangeChannel, CadDetected +// DIO2 - 3x FhssChangeChannel +// DIO3 - CadDone, ValidHeader, PayloadCrcError +// DIO4 - CadDetected, *PllLock, *PllLock +// DIO5 - *ModeReady, *ClkOut, *ClkOut + #[allow(dead_code)] pub enum DioMapping1Dio0 { RxDone = 0x00, @@ -34,6 +41,37 @@ impl DioMapping1Dio0 { } } +#[allow(dead_code)] +pub enum DioMapping1Dio1 { + RxTimeOut = 0b00 << 2, + FhssChangeChannel = 0b01 << 2, + CadDetected = 0b10 << 2, + Other = 0b11 << 2, + Mask = 0xf3, +} + +#[allow(dead_code)] +impl DioMapping1Dio1 { + pub fn value(self) -> u8 { + self as u8 + } +} + +#[allow(dead_code)] +pub enum DioMapping1Dio3 { + CadDone = 0, + ValidHeader = 0b01, + PayloadCrcError = 0b10, + Other = 0b11, + Mask = 0xfc, +} + +impl DioMapping1Dio3 { + pub fn value(self) -> u8 { + self as u8 + } +} + #[derive(Clone, Copy)] #[allow(dead_code)] pub enum IrqMask {