Skip to content
This repository has been archived by the owner on Dec 27, 2023. It is now read-only.

Commit

Permalink
Merge pull request #41 from plaes/preamble-detection
Browse files Browse the repository at this point in the history
sx127x: Add support for ValidHeader IRQ required for preamble detection
  • Loading branch information
lucasgranberg authored Nov 17, 2023
2 parents 2bdf5ec + c8c6af7 commit ae7231a
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 38 deletions.
85 changes: 48 additions & 37 deletions src/sx1276_7_8_9/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,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<RadioMode>) -> Result<(), RadioError> {
match radio_mode {
Some(RadioMode::Transmit) => {
Expand All @@ -616,15 +618,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?;
}
Expand Down Expand Up @@ -694,44 +703,46 @@ 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
);

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
Expand Down
40 changes: 39 additions & 1 deletion src/sx1276_7_8_9/radio_kind_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,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,
Expand All @@ -35,6 +42,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 {
Expand Down

0 comments on commit ae7231a

Please sign in to comment.