add a translation layer for sub-GHz SPI comms, enabling the radio works now
This commit is contained in:
@@ -5,4 +5,4 @@ runner = "probe-rs run --chip STM32WLE5JC"
|
|||||||
target = "thumbv7em-none-eabi"
|
target = "thumbv7em-none-eabi"
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
DEFMT_LOG = "debug"
|
DEFMT_LOG = "trace"
|
||||||
|
|||||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -773,6 +773,7 @@ dependencies = [
|
|||||||
"embassy-sync",
|
"embassy-sync",
|
||||||
"embassy-time",
|
"embassy-time",
|
||||||
"embedded-hal 1.0.0",
|
"embedded-hal 1.0.0",
|
||||||
|
"embedded-hal-async",
|
||||||
"embedded-storage",
|
"embedded-storage",
|
||||||
"heapless 0.9.2",
|
"heapless 0.9.2",
|
||||||
"panic-probe",
|
"panic-probe",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ defmt-rtt = "1.1.0"
|
|||||||
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
|
||||||
cortex-m-rt = "0.7.0"
|
cortex-m-rt = "0.7.0"
|
||||||
embedded-hal = "1.0.0"
|
embedded-hal = "1.0.0"
|
||||||
|
embedded-hal-async = "1.0.0"
|
||||||
embedded-storage = "0.3.1"
|
embedded-storage = "0.3.1"
|
||||||
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
|
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
|
||||||
heapless = { version = "0.9", default-features = false }
|
heapless = { version = "0.9", default-features = false }
|
||||||
|
|||||||
81
src/main.rs
81
src/main.rs
@@ -1,12 +1,71 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use defmt::*;
|
use defmt::{debug, trace};
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_stm32::{Config, gpio::{Level, Output, Speed}, rcc::{MSIRange, Sysclk, mux}};
|
use embassy_stm32::{Config, pac, rcc::{MSIRange, Sysclk, mux}, spi::Spi};
|
||||||
use embassy_time::Timer;
|
use embassy_time::{Duration, Timer};
|
||||||
|
use embedded_hal_async::spi::{ErrorType, Operation, SpiBus, SpiDevice};
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
|
/// Wrapper for the sub-GHz SPI device
|
||||||
|
struct SubGhzSpiDevice<T>(T);
|
||||||
|
|
||||||
|
impl<T: SpiBus> ErrorType for SubGhzSpiDevice<T> {
|
||||||
|
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<T: SpiBus> SpiDevice for SubGhzSpiDevice<T> {
|
||||||
|
/// 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]
|
#[embassy_executor::main]
|
||||||
async fn main(_spawner: Spawner) {
|
async fn main(_spawner: Spawner) {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
@@ -17,17 +76,15 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.enable_debug_during_sleep = true;
|
config.enable_debug_during_sleep = true;
|
||||||
}
|
}
|
||||||
let p = embassy_stm32::init(config);
|
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 {
|
loop {
|
||||||
info!("high");
|
Timer::after(Duration::from_secs(1)).await;
|
||||||
led.set_high();
|
|
||||||
Timer::after_millis(50).await;
|
|
||||||
|
|
||||||
info!("low");
|
|
||||||
led.set_low();
|
|
||||||
Timer::after_millis(50).await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user