Merge #514
514: Refactor sx127x driver to use async SPI r=lulf a=lulf It also contains a fix to SPI DMA transfer/read_write operations to ensure MISO doesn't contain any old data. Co-authored-by: Ulf Lilleengen <lulf@redhat.com>
This commit is contained in:
		| @@ -23,5 +23,5 @@ futures = { version = "0.3.17", default-features = false, features = [ "async-aw | ||||
| embedded-hal = { version = "0.2", features = ["unproven"] } | ||||
| bit_field = { version = "0.10" } | ||||
|  | ||||
| lorawan-device = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "4bff2e0021103adfbccedcbf49dbcd0474adc4b2", default-features = false, features = ["async"] } | ||||
| lorawan-encoding = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "4bff2e0021103adfbccedcbf49dbcd0474adc4b2", default-features = false } | ||||
| lorawan-device = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "53d2feb43e2f3ddcdc55f0587391b0d3f02d8d93", default-features = false, features = ["async"] } | ||||
| lorawan-encoding = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "53d2feb43e2f3ddcdc55f0587391b0d3f02d8d93", default-features = false } | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| use core::future::Future; | ||||
| use embassy::traits::gpio::WaitForRisingEdge; | ||||
| use embedded_hal::blocking::delay::DelayMs; | ||||
| use embedded_hal::blocking::spi::{Transfer, Write}; | ||||
| use embassy::traits::spi::*; | ||||
| use embedded_hal::digital::v2::OutputPin; | ||||
| use lorawan_device::async_device::{ | ||||
|     radio::{Bandwidth, PhyRxTx, RfConfig, RxQuality, SpreadingFactor, TxConfig}, | ||||
| @@ -21,7 +20,7 @@ pub trait RadioSwitch { | ||||
| /// Semtech Sx127x radio peripheral | ||||
| pub struct Sx127xRadio<SPI, CS, RESET, E, I, RFS> | ||||
| where | ||||
|     SPI: Transfer<u8, Error = E> + Write<u8, Error = E> + 'static, | ||||
|     SPI: FullDuplex<u8, Error = E> + 'static, | ||||
|     E: 'static, | ||||
|     CS: OutputPin + 'static, | ||||
|     RESET: OutputPin + 'static, | ||||
| @@ -43,29 +42,29 @@ pub enum State { | ||||
|  | ||||
| impl<SPI, CS, RESET, E, I, RFS> Sx127xRadio<SPI, CS, RESET, E, I, RFS> | ||||
| where | ||||
|     SPI: Transfer<u8, Error = E> + Write<u8, Error = E> + 'static, | ||||
|     SPI: FullDuplex<u8, Error = E> + 'static, | ||||
|     CS: OutputPin + 'static, | ||||
|     RESET: OutputPin + 'static, | ||||
|     I: WaitForRisingEdge + 'static, | ||||
|     RFS: RadioSwitch + 'static, | ||||
|     E: 'static, | ||||
| { | ||||
|     pub fn new<D: DelayMs<u32>>( | ||||
|     pub async fn new( | ||||
|         spi: SPI, | ||||
|         cs: CS, | ||||
|         reset: RESET, | ||||
|         irq: I, | ||||
|         rfs: RFS, | ||||
|         d: &mut D, | ||||
|     ) -> Result<Self, RadioError<E, CS::Error, RESET::Error>> { | ||||
|         let mut radio = LoRa::new(spi, cs, reset); | ||||
|         radio.reset(d)?; | ||||
|         radio.reset().await?; | ||||
|         Ok(Self { radio, irq, rfs }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl<SPI, CS, RESET, E, I, RFS> Timings for Sx127xRadio<SPI, CS, RESET, E, I, RFS> | ||||
| where | ||||
|     SPI: Transfer<u8, Error = E> + Write<u8, Error = E> + 'static, | ||||
|     SPI: FullDuplex<u8, Error = E> + 'static, | ||||
|     CS: OutputPin + 'static, | ||||
|     RESET: OutputPin + 'static, | ||||
|     I: WaitForRisingEdge + 'static, | ||||
| @@ -81,7 +80,7 @@ where | ||||
|  | ||||
| impl<SPI, CS, RESET, E, I, RFS> PhyRxTx for Sx127xRadio<SPI, CS, RESET, E, I, RFS> | ||||
| where | ||||
|     SPI: Transfer<u8, Error = E> + Write<u8, Error = E> + 'static, | ||||
|     SPI: FullDuplex<u8, Error = E> + 'static, | ||||
|     CS: OutputPin + 'static, | ||||
|     E: 'static, | ||||
|     RESET: OutputPin + 'static, | ||||
| @@ -96,29 +95,33 @@ where | ||||
|     fn tx<'m>(&'m mut self, config: TxConfig, buf: &'m [u8]) -> Self::TxFuture<'m> { | ||||
|         trace!("TX START"); | ||||
|         async move { | ||||
|             self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap(); | ||||
|             self.rfs.set_tx(); | ||||
|             self.radio.set_tx_power(14, 0)?; | ||||
|             self.radio.set_frequency(config.rf.frequency)?; | ||||
|             self.radio.set_tx_power(14, 0).await?; | ||||
|             self.radio.set_frequency(config.rf.frequency).await?; | ||||
|             // TODO: Modify radio to support other coding rates | ||||
|             self.radio.set_coding_rate_4(5)?; | ||||
|             self.radio.set_coding_rate_4(5).await?; | ||||
|             self.radio | ||||
|                 .set_signal_bandwidth(bandwidth_to_i64(config.rf.bandwidth))?; | ||||
|                 .set_signal_bandwidth(bandwidth_to_i64(config.rf.bandwidth)) | ||||
|                 .await?; | ||||
|             self.radio | ||||
|                 .set_spreading_factor(spreading_factor_to_u8(config.rf.spreading_factor))?; | ||||
|                 .set_spreading_factor(spreading_factor_to_u8(config.rf.spreading_factor)) | ||||
|                 .await?; | ||||
|  | ||||
|             self.radio.set_preamble_length(8)?; | ||||
|             self.radio.set_lora_pa_ramp()?; | ||||
|             self.radio.set_lora_sync_word()?; | ||||
|             self.radio.set_invert_iq(false)?; | ||||
|             self.radio.set_crc(true)?; | ||||
|             self.radio.set_preamble_length(8).await?; | ||||
|             self.radio.set_lora_pa_ramp().await?; | ||||
|             self.radio.set_lora_sync_word().await?; | ||||
|             self.radio.set_invert_iq(false).await?; | ||||
|             self.radio.set_crc(true).await?; | ||||
|  | ||||
|             self.radio.set_dio0_tx_done()?; | ||||
|             self.radio.transmit_payload(buf)?; | ||||
|             self.radio.set_dio0_tx_done().await?; | ||||
|  | ||||
|             self.radio.transmit_start(buf).await?; | ||||
|  | ||||
|             loop { | ||||
|                 self.irq.wait_for_rising_edge().await; | ||||
|                 self.radio.set_mode(RadioMode::Stdby).ok().unwrap(); | ||||
|                 let irq = self.radio.clear_irq().ok().unwrap(); | ||||
|                 self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap(); | ||||
|                 let irq = self.radio.clear_irq().await.ok().unwrap(); | ||||
|                 if (irq & IRQ::IrqTxDoneMask.addr()) != 0 { | ||||
|                     trace!("TX DONE"); | ||||
|                     return Ok(0); | ||||
| @@ -134,32 +137,34 @@ where | ||||
|         trace!("RX START"); | ||||
|         async move { | ||||
|             self.rfs.set_rx(); | ||||
|             self.radio.reset_payload_length()?; | ||||
|             self.radio.set_frequency(config.frequency)?; | ||||
|             self.radio.reset_payload_length().await?; | ||||
|             self.radio.set_frequency(config.frequency).await?; | ||||
|             // TODO: Modify radio to support other coding rates | ||||
|             self.radio.set_coding_rate_4(5)?; | ||||
|             self.radio.set_coding_rate_4(5).await?; | ||||
|             self.radio | ||||
|                 .set_signal_bandwidth(bandwidth_to_i64(config.bandwidth))?; | ||||
|                 .set_signal_bandwidth(bandwidth_to_i64(config.bandwidth)) | ||||
|                 .await?; | ||||
|             self.radio | ||||
|                 .set_spreading_factor(spreading_factor_to_u8(config.spreading_factor))?; | ||||
|                 .set_spreading_factor(spreading_factor_to_u8(config.spreading_factor)) | ||||
|                 .await?; | ||||
|  | ||||
|             self.radio.set_preamble_length(8)?; | ||||
|             self.radio.set_lora_sync_word()?; | ||||
|             self.radio.set_invert_iq(true)?; | ||||
|             self.radio.set_crc(true)?; | ||||
|             self.radio.set_preamble_length(8).await?; | ||||
|             self.radio.set_lora_sync_word().await?; | ||||
|             self.radio.set_invert_iq(true).await?; | ||||
|             self.radio.set_crc(true).await?; | ||||
|  | ||||
|             self.radio.set_dio0_rx_done()?; | ||||
|             self.radio.set_mode(RadioMode::RxContinuous)?; | ||||
|             self.radio.set_dio0_rx_done().await?; | ||||
|             self.radio.set_mode(RadioMode::RxContinuous).await?; | ||||
|  | ||||
|             loop { | ||||
|                 self.irq.wait_for_rising_edge().await; | ||||
|                 self.radio.set_mode(RadioMode::Stdby).ok().unwrap(); | ||||
|                 let irq = self.radio.clear_irq().ok().unwrap(); | ||||
|                 self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap(); | ||||
|                 let irq = self.radio.clear_irq().await.ok().unwrap(); | ||||
|                 if (irq & IRQ::IrqRxDoneMask.addr()) != 0 { | ||||
|                     let rssi = self.radio.get_packet_rssi().unwrap_or(0) as i16; | ||||
|                     let snr = self.radio.get_packet_snr().unwrap_or(0.0) as i8; | ||||
|                     let response = if let Ok(size) = self.radio.read_packet_size() { | ||||
|                         self.radio.read_packet(buf)?; | ||||
|                     let rssi = self.radio.get_packet_rssi().await.unwrap_or(0) as i16; | ||||
|                     let snr = self.radio.get_packet_snr().await.unwrap_or(0.0) as i8; | ||||
|                     let response = if let Ok(size) = self.radio.read_packet_size().await { | ||||
|                         self.radio.read_packet(buf).await?; | ||||
|                         Ok((size, RxQuality::new(rssi, snr))) | ||||
|                     } else { | ||||
|                         Ok((0, RxQuality::new(rssi, snr))) | ||||
|   | ||||
| @@ -6,24 +6,15 @@ | ||||
| #![allow(dead_code)] | ||||
|  | ||||
| use bit_field::BitField; | ||||
| use embedded_hal::blocking::{ | ||||
|     delay::DelayMs, | ||||
|     spi::{Transfer, Write}, | ||||
| }; | ||||
| use embassy::time::{Duration, Timer}; | ||||
| use embassy::traits::spi::*; | ||||
| use embedded_hal::digital::v2::OutputPin; | ||||
| use embedded_hal::spi::{Mode, Phase, Polarity}; | ||||
|  | ||||
| mod register; | ||||
| use self::register::PaConfig; | ||||
| use self::register::Register; | ||||
| pub use self::register::IRQ; | ||||
|  | ||||
| /// Provides the necessary SPI mode configuration for the radio | ||||
| pub const MODE: Mode = Mode { | ||||
|     phase: Phase::CaptureOnSecondTransition, | ||||
|     polarity: Polarity::IdleHigh, | ||||
| }; | ||||
|  | ||||
| /// Provides high-level access to Semtech SX1276/77/78/79 based boards connected to a Raspberry Pi | ||||
| pub struct LoRa<SPI, CS, RESET> { | ||||
|     spi: SPI, | ||||
| @@ -56,7 +47,7 @@ const VERSION_CHECK: u8 = 0x09; | ||||
|  | ||||
| impl<SPI, CS, RESET, E> LoRa<SPI, CS, RESET> | ||||
| where | ||||
|     SPI: Transfer<u8, Error = E> + Write<u8, Error = E>, | ||||
|     SPI: FullDuplex<u8, Error = E>, | ||||
|     CS: OutputPin, | ||||
|     RESET: OutputPin, | ||||
| { | ||||
| @@ -72,24 +63,25 @@ where | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn reset<D: DelayMs<u32>>( | ||||
|         &mut self, | ||||
|         d: &mut D, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn reset(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.reset.set_low().map_err(Reset)?; | ||||
|         d.delay_ms(10_u32); | ||||
|         Timer::after(Duration::from_millis(10)).await; | ||||
|         self.reset.set_high().map_err(Reset)?; | ||||
|         d.delay_ms(10_u32); | ||||
|         let version = self.read_register(Register::RegVersion.addr())?; | ||||
|         Timer::after(Duration::from_millis(10)).await; | ||||
|         let version = self.read_register(Register::RegVersion.addr()).await?; | ||||
|         if version == VERSION_CHECK { | ||||
|             self.set_mode(RadioMode::Sleep)?; | ||||
|             self.write_register(Register::RegFifoTxBaseAddr.addr(), 0)?; | ||||
|             self.write_register(Register::RegFifoRxBaseAddr.addr(), 0)?; | ||||
|             let lna = self.read_register(Register::RegLna.addr())?; | ||||
|             self.write_register(Register::RegLna.addr(), lna | 0x03)?; | ||||
|             self.write_register(Register::RegModemConfig3.addr(), 0x04)?; | ||||
|             self.set_tcxo(true)?; | ||||
|             self.set_mode(RadioMode::Stdby)?; | ||||
|             self.set_mode(RadioMode::Sleep).await?; | ||||
|             self.write_register(Register::RegFifoTxBaseAddr.addr(), 0) | ||||
|                 .await?; | ||||
|             self.write_register(Register::RegFifoRxBaseAddr.addr(), 0) | ||||
|                 .await?; | ||||
|             let lna = self.read_register(Register::RegLna.addr()).await?; | ||||
|             self.write_register(Register::RegLna.addr(), lna | 0x03) | ||||
|                 .await?; | ||||
|             self.write_register(Register::RegModemConfig3.addr(), 0x04) | ||||
|                 .await?; | ||||
|             self.set_tcxo(true).await?; | ||||
|             self.set_mode(RadioMode::Stdby).await?; | ||||
|             self.cs.set_high().map_err(CS)?; | ||||
|             Ok(()) | ||||
|         } else { | ||||
| @@ -97,137 +89,125 @@ where | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Transmits up to 255 bytes of data. To avoid the use of an allocator, this takes a fixed 255 u8 | ||||
|     /// array and a payload size and returns the number of bytes sent if successful. | ||||
|     pub fn transmit_payload_busy( | ||||
|         &mut self, | ||||
|         buffer: [u8; 255], | ||||
|         payload_size: usize, | ||||
|     ) -> Result<usize, Error<E, CS::Error, RESET::Error>> { | ||||
|         if self.transmitting()? { | ||||
|             Err(Transmitting) | ||||
|         } else { | ||||
|             self.set_mode(RadioMode::Stdby)?; | ||||
|             if self.explicit_header { | ||||
|                 self.set_explicit_header_mode()?; | ||||
|             } else { | ||||
|                 self.set_implicit_header_mode()?; | ||||
|             } | ||||
|  | ||||
|             self.write_register(Register::RegIrqFlags.addr(), 0)?; | ||||
|             self.write_register(Register::RegFifoAddrPtr.addr(), 0)?; | ||||
|             self.write_register(Register::RegPayloadLength.addr(), 0)?; | ||||
|             for byte in buffer.iter().take(payload_size) { | ||||
|                 self.write_register(Register::RegFifo.addr(), *byte)?; | ||||
|             } | ||||
|             self.write_register(Register::RegPayloadLength.addr(), payload_size as u8)?; | ||||
|             self.set_mode(RadioMode::Tx)?; | ||||
|             while self.transmitting()? {} | ||||
|             Ok(payload_size) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn set_dio0_tx_done(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegIrqFlagsMask.addr(), 0b1111_0111)?; | ||||
|         let mapping = self.read_register(Register::RegDioMapping1.addr())?; | ||||
|     pub async fn set_dio0_tx_done(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegIrqFlagsMask.addr(), 0b1111_0111) | ||||
|             .await?; | ||||
|         let mapping = self.read_register(Register::RegDioMapping1.addr()).await?; | ||||
|         self.write_register(Register::RegDioMapping1.addr(), (mapping & 0x3F) | 0x40) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     pub fn set_dio0_rx_done(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegIrqFlagsMask.addr(), 0b0001_1111)?; | ||||
|         let mapping = self.read_register(Register::RegDioMapping1.addr())?; | ||||
|     pub async fn set_dio0_rx_done(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegIrqFlagsMask.addr(), 0b0001_1111) | ||||
|             .await?; | ||||
|         let mapping = self.read_register(Register::RegDioMapping1.addr()).await?; | ||||
|         self.write_register(Register::RegDioMapping1.addr(), mapping & 0x3F) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     pub fn transmit_payload( | ||||
|     pub async fn transmit_start( | ||||
|         &mut self, | ||||
|         buffer: &[u8], | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         assert!(buffer.len() < 255); | ||||
|         if self.transmitting()? { | ||||
|         if self.transmitting().await? { | ||||
|             //trace!("ALREADY TRANSMNITTING"); | ||||
|             Err(Transmitting) | ||||
|         } else { | ||||
|             self.set_mode(RadioMode::Stdby)?; | ||||
|             self.set_mode(RadioMode::Stdby).await?; | ||||
|             if self.explicit_header { | ||||
|                 self.set_explicit_header_mode()?; | ||||
|                 self.set_explicit_header_mode().await?; | ||||
|             } else { | ||||
|                 self.set_implicit_header_mode()?; | ||||
|                 self.set_implicit_header_mode().await?; | ||||
|             } | ||||
|  | ||||
|             self.write_register(Register::RegIrqFlags.addr(), 0)?; | ||||
|             self.write_register(Register::RegFifoAddrPtr.addr(), 0)?; | ||||
|             self.write_register(Register::RegPayloadLength.addr(), 0)?; | ||||
|             self.write_register(Register::RegIrqFlags.addr(), 0).await?; | ||||
|             self.write_register(Register::RegFifoAddrPtr.addr(), 0) | ||||
|                 .await?; | ||||
|             self.write_register(Register::RegPayloadLength.addr(), 0) | ||||
|                 .await?; | ||||
|             for byte in buffer.iter() { | ||||
|                 self.write_register(Register::RegFifo.addr(), *byte)?; | ||||
|                 self.write_register(Register::RegFifo.addr(), *byte).await?; | ||||
|             } | ||||
|             self.write_register(Register::RegPayloadLength.addr(), buffer.len() as u8)?; | ||||
|             self.set_mode(RadioMode::Tx)?; | ||||
|             self.write_register(Register::RegPayloadLength.addr(), buffer.len() as u8) | ||||
|                 .await?; | ||||
|             self.set_mode(RadioMode::Tx).await?; | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn packet_ready(&mut self) -> Result<bool, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegIrqFlags.addr())?.get_bit(6)) | ||||
|     pub async fn packet_ready(&mut self) -> Result<bool, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self | ||||
|             .read_register(Register::RegIrqFlags.addr()) | ||||
|             .await? | ||||
|             .get_bit(6)) | ||||
|     } | ||||
|  | ||||
|     pub fn irq_flags_mask(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegIrqFlagsMask.addr())? as u8) | ||||
|     pub async fn irq_flags_mask(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegIrqFlagsMask.addr()).await? as u8) | ||||
|     } | ||||
|  | ||||
|     pub fn irq_flags(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegIrqFlags.addr())? as u8) | ||||
|     pub async fn irq_flags(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegIrqFlags.addr()).await? as u8) | ||||
|     } | ||||
|  | ||||
|     pub fn read_packet_size(&mut self) -> Result<usize, Error<E, CS::Error, RESET::Error>> { | ||||
|         let size = self.read_register(Register::RegRxNbBytes.addr())?; | ||||
|     pub async fn read_packet_size(&mut self) -> Result<usize, Error<E, CS::Error, RESET::Error>> { | ||||
|         let size = self.read_register(Register::RegRxNbBytes.addr()).await?; | ||||
|         Ok(size as usize) | ||||
|     } | ||||
|  | ||||
|     /// Returns the contents of the fifo as a fixed 255 u8 array. This should only be called is there is a | ||||
|     /// new packet ready to be read. | ||||
|     pub fn read_packet( | ||||
|     pub async fn read_packet( | ||||
|         &mut self, | ||||
|         buffer: &mut [u8], | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.clear_irq()?; | ||||
|         let size = self.read_register(Register::RegRxNbBytes.addr())?; | ||||
|         self.clear_irq().await?; | ||||
|         let size = self.read_register(Register::RegRxNbBytes.addr()).await?; | ||||
|         assert!(size as usize <= buffer.len()); | ||||
|         let fifo_addr = self.read_register(Register::RegFifoRxCurrentAddr.addr())?; | ||||
|         self.write_register(Register::RegFifoAddrPtr.addr(), fifo_addr)?; | ||||
|         let fifo_addr = self | ||||
|             .read_register(Register::RegFifoRxCurrentAddr.addr()) | ||||
|             .await?; | ||||
|         self.write_register(Register::RegFifoAddrPtr.addr(), fifo_addr) | ||||
|             .await?; | ||||
|         for i in 0..size { | ||||
|             let byte = self.read_register(Register::RegFifo.addr())?; | ||||
|             let byte = self.read_register(Register::RegFifo.addr()).await?; | ||||
|             buffer[i as usize] = byte; | ||||
|         } | ||||
|         self.write_register(Register::RegFifoAddrPtr.addr(), 0)?; | ||||
|         self.write_register(Register::RegFifoAddrPtr.addr(), 0) | ||||
|             .await?; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     /// Returns true if the radio is currently transmitting a packet. | ||||
|     pub fn transmitting(&mut self) -> Result<bool, Error<E, CS::Error, RESET::Error>> { | ||||
|         if (self.read_register(Register::RegOpMode.addr())? & RadioMode::Tx.addr()) | ||||
|     pub async fn transmitting(&mut self) -> Result<bool, Error<E, CS::Error, RESET::Error>> { | ||||
|         if (self.read_register(Register::RegOpMode.addr()).await?) & RadioMode::Tx.addr() | ||||
|             == RadioMode::Tx.addr() | ||||
|         { | ||||
|             Ok(true) | ||||
|         } else { | ||||
|             if (self.read_register(Register::RegIrqFlags.addr())? & IRQ::IrqTxDoneMask.addr()) == 1 | ||||
|             if (self.read_register(Register::RegIrqFlags.addr()).await? & IRQ::IrqTxDoneMask.addr()) | ||||
|                 == 1 | ||||
|             { | ||||
|                 self.write_register(Register::RegIrqFlags.addr(), IRQ::IrqTxDoneMask.addr())?; | ||||
|                 self.write_register(Register::RegIrqFlags.addr(), IRQ::IrqTxDoneMask.addr()) | ||||
|                     .await?; | ||||
|             } | ||||
|             Ok(false) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Clears the radio's IRQ registers. | ||||
|     pub fn clear_irq(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         let irq_flags = self.read_register(Register::RegIrqFlags.addr())?; | ||||
|         self.write_register(Register::RegIrqFlags.addr(), 0xFF)?; | ||||
|     pub async fn clear_irq(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         let irq_flags = self.read_register(Register::RegIrqFlags.addr()).await?; | ||||
|         self.write_register(Register::RegIrqFlags.addr(), 0xFF) | ||||
|             .await?; | ||||
|         Ok(irq_flags) | ||||
|     } | ||||
|  | ||||
|     /// Sets the transmit power and pin. Levels can range from 0-14 when the output | ||||
|     /// pin = 0(RFO), and form 0-20 when output pin = 1(PaBoost). Power is in dB. | ||||
|     /// Default value is `17`. | ||||
|     pub fn set_tx_power( | ||||
|     pub async fn set_tx_power( | ||||
|         &mut self, | ||||
|         mut level: i32, | ||||
|         output_pin: u8, | ||||
| @@ -240,6 +220,7 @@ where | ||||
|                 level = 14; | ||||
|             } | ||||
|             self.write_register(Register::RegPaConfig.addr(), (0x70 | level) as u8) | ||||
|                 .await | ||||
|         } else { | ||||
|             // PA BOOST | ||||
|             if level > 17 { | ||||
| @@ -250,30 +231,31 @@ where | ||||
|                 level -= 3; | ||||
|  | ||||
|                 // High Power +20 dBm Operation (Semtech SX1276/77/78/79 5.4.3.) | ||||
|                 self.write_register(Register::RegPaDac.addr(), 0x87)?; | ||||
|                 self.set_ocp(140)?; | ||||
|                 self.write_register(Register::RegPaDac.addr(), 0x87).await?; | ||||
|                 self.set_ocp(140).await?; | ||||
|             } else { | ||||
|                 if level < 2 { | ||||
|                     level = 2; | ||||
|                 } | ||||
|                 //Default value PA_HF/LF or +17dBm | ||||
|                 self.write_register(Register::RegPaDac.addr(), 0x84)?; | ||||
|                 self.set_ocp(100)?; | ||||
|                 self.write_register(Register::RegPaDac.addr(), 0x84).await?; | ||||
|                 self.set_ocp(100).await?; | ||||
|             } | ||||
|             level -= 2; | ||||
|             self.write_register( | ||||
|                 Register::RegPaConfig.addr(), | ||||
|                 PaConfig::PaBoost.addr() | level as u8, | ||||
|             ) | ||||
|             .await | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn get_modem_stat(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegModemStat.addr())? as u8) | ||||
|     pub async fn get_modem_stat(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegModemStat.addr()).await? as u8) | ||||
|     } | ||||
|  | ||||
|     /// Sets the over current protection on the radio(mA). | ||||
|     pub fn set_ocp(&mut self, ma: u8) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn set_ocp(&mut self, ma: u8) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let mut ocp_trim: u8 = 27; | ||||
|  | ||||
|         if ma <= 120 { | ||||
| @@ -282,31 +264,40 @@ where | ||||
|             ocp_trim = (ma + 30) / 10; | ||||
|         } | ||||
|         self.write_register(Register::RegOcp.addr(), 0x20 | (0x1F & ocp_trim)) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     /// Sets the state of the radio. Default mode after initiation is `Standby`. | ||||
|     pub fn set_mode(&mut self, mode: RadioMode) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn set_mode( | ||||
|         &mut self, | ||||
|         mode: RadioMode, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         if self.explicit_header { | ||||
|             self.set_explicit_header_mode()?; | ||||
|             self.set_explicit_header_mode().await?; | ||||
|         } else { | ||||
|             self.set_implicit_header_mode()?; | ||||
|             self.set_implicit_header_mode().await?; | ||||
|         } | ||||
|         self.write_register( | ||||
|             Register::RegOpMode.addr(), | ||||
|             RadioMode::LongRangeMode.addr() | mode.addr(), | ||||
|         )?; | ||||
|         ) | ||||
|         .await?; | ||||
|  | ||||
|         self.mode = mode; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub fn reset_payload_length(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn reset_payload_length(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegPayloadLength.addr(), 0xFF) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     /// Sets the frequency of the radio. Values are in megahertz. | ||||
|     /// I.E. 915 MHz must be used for North America. Check regulation for your area. | ||||
|     pub fn set_frequency(&mut self, freq: u32) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn set_frequency( | ||||
|         &mut self, | ||||
|         freq: u32, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         const FREQ_STEP: f64 = 61.03515625; | ||||
|         // calculate register values | ||||
|         let frf = (freq as f64 / FREQ_STEP) as u32; | ||||
| @@ -314,23 +305,28 @@ where | ||||
|         self.write_register( | ||||
|             Register::RegFrfMsb.addr(), | ||||
|             ((frf & 0x00FF_0000) >> 16) as u8, | ||||
|         )?; | ||||
|         self.write_register(Register::RegFrfMid.addr(), ((frf & 0x0000_FF00) >> 8) as u8)?; | ||||
|         ) | ||||
|         .await?; | ||||
|         self.write_register(Register::RegFrfMid.addr(), ((frf & 0x0000_FF00) >> 8) as u8) | ||||
|             .await?; | ||||
|         self.write_register(Register::RegFrfLsb.addr(), (frf & 0x0000_00FF) as u8) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     /// Sets the radio to use an explicit header. Default state is `ON`. | ||||
|     fn set_explicit_header_mode(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let reg_modem_config_1 = self.read_register(Register::RegModemConfig1.addr())?; | ||||
|         self.write_register(Register::RegModemConfig1.addr(), reg_modem_config_1 & 0xfe)?; | ||||
|     async fn set_explicit_header_mode(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let reg_modem_config_1 = self.read_register(Register::RegModemConfig1.addr()).await?; | ||||
|         self.write_register(Register::RegModemConfig1.addr(), reg_modem_config_1 & 0xfe) | ||||
|             .await?; | ||||
|         self.explicit_header = true; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     /// Sets the radio to use an implicit header. Default state is `OFF`. | ||||
|     fn set_implicit_header_mode(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let reg_modem_config_1 = self.read_register(Register::RegModemConfig1.addr())?; | ||||
|         self.write_register(Register::RegModemConfig1.addr(), reg_modem_config_1 & 0x01)?; | ||||
|     async fn set_implicit_header_mode(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let reg_modem_config_1 = self.read_register(Register::RegModemConfig1.addr()).await?; | ||||
|         self.write_register(Register::RegModemConfig1.addr(), reg_modem_config_1 & 0x01) | ||||
|             .await?; | ||||
|         self.explicit_header = false; | ||||
|         Ok(()) | ||||
|     } | ||||
| @@ -338,7 +334,7 @@ where | ||||
|     /// Sets the spreading factor of the radio. Supported values are between 6 and 12. | ||||
|     /// If a spreading factor of 6 is set, implicit header mode must be used to transmit | ||||
|     /// and receive packets. Default value is `7`. | ||||
|     pub fn set_spreading_factor( | ||||
|     pub async fn set_spreading_factor( | ||||
|         &mut self, | ||||
|         mut sf: u8, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
| @@ -349,36 +345,45 @@ where | ||||
|         } | ||||
|  | ||||
|         if sf == 6 { | ||||
|             self.write_register(Register::RegDetectionOptimize.addr(), 0xc5)?; | ||||
|             self.write_register(Register::RegDetectionThreshold.addr(), 0x0c)?; | ||||
|             self.write_register(Register::RegDetectionOptimize.addr(), 0xc5) | ||||
|                 .await?; | ||||
|             self.write_register(Register::RegDetectionThreshold.addr(), 0x0c) | ||||
|                 .await?; | ||||
|         } else { | ||||
|             self.write_register(Register::RegDetectionOptimize.addr(), 0xc3)?; | ||||
|             self.write_register(Register::RegDetectionThreshold.addr(), 0x0a)?; | ||||
|             self.write_register(Register::RegDetectionOptimize.addr(), 0xc3) | ||||
|                 .await?; | ||||
|             self.write_register(Register::RegDetectionThreshold.addr(), 0x0a) | ||||
|                 .await?; | ||||
|         } | ||||
|         let modem_config_2 = self.read_register(Register::RegModemConfig2.addr())?; | ||||
|         let modem_config_2 = self.read_register(Register::RegModemConfig2.addr()).await?; | ||||
|         self.write_register( | ||||
|             Register::RegModemConfig2.addr(), | ||||
|             (modem_config_2 & 0x0f) | ((sf << 4) & 0xf0), | ||||
|         )?; | ||||
|         self.set_ldo_flag()?; | ||||
|         ) | ||||
|         .await?; | ||||
|         self.set_ldo_flag().await?; | ||||
|  | ||||
|         self.write_register(Register::RegSymbTimeoutLsb.addr(), 0x05)?; | ||||
|         self.write_register(Register::RegSymbTimeoutLsb.addr(), 0x05) | ||||
|             .await?; | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub fn set_tcxo(&mut self, external: bool) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn set_tcxo( | ||||
|         &mut self, | ||||
|         external: bool, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         if external { | ||||
|             self.write_register(Register::RegTcxo.addr(), 0x10) | ||||
|             self.write_register(Register::RegTcxo.addr(), 0x10).await | ||||
|         } else { | ||||
|             self.write_register(Register::RegTcxo.addr(), 0x00) | ||||
|             self.write_register(Register::RegTcxo.addr(), 0x00).await | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Sets the signal bandwidth of the radio. Supported values are: `7800 Hz`, `10400 Hz`, | ||||
|     /// `15600 Hz`, `20800 Hz`, `31250 Hz`,`41700 Hz` ,`62500 Hz`,`125000 Hz` and `250000 Hz` | ||||
|     /// Default value is `125000 Hz` | ||||
|     pub fn set_signal_bandwidth( | ||||
|     pub async fn set_signal_bandwidth( | ||||
|         &mut self, | ||||
|         sbw: i64, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
| @@ -394,19 +399,20 @@ where | ||||
|             250_000 => 8, | ||||
|             _ => 9, | ||||
|         }; | ||||
|         let modem_config_1 = self.read_register(Register::RegModemConfig1.addr())?; | ||||
|         let modem_config_1 = self.read_register(Register::RegModemConfig1.addr()).await?; | ||||
|         self.write_register( | ||||
|             Register::RegModemConfig1.addr(), | ||||
|             (modem_config_1 & 0x0f) | ((bw << 4) as u8), | ||||
|         )?; | ||||
|         self.set_ldo_flag()?; | ||||
|         ) | ||||
|         .await?; | ||||
|         self.set_ldo_flag().await?; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     /// Sets the coding rate of the radio with the numerator fixed at 4. Supported values | ||||
|     /// are between `5` and `8`, these correspond to coding rates of `4/5` and `4/8`. | ||||
|     /// Default value is `5`. | ||||
|     pub fn set_coding_rate_4( | ||||
|     pub async fn set_coding_rate_4( | ||||
|         &mut self, | ||||
|         mut denominator: u8, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
| @@ -416,52 +422,64 @@ where | ||||
|             denominator = 8; | ||||
|         } | ||||
|         let cr = denominator - 4; | ||||
|         let modem_config_1 = self.read_register(Register::RegModemConfig1.addr())?; | ||||
|         let modem_config_1 = self.read_register(Register::RegModemConfig1.addr()).await?; | ||||
|         self.write_register( | ||||
|             Register::RegModemConfig1.addr(), | ||||
|             (modem_config_1 & 0xf1) | (cr << 1), | ||||
|         ) | ||||
|         .await | ||||
|     } | ||||
|  | ||||
|     /// Sets the preamble length of the radio. Values are between 6 and 65535. | ||||
|     /// Default value is `8`. | ||||
|     pub fn set_preamble_length( | ||||
|     pub async fn set_preamble_length( | ||||
|         &mut self, | ||||
|         length: i64, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegPreambleMsb.addr(), (length >> 8) as u8)?; | ||||
|         self.write_register(Register::RegPreambleMsb.addr(), (length >> 8) as u8) | ||||
|             .await?; | ||||
|         self.write_register(Register::RegPreambleLsb.addr(), length as u8) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     /// Enables are disables the radio's CRC check. Default value is `false`. | ||||
|     pub fn set_crc(&mut self, value: bool) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let modem_config_2 = self.read_register(Register::RegModemConfig2.addr())?; | ||||
|     pub async fn set_crc(&mut self, value: bool) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let modem_config_2 = self.read_register(Register::RegModemConfig2.addr()).await?; | ||||
|         if value { | ||||
|             self.write_register(Register::RegModemConfig2.addr(), modem_config_2 | 0x04) | ||||
|                 .await | ||||
|         } else { | ||||
|             self.write_register(Register::RegModemConfig2.addr(), modem_config_2 & 0xfb) | ||||
|                 .await | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Inverts the radio's IQ signals. Default value is `false`. | ||||
|     pub fn set_invert_iq(&mut self, value: bool) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn set_invert_iq( | ||||
|         &mut self, | ||||
|         value: bool, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         if value { | ||||
|             self.write_register(Register::RegInvertiq.addr(), 0x66)?; | ||||
|             self.write_register(Register::RegInvertiq.addr(), 0x66) | ||||
|                 .await?; | ||||
|             self.write_register(Register::RegInvertiq2.addr(), 0x19) | ||||
|                 .await | ||||
|         } else { | ||||
|             self.write_register(Register::RegInvertiq.addr(), 0x27)?; | ||||
|             self.write_register(Register::RegInvertiq.addr(), 0x27) | ||||
|                 .await?; | ||||
|             self.write_register(Register::RegInvertiq2.addr(), 0x1d) | ||||
|                 .await | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Returns the spreading factor of the radio. | ||||
|     pub fn get_spreading_factor(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegModemConfig2.addr())? >> 4) | ||||
|     pub async fn get_spreading_factor(&mut self) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(self.read_register(Register::RegModemConfig2.addr()).await? >> 4) | ||||
|     } | ||||
|  | ||||
|     /// Returns the signal bandwidth of the radio. | ||||
|     pub fn get_signal_bandwidth(&mut self) -> Result<i64, Error<E, CS::Error, RESET::Error>> { | ||||
|         let bw = self.read_register(Register::RegModemConfig1.addr())? >> 4; | ||||
|     pub async fn get_signal_bandwidth(&mut self) -> Result<i64, Error<E, CS::Error, RESET::Error>> { | ||||
|         let bw = self.read_register(Register::RegModemConfig1.addr()).await? >> 4; | ||||
|         let bw = match bw { | ||||
|             0 => 7_800, | ||||
|             1 => 10_400, | ||||
| @@ -479,69 +497,76 @@ where | ||||
|     } | ||||
|  | ||||
|     /// Returns the RSSI of the last received packet. | ||||
|     pub fn get_packet_rssi(&mut self) -> Result<i32, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(i32::from(self.read_register(Register::RegPktRssiValue.addr())?) - 157) | ||||
|     pub async fn get_packet_rssi(&mut self) -> Result<i32, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(i32::from(self.read_register(Register::RegPktRssiValue.addr()).await?) - 157) | ||||
|     } | ||||
|  | ||||
|     /// Returns the signal to noise radio of the the last received packet. | ||||
|     pub fn get_packet_snr(&mut self) -> Result<f64, Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn get_packet_snr(&mut self) -> Result<f64, Error<E, CS::Error, RESET::Error>> { | ||||
|         Ok(f64::from( | ||||
|             self.read_register(Register::RegPktSnrValue.addr())?, | ||||
|             self.read_register(Register::RegPktSnrValue.addr()).await?, | ||||
|         )) | ||||
|     } | ||||
|  | ||||
|     /// Returns the frequency error of the last received packet in Hz. | ||||
|     pub fn get_packet_frequency_error(&mut self) -> Result<i64, Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn get_packet_frequency_error( | ||||
|         &mut self, | ||||
|     ) -> Result<i64, Error<E, CS::Error, RESET::Error>> { | ||||
|         let mut freq_error: i32; | ||||
|         freq_error = i32::from(self.read_register(Register::RegFreqErrorMsb.addr())? & 0x7); | ||||
|         freq_error = i32::from(self.read_register(Register::RegFreqErrorMsb.addr()).await? & 0x7); | ||||
|         freq_error <<= 8i64; | ||||
|         freq_error += i32::from(self.read_register(Register::RegFreqErrorMid.addr())?); | ||||
|         freq_error += i32::from(self.read_register(Register::RegFreqErrorMid.addr()).await?); | ||||
|         freq_error <<= 8i64; | ||||
|         freq_error += i32::from(self.read_register(Register::RegFreqErrorLsb.addr())?); | ||||
|         freq_error += i32::from(self.read_register(Register::RegFreqErrorLsb.addr()).await?); | ||||
|  | ||||
|         let f_xtal = 32_000_000; // FXOSC: crystal oscillator (XTAL) frequency (2.5. Chip Specification, p. 14) | ||||
|         let f_error = ((f64::from(freq_error) * (1i64 << 24) as f64) / f64::from(f_xtal)) | ||||
|             * (self.get_signal_bandwidth()? as f64 / 500_000.0f64); // p. 37 | ||||
|             * (self.get_signal_bandwidth().await? as f64 / 500_000.0f64); // p. 37 | ||||
|         Ok(f_error as i64) | ||||
|     } | ||||
|  | ||||
|     fn set_ldo_flag(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let sw = self.get_signal_bandwidth()?; | ||||
|     async fn set_ldo_flag(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         let sw = self.get_signal_bandwidth().await?; | ||||
|         // Section 4.1.1.5 | ||||
|         let symbol_duration = 1000 / (sw / ((1_i64) << self.get_spreading_factor()?)); | ||||
|         let symbol_duration = 1000 / (sw / ((1_i64) << self.get_spreading_factor().await?)); | ||||
|  | ||||
|         // Section 4.1.1.6 | ||||
|         let ldo_on = symbol_duration > 16; | ||||
|  | ||||
|         let mut config_3 = self.read_register(Register::RegModemConfig3.addr())?; | ||||
|         let mut config_3 = self.read_register(Register::RegModemConfig3.addr()).await?; | ||||
|         config_3.set_bit(3, ldo_on); | ||||
|         //config_3.set_bit(2, true); | ||||
|         self.write_register(Register::RegModemConfig3.addr(), config_3) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     fn read_register(&mut self, reg: u8) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|     async fn read_register(&mut self, reg: u8) -> Result<u8, Error<E, CS::Error, RESET::Error>> { | ||||
|         let mut buffer = [reg & 0x7f, 0]; | ||||
|         self.cs.set_low().map_err(CS)?; | ||||
|  | ||||
|         let mut buffer = [reg & 0x7f, 0]; | ||||
|         let transfer = self.spi.transfer(&mut buffer).map_err(SPI)?; | ||||
|         let _ = self | ||||
|             .spi | ||||
|             .read_write(&mut buffer, &[reg & 0x7f, 0]) | ||||
|             .await | ||||
|             .map_err(SPI)?; | ||||
|  | ||||
|         self.cs.set_high().map_err(CS)?; | ||||
|         Ok(transfer[1]) | ||||
|         Ok(buffer[1]) | ||||
|     } | ||||
|  | ||||
|     fn write_register( | ||||
|     async fn write_register( | ||||
|         &mut self, | ||||
|         reg: u8, | ||||
|         byte: u8, | ||||
|     ) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.cs.set_low().map_err(CS)?; | ||||
|  | ||||
|         let buffer = [reg | 0x80, byte]; | ||||
|         self.spi.write(&buffer).map_err(SPI)?; | ||||
|         self.spi.write(&buffer).await.map_err(SPI)?; | ||||
|         self.cs.set_high().map_err(CS)?; | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     pub fn put_in_fsk_mode(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|     pub async fn put_in_fsk_mode(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         // Put in FSK mode | ||||
|         let mut op_mode = 0; | ||||
|         op_mode | ||||
| @@ -551,9 +576,10 @@ where | ||||
|             .set_bits(0..2, 0b011); // Mode | ||||
|  | ||||
|         self.write_register(Register::RegOpMode as u8, op_mode) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     pub fn set_fsk_pa_ramp( | ||||
|     pub async fn set_fsk_pa_ramp( | ||||
|         &mut self, | ||||
|         modulation_shaping: FskDataModulationShaping, | ||||
|         ramp: FskRampUpRamDown, | ||||
| @@ -564,14 +590,15 @@ where | ||||
|             .set_bits(0..3, ramp as u8); | ||||
|  | ||||
|         self.write_register(Register::RegPaRamp as u8, pa_ramp) | ||||
|             .await | ||||
|     } | ||||
|  | ||||
|     pub fn set_lora_pa_ramp(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegPaRamp as u8, 0b1000) | ||||
|     pub async fn set_lora_pa_ramp(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegPaRamp as u8, 0b1000).await | ||||
|     } | ||||
|  | ||||
|     pub fn set_lora_sync_word(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegSyncWord as u8, 0x34) | ||||
|     pub async fn set_lora_sync_word(&mut self) -> Result<(), Error<E, CS::Error, RESET::Error>> { | ||||
|         self.write_register(Register::RegSyncWord as u8, 0x34).await | ||||
|     } | ||||
| } | ||||
| /// Modes of the radio and their corresponding register values. | ||||
|   | ||||
| @@ -262,6 +262,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||||
|             T::regs().cr2().modify(|reg| { | ||||
|                 reg.set_rxdmaen(true); | ||||
|             }); | ||||
|  | ||||
|             // Flush the read buffer to avoid errornous data from being read | ||||
|             while T::regs().sr().read().rxne() { | ||||
|                 let _ = T::regs().dr().read(); | ||||
|             } | ||||
|         } | ||||
|         Self::set_word_size(WordSize::EightBit); | ||||
|  | ||||
|   | ||||
| @@ -284,6 +284,11 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { | ||||
|             T::regs().cfg1().modify(|reg| { | ||||
|                 reg.set_rxdmaen(true); | ||||
|             }); | ||||
|  | ||||
|             // Flush the read buffer to avoid errornous data from being read | ||||
|             while T::regs().sr().read().rxp() { | ||||
|                 let _ = T::regs().rxdr().read(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         let rx_request = self.rxdma.request(); | ||||
|   | ||||
| @@ -10,16 +10,17 @@ embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] } | ||||
| embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } | ||||
| embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-tim3"]  } | ||||
|  | ||||
| embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time"] } | ||||
| lorawan-device = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "4bff2e0021103adfbccedcbf49dbcd0474adc4b2", default-features = false, features = ["async"] } | ||||
| lorawan-encoding = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "4bff2e0021103adfbccedcbf49dbcd0474adc4b2", default-features = false, features = ["default-crypto"] } | ||||
| embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"] } | ||||
|  | ||||
| lorawan-device = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "53d2feb43e2f3ddcdc55f0587391b0d3f02d8d93", default-features = false, features = ["async"] } | ||||
| lorawan-encoding = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "53d2feb43e2f3ddcdc55f0587391b0d3f02d8d93", default-features = false, features = ["default-crypto"] } | ||||
|  | ||||
| defmt = "0.3" | ||||
| defmt-rtt = "0.3" | ||||
|  | ||||
| cortex-m = "0.7.3" | ||||
| cortex-m-rt = "0.7.0" | ||||
| embedded-hal = "0.2.6" | ||||
| panic-probe = { version = "0.3", features = ["print-defmt"] } | ||||
| futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||||
| heapless = { version = "0.7.5", default-features = false } | ||||
| embedded-hal = "0.2.6" | ||||
|   | ||||
| @@ -12,7 +12,6 @@ mod example_common; | ||||
| use embassy_lora::{sx127x::*, LoraTimer}; | ||||
| use embassy_stm32::{ | ||||
|     dbgmcu::Dbgmcu, | ||||
|     dma::NoDma, | ||||
|     exti::ExtiInput, | ||||
|     gpio::{Input, Level, Output, Pull, Speed}, | ||||
|     rcc, | ||||
| @@ -45,8 +44,8 @@ async fn main(_spawner: embassy::executor::Spawner, mut p: Peripherals) { | ||||
|         p.PB3, | ||||
|         p.PA7, | ||||
|         p.PA6, | ||||
|         NoDma, | ||||
|         NoDma, | ||||
|         p.DMA1_CH3, | ||||
|         p.DMA1_CH2, | ||||
|         200_000.hz(), | ||||
|         spi::Config::default(), | ||||
|     ); | ||||
| @@ -58,15 +57,9 @@ async fn main(_spawner: embassy::executor::Spawner, mut p: Peripherals) { | ||||
|     let ready = Input::new(p.PB4, Pull::Up); | ||||
|     let ready_pin = ExtiInput::new(ready, p.EXTI4); | ||||
|  | ||||
|     let radio = Sx127xRadio::new( | ||||
|         spi, | ||||
|         cs, | ||||
|         reset, | ||||
|         ready_pin, | ||||
|         DummySwitch, | ||||
|         &mut embassy::time::Delay, | ||||
|     ) | ||||
|     .unwrap(); | ||||
|     let radio = Sx127xRadio::new(spi, cs, reset, ready_pin, DummySwitch) | ||||
|         .await | ||||
|         .unwrap(); | ||||
|  | ||||
|     let region = region::EU868::default().into(); | ||||
|     let mut radio_buffer = [0; 256]; | ||||
|   | ||||
| @@ -11,8 +11,8 @@ embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = | ||||
| embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32wl55jc-cm4", "time-driver-tim2", "memory-x", "subghz", "unstable-pac"]  } | ||||
| embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time"] } | ||||
|  | ||||
| lorawan-device = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "4bff2e0021103adfbccedcbf49dbcd0474adc4b2", default-features = false, features = ["async"] } | ||||
| lorawan-encoding = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "4bff2e0021103adfbccedcbf49dbcd0474adc4b2", default-features = false, features = ["default-crypto"] } | ||||
| lorawan-device = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "53d2feb43e2f3ddcdc55f0587391b0d3f02d8d93", default-features = false, features = ["async"] } | ||||
| lorawan-encoding = { git = "https://github.com/ivajloip/rust-lorawan.git", rev = "53d2feb43e2f3ddcdc55f0587391b0d3f02d8d93", default-features = false, features = ["default-crypto"] } | ||||
|  | ||||
| defmt = "0.3" | ||||
| defmt-rtt = "0.3" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user