use hard-coded SPI commands to send a LoRa packet
This commit is contained in:
83
src/main.rs
83
src/main.rs
@@ -3,7 +3,7 @@
|
||||
|
||||
use defmt::{debug, trace};
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_stm32::{Config, pac, rcc::{MSIRange, Sysclk, mux}, spi::Spi};
|
||||
use embassy_stm32::{Config, gpio::{Level, Output, Speed}, 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 _};
|
||||
@@ -57,12 +57,8 @@ impl<T: SpiBus> SpiDevice for SubGhzSpiDevice<T> {
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -77,13 +73,88 @@ async fn main(_spawner: Spawner) {
|
||||
}
|
||||
let p = embassy_stm32::init(config);
|
||||
|
||||
let mut spi = SubGhzSpiDevice(Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2));
|
||||
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!");
|
||||
|
||||
// SetDIO3AsTCXOCtrl - 1.7V, 5ms timeout
|
||||
debug!("SetDIO3AsTCXOCtrl");
|
||||
let _ = spi.write(&[0x97, 0x01, 0x00, 0x01, 0x45]).await;
|
||||
// Calibrate - all blocks (RC64k, RC13M, PLL, ADC pulse, ADC bulk N, ADC bulk P, image)
|
||||
debug!("Calibrate");
|
||||
let _ = spi.write(&[0x89, 0x7F]).await;
|
||||
// CalibrateImage - for 863-870 MHz band
|
||||
debug!("CalibrateImage");
|
||||
let _ = spi.write(&[0x98, 0xD7, 0xDB]).await;
|
||||
// SetBufferBaseAddress
|
||||
debug!("SetBufferBaseAddress");
|
||||
let _ = spi.write(&[0x8f, 0x00, 0x00]).await;
|
||||
// WriteBuffer (max 255 bytes, wraps around after that)
|
||||
debug!("WriteBuffer");
|
||||
let _ = spi.write(&[0x0e, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05]).await;
|
||||
// SetPacketType to LoRa
|
||||
debug!("LoRa SetPacketType");
|
||||
let _ = spi.write(&[0x8a, 0x01]).await;
|
||||
// SetPacketParam - 8 preamble length, explicit header, 5-byte payload,
|
||||
// CRC enabled, standard IQ setup
|
||||
debug!("SetPacketParam");
|
||||
let _ = spi.write(&[0x8c, 0x00, 0x08, 0x00, 0x05, 0x01, 0x00]).await;
|
||||
// Probably redundant, but:
|
||||
// Defining LoRa sync word (public network) with WriteRegister to SUBGHZ_LSYNCR (0x740)
|
||||
debug!("WriteRegister to SUBGHZ_LSYNCR");
|
||||
let _ = spi.write(&[0x0D, 0x07, 0x40, 0x14, 0x24]).await;
|
||||
// SetRfFrequency: rffreq = (rf_frequency * 2^25) / f_xtal
|
||||
// (868_100_000 * 33_554_432) / 32_000_000 = 910_268_825
|
||||
// hex(910_268_825) = 0x36419999
|
||||
debug!("SetRfFrequency");
|
||||
let _ = spi.write(&[0x86, 0x36, 0x41, 0x99, 0x99]).await;
|
||||
// SetPaConfig - +14dBm for SX1262
|
||||
debug!("SetPaConfig");
|
||||
let _ = spi.write(&[0x95, 0x02, 0x02, 0x00, 0x01]).await;
|
||||
// SetTxParams - +22dBm (as written in the docs), 40µs ramp time
|
||||
debug!("SetTxParams");
|
||||
let _ = spi.write(&[0x8e, 0x16, 0x02]).await;
|
||||
// SetModulationParams - sf12, 15.63kHz bandwidth, CR 4/5, ldro off
|
||||
debug!("SetModulationParams");
|
||||
let _ = spi.write(&[0x8b, 0x0c, 0x01, 0x01, 0x00]).await;
|
||||
// SetDioIrqParams - set TxDone and Timeout IRQs
|
||||
debug!("SetDioIrqParams");
|
||||
let _ = spi.write(&[0x08,
|
||||
0b00000000, 0b00000001, // IrqMask: bit 0 (TxDone)
|
||||
0b00000000, 0b00000001, // DIO1Mask: same as IrqMask
|
||||
0b00000000, 0b00000000, // DIO2Mask: none
|
||||
0b00000000, 0b00000000, // DIO3Mask: none
|
||||
]).await;
|
||||
// Enable RF switch before tx
|
||||
let _ctrl1 = Output::new(p.PC4, Level::High, Speed::High); // TX
|
||||
let _ctrl2 = Output::new(p.PC5, Level::Low, Speed::High); // RX
|
||||
let _ctrl3 = Output::new(p.PC3, Level::High, Speed::High); // EN
|
||||
// SetTx - no timeout
|
||||
debug!("SetTx - transmitting now");
|
||||
let _ = spi.write(&[0x83, 0x00, 0x00, 0x00]).await;
|
||||
// GetIrqStatus loop to poll when the command finishes
|
||||
loop {
|
||||
debug!("GetIrqStatus");
|
||||
// Send 0x12 opcode + 4 nops (extra NOP because SPI is full-duplex, response is shifted)
|
||||
let mut buf = [0x12, 0x00, 0x00, 0x00, 0x00];
|
||||
let _ = spi.transfer_in_place(&mut buf).await;
|
||||
trace!("IRQ raw: {:x}", buf);
|
||||
|
||||
// buf[0] = garbage, buf[1] = status, buf[2] = NOP, buf[3-4] = IrqStatus
|
||||
if buf[3] & 0x01 != 0 {
|
||||
debug!("GetIrqStatus - tx done");
|
||||
break;
|
||||
}
|
||||
|
||||
Timer::after_millis(1).await;
|
||||
}
|
||||
// ClearIrqStatus - all IRQs
|
||||
debug!("ClearIrqStatus");
|
||||
let _ = spi.write(&[0x02, 0xff, 0xff]).await;
|
||||
|
||||
loop {
|
||||
Timer::after(Duration::from_secs(1)).await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user