aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorceekdee <[email protected]>2023-04-21 01:20:46 -0500
committerceekdee <[email protected]>2023-04-21 01:20:46 -0500
commit02c86bca5275328a15376176ff44487ab7655866 (patch)
tree4f4c3c76261e95e389219b7732cfe6da5777de98 /examples
parentfb27594b2eb2cca2aea25dd92a7b730c185b6ecc (diff)
Add external LoRa physical layer functionality.
Diffstat (limited to 'examples')
-rw-r--r--examples/nrf52840/Cargo.toml10
-rw-r--r--examples/nrf52840/src/bin/lora_cad.rs92
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs124
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_report.rs81
-rw-r--r--examples/rp/Cargo.toml6
-rw-r--r--examples/stm32l0/Cargo.toml10
-rw-r--r--examples/stm32l0/src/bin/lora_p2p_receive.rs120
-rw-r--r--examples/stm32wl/Cargo.toml13
-rw-r--r--examples/stm32wl/src/bin/lora_lorawan.rs88
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_send.rs103
10 files changed, 549 insertions, 98 deletions
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index 10c269a76..7a1fe281a 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -13,15 +13,15 @@ nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/night
13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
14embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 14embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
15embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 15embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
16embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 16embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] }
17embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } 17embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] }
18embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true } 18embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"], optional = true }
19embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true } 19embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt", "msos-descriptor",], optional = true }
20embedded-io = "0.4.0" 20embedded-io = "0.4.0"
21embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true } 21embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt", "external-lora-phy"], optional = true }
22 22lora-phy = { version = "1", path = "../../../lora-phy" }
23lorawan-device = { version = "0.9.0", default-features = false, features = ["async"], optional = true } 23lorawan-device = { version = "0.9.0", path = "../../../rust-lorawan/device", default-features = false, features = ["async", "external-lora-phy"], optional = true }
24lorawan = { version = "0.7.2", default-features = false, features = ["default-crypto"], optional = true } 24lorawan = { version = "0.7.2", path = "../../../rust-lorawan/encoding", default-features = false, features = ["default-crypto"], optional = true }
25 25
26defmt = "0.3" 26defmt = "0.3"
27defmt-rtt = "0.4" 27defmt-rtt = "0.4"
diff --git a/examples/nrf52840/src/bin/lora_cad.rs b/examples/nrf52840/src/bin/lora_cad.rs
new file mode 100644
index 000000000..8899c1b23
--- /dev/null
+++ b/examples/nrf52840/src/bin/lora_cad.rs
@@ -0,0 +1,92 @@
1//! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio.
2//! Other nrf/sx126x combinations may work with appropriate pin modifications.
3//! It demonstates LORA CAD functionality.
4#![no_std]
5#![no_main]
6#![macro_use]
7#![feature(type_alias_impl_trait)]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_lora::iv::GenericSx126xInterfaceVariant;
12use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
13use embassy_nrf::{bind_interrupts, peripherals, spim};
14use embassy_time::{Delay, Duration, Timer};
15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa;
18use {defmt_rtt as _, panic_probe as _};
19
20bind_interrupts!(struct Irqs {
21 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
22});
23
24#[embassy_executor::main]
25async fn main(_spawner: Spawner) {
26 let p = embassy_nrf::init(Default::default());
27 let mut spi_config = spim::Config::default();
28 spi_config.frequency = spim::Frequency::M16;
29
30 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
31
32 let nss = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
33 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
34 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
35 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
36 let rf_switch_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
37 let rf_switch_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
38
39 let iv =
40 GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, Some(rf_switch_rx), Some(rf_switch_tx)).unwrap();
41
42 let mut delay = Delay;
43
44 let mut lora = {
45 match LoRa::new(SX1261_2::new(BoardType::Rak4631Sx1262, spim, iv), false, &mut delay).await {
46 Ok(l) => l,
47 Err(err) => {
48 info!("Radio error = {}", err);
49 return;
50 }
51 }
52 };
53
54 let mut debug_indicator = Output::new(p.P1_03, Level::Low, OutputDrive::Standard);
55 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
56
57 start_indicator.set_high();
58 Timer::after(Duration::from_secs(5)).await;
59 start_indicator.set_low();
60
61 let mdltn_params = {
62 match lora.create_modulation_params(SpreadingFactor::_10, Bandwidth::_250KHz, CodingRate::_4_8, 903900000) {
63 Ok(mp) => mp,
64 Err(err) => {
65 info!("Radio error = {}", err);
66 return;
67 }
68 }
69 };
70
71 match lora.prepare_for_cad(&mdltn_params, true).await {
72 Ok(()) => {}
73 Err(err) => {
74 info!("Radio error = {}", err);
75 return;
76 }
77 };
78
79 match lora.cad().await {
80 Ok(cad_activity_detected) => {
81 if cad_activity_detected {
82 info!("cad successful with activity detected")
83 } else {
84 info!("cad successful without activity detected")
85 }
86 debug_indicator.set_high();
87 Timer::after(Duration::from_secs(15)).await;
88 debug_indicator.set_low();
89 }
90 Err(err) => info!("cad unsuccessful = {}", err),
91 }
92}
diff --git a/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs b/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
new file mode 100644
index 000000000..d84701742
--- /dev/null
+++ b/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
@@ -0,0 +1,124 @@
1//! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio.
2//! Other nrf/sx126x combinations may work with appropriate pin modifications.
3//! It demonstates LoRa Rx duty cycle functionality.
4#![no_std]
5#![no_main]
6#![macro_use]
7#![feature(type_alias_impl_trait)]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_lora::iv::GenericSx126xInterfaceVariant;
12use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
13use embassy_nrf::{bind_interrupts, peripherals, spim};
14use embassy_time::{Delay, Duration, Timer};
15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa;
18use {defmt_rtt as _, panic_probe as _};
19
20bind_interrupts!(struct Irqs {
21 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
22});
23
24#[embassy_executor::main]
25async fn main(_spawner: Spawner) {
26 let p = embassy_nrf::init(Default::default());
27 let mut spi_config = spim::Config::default();
28 spi_config.frequency = spim::Frequency::M16;
29
30 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
31
32 let nss = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
33 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
34 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
35 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
36 let rf_switch_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
37 let rf_switch_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
38
39 let iv =
40 GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, Some(rf_switch_rx), Some(rf_switch_tx)).unwrap();
41
42 let mut delay = Delay;
43
44 let mut lora = {
45 match LoRa::new(SX1261_2::new(BoardType::Rak4631Sx1262, spim, iv), false, &mut delay).await {
46 Ok(l) => l,
47 Err(err) => {
48 info!("Radio error = {}", err);
49 return;
50 }
51 }
52 };
53
54 let mut debug_indicator = Output::new(p.P1_03, Level::Low, OutputDrive::Standard);
55 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
56
57 start_indicator.set_high();
58 Timer::after(Duration::from_secs(5)).await;
59 start_indicator.set_low();
60
61 let mut receiving_buffer = [00u8; 100];
62
63 let mdltn_params = {
64 match lora.create_modulation_params(SpreadingFactor::_10, Bandwidth::_250KHz, CodingRate::_4_8, 903900000) {
65 Ok(mp) => mp,
66 Err(err) => {
67 info!("Radio error = {}", err);
68 return;
69 }
70 }
71 };
72
73 let rx_pkt_params = {
74 match lora.create_rx_packet_params(4, false, receiving_buffer.len() as u8, true, false, &mdltn_params) {
75 Ok(pp) => pp,
76 Err(err) => {
77 info!("Radio error = {}", err);
78 return;
79 }
80 }
81 };
82
83 // See "RM0453 Reference manual STM32WL5x advanced Arm®-based 32-bit MCUs with sub-GHz radio solution" for the best explanation of Rx duty cycle processing.
84 match lora
85 .prepare_for_rx(
86 &mdltn_params,
87 &rx_pkt_params,
88 Some(&DutyCycleParams {
89 rx_time: 300_000, // 300_000 units * 15.625 us/unit = 4.69 s
90 sleep_time: 200_000, // 200_000 units * 15.625 us/unit = 3.13 s
91 }),
92 false,
93 false,
94 0,
95 0,
96 )
97 .await
98 {
99 Ok(()) => {}
100 Err(err) => {
101 info!("Radio error = {}", err);
102 return;
103 }
104 };
105
106 receiving_buffer = [00u8; 100];
107 match lora.rx(&rx_pkt_params, &mut receiving_buffer).await {
108 Ok((received_len, _rx_pkt_status)) => {
109 if (received_len == 3)
110 && (receiving_buffer[0] == 0x01u8)
111 && (receiving_buffer[1] == 0x02u8)
112 && (receiving_buffer[2] == 0x03u8)
113 {
114 info!("rx successful");
115 debug_indicator.set_high();
116 Timer::after(Duration::from_secs(5)).await;
117 debug_indicator.set_low();
118 } else {
119 info!("rx unknown packet")
120 }
121 }
122 Err(err) => info!("rx unsuccessful = {}", err),
123 }
124}
diff --git a/examples/nrf52840/src/bin/lora_p2p_report.rs b/examples/nrf52840/src/bin/lora_p2p_report.rs
deleted file mode 100644
index e24f0db03..000000000
--- a/examples/nrf52840/src/bin/lora_p2p_report.rs
+++ /dev/null
@@ -1,81 +0,0 @@
1//! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio.
2//! Other nrf/sx126x combinations may work with appropriate pin modifications.
3//! It demonstates LORA P2P functionality in conjunction with example lora_p2p_sense.rs.
4#![no_std]
5#![no_main]
6#![macro_use]
7#![allow(dead_code)]
8#![feature(type_alias_impl_trait)]
9
10use defmt::*;
11use embassy_executor::Spawner;
12use embassy_lora::sx126x::*;
13use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
14use embassy_nrf::{bind_interrupts, peripherals, spim};
15use embassy_time::{Duration, Timer};
16use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor};
17use {defmt_rtt as _, panic_probe as _};
18
19bind_interrupts!(struct Irqs {
20 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
21});
22
23#[embassy_executor::main]
24async fn main(_spawner: Spawner) {
25 let p = embassy_nrf::init(Default::default());
26 let mut spi_config = spim::Config::default();
27 spi_config.frequency = spim::Frequency::M16;
28
29 let mut radio = {
30 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
31
32 let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
33 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
34 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
35 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
36 let antenna_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
37 let antenna_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
38
39 match Sx126xRadio::new(spim, cs, reset, antenna_rx, antenna_tx, dio1, busy, false).await {
40 Ok(r) => r,
41 Err(err) => {
42 info!("Sx126xRadio error = {}", err);
43 return;
44 }
45 }
46 };
47
48 let mut debug_indicator = Output::new(p.P1_03, Level::Low, OutputDrive::Standard);
49 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
50
51 start_indicator.set_high();
52 Timer::after(Duration::from_secs(5)).await;
53 start_indicator.set_low();
54
55 loop {
56 let rf_config = RfConfig {
57 frequency: 903900000, // channel in Hz
58 bandwidth: Bandwidth::_250KHz,
59 spreading_factor: SpreadingFactor::_10,
60 coding_rate: CodingRate::_4_8,
61 };
62
63 let mut buffer = [00u8; 100];
64
65 // P2P receive
66 match radio.rx(rf_config, &mut buffer).await {
67 Ok((buffer_len, rx_quality)) => info!(
68 "RX received = {:?} with length = {} rssi = {} snr = {}",
69 &buffer[0..buffer_len],
70 buffer_len,
71 rx_quality.rssi(),
72 rx_quality.snr()
73 ),
74 Err(err) => info!("RX error = {}", err),
75 }
76
77 debug_indicator.set_high();
78 Timer::after(Duration::from_secs(2)).await;
79 debug_indicator.set_low();
80 }
81}
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index 8067f7ba5..1787e4f8a 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -9,12 +9,16 @@ license = "MIT OR Apache-2.0"
9embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] } 9embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal", features = ["defmt"] }
10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 10embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
11embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 11embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
12embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "pio", "critical-section-impl"] } 13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "pio", "critical-section-impl"] }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
15embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } 15embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
17embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" } 17embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" }
18embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt", "external-lora-phy"] }
19lora-phy = { version = "1", path = "../../../lora-phy" }
20lorawan-device = { version = "0.9.0", path = "../../../rust-lorawan/device", default-features = false, features = ["async", "external-lora-phy"] }
21lorawan = { version = "0.7.2", path = "../../../rust-lorawan/encoding", default-features = false, features = ["default-crypto"] }
18 22
19defmt = "0.3" 23defmt = "0.3"
20defmt-rtt = "0.4" 24defmt-rtt = "0.4"
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index d08e2b61a..7e9827a84 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -11,12 +11,12 @@ nightly = ["embassy-stm32/nightly", "embassy-lora", "lorawan-device", "lorawan",
11[dependencies] 11[dependencies]
12embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
13embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 13embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
14embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 14embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
15embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] } 15embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32l072cz", "time-driver-any", "exti", "unstable-traits", "memory-x"] }
16embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt"], optional = true} 16embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx127x", "time", "defmt", "external-lora-phy"], optional = true }
17 17lora-phy = { version = "1", path = "../../../lora-phy" }
18lorawan-device = { version = "0.9.0", default-features = false, features = ["async"], optional = true } 18lorawan-device = { version = "0.9.0", path = "../../../rust-lorawan/device", default-features = false, features = ["async", "external-lora-phy"], optional = true }
19lorawan = { version = "0.7.2", default-features = false, features = ["default-crypto"], optional = true } 19lorawan = { version = "0.7.2", path = "../../../rust-lorawan/encoding", default-features = false, features = ["default-crypto"], optional = true }
20 20
21defmt = "0.3" 21defmt = "0.3"
22defmt-rtt = "0.4" 22defmt-rtt = "0.4"
diff --git a/examples/stm32l0/src/bin/lora_p2p_receive.rs b/examples/stm32l0/src/bin/lora_p2p_receive.rs
new file mode 100644
index 000000000..a5c5f75ea
--- /dev/null
+++ b/examples/stm32l0/src/bin/lora_p2p_receive.rs
@@ -0,0 +1,120 @@
1//! This example runs on the STM32 LoRa Discovery board, which has a builtin Semtech Sx1276 radio.
2//! It demonstrates LORA P2P receive functionality.
3#![no_std]
4#![no_main]
5#![macro_use]
6#![feature(type_alias_impl_trait)]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_lora::iv::Stm32l0InterfaceVariant;
11use embassy_stm32::exti::{Channel, ExtiInput};
12use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed};
13use embassy_stm32::spi;
14use embassy_stm32::time::khz;
15use embassy_time::{Delay, Duration, Timer};
16use lora_phy::mod_params::*;
17use lora_phy::sx1276_7_8_9::SX1276_7_8_9;
18use lora_phy::LoRa;
19use {defmt_rtt as _, panic_probe as _};
20
21#[embassy_executor::main]
22async fn main(_spawner: Spawner) {
23 let mut config = embassy_stm32::Config::default();
24 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
25 config.rcc.enable_hsi48 = true;
26 let p = embassy_stm32::init(config);
27
28 // SPI for sx1276
29 let spi = spi::Spi::new(
30 p.SPI1,
31 p.PB3,
32 p.PA7,
33 p.PA6,
34 p.DMA1_CH3,
35 p.DMA1_CH2,
36 khz(200),
37 spi::Config::default(),
38 );
39
40 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low);
41 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low);
42
43 let irq_pin = Input::new(p.PB4.degrade(), Pull::Up);
44 let irq = ExtiInput::new(irq_pin, p.EXTI4.degrade());
45
46 let iv = Stm32l0InterfaceVariant::new(nss, reset, irq, None, None).unwrap();
47
48 let mut delay = Delay;
49
50 let mut lora = {
51 match LoRa::new(SX1276_7_8_9::new(BoardType::Stm32l0Sx1276, spi, iv), false, &mut delay).await {
52 Ok(l) => l,
53 Err(err) => {
54 info!("Radio error = {}", err);
55 return;
56 }
57 }
58 };
59
60 let mut debug_indicator = Output::new(p.PB5, Level::Low, Speed::Low);
61 let mut start_indicator = Output::new(p.PB6, Level::Low, Speed::Low);
62
63 start_indicator.set_high();
64 Timer::after(Duration::from_secs(5)).await;
65 start_indicator.set_low();
66
67 let mut receiving_buffer = [00u8; 100];
68
69 let mdltn_params = {
70 match lora.create_modulation_params(SpreadingFactor::_10, Bandwidth::_250KHz, CodingRate::_4_8, 903900000) {
71 Ok(mp) => mp,
72 Err(err) => {
73 info!("Radio error = {}", err);
74 return;
75 }
76 }
77 };
78
79 let rx_pkt_params = {
80 match lora.create_rx_packet_params(4, false, receiving_buffer.len() as u8, true, false, &mdltn_params) {
81 Ok(pp) => pp,
82 Err(err) => {
83 info!("Radio error = {}", err);
84 return;
85 }
86 }
87 };
88
89 match lora
90 .prepare_for_rx(&mdltn_params, &rx_pkt_params, None, true, false, 0, 0x00ffffffu32)
91 .await
92 {
93 Ok(()) => {}
94 Err(err) => {
95 info!("Radio error = {}", err);
96 return;
97 }
98 };
99
100 loop {
101 receiving_buffer = [00u8; 100];
102 match lora.rx(&rx_pkt_params, &mut receiving_buffer).await {
103 Ok((received_len, _rx_pkt_status)) => {
104 if (received_len == 3)
105 && (receiving_buffer[0] == 0x01u8)
106 && (receiving_buffer[1] == 0x02u8)
107 && (receiving_buffer[2] == 0x03u8)
108 {
109 info!("rx successful");
110 debug_indicator.set_high();
111 Timer::after(Duration::from_secs(5)).await;
112 debug_indicator.set_low();
113 } else {
114 info!("rx unknown packet");
115 }
116 }
117 Err(err) => info!("rx unsuccessful = {}", err),
118 }
119 }
120}
diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml
index 07f136b40..80c7bccd4 100644
--- a/examples/stm32wl/Cargo.toml
+++ b/examples/stm32wl/Cargo.toml
@@ -7,12 +7,13 @@ license = "MIT OR Apache-2.0"
7[dependencies] 7[dependencies]
8embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } 8embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] }
9embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } 9embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 10embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"] } 11embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "unstable-traits", "defmt", "stm32wl55jc-cm4", "time-driver-any", "memory-x", "unstable-pac", "exti"] }
12embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt"] } 12embassy-embedded-hal = {version = "0.1.0", path = "../../embassy-embedded-hal" }
13 13embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["stm32wl", "time", "defmt", "external-lora-phy"] }
14lorawan-device = { version = "0.9.0", default-features = false, features = ["async"] } 14lora-phy = { version = "1", path = "../../../lora-phy" }
15lorawan = { version = "0.7.2", default-features = false, features = ["default-crypto"] } 15lorawan-device = { version = "0.9.0", path = "../../../rust-lorawan/device", default-features = false, features = ["async", "external-lora-phy"] }
16lorawan = { version = "0.7.2", path = "../../../rust-lorawan/encoding", default-features = false, features = ["default-crypto"] }
16 17
17defmt = "0.3" 18defmt = "0.3"
18defmt-rtt = "0.4" 19defmt-rtt = "0.4"
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
new file mode 100644
index 000000000..f7cf03595
--- /dev/null
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -0,0 +1,88 @@
1//! This example runs on a STM32WL board, which has a builtin Semtech Sx1262 radio.
2//! It demonstrates LoRaWAN functionality.
3#![no_std]
4#![no_main]
5#![macro_use]
6#![feature(type_alias_impl_trait, async_fn_in_trait)]
7#![allow(incomplete_features)]
8
9use defmt::info;
10use embassy_embedded_hal::adapter::BlockingAsync;
11use embassy_executor::Spawner;
12use embassy_lora::iv::Stm32wlInterfaceVariant;
13use embassy_lora::LoraTimer;
14use embassy_stm32::dma::NoDma;
15use embassy_stm32::gpio::{Level, Output, Pin, Speed};
16use embassy_stm32::peripherals::SUBGHZSPI;
17use embassy_stm32::rcc::low_level::RccPeripheral;
18use embassy_stm32::rng::Rng;
19use embassy_stm32::spi::{BitOrder, Config as SpiConfig, Spi, MODE_0};
20use embassy_stm32::time::Hertz;
21use embassy_stm32::{interrupt, into_ref, pac, Peripheral};
22use embassy_time::Delay;
23use lora_phy::mod_params::*;
24use lora_phy::sx1261_2::SX1261_2;
25use lora_phy::LoRa;
26use lorawan::default_crypto::DefaultFactory as Crypto;
27use lorawan_device::async_device::lora_radio::LoRaRadio;
28use lorawan_device::async_device::{region, Device, JoinMode};
29use {defmt_rtt as _, panic_probe as _};
30
31#[embassy_executor::main]
32async fn main(_spawner: Spawner) {
33 let mut config = embassy_stm32::Config::default();
34 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
35 config.rcc.enable_lsi = true;
36 let p = embassy_stm32::init(config);
37
38 unsafe { pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)) }
39
40 let clk = Hertz(core::cmp::min(SUBGHZSPI::frequency().0 / 2, 16_000_000));
41 let mut spi_config = SpiConfig::default();
42 spi_config.mode = MODE_0;
43 spi_config.bit_order = BitOrder::MsbFirst;
44 let spi = Spi::new_subghz(p.SUBGHZSPI, NoDma, NoDma, clk, spi_config);
45
46 let spi = BlockingAsync::new(spi);
47
48 let irq = interrupt::take!(SUBGHZ_RADIO);
49 into_ref!(irq);
50 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx
51 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High);
52 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High);
53 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High);
54 let iv = Stm32wlInterfaceVariant::new(irq, None, Some(ctrl2)).unwrap();
55
56 let mut delay = Delay;
57
58 let lora = {
59 match LoRa::new(SX1261_2::new(BoardType::Stm32wlSx1262, spi, iv), true, &mut delay).await {
60 Ok(l) => l,
61 Err(err) => {
62 info!("Radio error = {}", err);
63 return;
64 }
65 }
66 };
67 let radio = LoRaRadio::new(lora);
68 let region: region::Configuration = region::Configuration::new(region::Region::EU868);
69 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG));
70
71 defmt::info!("Joining LoRaWAN network");
72
73 // TODO: Adjust the EUI and Keys according to your network credentials
74 match device
75 .join(&JoinMode::OTAA {
76 deveui: [0, 0, 0, 0, 0, 0, 0, 0],
77 appeui: [0, 0, 0, 0, 0, 0, 0, 0],
78 appkey: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
79 })
80 .await
81 {
82 Ok(()) => defmt::info!("LoRaWAN network joined"),
83 Err(err) => {
84 info!("Radio error = {}", err);
85 return;
86 }
87 };
88}
diff --git a/examples/stm32wl/src/bin/lora_p2p_send.rs b/examples/stm32wl/src/bin/lora_p2p_send.rs
new file mode 100644
index 000000000..11c35a8fe
--- /dev/null
+++ b/examples/stm32wl/src/bin/lora_p2p_send.rs
@@ -0,0 +1,103 @@
1//! This example runs on a STM32WL board, which has a builtin Semtech Sx1262 radio.
2//! It demonstrates LORA P2P send functionality.
3#![no_std]
4#![no_main]
5#![macro_use]
6#![feature(type_alias_impl_trait, async_fn_in_trait)]
7#![allow(incomplete_features)]
8
9use defmt::info;
10use embassy_embedded_hal::adapter::BlockingAsync;
11use embassy_executor::Spawner;
12use embassy_lora::iv::Stm32wlInterfaceVariant;
13use embassy_stm32::dma::NoDma;
14use embassy_stm32::gpio::{Level, Output, Pin, Speed};
15use embassy_stm32::peripherals::SUBGHZSPI;
16use embassy_stm32::rcc::low_level::RccPeripheral;
17use embassy_stm32::spi::{BitOrder, Config as SpiConfig, Spi, MODE_0};
18use embassy_stm32::time::Hertz;
19use embassy_stm32::{interrupt, into_ref, Peripheral};
20use embassy_time::Delay;
21use lora_phy::mod_params::*;
22use lora_phy::sx1261_2::SX1261_2;
23use lora_phy::LoRa;
24use {defmt_rtt as _, panic_probe as _};
25
26#[embassy_executor::main]
27async fn main(_spawner: Spawner) {
28 let mut config = embassy_stm32::Config::default();
29 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32;
30 let p = embassy_stm32::init(config);
31
32 let clk = Hertz(core::cmp::min(SUBGHZSPI::frequency().0 / 2, 16_000_000));
33 let mut spi_config = SpiConfig::default();
34 spi_config.mode = MODE_0;
35 spi_config.bit_order = BitOrder::MsbFirst;
36 let spi = Spi::new_subghz(p.SUBGHZSPI, NoDma, NoDma, clk, spi_config);
37
38 let spi = BlockingAsync::new(spi);
39
40 let irq = interrupt::take!(SUBGHZ_RADIO);
41 into_ref!(irq);
42 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx
43 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High);
44 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High);
45 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High);
46 let iv = Stm32wlInterfaceVariant::new(irq, None, Some(ctrl2)).unwrap();
47
48 let mut delay = Delay;
49
50 let mut lora = {
51 match LoRa::new(SX1261_2::new(BoardType::Stm32wlSx1262, spi, iv), false, &mut delay).await {
52 Ok(l) => l,
53 Err(err) => {
54 info!("Radio error = {}", err);
55 return;
56 }
57 }
58 };
59
60 let mdltn_params = {
61 match lora.create_modulation_params(SpreadingFactor::_10, Bandwidth::_250KHz, CodingRate::_4_8, 903900000) {
62 Ok(mp) => mp,
63 Err(err) => {
64 info!("Radio error = {}", err);
65 return;
66 }
67 }
68 };
69
70 let mut tx_pkt_params = {
71 match lora.create_tx_packet_params(4, false, true, false, &mdltn_params) {
72 Ok(pp) => pp,
73 Err(err) => {
74 info!("Radio error = {}", err);
75 return;
76 }
77 }
78 };
79
80 match lora.prepare_for_tx(&mdltn_params, 20, false).await {
81 Ok(()) => {}
82 Err(err) => {
83 info!("Radio error = {}", err);
84 return;
85 }
86 };
87
88 let buffer = [0x01u8, 0x02u8, 0x03u8];
89 match lora.tx(&mdltn_params, &mut tx_pkt_params, &buffer, 0xffffff).await {
90 Ok(()) => {
91 info!("TX DONE");
92 }
93 Err(err) => {
94 info!("Radio error = {}", err);
95 return;
96 }
97 };
98
99 match lora.sleep(&mut delay).await {
100 Ok(()) => info!("Sleep successful"),
101 Err(err) => info!("Sleep unsuccessful = {}", err),
102 }
103}