From 63941432e3f68a0a3f2f4e97a807bfe16f4aff2b Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Fri, 14 Apr 2023 23:01:13 +0200 Subject: [PATCH] Update to rust-lorawan with afit support --- embassy-lora/Cargo.toml | 4 +- embassy-lora/src/lib.rs | 13 ++- embassy-lora/src/stm32wl/mod.rs | 12 +-- embassy-lora/src/sx126x/mod.rs | 132 +++++++++++------------- embassy-lora/src/sx127x/mod.rs | 151 ++++++++++++---------------- examples/nrf52840/Cargo.toml | 4 +- examples/stm32l0/Cargo.toml | 4 +- examples/stm32l0/src/bin/lorawan.rs | 2 +- examples/stm32wl/Cargo.toml | 4 +- examples/stm32wl/src/bin/lorawan.rs | 2 +- 10 files changed, 142 insertions(+), 186 deletions(-) diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml index 79d5660f4..13b3acab2 100644 --- a/embassy-lora/Cargo.toml +++ b/embassy-lora/Cargo.toml @@ -38,5 +38,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 = { version = "0.8.0", default-features = false, features = ["async"] } -lorawan = { version = "0.7.1", default-features = false } +lorawan-device = { version = "0.8.0", git = "https://github.com/ivajloip/rust-lorawan.git", rev = "7d3eb40bc2412536c846cea40caff25198b6b068", default-features = false, features = ["async"] } +lorawan = { version = "0.7.1", git = "https://github.com/ivajloip/rust-lorawan.git", rev = "7d3eb40bc2412536c846cea40caff25198b6b068", default-features = false } diff --git a/embassy-lora/src/lib.rs b/embassy-lora/src/lib.rs index 3e4748430..5c919cbb6 100644 --- a/embassy-lora/src/lib.rs +++ b/embassy-lora/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] -#![feature(type_alias_impl_trait)] +#![feature(async_fn_in_trait, impl_trait_projections)] +#![allow(incomplete_features)] //! embassy-lora is a collection of async radio drivers that integrate with the lorawan-device //! crate's async LoRaWAN MAC implementation. @@ -34,13 +35,11 @@ impl lorawan_device::async_device::radio::Timer for LoraTimer { self.start = Instant::now(); } - type AtFuture<'m> = impl core::future::Future + 'm; - fn at<'m>(&'m mut self, millis: u64) -> Self::AtFuture<'m> { - Timer::at(self.start + Duration::from_millis(millis)) + async fn at(&mut self, millis: u64) { + Timer::at(self.start + Duration::from_millis(millis)).await } - type DelayFuture<'m> = impl core::future::Future + 'm; - fn delay_ms<'m>(&'m mut self, millis: u64) -> Self::DelayFuture<'m> { - Timer::after(Duration::from_millis(millis)) + async fn delay_ms(&mut self, millis: u64) { + Timer::after(Duration::from_millis(millis)).await } } diff --git a/embassy-lora/src/stm32wl/mod.rs b/embassy-lora/src/stm32wl/mod.rs index 3d52c1cc7..d76e8c43b 100644 --- a/embassy-lora/src/stm32wl/mod.rs +++ b/embassy-lora/src/stm32wl/mod.rs @@ -1,5 +1,5 @@ //! A radio driver integration for the radio found on STM32WL family devices. -use core::future::{poll_fn, Future}; +use core::future::poll_fn; use core::task::Poll; use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; @@ -241,14 +241,12 @@ fn configure_radio(radio: &mut SubGhz<'_, NoDma, NoDma>, config: SubGhzRadioConf impl<'d, RS: RadioSwitch> PhyRxTx for SubGhzRadio<'d, RS> { type PhyError = RadioError; - type TxFuture<'m> = impl Future> + 'm where Self: 'm; - fn tx<'m>(&'m mut self, config: TxConfig, buf: &'m [u8]) -> Self::TxFuture<'m> { - async move { self.do_tx(config, buf).await } + async fn tx(&mut self, config: TxConfig, buf: &[u8]) -> Result { + self.do_tx(config, buf).await } - type RxFuture<'m> = impl Future> + 'm where Self: 'm; - fn rx<'m>(&'m mut self, config: RfConfig, buf: &'m mut [u8]) -> Self::RxFuture<'m> { - async move { self.do_rx(config, buf).await } + async fn rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), Self::PhyError> { + self.do_rx(config, buf).await } } diff --git a/embassy-lora/src/sx126x/mod.rs b/embassy-lora/src/sx126x/mod.rs index 8559574cb..2f0b8c8e3 100644 --- a/embassy-lora/src/sx126x/mod.rs +++ b/embassy-lora/src/sx126x/mod.rs @@ -1,5 +1,3 @@ -use core::future::Future; - use defmt::Format; use embedded_hal::digital::v2::OutputPin; use embedded_hal_async::digital::Wait; @@ -71,83 +69,69 @@ where { type PhyError = RadioError; - type TxFuture<'m> = impl Future> + 'm - where - SPI: 'm, - CTRL: 'm, - WAIT: 'm, - BUS: 'm; - - fn tx<'m>(&'m mut self, config: TxConfig, buffer: &'m [u8]) -> Self::TxFuture<'m> { + async fn tx(&mut self, config: TxConfig, buffer: &[u8]) -> Result { trace!("TX START"); - async move { - self.lora - .set_tx_config( - config.pw, - config.rf.spreading_factor.into(), - config.rf.bandwidth.into(), - config.rf.coding_rate.into(), - 8, - false, - true, - false, - 0, - false, - ) - .await?; - self.lora.set_max_payload_length(buffer.len() as u8).await?; - self.lora.set_channel(config.rf.frequency).await?; - self.lora.send(buffer, 0xffffff).await?; - self.lora.process_irq(None, None, None).await?; - trace!("TX DONE"); - return Ok(0); - } + self.lora + .set_tx_config( + config.pw, + config.rf.spreading_factor.into(), + config.rf.bandwidth.into(), + config.rf.coding_rate.into(), + 8, + false, + true, + false, + 0, + false, + ) + .await?; + self.lora.set_max_payload_length(buffer.len() as u8).await?; + self.lora.set_channel(config.rf.frequency).await?; + self.lora.send(buffer, 0xffffff).await?; + self.lora.process_irq(None, None, None).await?; + trace!("TX DONE"); + return Ok(0); } - type RxFuture<'m> = impl Future> + 'm - where - SPI: 'm, - CTRL: 'm, - WAIT: 'm, - BUS: 'm; - - fn rx<'m>(&'m mut self, config: RfConfig, receiving_buffer: &'m mut [u8]) -> Self::RxFuture<'m> { + async fn rx( + &mut self, + config: RfConfig, + receiving_buffer: &mut [u8], + ) -> Result<(usize, RxQuality), Self::PhyError> { trace!("RX START"); - async move { - self.lora - .set_rx_config( - config.spreading_factor.into(), - config.bandwidth.into(), - config.coding_rate.into(), - 8, - 4, - false, - 0u8, - true, - false, - 0, - true, - true, - ) - .await?; - self.lora.set_max_payload_length(receiving_buffer.len() as u8).await?; - self.lora.set_channel(config.frequency).await?; - self.lora.rx(90 * 1000).await?; - let mut received_len = 0u8; - self.lora - .process_irq(Some(receiving_buffer), Some(&mut received_len), None) - .await?; - trace!("RX DONE"); + self.lora + .set_rx_config( + config.spreading_factor.into(), + config.bandwidth.into(), + config.coding_rate.into(), + 8, + 4, + false, + 0u8, + true, + false, + 0, + true, + true, + ) + .await?; + self.lora.set_max_payload_length(receiving_buffer.len() as u8).await?; + self.lora.set_channel(config.frequency).await?; + self.lora.rx(90 * 1000).await?; + let mut received_len = 0u8; + self.lora + .process_irq(Some(receiving_buffer), Some(&mut received_len), None) + .await?; + trace!("RX DONE"); - let packet_status = self.lora.get_latest_packet_status(); - let mut rssi = 0i16; - let mut snr = 0i8; - if packet_status.is_some() { - rssi = packet_status.unwrap().rssi as i16; - snr = packet_status.unwrap().snr; - } - - Ok((received_len as usize, RxQuality::new(rssi, snr))) + let packet_status = self.lora.get_latest_packet_status(); + let mut rssi = 0i16; + let mut snr = 0i8; + if packet_status.is_some() { + rssi = packet_status.unwrap().rssi as i16; + snr = packet_status.unwrap().snr; } + + Ok((received_len as usize, RxQuality::new(rssi, snr))) } } diff --git a/embassy-lora/src/sx127x/mod.rs b/embassy-lora/src/sx127x/mod.rs index 8904c9a13..4e8dc2232 100644 --- a/embassy-lora/src/sx127x/mod.rs +++ b/embassy-lora/src/sx127x/mod.rs @@ -1,5 +1,3 @@ -use core::future::Future; - use embedded_hal::digital::v2::OutputPin; use embedded_hal_async::digital::Wait; use embedded_hal_async::spi::*; @@ -88,101 +86,78 @@ where { type PhyError = Sx127xError; - type TxFuture<'m> = impl Future> + 'm - where - SPI: 'm, - CS: 'm, - RESET: 'm, - E: 'm, - I: 'm, - RFS: 'm; - - fn tx<'m>(&'m mut self, config: TxConfig, buf: &'m [u8]) -> Self::TxFuture<'m> { + async fn tx(&mut self, config: TxConfig, buf: &[u8]) -> Result { 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).await?; + self.radio.set_frequency(config.rf.frequency).await?; + // TODO: Modify radio to support other coding rates + self.radio.set_coding_rate_4(5).await?; + self.radio + .set_signal_bandwidth(bandwidth_to_i64(config.rf.bandwidth)) + .await?; + self.radio + .set_spreading_factor(spreading_factor_to_u8(config.rf.spreading_factor)) + .await?; + + 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().await?; + + self.radio.transmit_start(buf).await?; + + loop { + self.irq.wait_for_rising_edge().await.unwrap(); self.radio.set_mode(RadioMode::Stdby).await.ok().unwrap(); - self.rfs.set_tx(); - 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).await?; - self.radio - .set_signal_bandwidth(bandwidth_to_i64(config.rf.bandwidth)) - .await?; - self.radio - .set_spreading_factor(spreading_factor_to_u8(config.rf.spreading_factor)) - .await?; - - 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().await?; - - self.radio.transmit_start(buf).await?; - - loop { - self.irq.wait_for_rising_edge().await.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); - } + let irq = self.radio.clear_irq().await.ok().unwrap(); + if (irq & IRQ::IrqTxDoneMask.addr()) != 0 { + trace!("TX DONE"); + return Ok(0); } } } - type RxFuture<'m> = impl Future> + 'm - where - SPI: 'm, - CS: 'm, - RESET: 'm, - E: 'm, - I: 'm, - RFS: 'm; + async fn rx(&mut self, config: RfConfig, buf: &mut [u8]) -> Result<(usize, RxQuality), Self::PhyError> { + self.rfs.set_rx(); + 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).await?; + self.radio + .set_signal_bandwidth(bandwidth_to_i64(config.bandwidth)) + .await?; + self.radio + .set_spreading_factor(spreading_factor_to_u8(config.spreading_factor)) + .await?; - fn rx<'m>(&'m mut self, config: RfConfig, buf: &'m mut [u8]) -> Self::RxFuture<'m> { - trace!("RX START"); - async move { - self.rfs.set_rx(); - 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).await?; - self.radio - .set_signal_bandwidth(bandwidth_to_i64(config.bandwidth)) - .await?; - self.radio - .set_spreading_factor(spreading_factor_to_u8(config.spreading_factor)) - .await?; + 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_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().await?; + self.radio.set_mode(RadioMode::RxContinuous).await?; - self.radio.set_dio0_rx_done().await?; - self.radio.set_mode(RadioMode::RxContinuous).await?; - - loop { - self.irq.wait_for_rising_edge().await.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().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))) - }; - trace!("RX DONE"); - return response; - } + loop { + self.irq.wait_for_rising_edge().await.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().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))) + }; + trace!("RX DONE"); + return response; } } } diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index fc614cb80..9ef7944c4 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -20,8 +20,8 @@ embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defm embedded-io = "0.4.0" embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } -lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true } -lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true } +lorawan-device = { version = "0.8.0", git = "https://github.com/ivajloip/rust-lorawan.git", rev = "7d3eb40bc2412536c846cea40caff25198b6b068", default-features = false, features = ["async"], optional = true } +lorawan = { version = "0.7.1", git = "https://github.com/ivajloip/rust-lorawan.git", rev = "7d3eb40bc2412536c846cea40caff25198b6b068", default-features = false, features = ["default-crypto"], optional = true } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index d446d41b2..9f63fee1c 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -15,8 +15,8 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true} -lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true } -lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true } +lorawan-device = { version = "0.8.0", git = "https://github.com/ivajloip/rust-lorawan.git", rev = "7d3eb40bc2412536c846cea40caff25198b6b068", default-features = false, features = ["async"], optional = true } +lorawan = { version = "0.7.1", git = "https://github.com/ivajloip/rust-lorawan.git", rev = "7d3eb40bc2412536c846cea40caff25198b6b068", default-features = false, features = ["default-crypto"], optional = true } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32l0/src/bin/lorawan.rs b/examples/stm32l0/src/bin/lorawan.rs index 27d7c29c2..ea01f610c 100644 --- a/examples/stm32l0/src/bin/lorawan.rs +++ b/examples/stm32l0/src/bin/lorawan.rs @@ -45,7 +45,7 @@ async fn main(_spawner: Spawner) { let radio = Sx127xRadio::new(spi, cs, reset, ready_pin, DummySwitch).await.unwrap(); - let region = region::EU868::default().into(); + let region = region::Configuration::new(region::Region::EU868); let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG)); defmt::info!("Joining LoRaWAN network"); diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index df295ca49..19a7cfcea 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -11,8 +11,8 @@ embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["de embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"] } embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] } -lorawan-device = { version = "0.8.0", default-features = false, features = ["async"] } -lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"] } +lorawan-device = { version = "0.8.0", git = "https://github.com/ivajloip/rust-lorawan.git", rev = "7d3eb40bc2412536c846cea40caff25198b6b068", default-features = false, features = ["async"] } +lorawan = { version = "0.7.1", git = "https://github.com/ivajloip/rust-lorawan.git", rev = "7d3eb40bc2412536c846cea40caff25198b6b068", default-features = false, features = ["default-crypto"] } defmt = "0.3" defmt-rtt = "0.4" diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs index 7f34dd306..32f29cc5d 100644 --- a/examples/stm32wl/src/bin/lorawan.rs +++ b/examples/stm32wl/src/bin/lorawan.rs @@ -63,7 +63,7 @@ async fn main(_spawner: Spawner) { radio_config.calibrate_image = CalibrateImage::ISM_863_870; let radio = SubGhzRadio::new(radio, rfs, irq, radio_config).unwrap(); - let mut region: region::Configuration = region::EU868::default().into(); + let mut region = region::Configuration::new(region::Region::EU868); // NOTE: This is specific for TTN, as they have a special RX1 delay region.set_receive_delay1(5000);