aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2021-08-31 14:32:48 +0200
committerUlf Lilleengen <[email protected]>2021-09-02 10:39:56 +0200
commit7ad6280e6575fc400f84caa5c26eb3ba9770877f (patch)
tree4a888ee84f7c5c59a713e08e53d41fdd6a21f020 /examples
parentdb3cb02032fd6b861b2c39a0a354767cc72af1df (diff)
Add HAL for SubGhz peripheral for STM32 WL series
Based on the HAL from stm32wl, the peripheral driver has been modified to fit into embassy, using the embassy APIs, providing operation of the radio peripheral. The initial version does not offer any async APIs, but the example shows how the radio IRQ can be used to perform async TX of the radio.
Diffstat (limited to 'examples')
-rw-r--r--examples/stm32wl55/Cargo.toml2
-rw-r--r--examples/stm32wl55/src/bin/subghz.rs129
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]
20embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-trace"] } 20embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-trace"] }
21embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } 21embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] }
22embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32wl55jc_cm4", "time-driver-tim2", "memory-x"] } 22embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32wl55jc_cm4", "time-driver-tim2", "memory-x", "subghz"] }
23embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } 23embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" }
24 24
25defmt = "0.2.0" 25defmt = "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"]
9mod example_common;
10
11use embassy::{traits::gpio::WaitForRisingEdge, util::InterruptFuture};
12use 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};
21use embedded_hal::digital::v2::OutputPin;
22use example_common::unwrap;
23
24const PING_DATA: &str = "PING";
25const DATA_LEN: u8 = PING_DATA.len() as u8;
26const PING_DATA_BYTES: &[u8] = PING_DATA.as_bytes();
27const PREAMBLE_LEN: u16 = 5 * 8;
28
29const RF_FREQ: RfFreq = RfFreq::from_frequency(867_500_000);
30
31const SYNC_WORD: [u8; 8] = [0x79, 0x80, 0x0C, 0xC0, 0x29, 0x95, 0xF8, 0x4A];
32const SYNC_WORD_LEN: u8 = SYNC_WORD.len() as u8;
33const SYNC_WORD_LEN_BITS: u8 = SYNC_WORD_LEN * 8;
34
35const TX_BUF_OFFSET: u8 = 128;
36const RX_BUF_OFFSET: u8 = 0;
37const 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
44const 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"
52const PA_CONFIG: PaConfig = PaConfig::new()
53 .set_pa_duty_cycle(0x1)
54 .set_hp_max(0x0)
55 .set_pa(PaSel::Lp);
56
57const 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
63const TX_PARAMS: TxParams = TxParams::new()
64 .set_power(0x0D)
65 .set_ramp_time(RampTime::Micros40);
66
67fn 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()")]
74async 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}