aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorceekdee <[email protected]>2023-04-23 18:32:34 -0500
committerceekdee <[email protected]>2023-04-23 18:32:34 -0500
commit73f25093c7793ad2e8bd6fceeca46d9b5b1031ad (patch)
tree9374f5a637e1337ceb40a51426f24f3fe68249ef /examples
parenta3f727e2e1dd81fe00f19d74f7e0e590250a6970 (diff)
Add lora-phy examples.
Diffstat (limited to 'examples')
-rw-r--r--examples/nrf52840/src/bin/lora_cad.rs13
-rw-r--r--examples/nrf52840/src/bin/lora_lorawan.rs83
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_receive.rs121
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs11
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_send.rs104
-rw-r--r--examples/nrf52840/src/bin/lora_p2p_sense.rs128
-rw-r--r--examples/rp/src/bin/lora_lorawan.rs80
-rw-r--r--examples/rp/src/bin/lora_p2p_receive.rs115
-rw-r--r--examples/rp/src/bin/lora_p2p_send.rs103
-rw-r--r--examples/rp/src/bin/lora_p2p_send_multicore.rs139
-rw-r--r--examples/stm32l0/src/bin/lora_cad.rs105
-rw-r--r--examples/stm32l0/src/bin/lora_lorawan.rs88
-rw-r--r--examples/stm32l0/src/bin/lora_p2p_receive.rs11
-rw-r--r--examples/stm32l0/src/bin/lora_p2p_send.rs110
-rw-r--r--examples/stm32l0/src/bin/lorawan.rs74
-rw-r--r--examples/stm32wl/src/bin/lora_lorawan.rs6
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_receive.rs127
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_send.rs9
-rw-r--r--examples/stm32wl/src/bin/lorawan.rs104
19 files changed, 1215 insertions, 316 deletions
diff --git a/examples/nrf52840/src/bin/lora_cad.rs b/examples/nrf52840/src/bin/lora_cad.rs
index 8899c1b23..beca061ed 100644
--- a/examples/nrf52840/src/bin/lora_cad.rs
+++ b/examples/nrf52840/src/bin/lora_cad.rs
@@ -1,6 +1,6 @@
1//! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio. 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. 2//! Other nrf/sx126x combinations may work with appropriate pin modifications.
3//! It demonstates LORA CAD functionality. 3//! It demonstrates LORA CAD functionality.
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![macro_use] 6#![macro_use]
@@ -17,6 +17,8 @@ use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa; 17use lora_phy::LoRa;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
20const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
21
20bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
21 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>; 23 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
22}); 24});
@@ -59,7 +61,12 @@ async fn main(_spawner: Spawner) {
59 start_indicator.set_low(); 61 start_indicator.set_low();
60 62
61 let mdltn_params = { 63 let mdltn_params = {
62 match lora.create_modulation_params(SpreadingFactor::_10, Bandwidth::_250KHz, CodingRate::_4_8, 903900000) { 64 match lora.create_modulation_params(
65 SpreadingFactor::_10,
66 Bandwidth::_250KHz,
67 CodingRate::_4_8,
68 LORA_FREQUENCY_IN_HZ,
69 ) {
63 Ok(mp) => mp, 70 Ok(mp) => mp,
64 Err(err) => { 71 Err(err) => {
65 info!("Radio error = {}", err); 72 info!("Radio error = {}", err);
@@ -84,7 +91,7 @@ async fn main(_spawner: Spawner) {
84 info!("cad successful without activity detected") 91 info!("cad successful without activity detected")
85 } 92 }
86 debug_indicator.set_high(); 93 debug_indicator.set_high();
87 Timer::after(Duration::from_secs(15)).await; 94 Timer::after(Duration::from_secs(5)).await;
88 debug_indicator.set_low(); 95 debug_indicator.set_low();
89 } 96 }
90 Err(err) => info!("cad unsuccessful = {}", err), 97 Err(err) => info!("cad unsuccessful = {}", err),
diff --git a/examples/nrf52840/src/bin/lora_lorawan.rs b/examples/nrf52840/src/bin/lora_lorawan.rs
new file mode 100644
index 000000000..c953680c6
--- /dev/null
+++ b/examples/nrf52840/src/bin/lora_lorawan.rs
@@ -0,0 +1,83 @@
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 demonstrates LoRaWAN join 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_lora::LoraTimer;
13use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
14use embassy_nrf::rng::Rng;
15use embassy_nrf::{bind_interrupts, peripherals, rng, spim};
16use embassy_time::Delay;
17use lora_phy::mod_params::*;
18use lora_phy::sx1261_2::SX1261_2;
19use lora_phy::LoRa;
20use lorawan::default_crypto::DefaultFactory as Crypto;
21use lorawan_device::async_device::lora_radio::LoRaRadio;
22use lorawan_device::async_device::{region, Device, JoinMode};
23use {defmt_rtt as _, panic_probe as _};
24
25const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region
26
27bind_interrupts!(struct Irqs {
28 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
29 RNG => rng::InterruptHandler<peripherals::RNG>;
30});
31
32#[embassy_executor::main]
33async fn main(_spawner: Spawner) {
34 let p = embassy_nrf::init(Default::default());
35 let mut spi_config = spim::Config::default();
36 spi_config.frequency = spim::Frequency::M16;
37
38 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
39
40 let nss = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
41 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
42 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
43 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
44 let rf_switch_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
45 let rf_switch_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
46
47 let iv =
48 GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, Some(rf_switch_rx), Some(rf_switch_tx)).unwrap();
49
50 let mut delay = Delay;
51
52 let lora = {
53 match LoRa::new(SX1261_2::new(BoardType::Rak4631Sx1262, spim, iv), true, &mut delay).await {
54 Ok(l) => l,
55 Err(err) => {
56 info!("Radio error = {}", err);
57 return;
58 }
59 }
60 };
61
62 let radio = LoRaRadio::new(lora);
63 let region: region::Configuration = region::Configuration::new(LORAWAN_REGION);
64 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG, Irqs));
65
66 defmt::info!("Joining LoRaWAN network");
67
68 // TODO: Adjust the EUI and Keys according to your network credentials
69 match device
70 .join(&JoinMode::OTAA {
71 deveui: [0, 0, 0, 0, 0, 0, 0, 0],
72 appeui: [0, 0, 0, 0, 0, 0, 0, 0],
73 appkey: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
74 })
75 .await
76 {
77 Ok(()) => defmt::info!("LoRaWAN network joined"),
78 Err(err) => {
79 info!("Radio error = {}", err);
80 return;
81 }
82 };
83}
diff --git a/examples/nrf52840/src/bin/lora_p2p_receive.rs b/examples/nrf52840/src/bin/lora_p2p_receive.rs
new file mode 100644
index 000000000..563fe42ec
--- /dev/null
+++ b/examples/nrf52840/src/bin/lora_p2p_receive.rs
@@ -0,0 +1,121 @@
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 demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example.
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
20const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
21
22bind_interrupts!(struct Irqs {
23 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
24});
25
26#[embassy_executor::main]
27async fn main(_spawner: Spawner) {
28 let p = embassy_nrf::init(Default::default());
29 let mut spi_config = spim::Config::default();
30 spi_config.frequency = spim::Frequency::M16;
31
32 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
33
34 let nss = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
35 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
36 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
37 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
38 let rf_switch_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
39 let rf_switch_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
40
41 let iv =
42 GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, Some(rf_switch_rx), Some(rf_switch_tx)).unwrap();
43
44 let mut delay = Delay;
45
46 let mut lora = {
47 match LoRa::new(SX1261_2::new(BoardType::Rak4631Sx1262, spim, iv), false, &mut delay).await {
48 Ok(l) => l,
49 Err(err) => {
50 info!("Radio error = {}", err);
51 return;
52 }
53 }
54 };
55
56 let mut debug_indicator = Output::new(p.P1_03, Level::Low, OutputDrive::Standard);
57 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
58
59 start_indicator.set_high();
60 Timer::after(Duration::from_secs(5)).await;
61 start_indicator.set_low();
62
63 let mut receiving_buffer = [00u8; 100];
64
65 let mdltn_params = {
66 match lora.create_modulation_params(
67 SpreadingFactor::_10,
68 Bandwidth::_250KHz,
69 CodingRate::_4_8,
70 LORA_FREQUENCY_IN_HZ,
71 ) {
72 Ok(mp) => mp,
73 Err(err) => {
74 info!("Radio error = {}", err);
75 return;
76 }
77 }
78 };
79
80 let rx_pkt_params = {
81 match lora.create_rx_packet_params(4, false, receiving_buffer.len() as u8, true, false, &mdltn_params) {
82 Ok(pp) => pp,
83 Err(err) => {
84 info!("Radio error = {}", err);
85 return;
86 }
87 }
88 };
89
90 match lora
91 .prepare_for_rx(&mdltn_params, &rx_pkt_params, None, true, false, 0, 0x00ffffffu32)
92 .await
93 {
94 Ok(()) => {}
95 Err(err) => {
96 info!("Radio error = {}", err);
97 return;
98 }
99 };
100
101 loop {
102 receiving_buffer = [00u8; 100];
103 match lora.rx(&rx_pkt_params, &mut receiving_buffer).await {
104 Ok((received_len, _rx_pkt_status)) => {
105 if (received_len == 3)
106 && (receiving_buffer[0] == 0x01u8)
107 && (receiving_buffer[1] == 0x02u8)
108 && (receiving_buffer[2] == 0x03u8)
109 {
110 info!("rx successful");
111 debug_indicator.set_high();
112 Timer::after(Duration::from_secs(5)).await;
113 debug_indicator.set_low();
114 } else {
115 info!("rx unknown packet");
116 }
117 }
118 Err(err) => info!("rx unsuccessful = {}", err),
119 }
120 }
121}
diff --git a/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs b/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
index d84701742..1fd8f61a2 100644
--- a/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
+++ b/examples/nrf52840/src/bin/lora_p2p_receive_duty_cycle.rs
@@ -1,6 +1,6 @@
1//! This example runs on the RAK4631 WisBlock, which has an nRF52840 MCU and Semtech Sx126x radio. 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. 2//! Other nrf/sx126x combinations may work with appropriate pin modifications.
3//! It demonstates LoRa Rx duty cycle functionality. 3//! It demonstrates LoRa Rx duty cycle functionality in conjunction with the lora_p2p_send example.
4#![no_std] 4#![no_std]
5#![no_main] 5#![no_main]
6#![macro_use] 6#![macro_use]
@@ -17,6 +17,8 @@ use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa; 17use lora_phy::LoRa;
18use {defmt_rtt as _, panic_probe as _}; 18use {defmt_rtt as _, panic_probe as _};
19 19
20const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
21
20bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
21 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>; 23 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
22}); 24});
@@ -61,7 +63,12 @@ async fn main(_spawner: Spawner) {
61 let mut receiving_buffer = [00u8; 100]; 63 let mut receiving_buffer = [00u8; 100];
62 64
63 let mdltn_params = { 65 let mdltn_params = {
64 match lora.create_modulation_params(SpreadingFactor::_10, Bandwidth::_250KHz, CodingRate::_4_8, 903900000) { 66 match lora.create_modulation_params(
67 SpreadingFactor::_10,
68 Bandwidth::_250KHz,
69 CodingRate::_4_8,
70 LORA_FREQUENCY_IN_HZ,
71 ) {
65 Ok(mp) => mp, 72 Ok(mp) => mp,
66 Err(err) => { 73 Err(err) => {
67 info!("Radio error = {}", err); 74 info!("Radio error = {}", err);
diff --git a/examples/nrf52840/src/bin/lora_p2p_send.rs b/examples/nrf52840/src/bin/lora_p2p_send.rs
new file mode 100644
index 000000000..1c8bbc27a
--- /dev/null
+++ b/examples/nrf52840/src/bin/lora_p2p_send.rs
@@ -0,0 +1,104 @@
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 demonstrates LORA P2P send 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;
15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa;
18use {defmt_rtt as _, panic_probe as _};
19
20const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
21
22bind_interrupts!(struct Irqs {
23 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
24});
25
26#[embassy_executor::main]
27async fn main(_spawner: Spawner) {
28 let p = embassy_nrf::init(Default::default());
29 let mut spi_config = spim::Config::default();
30 spi_config.frequency = spim::Frequency::M16;
31
32 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
33
34 let nss = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
35 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
36 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
37 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
38 let rf_switch_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
39 let rf_switch_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
40
41 let iv =
42 GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, Some(rf_switch_rx), Some(rf_switch_tx)).unwrap();
43
44 let mut delay = Delay;
45
46 let mut lora = {
47 match LoRa::new(SX1261_2::new(BoardType::Rak4631Sx1262, spim, iv), false, &mut delay).await {
48 Ok(l) => l,
49 Err(err) => {
50 info!("Radio error = {}", err);
51 return;
52 }
53 }
54 };
55
56 let mdltn_params = {
57 match lora.create_modulation_params(
58 SpreadingFactor::_10,
59 Bandwidth::_250KHz,
60 CodingRate::_4_8,
61 LORA_FREQUENCY_IN_HZ,
62 ) {
63 Ok(mp) => mp,
64 Err(err) => {
65 info!("Radio error = {}", err);
66 return;
67 }
68 }
69 };
70
71 let mut tx_pkt_params = {
72 match lora.create_tx_packet_params(4, false, true, false, &mdltn_params) {
73 Ok(pp) => pp,
74 Err(err) => {
75 info!("Radio error = {}", err);
76 return;
77 }
78 }
79 };
80
81 match lora.prepare_for_tx(&mdltn_params, 20, false).await {
82 Ok(()) => {}
83 Err(err) => {
84 info!("Radio error = {}", err);
85 return;
86 }
87 };
88
89 let buffer = [0x01u8, 0x02u8, 0x03u8];
90 match lora.tx(&mdltn_params, &mut tx_pkt_params, &buffer, 0xffffff).await {
91 Ok(()) => {
92 info!("TX DONE");
93 }
94 Err(err) => {
95 info!("Radio error = {}", err);
96 return;
97 }
98 };
99
100 match lora.sleep(&mut delay).await {
101 Ok(()) => info!("Sleep successful"),
102 Err(err) => info!("Sleep unsuccessful = {}", err),
103 }
104}
diff --git a/examples/nrf52840/src/bin/lora_p2p_sense.rs b/examples/nrf52840/src/bin/lora_p2p_sense.rs
deleted file mode 100644
index b6f41ffcc..000000000
--- a/examples/nrf52840/src/bin/lora_p2p_sense.rs
+++ /dev/null
@@ -1,128 +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_report.rs.
4#![no_std]
5#![no_main]
6#![macro_use]
7#![feature(type_alias_impl_trait)]
8#![feature(alloc_error_handler)]
9#![allow(incomplete_features)]
10
11use defmt::*;
12use embassy_executor::Spawner;
13use embassy_lora::sx126x::*;
14use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull};
15use embassy_nrf::{bind_interrupts, peripherals, spim};
16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
17use embassy_sync::pubsub::{PubSubChannel, Publisher};
18use embassy_time::{Duration, Timer};
19use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig};
20use {defmt_rtt as _, panic_probe as _, panic_probe as _};
21
22bind_interrupts!(struct Irqs {
23 SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>;
24});
25
26// Message bus: queue of 2, 1 subscriber (Lora P2P), 2 publishers (temperature, motion detection)
27static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new();
28
29#[derive(Clone, defmt::Format)]
30enum Message {
31 Temperature(i32),
32 MotionDetected,
33}
34
35#[embassy_executor::task]
36async fn temperature_task(publisher: Publisher<'static, CriticalSectionRawMutex, Message, 2, 1, 2>) {
37 // Publish a fake temperature every 43 seconds, minimizing LORA traffic.
38 loop {
39 Timer::after(Duration::from_secs(43)).await;
40 publisher.publish(Message::Temperature(9)).await;
41 }
42}
43
44#[embassy_executor::task]
45async fn motion_detection_task(publisher: Publisher<'static, CriticalSectionRawMutex, Message, 2, 1, 2>) {
46 // Publish a fake motion detection every 79 seconds, minimizing LORA traffic.
47 loop {
48 Timer::after(Duration::from_secs(79)).await;
49 publisher.publish(Message::MotionDetected).await;
50 }
51}
52
53#[embassy_executor::main]
54async fn main(spawner: Spawner) {
55 let p = embassy_nrf::init(Default::default());
56 // set up to funnel temperature and motion detection events to the Lora Tx task
57 let mut lora_tx_subscriber = unwrap!(MESSAGE_BUS.subscriber());
58 let temperature_publisher = unwrap!(MESSAGE_BUS.publisher());
59 let motion_detection_publisher = unwrap!(MESSAGE_BUS.publisher());
60
61 let mut spi_config = spim::Config::default();
62 spi_config.frequency = spim::Frequency::M16;
63
64 let mut radio = {
65 let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config);
66
67 let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
68 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
69 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
70 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
71 let antenna_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
72 let antenna_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
73
74 match Sx126xRadio::new(spim, cs, reset, antenna_rx, antenna_tx, dio1, busy, false).await {
75 Ok(r) => r,
76 Err(err) => {
77 info!("Sx126xRadio error = {}", err);
78 return;
79 }
80 }
81 };
82
83 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
84
85 start_indicator.set_high();
86 Timer::after(Duration::from_secs(5)).await;
87 start_indicator.set_low();
88
89 match radio.lora.sleep().await {
90 Ok(()) => info!("Sleep successful"),
91 Err(err) => info!("Sleep unsuccessful = {}", err),
92 }
93
94 unwrap!(spawner.spawn(temperature_task(temperature_publisher)));
95 unwrap!(spawner.spawn(motion_detection_task(motion_detection_publisher)));
96
97 loop {
98 let message = lora_tx_subscriber.next_message_pure().await;
99
100 let tx_config = TxConfig {
101 // 11 byte maximum payload for Bandwidth 125 and SF 10
102 pw: 10, // up to 20
103 rf: RfConfig {
104 frequency: 903900000, // channel in Hz, not MHz
105 bandwidth: Bandwidth::_250KHz,
106 spreading_factor: SpreadingFactor::_10,
107 coding_rate: CodingRate::_4_8,
108 },
109 };
110
111 let mut buffer = [0x00u8];
112 match message {
113 Message::Temperature(temperature) => buffer[0] = temperature as u8,
114 Message::MotionDetected => buffer[0] = 0x01u8,
115 };
116
117 // unencrypted
118 match radio.tx(tx_config, &buffer).await {
119 Ok(ret_val) => info!("TX ret_val = {}", ret_val),
120 Err(err) => info!("TX error = {}", err),
121 }
122
123 match radio.lora.sleep().await {
124 Ok(()) => info!("Sleep successful"),
125 Err(err) => info!("Sleep unsuccessful = {}", err),
126 }
127 }
128}
diff --git a/examples/rp/src/bin/lora_lorawan.rs b/examples/rp/src/bin/lora_lorawan.rs
new file mode 100644
index 000000000..a9c84bf95
--- /dev/null
+++ b/examples/rp/src/bin/lora_lorawan.rs
@@ -0,0 +1,80 @@
1//! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio.
2//! It demonstrates LoRaWAN join 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::GenericSx126xInterfaceVariant;
11use embassy_lora::LoraTimer;
12use embassy_rp::gpio::{Input, Level, Output, Pin, Pull};
13use embassy_rp::spi::{Config, Spi};
14use embassy_time::Delay;
15use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2;
17use lora_phy::LoRa;
18use lorawan::default_crypto::DefaultFactory as Crypto;
19use lorawan_device::async_device::lora_radio::LoRaRadio;
20use lorawan_device::async_device::{region, Device, JoinMode};
21use {defmt_rtt as _, panic_probe as _};
22
23const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region
24
25#[embassy_executor::main]
26async fn main(_spawner: Spawner) {
27 let p = embassy_rp::init(Default::default());
28
29 let miso = p.PIN_12;
30 let mosi = p.PIN_11;
31 let clk = p.PIN_10;
32 let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default());
33
34 let nss = Output::new(p.PIN_3.degrade(), Level::High);
35 let reset = Output::new(p.PIN_15.degrade(), Level::High);
36 let dio1 = Input::new(p.PIN_20.degrade(), Pull::None);
37 let busy = Input::new(p.PIN_2.degrade(), Pull::None);
38
39 let iv = GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, None, None).unwrap();
40
41 let mut delay = Delay;
42
43 let lora = {
44 match LoRa::new(
45 SX1261_2::new(BoardType::RpPicoWaveshareSx1262, spi, iv),
46 true,
47 &mut delay,
48 )
49 .await
50 {
51 Ok(l) => l,
52 Err(err) => {
53 info!("Radio error = {}", err);
54 return;
55 }
56 }
57 };
58
59 let radio = LoRaRadio::new(lora);
60 let region: region::Configuration = region::Configuration::new(LORAWAN_REGION);
61 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), embassy_rp::clocks::RoscRng);
62
63 defmt::info!("Joining LoRaWAN network");
64
65 // TODO: Adjust the EUI and Keys according to your network credentials
66 match device
67 .join(&JoinMode::OTAA {
68 deveui: [0, 0, 0, 0, 0, 0, 0, 0],
69 appeui: [0, 0, 0, 0, 0, 0, 0, 0],
70 appkey: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
71 })
72 .await
73 {
74 Ok(()) => defmt::info!("LoRaWAN network joined"),
75 Err(err) => {
76 info!("Radio error = {}", err);
77 return;
78 }
79 };
80}
diff --git a/examples/rp/src/bin/lora_p2p_receive.rs b/examples/rp/src/bin/lora_p2p_receive.rs
new file mode 100644
index 000000000..250419202
--- /dev/null
+++ b/examples/rp/src/bin/lora_p2p_receive.rs
@@ -0,0 +1,115 @@
1//! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio.
2//! It demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example.
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::GenericSx126xInterfaceVariant;
11use embassy_rp::gpio::{Input, Level, Output, Pin, Pull};
12use embassy_rp::spi::{Config, Spi};
13use embassy_time::{Delay, Duration, Timer};
14use lora_phy::mod_params::*;
15use lora_phy::sx1261_2::SX1261_2;
16use lora_phy::LoRa;
17use {defmt_rtt as _, panic_probe as _};
18
19const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
20
21#[embassy_executor::main]
22async fn main(_spawner: Spawner) {
23 let p = embassy_rp::init(Default::default());
24
25 let miso = p.PIN_12;
26 let mosi = p.PIN_11;
27 let clk = p.PIN_10;
28 let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default());
29
30 let nss = Output::new(p.PIN_3.degrade(), Level::High);
31 let reset = Output::new(p.PIN_15.degrade(), Level::High);
32 let dio1 = Input::new(p.PIN_20.degrade(), Pull::None);
33 let busy = Input::new(p.PIN_2.degrade(), Pull::None);
34
35 let iv = GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, None, None).unwrap();
36
37 let mut delay = Delay;
38
39 let mut lora = {
40 match LoRa::new(
41 SX1261_2::new(BoardType::RpPicoWaveshareSx1262, spi, iv),
42 false,
43 &mut delay,
44 )
45 .await
46 {
47 Ok(l) => l,
48 Err(err) => {
49 info!("Radio error = {}", err);
50 return;
51 }
52 }
53 };
54
55 let mut debug_indicator = Output::new(p.PIN_25, Level::Low);
56
57 let mut receiving_buffer = [00u8; 100];
58
59 let mdltn_params = {
60 match lora.create_modulation_params(
61 SpreadingFactor::_10,
62 Bandwidth::_250KHz,
63 CodingRate::_4_8,
64 LORA_FREQUENCY_IN_HZ,
65 ) {
66 Ok(mp) => mp,
67 Err(err) => {
68 info!("Radio error = {}", err);
69 return;
70 }
71 }
72 };
73
74 let rx_pkt_params = {
75 match lora.create_rx_packet_params(4, false, receiving_buffer.len() as u8, true, false, &mdltn_params) {
76 Ok(pp) => pp,
77 Err(err) => {
78 info!("Radio error = {}", err);
79 return;
80 }
81 }
82 };
83
84 match lora
85 .prepare_for_rx(&mdltn_params, &rx_pkt_params, None, true, false, 0, 0x00ffffffu32)
86 .await
87 {
88 Ok(()) => {}
89 Err(err) => {
90 info!("Radio error = {}", err);
91 return;
92 }
93 };
94
95 loop {
96 receiving_buffer = [00u8; 100];
97 match lora.rx(&rx_pkt_params, &mut receiving_buffer).await {
98 Ok((received_len, _rx_pkt_status)) => {
99 if (received_len == 3)
100 && (receiving_buffer[0] == 0x01u8)
101 && (receiving_buffer[1] == 0x02u8)
102 && (receiving_buffer[2] == 0x03u8)
103 {
104 info!("rx successful");
105 debug_indicator.set_high();
106 Timer::after(Duration::from_secs(5)).await;
107 debug_indicator.set_low();
108 } else {
109 info!("rx unknown packet");
110 }
111 }
112 Err(err) => info!("rx unsuccessful = {}", err),
113 }
114 }
115}
diff --git a/examples/rp/src/bin/lora_p2p_send.rs b/examples/rp/src/bin/lora_p2p_send.rs
new file mode 100644
index 000000000..3a0544b17
--- /dev/null
+++ b/examples/rp/src/bin/lora_p2p_send.rs
@@ -0,0 +1,103 @@
1//! This example runs on the Raspberry Pi Pico with a Waveshare board containing a 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)]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_lora::iv::GenericSx126xInterfaceVariant;
11use embassy_rp::gpio::{Input, Level, Output, Pin, Pull};
12use embassy_rp::spi::{Config, Spi};
13use embassy_time::Delay;
14use lora_phy::mod_params::*;
15use lora_phy::sx1261_2::SX1261_2;
16use lora_phy::LoRa;
17use {defmt_rtt as _, panic_probe as _};
18
19const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
20
21#[embassy_executor::main]
22async fn main(_spawner: Spawner) {
23 let p = embassy_rp::init(Default::default());
24
25 let miso = p.PIN_12;
26 let mosi = p.PIN_11;
27 let clk = p.PIN_10;
28 let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default());
29
30 let nss = Output::new(p.PIN_3.degrade(), Level::High);
31 let reset = Output::new(p.PIN_15.degrade(), Level::High);
32 let dio1 = Input::new(p.PIN_20.degrade(), Pull::None);
33 let busy = Input::new(p.PIN_2.degrade(), Pull::None);
34
35 let iv = GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, None, None).unwrap();
36
37 let mut delay = Delay;
38
39 let mut lora = {
40 match LoRa::new(
41 SX1261_2::new(BoardType::RpPicoWaveshareSx1262, spi, iv),
42 false,
43 &mut delay,
44 )
45 .await
46 {
47 Ok(l) => l,
48 Err(err) => {
49 info!("Radio error = {}", err);
50 return;
51 }
52 }
53 };
54
55 let mdltn_params = {
56 match lora.create_modulation_params(
57 SpreadingFactor::_10,
58 Bandwidth::_250KHz,
59 CodingRate::_4_8,
60 LORA_FREQUENCY_IN_HZ,
61 ) {
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}
diff --git a/examples/rp/src/bin/lora_p2p_send_multicore.rs b/examples/rp/src/bin/lora_p2p_send_multicore.rs
new file mode 100644
index 000000000..5585606d8
--- /dev/null
+++ b/examples/rp/src/bin/lora_p2p_send_multicore.rs
@@ -0,0 +1,139 @@
1//! This example runs on the Raspberry Pi Pico with a Waveshare board containing a Semtech Sx1262 radio.
2//! It demonstrates LORA P2P send functionality using the second core, with data provided by the first core.
3#![no_std]
4#![no_main]
5#![macro_use]
6#![feature(type_alias_impl_trait)]
7
8use defmt::*;
9use embassy_executor::Executor;
10use embassy_executor::_export::StaticCell;
11use embassy_lora::iv::GenericSx126xInterfaceVariant;
12use embassy_rp::gpio::{AnyPin, Input, Level, Output, Pin, Pull};
13use embassy_rp::multicore::{spawn_core1, Stack};
14use embassy_rp::peripherals::SPI1;
15use embassy_rp::spi::{Async, Config, Spi};
16use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
17use embassy_sync::channel::Channel;
18use embassy_time::{Delay, Duration, Timer};
19use lora_phy::mod_params::*;
20use lora_phy::sx1261_2::SX1261_2;
21use lora_phy::LoRa;
22use {defmt_rtt as _, panic_probe as _};
23
24static mut CORE1_STACK: Stack<4096> = Stack::new();
25static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
26static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
27static CHANNEL: Channel<CriticalSectionRawMutex, [u8; 3], 1> = Channel::new();
28
29const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
30
31#[cortex_m_rt::entry]
32fn main() -> ! {
33 let p = embassy_rp::init(Default::default());
34
35 let miso = p.PIN_12;
36 let mosi = p.PIN_11;
37 let clk = p.PIN_10;
38 let spi = Spi::new(p.SPI1, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, Config::default());
39
40 let nss = Output::new(p.PIN_3.degrade(), Level::High);
41 let reset = Output::new(p.PIN_15.degrade(), Level::High);
42 let dio1 = Input::new(p.PIN_20.degrade(), Pull::None);
43 let busy = Input::new(p.PIN_2.degrade(), Pull::None);
44
45 let iv = GenericSx126xInterfaceVariant::new(nss, reset, dio1, busy, None, None).unwrap();
46
47 spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || {
48 let executor1 = EXECUTOR1.init(Executor::new());
49 executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(spi, iv))));
50 });
51
52 let executor0 = EXECUTOR0.init(Executor::new());
53 executor0.run(|spawner| unwrap!(spawner.spawn(core0_task())));
54}
55
56#[embassy_executor::task]
57async fn core0_task() {
58 info!("Hello from core 0");
59 loop {
60 CHANNEL.send([0x01u8, 0x02u8, 0x03u8]).await;
61 Timer::after(Duration::from_millis(60 * 1000)).await;
62 }
63}
64
65#[embassy_executor::task]
66async fn core1_task(
67 spi: Spi<'static, SPI1, Async>,
68 iv: GenericSx126xInterfaceVariant<Output<'static, AnyPin>, Input<'static, AnyPin>>,
69) {
70 info!("Hello from core 1");
71 let mut delay = Delay;
72
73 let mut lora = {
74 match LoRa::new(
75 SX1261_2::new(BoardType::RpPicoWaveshareSx1262, spi, iv),
76 false,
77 &mut delay,
78 )
79 .await
80 {
81 Ok(l) => l,
82 Err(err) => {
83 info!("Radio error = {}", err);
84 return;
85 }
86 }
87 };
88
89 let mdltn_params = {
90 match lora.create_modulation_params(
91 SpreadingFactor::_10,
92 Bandwidth::_250KHz,
93 CodingRate::_4_8,
94 LORA_FREQUENCY_IN_HZ,
95 ) {
96 Ok(mp) => mp,
97 Err(err) => {
98 info!("Radio error = {}", err);
99 return;
100 }
101 }
102 };
103
104 let mut tx_pkt_params = {
105 match lora.create_tx_packet_params(4, false, true, false, &mdltn_params) {
106 Ok(pp) => pp,
107 Err(err) => {
108 info!("Radio error = {}", err);
109 return;
110 }
111 }
112 };
113
114 loop {
115 let buffer: [u8; 3] = CHANNEL.recv().await;
116 match lora.prepare_for_tx(&mdltn_params, 20, false).await {
117 Ok(()) => {}
118 Err(err) => {
119 info!("Radio error = {}", err);
120 return;
121 }
122 };
123
124 match lora.tx(&mdltn_params, &mut tx_pkt_params, &buffer, 0xffffff).await {
125 Ok(()) => {
126 info!("TX DONE");
127 }
128 Err(err) => {
129 info!("Radio error = {}", err);
130 return;
131 }
132 };
133
134 match lora.sleep(&mut delay).await {
135 Ok(()) => info!("Sleep successful"),
136 Err(err) => info!("Sleep unsuccessful = {}", err),
137 }
138 }
139}
diff --git a/examples/stm32l0/src/bin/lora_cad.rs b/examples/stm32l0/src/bin/lora_cad.rs
new file mode 100644
index 000000000..588cea1e5
--- /dev/null
+++ b/examples/stm32l0/src/bin/lora_cad.rs
@@ -0,0 +1,105 @@
1//! This example runs on the STM32 LoRa Discovery board, which has a builtin Semtech Sx1276 radio.
2//! It demonstrates LORA P2P CAD 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
21const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
22
23#[embassy_executor::main]
24async fn main(_spawner: Spawner) {
25 let mut config = embassy_stm32::Config::default();
26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
27 config.rcc.enable_hsi48 = true;
28 let p = embassy_stm32::init(config);
29
30 // SPI for sx1276
31 let spi = spi::Spi::new(
32 p.SPI1,
33 p.PB3,
34 p.PA7,
35 p.PA6,
36 p.DMA1_CH3,
37 p.DMA1_CH2,
38 khz(200),
39 spi::Config::default(),
40 );
41
42 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low);
43 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low);
44
45 let irq_pin = Input::new(p.PB4.degrade(), Pull::Up);
46 let irq = ExtiInput::new(irq_pin, p.EXTI4.degrade());
47
48 let iv = Stm32l0InterfaceVariant::new(nss, reset, irq, None, None).unwrap();
49
50 let mut delay = Delay;
51
52 let mut lora = {
53 match LoRa::new(SX1276_7_8_9::new(BoardType::Stm32l0Sx1276, spi, iv), false, &mut delay).await {
54 Ok(l) => l,
55 Err(err) => {
56 info!("Radio error = {}", err);
57 return;
58 }
59 }
60 };
61
62 let mut debug_indicator = Output::new(p.PB5, Level::Low, Speed::Low);
63 let mut start_indicator = Output::new(p.PB6, Level::Low, Speed::Low);
64
65 start_indicator.set_high();
66 Timer::after(Duration::from_secs(5)).await;
67 start_indicator.set_low();
68
69 let mdltn_params = {
70 match lora.create_modulation_params(
71 SpreadingFactor::_10,
72 Bandwidth::_250KHz,
73 CodingRate::_4_8,
74 LORA_FREQUENCY_IN_HZ,
75 ) {
76 Ok(mp) => mp,
77 Err(err) => {
78 info!("Radio error = {}", err);
79 return;
80 }
81 }
82 };
83
84 match lora.prepare_for_cad(&mdltn_params, true).await {
85 Ok(()) => {}
86 Err(err) => {
87 info!("Radio error = {}", err);
88 return;
89 }
90 };
91
92 match lora.cad().await {
93 Ok(cad_activity_detected) => {
94 if cad_activity_detected {
95 info!("cad successful with activity detected")
96 } else {
97 info!("cad successful without activity detected")
98 }
99 debug_indicator.set_high();
100 Timer::after(Duration::from_secs(5)).await;
101 debug_indicator.set_low();
102 }
103 Err(err) => info!("cad unsuccessful = {}", err),
104 }
105}
diff --git a/examples/stm32l0/src/bin/lora_lorawan.rs b/examples/stm32l0/src/bin/lora_lorawan.rs
new file mode 100644
index 000000000..c397edd58
--- /dev/null
+++ b/examples/stm32l0/src/bin/lora_lorawan.rs
@@ -0,0 +1,88 @@
1//! This example runs on the STM32 LoRa Discovery board, which has a builtin Semtech Sx1276 radio.
2//! It demonstrates LoRaWAN join 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_lora::LoraTimer;
12use embassy_stm32::exti::{Channel, ExtiInput};
13use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed};
14use embassy_stm32::rng::Rng;
15use embassy_stm32::spi;
16use embassy_stm32::time::khz;
17use embassy_time::Delay;
18use lora_phy::mod_params::*;
19use lora_phy::sx1276_7_8_9::SX1276_7_8_9;
20use lora_phy::LoRa;
21use lorawan::default_crypto::DefaultFactory as Crypto;
22use lorawan_device::async_device::lora_radio::LoRaRadio;
23use lorawan_device::async_device::{region, Device, JoinMode};
24use {defmt_rtt as _, panic_probe as _};
25
26const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region
27
28#[embassy_executor::main]
29async fn main(_spawner: Spawner) {
30 let mut config = embassy_stm32::Config::default();
31 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
32 config.rcc.enable_hsi48 = true;
33 let p = embassy_stm32::init(config);
34
35 // SPI for sx1276
36 let spi = spi::Spi::new(
37 p.SPI1,
38 p.PB3,
39 p.PA7,
40 p.PA6,
41 p.DMA1_CH3,
42 p.DMA1_CH2,
43 khz(200),
44 spi::Config::default(),
45 );
46
47 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low);
48 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low);
49
50 let irq_pin = Input::new(p.PB4.degrade(), Pull::Up);
51 let irq = ExtiInput::new(irq_pin, p.EXTI4.degrade());
52
53 let iv = Stm32l0InterfaceVariant::new(nss, reset, irq, None, None).unwrap();
54
55 let mut delay = Delay;
56
57 let lora = {
58 match LoRa::new(SX1276_7_8_9::new(BoardType::Stm32l0Sx1276, spi, iv), true, &mut delay).await {
59 Ok(l) => l,
60 Err(err) => {
61 info!("Radio error = {}", err);
62 return;
63 }
64 }
65 };
66
67 let radio = LoRaRadio::new(lora);
68 let region: region::Configuration = region::Configuration::new(LORAWAN_REGION);
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/stm32l0/src/bin/lora_p2p_receive.rs b/examples/stm32l0/src/bin/lora_p2p_receive.rs
index a5c5f75ea..bb7509509 100644
--- a/examples/stm32l0/src/bin/lora_p2p_receive.rs
+++ b/examples/stm32l0/src/bin/lora_p2p_receive.rs
@@ -1,5 +1,5 @@
1//! This example runs on the STM32 LoRa Discovery board, which has a builtin Semtech Sx1276 radio. 1//! This example runs on the STM32 LoRa Discovery board, which has a builtin Semtech Sx1276 radio.
2//! It demonstrates LORA P2P receive functionality. 2//! It demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example.
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![macro_use] 5#![macro_use]
@@ -18,6 +18,8 @@ use lora_phy::sx1276_7_8_9::SX1276_7_8_9;
18use lora_phy::LoRa; 18use lora_phy::LoRa;
19use {defmt_rtt as _, panic_probe as _}; 19use {defmt_rtt as _, panic_probe as _};
20 20
21const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
22
21#[embassy_executor::main] 23#[embassy_executor::main]
22async fn main(_spawner: Spawner) { 24async fn main(_spawner: Spawner) {
23 let mut config = embassy_stm32::Config::default(); 25 let mut config = embassy_stm32::Config::default();
@@ -67,7 +69,12 @@ async fn main(_spawner: Spawner) {
67 let mut receiving_buffer = [00u8; 100]; 69 let mut receiving_buffer = [00u8; 100];
68 70
69 let mdltn_params = { 71 let mdltn_params = {
70 match lora.create_modulation_params(SpreadingFactor::_10, Bandwidth::_250KHz, CodingRate::_4_8, 903900000) { 72 match lora.create_modulation_params(
73 SpreadingFactor::_10,
74 Bandwidth::_250KHz,
75 CodingRate::_4_8,
76 LORA_FREQUENCY_IN_HZ,
77 ) {
71 Ok(mp) => mp, 78 Ok(mp) => mp,
72 Err(err) => { 79 Err(err) => {
73 info!("Radio error = {}", err); 80 info!("Radio error = {}", err);
diff --git a/examples/stm32l0/src/bin/lora_p2p_send.rs b/examples/stm32l0/src/bin/lora_p2p_send.rs
new file mode 100644
index 000000000..e6fadc01d
--- /dev/null
+++ b/examples/stm32l0/src/bin/lora_p2p_send.rs
@@ -0,0 +1,110 @@
1//! This example runs on the STM32 LoRa Discovery board, which has a builtin Semtech Sx1276 radio.
2//! It demonstrates LORA P2P send 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;
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
21const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
22
23#[embassy_executor::main]
24async fn main(_spawner: Spawner) {
25 let mut config = embassy_stm32::Config::default();
26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
27 config.rcc.enable_hsi48 = true;
28 let p = embassy_stm32::init(config);
29
30 // SPI for sx1276
31 let spi = spi::Spi::new(
32 p.SPI1,
33 p.PB3,
34 p.PA7,
35 p.PA6,
36 p.DMA1_CH3,
37 p.DMA1_CH2,
38 khz(200),
39 spi::Config::default(),
40 );
41
42 let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low);
43 let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low);
44
45 let irq_pin = Input::new(p.PB4.degrade(), Pull::Up);
46 let irq = ExtiInput::new(irq_pin, p.EXTI4.degrade());
47
48 let iv = Stm32l0InterfaceVariant::new(nss, reset, irq, None, None).unwrap();
49
50 let mut delay = Delay;
51
52 let mut lora = {
53 match LoRa::new(SX1276_7_8_9::new(BoardType::Stm32l0Sx1276, spi, iv), false, &mut delay).await {
54 Ok(l) => l,
55 Err(err) => {
56 info!("Radio error = {}", err);
57 return;
58 }
59 }
60 };
61
62 let mdltn_params = {
63 match lora.create_modulation_params(
64 SpreadingFactor::_10,
65 Bandwidth::_250KHz,
66 CodingRate::_4_8,
67 LORA_FREQUENCY_IN_HZ,
68 ) {
69 Ok(mp) => mp,
70 Err(err) => {
71 info!("Radio error = {}", err);
72 return;
73 }
74 }
75 };
76
77 let mut tx_pkt_params = {
78 match lora.create_tx_packet_params(4, false, true, false, &mdltn_params) {
79 Ok(pp) => pp,
80 Err(err) => {
81 info!("Radio error = {}", err);
82 return;
83 }
84 }
85 };
86
87 match lora.prepare_for_tx(&mdltn_params, 17, true).await {
88 Ok(()) => {}
89 Err(err) => {
90 info!("Radio error = {}", err);
91 return;
92 }
93 };
94
95 let buffer = [0x01u8, 0x02u8, 0x03u8];
96 match lora.tx(&mdltn_params, &mut tx_pkt_params, &buffer, 0xffffff).await {
97 Ok(()) => {
98 info!("TX DONE");
99 }
100 Err(err) => {
101 info!("Radio error = {}", err);
102 return;
103 }
104 };
105
106 match lora.sleep(&mut delay).await {
107 Ok(()) => info!("Sleep successful"),
108 Err(err) => info!("Sleep unsuccessful = {}", err),
109 }
110}
diff --git a/examples/stm32l0/src/bin/lorawan.rs b/examples/stm32l0/src/bin/lorawan.rs
deleted file mode 100644
index ea01f610c..000000000
--- a/examples/stm32l0/src/bin/lorawan.rs
+++ /dev/null
@@ -1,74 +0,0 @@
1//! This example runs on the STM32 LoRa Discovery board which has a builtin Semtech Sx127x radio
2#![no_std]
3#![no_main]
4#![macro_use]
5#![allow(dead_code)]
6#![feature(type_alias_impl_trait)]
7
8use embassy_executor::Spawner;
9use embassy_lora::sx127x::*;
10use embassy_lora::LoraTimer;
11use embassy_stm32::exti::ExtiInput;
12use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
13use embassy_stm32::rng::Rng;
14use embassy_stm32::spi;
15use embassy_stm32::time::khz;
16use lorawan::default_crypto::DefaultFactory as Crypto;
17use lorawan_device::async_device::{region, Device, JoinMode};
18use {defmt_rtt as _, panic_probe as _};
19
20#[embassy_executor::main]
21async fn main(_spawner: Spawner) {
22 let mut config = embassy_stm32::Config::default();
23 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
24 config.rcc.enable_hsi48 = true;
25 let p = embassy_stm32::init(config);
26
27 // SPI for sx127x
28 let spi = spi::Spi::new(
29 p.SPI1,
30 p.PB3,
31 p.PA7,
32 p.PA6,
33 p.DMA1_CH3,
34 p.DMA1_CH2,
35 khz(200),
36 spi::Config::default(),
37 );
38
39 let cs = Output::new(p.PA15, Level::High, Speed::Low);
40 let reset = Output::new(p.PC0, Level::High, Speed::Low);
41 let _ = Input::new(p.PB1, Pull::None);
42
43 let ready = Input::new(p.PB4, Pull::Up);
44 let ready_pin = ExtiInput::new(ready, p.EXTI4);
45
46 let radio = Sx127xRadio::new(spi, cs, reset, ready_pin, DummySwitch).await.unwrap();
47
48 let region = region::Configuration::new(region::Region::EU868);
49 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG));
50
51 defmt::info!("Joining LoRaWAN network");
52
53 // TODO: Adjust the EUI and Keys according to your network credentials
54 device
55 .join(&JoinMode::OTAA {
56 deveui: [0, 0, 0, 0, 0, 0, 0, 0],
57 appeui: [0, 0, 0, 0, 0, 0, 0, 0],
58 appkey: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
59 })
60 .await
61 .ok()
62 .unwrap();
63 defmt::info!("LoRaWAN network joined");
64
65 defmt::info!("Sending 'PING'");
66 device.send(b"PING", 1, false).await.ok().unwrap();
67 defmt::info!("Message sent!");
68}
69
70pub struct DummySwitch;
71impl RadioSwitch for DummySwitch {
72 fn set_rx(&mut self) {}
73 fn set_tx(&mut self) {}
74}
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
index f7cf03595..4bcc5420e 100644
--- a/examples/stm32wl/src/bin/lora_lorawan.rs
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -1,5 +1,5 @@
1//! This example runs on a STM32WL board, which has a builtin Semtech Sx1262 radio. 1//! This example runs on a STM32WL board, which has a builtin Semtech Sx1262 radio.
2//! It demonstrates LoRaWAN functionality. 2//! It demonstrates LoRaWAN join functionality.
3#![no_std] 3#![no_std]
4#![no_main] 4#![no_main]
5#![macro_use] 5#![macro_use]
@@ -28,6 +28,8 @@ use lorawan_device::async_device::lora_radio::LoRaRadio;
28use lorawan_device::async_device::{region, Device, JoinMode}; 28use lorawan_device::async_device::{region, Device, JoinMode};
29use {defmt_rtt as _, panic_probe as _}; 29use {defmt_rtt as _, panic_probe as _};
30 30
31const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region
32
31#[embassy_executor::main] 33#[embassy_executor::main]
32async fn main(_spawner: Spawner) { 34async fn main(_spawner: Spawner) {
33 let mut config = embassy_stm32::Config::default(); 35 let mut config = embassy_stm32::Config::default();
@@ -65,7 +67,7 @@ async fn main(_spawner: Spawner) {
65 } 67 }
66 }; 68 };
67 let radio = LoRaRadio::new(lora); 69 let radio = LoRaRadio::new(lora);
68 let region: region::Configuration = region::Configuration::new(region::Region::EU868); 70 let region: region::Configuration = region::Configuration::new(LORAWAN_REGION);
69 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG)); 71 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG));
70 72
71 defmt::info!("Joining LoRaWAN network"); 73 defmt::info!("Joining LoRaWAN network");
diff --git a/examples/stm32wl/src/bin/lora_p2p_receive.rs b/examples/stm32wl/src/bin/lora_p2p_receive.rs
new file mode 100644
index 000000000..bb31518c4
--- /dev/null
+++ b/examples/stm32wl/src/bin/lora_p2p_receive.rs
@@ -0,0 +1,127 @@
1//! This example runs on the STM32WL board, which has a builtin Semtech Sx1262 radio.
2//! It demonstrates LORA P2P receive functionality in conjunction with the lora_p2p_send example.
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, Duration, Timer};
21use lora_phy::mod_params::*;
22use lora_phy::sx1261_2::SX1261_2;
23use lora_phy::LoRa;
24use {defmt_rtt as _, panic_probe as _};
25
26const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
27
28#[embassy_executor::main]
29async fn main(_spawner: Spawner) {
30 let mut config = embassy_stm32::Config::default();
31 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE32;
32 let p = embassy_stm32::init(config);
33
34 let clk = Hertz(core::cmp::min(SUBGHZSPI::frequency().0 / 2, 16_000_000));
35 let mut spi_config = SpiConfig::default();
36 spi_config.mode = MODE_0;
37 spi_config.bit_order = BitOrder::MsbFirst;
38 let spi = Spi::new_subghz(p.SUBGHZSPI, NoDma, NoDma, clk, spi_config);
39
40 let spi = BlockingAsync::new(spi);
41
42 let irq = interrupt::take!(SUBGHZ_RADIO);
43 into_ref!(irq);
44 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx
45 let _ctrl1 = Output::new(p.PC4.degrade(), Level::Low, Speed::High);
46 let ctrl2 = Output::new(p.PC5.degrade(), Level::High, Speed::High);
47 let _ctrl3 = Output::new(p.PC3.degrade(), Level::High, Speed::High);
48 let iv = Stm32wlInterfaceVariant::new(irq, None, Some(ctrl2)).unwrap();
49
50 let mut delay = Delay;
51
52 let mut lora = {
53 match LoRa::new(SX1261_2::new(BoardType::Stm32wlSx1262, spi, iv), false, &mut delay).await {
54 Ok(l) => l,
55 Err(err) => {
56 info!("Radio error = {}", err);
57 return;
58 }
59 }
60 };
61
62 let mut debug_indicator = Output::new(p.PB9, Level::Low, Speed::Low);
63 let mut start_indicator = Output::new(p.PB15, Level::Low, Speed::Low);
64
65 start_indicator.set_high();
66 Timer::after(Duration::from_secs(5)).await;
67 start_indicator.set_low();
68
69 let mut receiving_buffer = [00u8; 100];
70
71 let mdltn_params = {
72 match lora.create_modulation_params(
73 SpreadingFactor::_10,
74 Bandwidth::_250KHz,
75 CodingRate::_4_8,
76 LORA_FREQUENCY_IN_HZ,
77 ) {
78 Ok(mp) => mp,
79 Err(err) => {
80 info!("Radio error = {}", err);
81 return;
82 }
83 }
84 };
85
86 let rx_pkt_params = {
87 match lora.create_rx_packet_params(4, false, receiving_buffer.len() as u8, true, false, &mdltn_params) {
88 Ok(pp) => pp,
89 Err(err) => {
90 info!("Radio error = {}", err);
91 return;
92 }
93 }
94 };
95
96 match lora
97 .prepare_for_rx(&mdltn_params, &rx_pkt_params, None, true, false, 0, 0x00ffffffu32)
98 .await
99 {
100 Ok(()) => {}
101 Err(err) => {
102 info!("Radio error = {}", err);
103 return;
104 }
105 };
106
107 loop {
108 receiving_buffer = [00u8; 100];
109 match lora.rx(&rx_pkt_params, &mut receiving_buffer).await {
110 Ok((received_len, _rx_pkt_status)) => {
111 if (received_len == 3)
112 && (receiving_buffer[0] == 0x01u8)
113 && (receiving_buffer[1] == 0x02u8)
114 && (receiving_buffer[2] == 0x03u8)
115 {
116 info!("rx successful");
117 debug_indicator.set_high();
118 Timer::after(Duration::from_secs(5)).await;
119 debug_indicator.set_low();
120 } else {
121 info!("rx unknown packet");
122 }
123 }
124 Err(err) => info!("rx unsuccessful = {}", err),
125 }
126 }
127}
diff --git a/examples/stm32wl/src/bin/lora_p2p_send.rs b/examples/stm32wl/src/bin/lora_p2p_send.rs
index 11c35a8fe..8a38402fa 100644
--- a/examples/stm32wl/src/bin/lora_p2p_send.rs
+++ b/examples/stm32wl/src/bin/lora_p2p_send.rs
@@ -23,6 +23,8 @@ use lora_phy::sx1261_2::SX1261_2;
23use lora_phy::LoRa; 23use lora_phy::LoRa;
24use {defmt_rtt as _, panic_probe as _}; 24use {defmt_rtt as _, panic_probe as _};
25 25
26const LORA_FREQUENCY_IN_HZ: u32 = 903_900_000; // warning: set this appropriately for the region
27
26#[embassy_executor::main] 28#[embassy_executor::main]
27async fn main(_spawner: Spawner) { 29async fn main(_spawner: Spawner) {
28 let mut config = embassy_stm32::Config::default(); 30 let mut config = embassy_stm32::Config::default();
@@ -58,7 +60,12 @@ async fn main(_spawner: Spawner) {
58 }; 60 };
59 61
60 let mdltn_params = { 62 let mdltn_params = {
61 match lora.create_modulation_params(SpreadingFactor::_10, Bandwidth::_250KHz, CodingRate::_4_8, 903900000) { 63 match lora.create_modulation_params(
64 SpreadingFactor::_10,
65 Bandwidth::_250KHz,
66 CodingRate::_4_8,
67 LORA_FREQUENCY_IN_HZ,
68 ) {
62 Ok(mp) => mp, 69 Ok(mp) => mp,
63 Err(err) => { 70 Err(err) => {
64 info!("Radio error = {}", err); 71 info!("Radio error = {}", err);
diff --git a/examples/stm32wl/src/bin/lorawan.rs b/examples/stm32wl/src/bin/lorawan.rs
deleted file mode 100644
index 32f29cc5d..000000000
--- a/examples/stm32wl/src/bin/lorawan.rs
+++ /dev/null
@@ -1,104 +0,0 @@
1#![no_std]
2#![no_main]
3#![macro_use]
4#![allow(dead_code)]
5#![feature(type_alias_impl_trait)]
6
7use embassy_executor::Spawner;
8use embassy_lora::stm32wl::*;
9use embassy_lora::LoraTimer;
10use embassy_stm32::dma::NoDma;
11use embassy_stm32::gpio::{AnyPin, Level, Output, Pin, Speed};
12use embassy_stm32::rng::Rng;
13use embassy_stm32::subghz::*;
14use embassy_stm32::{interrupt, pac};
15use lorawan::default_crypto::DefaultFactory as Crypto;
16use lorawan_device::async_device::{region, Device, JoinMode};
17use {defmt_rtt as _, panic_probe as _};
18
19struct RadioSwitch<'a> {
20 ctrl1: Output<'a, AnyPin>,
21 ctrl2: Output<'a, AnyPin>,
22 ctrl3: Output<'a, AnyPin>,
23}
24
25impl<'a> RadioSwitch<'a> {
26 fn new(ctrl1: Output<'a, AnyPin>, ctrl2: Output<'a, AnyPin>, ctrl3: Output<'a, AnyPin>) -> Self {
27 Self { ctrl1, ctrl2, ctrl3 }
28 }
29}
30
31impl<'a> embassy_lora::stm32wl::RadioSwitch for RadioSwitch<'a> {
32 fn set_rx(&mut self) {
33 self.ctrl1.set_high();
34 self.ctrl2.set_low();
35 self.ctrl3.set_high();
36 }
37
38 fn set_tx(&mut self) {
39 self.ctrl1.set_high();
40 self.ctrl2.set_high();
41 self.ctrl3.set_high();
42 }
43}
44
45#[embassy_executor::main]
46async fn main(_spawner: Spawner) {
47 let mut config = embassy_stm32::Config::default();
48 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
49 config.rcc.enable_lsi = true;
50 let p = embassy_stm32::init(config);
51
52 unsafe { pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)) }
53
54 let ctrl1 = Output::new(p.PC3.degrade(), Level::High, Speed::High);
55 let ctrl2 = Output::new(p.PC4.degrade(), Level::High, Speed::High);
56 let ctrl3 = Output::new(p.PC5.degrade(), Level::High, Speed::High);
57 let rfs = RadioSwitch::new(ctrl1, ctrl2, ctrl3);
58
59 let radio = SubGhz::new(p.SUBGHZSPI, NoDma, NoDma);
60 let irq = interrupt::take!(SUBGHZ_RADIO);
61
62 let mut radio_config = SubGhzRadioConfig::default();
63 radio_config.calibrate_image = CalibrateImage::ISM_863_870;
64 let radio = SubGhzRadio::new(radio, rfs, irq, radio_config).unwrap();
65
66 let mut region = region::Configuration::new(region::Region::EU868);
67
68 // NOTE: This is specific for TTN, as they have a special RX1 delay
69 region.set_receive_delay1(5000);
70
71 let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG));
72
73 // Depending on network, this might be part of JOIN
74 device.set_datarate(region::DR::_0); // SF12
75
76 // device.set_datarate(region::DR::_1); // SF11
77 // device.set_datarate(region::DR::_2); // SF10
78 // device.set_datarate(region::DR::_3); // SF9
79 // device.set_datarate(region::DR::_4); // SF8
80 // device.set_datarate(region::DR::_5); // SF7
81
82 defmt::info!("Joining LoRaWAN network");
83
84 // TODO: Adjust the EUI and Keys according to your network credentials
85 device
86 .join(&JoinMode::OTAA {
87 deveui: [0, 0, 0, 0, 0, 0, 0, 0],
88 appeui: [0, 0, 0, 0, 0, 0, 0, 0],
89 appkey: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
90 })
91 .await
92 .ok()
93 .unwrap();
94 defmt::info!("LoRaWAN network joined");
95
96 let mut rx: [u8; 255] = [0; 255];
97 defmt::info!("Sending 'PING'");
98 let len = device.send_recv(b"PING", &mut rx[..], 1, true).await.ok().unwrap();
99 if len > 0 {
100 defmt::info!("Message sent, received downlink: {:?}", &rx[..len]);
101 } else {
102 defmt::info!("Message sent!");
103 }
104}