diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-09-06 00:58:42 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-09-06 00:58:42 +0200 |
| commit | eff8ae9c4d93cdd44e27af653b16b339f03f11dd (patch) | |
| tree | b7a1ffed1d911b9be88dcfd8dbe1d99764fa7637 /examples | |
| parent | 12894b3c7ad07642dd212c0ee283ac5948743257 (diff) | |
| parent | 0f3d278ce380bf5d8b29749c77cc46bb1a7da456 (diff) | |
Merge pull request #381 from lulf/stm32wl55-subghz
Add HAL for SubGhz peripheral for STM32 WL series
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/stm32wl55/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/stm32wl55/src/bin/subghz.rs | 129 |
2 files changed, 130 insertions, 1 deletions
diff --git a/examples/stm32wl55/Cargo.toml b/examples/stm32wl55/Cargo.toml index a7313e33f..1bdfe9bc9 100644 --- a/examples/stm32wl55/Cargo.toml +++ b/examples/stm32wl55/Cargo.toml | |||
| @@ -19,7 +19,7 @@ defmt-error = [] | |||
| 19 | [dependencies] | 19 | [dependencies] |
| 20 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-trace"] } | 20 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-trace"] } |
| 21 | embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } | 21 | embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } |
| 22 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32wl55jc_cm4", "time-driver-tim2", "memory-x"] } | 22 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32wl55jc_cm4", "time-driver-tim2", "memory-x", "subghz"] } |
| 23 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } | 23 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } |
| 24 | 24 | ||
| 25 | defmt = "0.2.0" | 25 | defmt = "0.2.0" |
diff --git a/examples/stm32wl55/src/bin/subghz.rs b/examples/stm32wl55/src/bin/subghz.rs new file mode 100644 index 000000000..1e406886a --- /dev/null +++ b/examples/stm32wl55/src/bin/subghz.rs | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![macro_use] | ||
| 4 | #![allow(dead_code)] | ||
| 5 | #![feature(generic_associated_types)] | ||
| 6 | #![feature(type_alias_impl_trait)] | ||
| 7 | |||
| 8 | #[path = "../example_common.rs"] | ||
| 9 | mod example_common; | ||
| 10 | |||
| 11 | use embassy::{traits::gpio::WaitForRisingEdge, util::InterruptFuture}; | ||
| 12 | use embassy_stm32::{ | ||
| 13 | dbgmcu::Dbgmcu, | ||
| 14 | dma::NoDma, | ||
| 15 | exti::ExtiInput, | ||
| 16 | gpio::{Input, Level, Output, Pull, Speed}, | ||
| 17 | interrupt, | ||
| 18 | subghz::*, | ||
| 19 | Peripherals, | ||
| 20 | }; | ||
| 21 | use embedded_hal::digital::v2::OutputPin; | ||
| 22 | use example_common::unwrap; | ||
| 23 | |||
| 24 | const PING_DATA: &str = "PING"; | ||
| 25 | const DATA_LEN: u8 = PING_DATA.len() as u8; | ||
| 26 | const PING_DATA_BYTES: &[u8] = PING_DATA.as_bytes(); | ||
| 27 | const PREAMBLE_LEN: u16 = 5 * 8; | ||
| 28 | |||
| 29 | const RF_FREQ: RfFreq = RfFreq::from_frequency(867_500_000); | ||
| 30 | |||
| 31 | const SYNC_WORD: [u8; 8] = [0x79, 0x80, 0x0C, 0xC0, 0x29, 0x95, 0xF8, 0x4A]; | ||
| 32 | const SYNC_WORD_LEN: u8 = SYNC_WORD.len() as u8; | ||
| 33 | const SYNC_WORD_LEN_BITS: u8 = SYNC_WORD_LEN * 8; | ||
| 34 | |||
| 35 | const TX_BUF_OFFSET: u8 = 128; | ||
| 36 | const RX_BUF_OFFSET: u8 = 0; | ||
| 37 | const LORA_PACKET_PARAMS: LoRaPacketParams = LoRaPacketParams::new() | ||
| 38 | .set_crc_en(true) | ||
| 39 | .set_preamble_len(PREAMBLE_LEN) | ||
| 40 | .set_payload_len(DATA_LEN) | ||
| 41 | .set_invert_iq(false) | ||
| 42 | .set_header_type(HeaderType::Fixed); | ||
| 43 | |||
| 44 | const LORA_MOD_PARAMS: LoRaModParams = LoRaModParams::new() | ||
| 45 | .set_bw(LoRaBandwidth::Bw125) | ||
| 46 | .set_cr(CodingRate::Cr45) | ||
| 47 | .set_ldro_en(true) | ||
| 48 | .set_sf(SpreadingFactor::Sf7); | ||
| 49 | |||
| 50 | // configuration for +10 dBm output power | ||
| 51 | // see table 35 "PA optimal setting and operating modes" | ||
| 52 | const PA_CONFIG: PaConfig = PaConfig::new() | ||
| 53 | .set_pa_duty_cycle(0x1) | ||
| 54 | .set_hp_max(0x0) | ||
| 55 | .set_pa(PaSel::Lp); | ||
| 56 | |||
| 57 | const TCXO_MODE: TcxoMode = TcxoMode::new() | ||
| 58 | .set_txco_trim(TcxoTrim::Volts1pt7) | ||
| 59 | .set_timeout(Timeout::from_duration_sat( | ||
| 60 | core::time::Duration::from_millis(10), | ||
| 61 | )); | ||
| 62 | |||
| 63 | const TX_PARAMS: TxParams = TxParams::new() | ||
| 64 | .set_power(0x0D) | ||
| 65 | .set_ramp_time(RampTime::Micros40); | ||
| 66 | |||
| 67 | fn config() -> embassy_stm32::Config { | ||
| 68 | let mut config = embassy_stm32::Config::default(); | ||
| 69 | config.rcc = config.rcc.clock_src(embassy_stm32::rcc::ClockSrc::HSE32); | ||
| 70 | config | ||
| 71 | } | ||
| 72 | |||
| 73 | #[embassy::main(config = "config()")] | ||
| 74 | async fn main(_spawner: embassy::executor::Spawner, p: Peripherals) { | ||
| 75 | unsafe { | ||
| 76 | Dbgmcu::enable_all(); | ||
| 77 | } | ||
| 78 | |||
| 79 | let mut led1 = Output::new(p.PB15, Level::High, Speed::Low); | ||
| 80 | let mut led2 = Output::new(p.PB9, Level::Low, Speed::Low); | ||
| 81 | let mut led3 = Output::new(p.PB11, Level::Low, Speed::Low); | ||
| 82 | |||
| 83 | let button = Input::new(p.PA0, Pull::Up); | ||
| 84 | let mut pin = ExtiInput::new(button, p.EXTI0); | ||
| 85 | |||
| 86 | let mut radio_irq = interrupt::take!(SUBGHZ_RADIO); | ||
| 87 | let mut radio = SubGhz::new(p.SUBGHZSPI, p.PA5, p.PA7, p.PA6, NoDma, NoDma); | ||
| 88 | |||
| 89 | defmt::info!("Radio ready for use"); | ||
| 90 | |||
| 91 | unwrap!(led1.set_low()); | ||
| 92 | |||
| 93 | unwrap!(led2.set_high()); | ||
| 94 | |||
| 95 | unwrap!(radio.set_standby(StandbyClk::Rc)); | ||
| 96 | unwrap!(radio.set_tcxo_mode(&TCXO_MODE)); | ||
| 97 | unwrap!(radio.set_standby(StandbyClk::Hse)); | ||
| 98 | unwrap!(radio.set_regulator_mode(RegMode::Ldo)); | ||
| 99 | unwrap!(radio.set_buffer_base_address(TX_BUF_OFFSET, RX_BUF_OFFSET)); | ||
| 100 | unwrap!(radio.set_pa_config(&PA_CONFIG)); | ||
| 101 | unwrap!(radio.set_pa_ocp(Ocp::Max60m)); | ||
| 102 | unwrap!(radio.set_tx_params(&TX_PARAMS)); | ||
| 103 | unwrap!(radio.set_packet_type(PacketType::LoRa)); | ||
| 104 | unwrap!(radio.set_lora_sync_word(LoRaSyncWord::Public)); | ||
| 105 | unwrap!(radio.set_lora_mod_params(&LORA_MOD_PARAMS)); | ||
| 106 | unwrap!(radio.set_lora_packet_params(&LORA_PACKET_PARAMS)); | ||
| 107 | unwrap!(radio.calibrate_image(CalibrateImage::ISM_863_870)); | ||
| 108 | unwrap!(radio.set_rf_frequency(&RF_FREQ)); | ||
| 109 | |||
| 110 | defmt::info!("Status: {:?}", unwrap!(radio.status())); | ||
| 111 | |||
| 112 | unwrap!(led2.set_low()); | ||
| 113 | |||
| 114 | loop { | ||
| 115 | pin.wait_for_rising_edge().await; | ||
| 116 | unwrap!(led3.set_high()); | ||
| 117 | unwrap!(radio.set_irq_cfg(&CfgIrq::new().irq_enable_all(Irq::TxDone))); | ||
| 118 | unwrap!(radio.write_buffer(TX_BUF_OFFSET, PING_DATA_BYTES)); | ||
| 119 | unwrap!(radio.set_tx(Timeout::DISABLED)); | ||
| 120 | |||
| 121 | InterruptFuture::new(&mut radio_irq).await; | ||
| 122 | let (_, irq_status) = unwrap!(radio.irq_status()); | ||
| 123 | if irq_status & Irq::TxDone.mask() != 0 { | ||
| 124 | defmt::info!("TX done"); | ||
| 125 | } | ||
| 126 | unwrap!(radio.clear_irq_status(irq_status)); | ||
| 127 | unwrap!(led3.set_low()); | ||
| 128 | } | ||
| 129 | } | ||
