From 3efbbf809545ecbea51a9f8f1fd31ab01a6bb159 Mon Sep 17 00:00:00 2001 From: Lukrecja Date: Wed, 25 Feb 2026 14:56:42 +0100 Subject: [PATCH] add a translation layer for sub-GHz SPI comms, enabling the radio works now --- .cargo/config.toml | 2 +- Cargo.lock | 1 + Cargo.toml | 1 + src/main.rs | 81 +++++++++++++++++++++++++++++++++++++++------- 4 files changed, 72 insertions(+), 13 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 2457682..9568bac 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -5,4 +5,4 @@ runner = "probe-rs run --chip STM32WLE5JC" target = "thumbv7em-none-eabi" [env] -DEFMT_LOG = "debug" +DEFMT_LOG = "trace" diff --git a/Cargo.lock b/Cargo.lock index 1959311..ec6fdd1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -773,6 +773,7 @@ dependencies = [ "embassy-sync", "embassy-time", "embedded-hal 1.0.0", + "embedded-hal-async", "embedded-storage", "heapless 0.9.2", "panic-probe", diff --git a/Cargo.toml b/Cargo.toml index 880c3ee..0ffd949 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ defmt-rtt = "1.1.0" cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } cortex-m-rt = "0.7.0" embedded-hal = "1.0.0" +embedded-hal-async = "1.0.0" embedded-storage = "0.3.1" panic-probe = { version = "1.0.0", features = ["print-defmt"] } heapless = { version = "0.9", default-features = false } diff --git a/src/main.rs b/src/main.rs index e9754fa..ddfd64b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,12 +1,71 @@ #![no_std] #![no_main] -use defmt::*; +use defmt::{debug, trace}; use embassy_executor::Spawner; -use embassy_stm32::{Config, gpio::{Level, Output, Speed}, rcc::{MSIRange, Sysclk, mux}}; -use embassy_time::Timer; +use embassy_stm32::{Config, pac, rcc::{MSIRange, Sysclk, mux}, spi::Spi}; +use embassy_time::{Duration, Timer}; +use embedded_hal_async::spi::{ErrorType, Operation, SpiBus, SpiDevice}; use {defmt_rtt as _, panic_probe as _}; +/// Wrapper for the sub-GHz SPI device +struct SubGhzSpiDevice(T); + +impl ErrorType for SubGhzSpiDevice { + type Error = T::Error; +} + +/// This works as a translation layer between normal SPI transactions and sub-GHz device SPI +/// transactions. Everything above this layer sees it like a normal SPI device! +impl SpiDevice for SubGhzSpiDevice { + /// Perform a transaction on the sub-GHz device + async fn transaction(&mut self, operations: &mut [Operation<'_, u8>]) -> Result<(), Self::Error> { + // Pull NSS low to allow SPI comms + pac::PWR.subghzspicr().modify(|w| w.set_nss(false)); + trace!("NSS low"); + for operation in operations { + match operation { + Operation::Read(buf) => { + self.0.read(buf).await?; + trace!("Read {:x}", buf); + }, + Operation::Write(buf) => { + self.0.write(buf).await?; + trace!("Wrote {:x}", buf); + }, + Operation::Transfer(read, write) => { + self.0.transfer(read, write).await?; + trace!("Read {:x} wrote {:x}", read, write); + }, + Operation::TransferInPlace(buf) => { + self.0.transfer_in_place(buf).await?; + trace!("Read+wrote {:x}", buf); + }, + Operation::DelayNs(_) => {} + } + } + // Pull NSS high + pac::PWR.subghzspicr().modify(|w| w.set_nss(true)); + trace!("NSS high"); + // Poll BUSY flag until it's done + while pac::PWR.sr2().read().rfbusys() {} + trace!("BUSY flag clear"); + Ok(()) + } +} + +async fn reset_radio() { + debug!("Resetting the radio"); + pac::RCC.csr().modify(|w| w.set_rfrst(true)); + trace!("RFRST high"); + Timer::after_millis(1).await; + pac::RCC.csr().modify(|w| w.set_rfrst(false)); + trace!("RFRST low"); + Timer::after_millis(1).await; + while pac::PWR.sr2().read().rfbusys() {} + debug!("Radio reset finished"); +} + #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); @@ -17,17 +76,15 @@ async fn main(_spawner: Spawner) { config.enable_debug_during_sleep = true; } let p = embassy_stm32::init(config); - info!("hiiiiiiii :3"); - let mut led = Output::new(p.PB5, Level::High, Speed::Low); + reset_radio().await; + + let mut spi = SubGhzSpiDevice(Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2)); + debug!("Writing SetStandby"); + let _ = spi.write(&[0x80, 0x00]).await; + debug!("Radio in standby!"); loop { - info!("high"); - led.set_high(); - Timer::after_millis(50).await; - - info!("low"); - led.set_low(); - Timer::after_millis(50).await; + Timer::after(Duration::from_secs(1)).await; } }