From 50bcdc4d1d77d9c5c4270f53ff60d8b8ef4f04d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojciech=20Przytu=C5=82a?= Date: Sat, 22 Jun 2024 19:40:22 +0200 Subject: [PATCH] 802.15.4 raw stack driver examples --- examples/ieee802154.rs | 54 ++++++++++++++++++++++++ examples/ieee802154_rx.rs | 50 ++++++++++++++++++++++ examples/ieee802154_rx_tx.rs | 81 ++++++++++++++++++++++++++++++++++++ examples/ieee802154_tx.rs | 60 ++++++++++++++++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 examples/ieee802154.rs create mode 100644 examples/ieee802154_rx.rs create mode 100644 examples/ieee802154_rx_tx.rs create mode 100644 examples/ieee802154_tx.rs diff --git a/examples/ieee802154.rs b/examples/ieee802154.rs new file mode 100644 index 00000000..bfd5471b --- /dev/null +++ b/examples/ieee802154.rs @@ -0,0 +1,54 @@ +//! An example showing use of IEEE 802.15.4 networking. + +#![no_main] +#![no_std] +use libtock::console::Console; +use libtock::ieee802154::{Ieee802154, RxOperator as _, RxRingBuffer, RxSingleBufferOperator}; +use libtock::runtime::{set_main, stack_size}; + +set_main! {main} +stack_size! {0x600} + +fn main() { + // Configure the radio + let pan: u16 = 0xcafe; + let addr_short: u16 = 0xdead; + let addr_long: u64 = 0xdead_dad; + let tx_power: i8 = -3; + let channel: u8 = 11; + + Ieee802154::set_pan(pan); + Ieee802154::set_address_short(addr_short); + Ieee802154::set_address_long(addr_long); + Ieee802154::set_tx_power(tx_power).unwrap(); + Ieee802154::set_channel(channel).unwrap(); + + // Don't forget to commit the config! + Ieee802154::commit_config(); + + // Turn the radio on + Ieee802154::radio_on().unwrap(); + assert!(Ieee802154::is_on()); + + // Transmit a frame + Ieee802154::transmit_frame(b"foobar").unwrap(); + + Console::write(b"Transmitted frame!\n").unwrap(); + + // Showcase receiving to a single buffer - there is a risk of losing some frames. + // See [RxSingleBufferOperator] docs for more details. + rx_single_buffer(); +} + +fn rx_single_buffer() { + let mut buf = RxRingBuffer::<2>::new(); + let mut operator = RxSingleBufferOperator::new(&mut buf); + + let frame1 = operator.receive_frame().unwrap(); + // Access frame1 data here: + let _body_len = frame1.payload_len; + let _first_body_byte = frame1.body[0]; + + let _frame2 = operator.receive_frame().unwrap(); + // Access frame2 data here +} diff --git a/examples/ieee802154_rx.rs b/examples/ieee802154_rx.rs new file mode 100644 index 00000000..cad7c2d7 --- /dev/null +++ b/examples/ieee802154_rx.rs @@ -0,0 +1,50 @@ +//! An example showing use of IEEE 802.15.4 networking. +//! It infinitely received a frame and prints its content to Console. + +#![no_main] +#![no_std] +use core::fmt::Write as _; +use libtock::console::Console; +use libtock::ieee802154::{Ieee802154, RxOperator as _, RxRingBuffer, RxSingleBufferOperator}; +use libtock::runtime::{set_main, stack_size}; + +set_main! {main} +stack_size! {0x600} + +fn main() { + // Configure the radio + let pan: u16 = 0xcafe; + let addr_short: u16 = 0xdead; + let addr_long: u64 = 0xdead_dad; + let tx_power: i8 = 5; + let channel: u8 = 11; + + Ieee802154::set_pan(pan); + Ieee802154::set_address_short(addr_short); + Ieee802154::set_address_long(addr_long); + Ieee802154::set_tx_power(tx_power).unwrap(); + Ieee802154::set_channel(channel).unwrap(); + + // Don't forget to commit the config! + Ieee802154::commit_config(); + + // Turn the radio on + Ieee802154::radio_on().unwrap(); + assert!(Ieee802154::is_on()); + + let mut buf = RxRingBuffer::<2>::new(); + let mut operator = RxSingleBufferOperator::new(&mut buf); + loop { + let frame = operator.receive_frame().unwrap(); + + let body_len = frame.payload_len; + writeln!( + Console::writer(), + "Received frame with body of len {}: {} {:?}!\n", + body_len, + core::str::from_utf8(&frame.body).unwrap(), + &frame.body[..frame.body.len() - core::mem::size_of::()] + ) + .unwrap(); + } +} diff --git a/examples/ieee802154_rx_tx.rs b/examples/ieee802154_rx_tx.rs new file mode 100644 index 00000000..3a940130 --- /dev/null +++ b/examples/ieee802154_rx_tx.rs @@ -0,0 +1,81 @@ +//! An example showing use of IEEE 802.15.4 networking. +//! It infinitely sends a frame with a constantly incremented counter, +//! and after each send receives a frame and prints it to Console. + +#![no_main] +#![no_std] +use core::fmt::Write as _; +use libtock::alarm::{Alarm, Milliseconds}; +use libtock::console::Console; +use libtock::ieee802154::{Ieee802154, RxOperator as _, RxRingBuffer, RxSingleBufferOperator}; +use libtock::runtime::{set_main, stack_size}; + +set_main! {main} +stack_size! {0x600} + +fn main() { + // Configure the radio + let pan: u16 = 0xcafe; + let addr_short: u16 = 0xdead; + let addr_long: u64 = 0xdead_dad; + let tx_power: i8 = 5; + let channel: u8 = 11; + + Ieee802154::set_pan(pan); + Ieee802154::set_address_short(addr_short); + Ieee802154::set_address_long(addr_long); + Ieee802154::set_tx_power(tx_power).unwrap(); + Ieee802154::set_channel(channel).unwrap(); + + // Don't forget to commit the config! + Ieee802154::commit_config(); + + // Turn the radio on + Ieee802154::radio_on().unwrap(); + assert!(Ieee802154::is_on()); + + let mut buf = RxRingBuffer::<2>::new(); + let mut operator = RxSingleBufferOperator::new(&mut buf); + + let mut counter = 0_usize; + let mut buf = [ + b'f', b'r', b'a', b'm', b'e', b' ', b'n', b'.', b'o', b'.', b' ', b'\0', b'\0', b'\0', + b'\0', + ]; + fn set_buf_cnt(buf: &mut [u8], counter: &mut usize) { + let buf_len = buf.len(); + let buf_cnt = &mut buf[buf_len - core::mem::size_of_val(&counter)..]; + buf_cnt.copy_from_slice(&counter.to_be_bytes()); + } + + loop { + Alarm::sleep_for(Milliseconds(1000)).unwrap(); + + set_buf_cnt(&mut buf, &mut counter); + + // Transmit a frame + Ieee802154::transmit_frame(&buf).unwrap(); + + writeln!(Console::writer(), "Transmitted frame {}!\n", counter).unwrap(); + + let frame = operator.receive_frame().unwrap(); + + let body_len = frame.payload_len; + writeln!( + Console::writer(), + "Received frame with body of len {}: {}-{} {:?}!\n", + body_len, + core::str::from_utf8(&frame.body[..frame.body.len() - core::mem::size_of::()]) + .unwrap_or(""), + usize::from_le_bytes( + frame.body[frame.body.len() - core::mem::size_of::()..] + .try_into() + .unwrap() + ), + frame.body + ) + .unwrap(); + + counter += 1; + } +} diff --git a/examples/ieee802154_tx.rs b/examples/ieee802154_tx.rs new file mode 100644 index 00000000..249b36e7 --- /dev/null +++ b/examples/ieee802154_tx.rs @@ -0,0 +1,60 @@ +//! An example showing use of IEEE 802.15.4 networking. +//! It infinitely sends a frame with a constantly incremented counter. + +#![no_main] +#![no_std] +use core::fmt::Write as _; + +use libtock::alarm::{Alarm, Milliseconds}; +use libtock::console::Console; +use libtock::ieee802154::Ieee802154; +use libtock::runtime::{set_main, stack_size}; + +set_main! {main} +stack_size! {0x600} + +fn main() { + // Configure the radio + let pan: u16 = 0xcafe; + let addr_short: u16 = 0xdead; + let addr_long: u64 = 0xdead_dad; + let tx_power: i8 = 5; + let channel: u8 = 11; + + Ieee802154::set_pan(pan); + Ieee802154::set_address_short(addr_short); + Ieee802154::set_address_long(addr_long); + Ieee802154::set_tx_power(tx_power).unwrap(); + Ieee802154::set_channel(channel).unwrap(); + + // Don't forget to commit the config! + Ieee802154::commit_config(); + + // Turn the radio on + Ieee802154::radio_on().unwrap(); + assert!(Ieee802154::is_on()); + + let mut counter = 0_usize; + let mut buf = [ + b'f', b'r', b'a', b'm', b'e', b' ', b'n', b'.', b'o', b'.', b' ', b'\0', b'\0', b'\0', + b'\0', + ]; + fn set_buf_cnt(buf: &mut [u8], counter: &mut usize) { + let buf_len = buf.len(); + let buf_cnt = &mut buf[buf_len - core::mem::size_of_val(&counter)..]; + buf_cnt.copy_from_slice(&counter.to_be_bytes()); + } + + loop { + Alarm::sleep_for(Milliseconds(1000)).unwrap(); + + set_buf_cnt(&mut buf, &mut counter); + + // Transmit a frame + Ieee802154::transmit_frame(&buf).unwrap(); + + writeln!(Console::writer(), "Transmitted frame {}!\n", counter).unwrap(); + + counter += 1; + } +}