lora: Make some options configurable

Call `config()` only once at construction not with every RX and TX operation.
The Lora-E5 only supports HP mode, use that instead.
The nucleo board supports both HP and LP and should continue to work.
This commit is contained in:
Timo Kröger 2022-06-25 11:59:07 +02:00
parent 69d80c086d
commit f31116cafa
2 changed files with 40 additions and 39 deletions

View File

@ -6,9 +6,9 @@ use embassy_hal_common::{into_ref, Peripheral, PeripheralRef};
use embassy_stm32::dma::NoDma;
use embassy_stm32::interrupt::{Interrupt, InterruptExt, SUBGHZ_RADIO};
use embassy_stm32::subghz::{
CalibrateImage, CfgIrq, CodingRate, Error, HeaderType, Irq, LoRaBandwidth, LoRaModParams, LoRaPacketParams,
LoRaSyncWord, Ocp, PaConfig, PaSel, PacketType, RampTime, RegMode, RfFreq, SpreadingFactor as SF, StandbyClk,
Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams,
CalibrateImage, CfgIrq, CodingRate, Error, HeaderType, HseTrim, Irq, LoRaBandwidth, LoRaModParams,
LoRaPacketParams, LoRaSyncWord, Ocp, PaConfig, PacketType, RampTime, RegMode, RfFreq, SpreadingFactor as SF,
StandbyClk, Status, SubGhz, TcxoMode, TcxoTrim, Timeout, TxParams,
};
use embassy_sync::waitqueue::AtomicWaker;
use futures::future::poll_fn;
@ -61,46 +61,17 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> {
unsafe { SUBGHZ_RADIO::steal().disable() };
});
Self { radio, switch, irq }
}
configure_radio(&mut radio, config)?;
/// Configure radio settings in preparation for TX or RX
pub(crate) fn configure(&mut self) -> Result<(), RadioError> {
trace!("Configuring STM32WL SUBGHZ radio");
self.radio.set_standby(StandbyClk::Rc)?;
let tcxo_mode = TcxoMode::new()
.set_txco_trim(TcxoTrim::Volts1pt7)
.set_timeout(Timeout::from_duration_sat(core::time::Duration::from_millis(40)));
self.radio.set_tcxo_mode(&tcxo_mode)?;
self.radio.set_regulator_mode(RegMode::Ldo)?;
self.radio.calibrate_image(CalibrateImage::ISM_863_870)?;
self.radio.set_buffer_base_address(0, 0)?;
self.radio
.set_pa_config(&PaConfig::new().set_pa_duty_cycle(0x1).set_hp_max(0x0).set_pa(PaSel::Lp))?;
self.radio.set_pa_ocp(Ocp::Max140m)?;
// let tx_params = TxParams::LP_14.set_ramp_time(RampTime::Micros40);
self.radio
.set_tx_params(&TxParams::new().set_ramp_time(RampTime::Micros40).set_power(0x0A))?;
self.radio.set_packet_type(PacketType::LoRa)?;
self.radio.set_lora_sync_word(LoRaSyncWord::Public)?;
trace!("Done initializing STM32WL SUBGHZ radio");
Ok(())
Ok(Self { radio, switch, irq })
}
/// Perform a transmission with the given parameters and payload. Returns any time adjustements needed form
/// the upcoming RX window start.
async fn do_tx(&mut self, config: TxConfig, buf: &[u8]) -> Result<u32, RadioError> {
//trace!("TX Request: {}", config);
trace!("TX START");
trace!("TX Request: {}", config);
//trace!("TX START");
self.switch.set_tx();
self.configure()?;
self.radio
.set_rf_frequency(&RfFreq::from_frequency(config.rf.frequency))?;
@ -164,7 +135,6 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> {
trace!("RX START");
// trace!("Starting RX: {}", config);
self.switch.set_rx();
self.configure()?;
self.radio.set_rf_frequency(&RfFreq::from_frequency(config.frequency))?;
@ -180,7 +150,7 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> {
let irq_cfg = CfgIrq::new()
.irq_enable_all(Irq::RxDone)
.irq_enable_all(Irq::PreambleDetected)
//.irq_enable_all(Irq::PreambleDetected)
.irq_enable_all(Irq::HeaderErr)
.irq_enable_all(Irq::Timeout)
.irq_enable_all(Irq::Err);
@ -235,6 +205,35 @@ impl<'d, RS: RadioSwitch> SubGhzRadio<'d, RS> {
}
}
fn configure_radio(radio: &mut SubGhz<'_, NoDma, NoDma>, config: SubGhzRadioConfig) -> Result<(), RadioError> {
trace!("Configuring STM32WL SUBGHZ radio");
radio.set_regulator_mode(config.reg_mode)?;
radio.set_standby(StandbyClk::Rc)?;
let tcxo_mode = TcxoMode::new()
.set_txco_trim(TcxoTrim::Volts1pt7)
.set_timeout(Timeout::from_duration_sat(core::time::Duration::from_millis(100)));
radio.set_tcxo_mode(&tcxo_mode)?;
// Reduce input capacitance as shown in Reference Manual "Figure 23. HSE32 TCXO control".
// The STM32CUBE C driver also does this.
radio.set_hse_in_trim(HseTrim::MIN)?;
// Re-calibrate everything after setting the TXCO config.
radio.calibrate(0x7F)?;
radio.calibrate_image(config.calibrate_image)?;
radio.set_pa_config(&PaConfig::HP_14)?;
radio.set_tx_params(&TxParams::HP.set_ramp_time(RampTime::Micros40))?;
radio.set_pa_ocp(Ocp::Max140m)?;
radio.set_packet_type(PacketType::LoRa)?;
radio.set_lora_sync_word(LoRaSyncWord::Public)?;
trace!("Done initializing STM32WL SUBGHZ radio");
Ok(())
}
impl<RS: RadioSwitch> PhyRxTx for SubGhzRadio<'static, RS> {
type PhyError = RadioError;

View File

@ -60,7 +60,9 @@ async fn main(_spawner: Spawner) {
let radio = SubGhz::new(p.SUBGHZSPI, NoDma, NoDma);
let irq = interrupt::take!(SUBGHZ_RADIO);
let radio = SubGhzRadio::new(radio, rfs, irq);
let mut radio_config = SubGhzRadioConfig::default();
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();