Skip to content

Commit

Permalink
Add the esp-ieee802154 package to the repository (#1554)
Browse files Browse the repository at this point in the history
* Add the `esp-ieee802154` package to the repo

* Add examples for `esp-ieee802154` package
  • Loading branch information
jessebraham authored May 15, 2024
1 parent 3c05759 commit 8a1df42
Show file tree
Hide file tree
Showing 17 changed files with 1,998 additions and 8 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exclude = [
"esp-hal",
"esp-hal-procmacros",
"esp-hal-smartled",
"esp-ieee802154",
"esp-lp-hal",
"esp-metadata",
"esp-riscv-rt",
Expand Down
31 changes: 31 additions & 0 deletions esp-ieee802154/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "esp-ieee802154"
version = "0.1.0"
edition = "2021"
rust-version = "1.76.0"
description = "Low-level IEEE 802.15.4 driver for the ESP32-C6 and ESP32-H2"
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"

[package.metadata.docs.rs]
default-target = "riscv32imac-unknown-none-elf"
features = ["esp32c6"]

[lib]
bench = false
test = false

[dependencies]
byte = "0.2.7"
critical-section = "1.1.2"
esp-hal = { version = "0.17.0", path = "../esp-hal" }
esp-wifi-sys = { git = "https://github.com/esp-rs/esp-wifi", rev = "2ceb4b3" }
heapless = "0.8.0"
ieee802154 = "0.6.1"
log = "0.4.21"
vcell = "0.1.3"

[features]
default = []
esp32c6 = ["esp-hal/esp32c6", "esp-wifi-sys/esp32c6"]
esp32h2 = ["esp-hal/esp32h2", "esp-wifi-sys/esp32h2"]
35 changes: 35 additions & 0 deletions esp-ieee802154/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# esp-ieee802154

[![Crates.io](https://img.shields.io/crates/v/esp-ieee802154?color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-ieee802154)
[![docs.rs](https://img.shields.io/docsrs/esp-ieee802154?color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-ieee802154)
![MSRV](https://img.shields.io/badge/MSRV-1.76-blue?labelColor=1C2C2E&style=flat-square)
![Crates.io](https://img.shields.io/crates/l/esp-ieee802154?style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)

Low-level [IEEE 802.15.4] driver for the ESP32-C6 and ESP32-H2.

Implements the PHY/MAC layers of the IEEE802.15.4 protocol stack, and supports sending and receiving of raw frames.

[IEEE 802.15.4]: https://en.wikipedia.org/wiki/IEEE_802.15.4

## [Documentation](https://docs.rs/crate/esp-ieee802154)

## Minimum Supported Rust Version (MSRV)

This crate is guaranteed to compile on stable Rust 1.76 and up. It _might_
compile with older versions but that may change in any new patch release.

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
any additional terms or conditions.
6 changes: 6 additions & 0 deletions esp-ieee802154/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std::{env, path::PathBuf};

fn main() {
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
println!("cargo:rustc-link-search={}", out.display());
}
130 changes: 130 additions & 0 deletions esp-ieee802154/src/compat/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use core::{ffi::VaListImpl, fmt::Write};

use log::info;

use self::str_buf::StrBuf;

mod str_buf;

#[no_mangle]
pub unsafe extern "C" fn phy_printf(format: *const u8, args: ...) {
syslog(format, args);
}

#[no_mangle]
pub unsafe extern "C" fn rtc_printf(format: *const u8, args: ...) {
syslog(format, args);
}

#[no_mangle]
pub unsafe extern "C" fn coexist_printf(format: *const u8, args: ...) {
syslog(format, args);
}

pub unsafe extern "C" fn syslog(format: *const u8, args: VaListImpl) {
let mut buf = [0u8; 512];
vsnprintf(&mut buf as *mut u8, 511, format, args);
let res_str = StrBuf::from(&buf as *const u8);
info!("{}", res_str.as_str_ref());
}

pub(crate) unsafe fn vsnprintf(
dst: *mut u8,
_n: u32,
format: *const u8,
mut args: VaListImpl,
) -> i32 {
let fmt_str_ptr = format;

let mut res_str = StrBuf::new();

let strbuf = StrBuf::from(fmt_str_ptr);
let s = strbuf.as_str_ref();

let mut format_char = ' ';
let mut is_long = false;
let mut found = false;
for c in s.chars() {
if !found {
if c == '%' {
found = true;
}

if !found {
res_str.append_char(c);
}
} else if c.is_numeric() || c == '-' || c == 'l' {
if c == 'l' {
is_long = true;
}
// ignore
} else {
// a format char
format_char = c;
}

if found && format_char != ' ' {
// have to format an arg
match format_char {
'd' => {
if is_long {
let v = args.arg::<i64>();
write!(res_str, "{}", v).ok();
} else {
let v = args.arg::<i32>();
write!(res_str, "{}", v).ok();
}
}

'u' => {
let v = args.arg::<u32>();
write!(res_str, "{}", v).ok();
}

'p' => {
let v = args.arg::<u32>();
write!(res_str, "0x{:x}", v).ok();
}

'X' => {
let v = args.arg::<u32>();
write!(res_str, "{:02x}", (v & 0xff000000) >> 24).ok();
}

'x' => {
let v = args.arg::<u32>();
write!(res_str, "{:02x}", v).ok();
}

's' => {
let v = args.arg::<u32>() as *const u8;
let vbuf = StrBuf::from(v);
write!(res_str, "{}", vbuf.as_str_ref()).ok();
}

'c' => {
let v = args.arg::<u8>();
if v != 0 {
write!(res_str, "{}", v as char).ok();
}
}

_ => {
write!(res_str, "<UNKNOWN{}>", format_char).ok();
}
}

format_char = ' ';
found = false;
is_long = false;
}
}
let mut idx = 0;
res_str.as_str_ref().chars().for_each(|c| {
*(dst.offset(idx)) = c as u8;
idx += 1;
});
*(dst.offset(idx)) = 0;

idx as i32
}
58 changes: 58 additions & 0 deletions esp-ieee802154/src/compat/str_buf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use core::fmt::Write;

pub struct StrBuf {
buffer: [u8; 512],
len: usize,
}

impl StrBuf {
pub fn new() -> StrBuf {
StrBuf {
buffer: [0u8; 512],
len: 0,
}
}

pub unsafe fn from(c_str: *const u8) -> StrBuf {
let mut res = StrBuf {
buffer: [0u8; 512],
len: 0,
};

let mut idx: usize = 0;
while *(c_str.add(idx)) != 0 {
res.buffer[idx] = *(c_str.add(idx));
idx += 1;
}

res.len = idx;
res
}

pub fn append(&mut self, s: &str) {
let mut idx: usize = self.len;
s.chars().for_each(|c| {
self.buffer[idx] = c as u8;
idx += 1;
});
self.len = idx;
}

pub fn append_char(&mut self, c: char) {
let mut idx: usize = self.len;
self.buffer[idx] = c as u8;
idx += 1;
self.len = idx;
}

pub unsafe fn as_str_ref(&self) -> &str {
core::str::from_utf8_unchecked(&self.buffer[..self.len])
}
}

impl Write for StrBuf {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
self.append(s);
Ok(())
}
}
45 changes: 45 additions & 0 deletions esp-ieee802154/src/frame.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use heapless::Vec;
use ieee802154::mac::{FrameContent, Header};

pub(crate) const FRAME_SIZE: usize = 129;
pub(crate) const FRAME_VERSION_1: u8 = 0x10; // IEEE 802.15.4 - 2006 & 2011
pub(crate) const FRAME_VERSION_2: u8 = 0x20; // IEEE 802.15.4 - 2015

const FRAME_AR_OFFSET: usize = 1;
const FRAME_AR_BIT: u8 = 0x20;
const FRAME_VERSION_OFFSET: usize = 2;
const FRAME_VERSION_MASK: u8 = 0x30;

/// IEEE 802.15.4 MAC frame
#[derive(Debug, Clone)]
pub struct Frame {
/// Header
pub header: Header,
/// Content
pub content: FrameContent,
/// Payload
pub payload: Vec<u8, FRAME_SIZE>,
/// This is a 2-byte CRC checksum
pub footer: [u8; 2],
}

/// IEEE 802.15.4 MAC frame which has been received
#[derive(Debug, Clone)]
pub struct ReceivedFrame {
/// Frame
pub frame: Frame,
/// Receiver channel
pub channel: u8,
/// Received Signal Strength Indicator (RSSI)
pub rssi: i8,
/// Link Quality Indication (LQI)
pub lqi: u8,
}

pub(crate) fn frame_is_ack_required(frame: &[u8]) -> bool {
(frame[FRAME_AR_OFFSET] & FRAME_AR_BIT) != 0
}

pub(crate) fn frame_get_version(frame: &[u8]) -> u8 {
frame[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK
}
Loading

0 comments on commit 8a1df42

Please sign in to comment.