aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/nrf/Cargo.toml7
-rw-r--r--examples/nrf/src/bin/lora_p2p_report.rs78
-rw-r--r--examples/nrf/src/bin/lora_p2p_sense.rs125
3 files changed, 209 insertions, 1 deletions
diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml
index 9ebd04845..6949042e2 100644
--- a/examples/nrf/Cargo.toml
+++ b/examples/nrf/Cargo.toml
@@ -6,7 +6,8 @@ license = "MIT OR Apache-2.0"
6 6
7[features] 7[features]
8default = ["nightly"] 8default = ["nightly"]
9nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net"] 9nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-net/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embedded-io/async", "embassy-net",
10 "embassy-lora", "lorawan-device", "lorawan"]
10 11
11[dependencies] 12[dependencies]
12embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 13embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
@@ -17,6 +18,10 @@ embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defm
17embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } 18embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true }
18embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } 19embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true }
19embedded-io = "0.3.0" 20embedded-io = "0.3.0"
21embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["sx126x", "time", "defmt"], optional = true }
22
23lorawan-device = { version = "0.8.0", default-features = false, features = ["async"], optional = true }
24lorawan = { version = "0.7.1", default-features = false, features = ["default-crypto"], optional = true }
20 25
21defmt = "0.3" 26defmt = "0.3"
22defmt-rtt = "0.3" 27defmt-rtt = "0.3"
diff --git a/examples/nrf/src/bin/lora_p2p_report.rs b/examples/nrf/src/bin/lora_p2p_report.rs
new file mode 100644
index 000000000..d512b83f6
--- /dev/null
+++ b/examples/nrf/src/bin/lora_p2p_report.rs
@@ -0,0 +1,78 @@
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::{interrupt, 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
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) {
21 let p = embassy_nrf::init(Default::default());
22 let mut spi_config = spim::Config::default();
23 spi_config.frequency = spim::Frequency::M16;
24
25 let mut radio = {
26 let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
27 let spim = spim::Spim::new(p.TWISPI1, irq, p.P1_11, p.P1_13, p.P1_12, spi_config);
28
29 let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
30 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
31 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
32 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
33 let antenna_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
34 let antenna_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
35
36 match Sx126xRadio::new(spim, cs, reset, antenna_rx, antenna_tx, dio1, busy, false).await {
37 Ok(r) => r,
38 Err(err) => {
39 info!("Sx126xRadio error = {}", err);
40 return;
41 }
42 }
43 };
44
45 let mut debug_indicator = Output::new(p.P1_03, Level::Low, OutputDrive::Standard);
46 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
47
48 start_indicator.set_high();
49 Timer::after(Duration::from_secs(5)).await;
50 start_indicator.set_low();
51
52 loop {
53 let rf_config = RfConfig {
54 frequency: 903900000, // channel in Hz
55 bandwidth: Bandwidth::_250KHz,
56 spreading_factor: SpreadingFactor::_10,
57 coding_rate: CodingRate::_4_8,
58 };
59
60 let mut buffer = [00u8; 100];
61
62 // P2P receive
63 match radio.rx(rf_config, &mut buffer).await {
64 Ok((buffer_len, rx_quality)) => info!(
65 "RX received = {:?} with length = {} rssi = {} snr = {}",
66 &buffer[0..buffer_len],
67 buffer_len,
68 rx_quality.rssi(),
69 rx_quality.snr()
70 ),
71 Err(err) => info!("RX error = {}", err),
72 }
73
74 debug_indicator.set_high();
75 Timer::after(Duration::from_secs(2)).await;
76 debug_indicator.set_low();
77 }
78}
diff --git a/examples/nrf/src/bin/lora_p2p_sense.rs b/examples/nrf/src/bin/lora_p2p_sense.rs
new file mode 100644
index 000000000..b9768874b
--- /dev/null
+++ b/examples/nrf/src/bin/lora_p2p_sense.rs
@@ -0,0 +1,125 @@
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::{interrupt, 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
22// Message bus: queue of 2, 1 subscriber (Lora P2P), 2 publishers (temperature, motion detection)
23static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new();
24
25#[derive(Clone, defmt::Format)]
26enum Message {
27 Temperature(i32),
28 MotionDetected,
29}
30
31#[embassy_executor::task]
32async fn temperature_task(publisher: Publisher<'static, CriticalSectionRawMutex, Message, 2, 1, 2>) {
33 // Publish a fake temperature every 43 seconds, minimizing LORA traffic.
34 loop {
35 Timer::after(Duration::from_secs(43)).await;
36 publisher.publish(Message::Temperature(9)).await;
37 }
38}
39
40#[embassy_executor::task]
41async fn motion_detection_task(publisher: Publisher<'static, CriticalSectionRawMutex, Message, 2, 1, 2>) {
42 // Publish a fake motion detection every 79 seconds, minimizing LORA traffic.
43 loop {
44 Timer::after(Duration::from_secs(79)).await;
45 publisher.publish(Message::MotionDetected).await;
46 }
47}
48
49#[embassy_executor::main]
50async fn main(spawner: Spawner) {
51 let p = embassy_nrf::init(Default::default());
52 // set up to funnel temperature and motion detection events to the Lora Tx task
53 let mut lora_tx_subscriber = unwrap!(MESSAGE_BUS.subscriber());
54 let temperature_publisher = unwrap!(MESSAGE_BUS.publisher());
55 let motion_detection_publisher = unwrap!(MESSAGE_BUS.publisher());
56
57 let mut spi_config = spim::Config::default();
58 spi_config.frequency = spim::Frequency::M16;
59
60 let mut radio = {
61 let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
62 let spim = spim::Spim::new(p.TWISPI1, irq, p.P1_11, p.P1_13, p.P1_12, spi_config);
63
64 let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard);
65 let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard);
66 let dio1 = Input::new(p.P1_15.degrade(), Pull::Down);
67 let busy = Input::new(p.P1_14.degrade(), Pull::Down);
68 let antenna_rx = Output::new(p.P1_05.degrade(), Level::Low, OutputDrive::Standard);
69 let antenna_tx = Output::new(p.P1_07.degrade(), Level::Low, OutputDrive::Standard);
70
71 match Sx126xRadio::new(spim, cs, reset, antenna_rx, antenna_tx, dio1, busy, false).await {
72 Ok(r) => r,
73 Err(err) => {
74 info!("Sx126xRadio error = {}", err);
75 return;
76 }
77 }
78 };
79
80 let mut start_indicator = Output::new(p.P1_04, Level::Low, OutputDrive::Standard);
81
82 start_indicator.set_high();
83 Timer::after(Duration::from_secs(5)).await;
84 start_indicator.set_low();
85
86 match radio.lora.sleep().await {
87 Ok(()) => info!("Sleep successful"),
88 Err(err) => info!("Sleep unsuccessful = {}", err),
89 }
90
91 unwrap!(spawner.spawn(temperature_task(temperature_publisher)));
92 unwrap!(spawner.spawn(motion_detection_task(motion_detection_publisher)));
93
94 loop {
95 let message = lora_tx_subscriber.next_message_pure().await;
96
97 let tx_config = TxConfig {
98 // 11 byte maximum payload for Bandwidth 125 and SF 10
99 pw: 10, // up to 20
100 rf: RfConfig {
101 frequency: 903900000, // channel in Hz, not MHz
102 bandwidth: Bandwidth::_250KHz,
103 spreading_factor: SpreadingFactor::_10,
104 coding_rate: CodingRate::_4_8,
105 },
106 };
107
108 let mut buffer = [0x00u8];
109 match message {
110 Message::Temperature(temperature) => buffer[0] = temperature as u8,
111 Message::MotionDetected => buffer[0] = 0x01u8,
112 };
113
114 // unencrypted
115 match radio.tx(tx_config, &buffer).await {
116 Ok(ret_val) => info!("TX ret_val = {}", ret_val),
117 Err(err) => info!("TX error = {}", err),
118 }
119
120 match radio.lora.sleep().await {
121 Ok(()) => info!("Sleep successful"),
122 Err(err) => info!("Sleep unsuccessful = {}", err),
123 }
124 }
125}