Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adv_nonconnectable_scannable_undirected #2

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 27 additions & 19 deletions examples/src/bin/beacon.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#![no_std]
#![no_main]

use defmt::info;
use defmt::{info, unwrap};
use embassy_executor::Spawner;
use embassy_nrf::{bind_interrupts, peripherals, radio};
use embassy_time::Duration;
use jewel::{phy::MAX_PDU_LENGTH, AdvData, Broadcaster, Flags};
use jewel::{ll::LinkLayer, phy::MAX_PDU_LENGTH, AdvData, Flags};
use jewel_nrf::RadioImpl;
use {defmt_rtt as _, panic_probe as _};

Expand All @@ -19,24 +19,32 @@ async fn main(_spawner: Spawner) {
config.hfclk_source = embassy_nrf::config::HfclkSource::ExternalXtal;
let p = embassy_nrf::init(config);

let mut buffer = [0u8; MAX_PDU_LENGTH];

info!("Starting BLE radio");
let mut radio: RadioImpl<'_, _> = radio::ble::Radio::new(p.RADIO, Irqs).into();

let mut broadcaster = Broadcaster::new(
&mut radio,
Duration::from_millis(300),
AdvData::empty()
.set_flags(Flags::discoverable())
.set_uuids16(&[0x0918])
.set_complete_local_name("HelloRust"),
&mut buffer,
)
.unwrap();

loop {
info!("Sending packet");
broadcaster.transmit().await.unwrap();
}
let adv_data = AdvData::empty()
.set_flags(Flags::discoverable())
.set_uuids16(&[0x0918])
.set_shortened_local_name("Hello");

let mut adv_data_buffer = [0u8; MAX_PDU_LENGTH];
let len = adv_data.bytes(&mut adv_data_buffer);
let adv_data_buffer = &adv_data_buffer[..len];

let scan_data = AdvData::empty().set_complete_local_name("HelloRust");

let mut scan_data_buffer = [0u8; MAX_PDU_LENGTH];
let len = scan_data.bytes(&mut scan_data_buffer);
let scan_data_buffer = &scan_data_buffer[..len];

let ll = LinkLayer::new(&mut radio);

unwrap!(
ll.adv_nonconnectable_scannable_undirected(
Duration::from_millis(500),
adv_data_buffer,
scan_data_buffer,
)
.await
);
}
1 change: 1 addition & 0 deletions jewel-nrf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ embassy-nrf = { version = "0.1.0", features = [
] }

[features]
default = ["nrf52840"]
nrf52840 = ["embassy-nrf/nrf52840"]
nrf52833 = ["embassy-nrf/nrf52833"]
6 changes: 6 additions & 0 deletions jewel-nrf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ impl<'d, T: Instance> Radio for RadioImpl<'d, T> {
self.radio.receive(buffer).await
}

fn crc_ok(&self) -> bool {
let radio: embassy_nrf::pac::RADIO = unsafe { mem::transmute(()) };
//radio.events_crcok.read().bits() != 0
radio.crcstatus.read().crcstatus().is_crcok()
}

fn device_address(&self) -> Address {
let ficr: embassy_nrf::pac::FICR = unsafe { mem::transmute(()) };
let device_address_public = ficr.deviceaddrtype.read().deviceaddrtype().is_public();
Expand Down
24 changes: 18 additions & 6 deletions jewel/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions jewel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,9 @@ embassy-time = { version = "0.3.0", default-features = false, features = [
"defmt",
] }
rand = { version = "0.8.5", default-features = false, features = ["small_rng"] }

[patch.crates-io]
embassy-executor = { git = "https://github.com/embassy-rs/embassy", branch = "main" }
embassy-futures = { git = "https://github.com/embassy-rs/embassy", branch = "main" }
embassy-nrf = { git = "https://github.com/embassy-rs/embassy", branch = "main" }
embassy-time = { git = "https://github.com/embassy-rs/embassy", branch = "main" }
12 changes: 11 additions & 1 deletion jewel/src/gap/adv_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use uuid::*;

use defmt::Format;

use crate::phy::MAX_PDU_LENGTH;

#[derive(Debug, Clone, PartialEq, Eq, Format, Default)]
#[non_exhaustive]
pub struct AdvData<'a> {
Expand Down Expand Up @@ -44,6 +46,14 @@ impl<'a> AdvData<'a> {
self
}

pub fn set_shortened_local_name(mut self, local_name: &'a str) -> Self {
self.local_name = Some(LocalName {
name: local_name.as_bytes(),
r#type: LocalNameType::Shortened,
});
self
}

pub fn set_uuids16(mut self, uuids: &'a [Uuid16]) -> Self {
self.uuids16 = Some(List(uuids));
self
Expand All @@ -61,7 +71,7 @@ impl<'a> AdvData<'a> {
}

impl<'a> AdvData<'a> {
pub(crate) fn bytes(&self, dest: &mut [u8]) -> usize {
pub fn bytes(&self, dest: &mut [u8]) -> usize {
let mut start = 0;
if let Some(flags) = &self.flags {
start += 1;
Expand Down
91 changes: 0 additions & 91 deletions jewel/src/gap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,94 +3,3 @@
mod adv_struct;

pub use adv_struct::*;
use embassy_time::Duration;
use rand::rngs::SmallRng;

use crate::{
ll::{Address, AddressAndData, AdvNonconnInd, Advertising, LinkLayer},
phy::{Radio, MAX_PDU_LENGTH},
};

pub struct Broadcaster<'r, 'a, R: Radio> {
ll: LinkLayer<'r, R, Advertising<'a, SmallRng>>,

// you should never access this buffer directly
// it's only used to keep borrow of the buffer
#[allow(dead_code)]
_buffer: &'a [u8],
}

/// Brodcast provile. Advertise legacy packages on the 3 primary advertising channels.
/// ```no_run
/// #![no_std]
/// #![no_main]
///
/// use defmt::info;
/// use embassy_executor::Spawner;
/// use embassy_nrf::{bind_interrupts, peripherals, radio};
/// use embassy_time::Duration;
/// use jewel::{Address, AdvData, Broadcaster, Flags};
/// use {defmt_rtt as _, panic_probe as _};
///
/// bind_interrupts!(struct Irqs {
/// RADIO => radio::InterruptHandler<peripherals::RADIO>;
/// });
///
/// #[embassy_executor::main]
/// async fn main(_spawner: Spawner) {
/// let mut config = embassy_nrf::config::Config::default();
/// config.hfclk_source = embassy_nrf::config::HfclkSource::ExternalXtal;
/// let p = embassy_nrf::init(config);
///
/// info!("Starting BLE radio");
/// let mut radio = radio::ble::Radio::new(p.RADIO, Irqs);
/// let mut broadcaster = Broadcaster::new(
/// &mut radio,
/// Duration::from_millis(300),
/// Address::new_random(0xffe1e8d0dc27),
/// AdvData::empty()
/// .set_flags(Flags::discoverable())
/// .set_uuids16(&[0x0918])
/// .set_complete_local_name("HelloRust"),
/// )
/// .unwrap();
///
/// loop {
/// info!("Sending packet");
/// broadcaster.transmit().await;
/// }
/// }
/// ```
impl<'r, 'a, R: Radio> Broadcaster<'r, 'a, R> {
/// Create a new broadcaster
pub fn new(
radio: &'r mut R,
interval: Duration,
data: AdvData<'a>,
buffer: &'a mut [u8; MAX_PDU_LENGTH],
) -> Result<Broadcaster<'r, 'a, R>, R::Error> {
let mut body_buffer = [0u8; MAX_PDU_LENGTH];
let len = data.bytes(&mut body_buffer);

let addr = radio.device_address();
let pdu = AdvNonconnInd::new(addr, &body_buffer[..len]);

pdu.bytes(buffer);

let ll = LinkLayer::new(radio);

// FIXME: it should be a better way to do this
let ll = ll.advertise(interval, buffer);

Ok(Broadcaster {
ll,
_buffer: buffer,
})
}

/// Transmit the packet respecting the given interval
/// You should call this method before the interval time
pub async fn transmit(&mut self) -> Result<(), R::Error> {
self.ll.transmit().await
}
}
2 changes: 1 addition & 1 deletion jewel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![allow(dead_code)] // while in development

pub mod gap;
pub(crate) mod ll;
pub mod ll;
pub mod phy;

pub use gap::*;
Expand Down
21 changes: 20 additions & 1 deletion jewel/src/ll/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@
/// Ref: https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/low-energy-controller/link-layer-specification.html#UUID-3815b05a-b69c-4e3c-5897-c8d3baa4fc30
use defmt::Format;

#[derive(Debug, Clone, Eq, PartialEq, Format)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Address {
// Little endian address
address_le: [u8; 6],
pub r#type: AddressType,
}

impl Format for Address {
fn format(&self, f: defmt::Formatter) {
defmt::write!(f, "Address({:#08X}, {:?})", self.u64_address(), self.r#type);
}
}

#[derive(Debug, Clone, Copy, Eq, PartialEq, Format)]
pub enum AddressType {
Public,
Expand Down Expand Up @@ -75,4 +81,17 @@ impl Address {
pub fn bytes(&self) -> [u8; 6] {
self.address_le
}

fn u64_address(&self) -> u64 {
u64::from_le_bytes([
self.address_le[0],
self.address_le[1],
self.address_le[2],
self.address_le[3],
self.address_le[4],
self.address_le[5],
0,
0,
])
}
}
17 changes: 11 additions & 6 deletions jewel/src/ll/adv/pdu.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Ref: [Core 6.B.2.3.1](https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-54/out/en/low-energy-controller/link-layer-specification.html#UUID-8909a735-7143-2804-ce68-c535a4fc011d)

use crate::ll::Address;
use defmt::trace;
use defmt::Format;

use super::Header;
Expand Down Expand Up @@ -115,24 +116,28 @@ pub trait TwoAddress: Sized {
}

let (header, pdu) = bytes.split_at(2);

let header = Header::parse(header.try_into().unwrap());
let header = Header::parse(header.try_into().map_err(|_| ParseError::InvalidHeader)?);
if header.flags.pdu_type != Self::PDU_TYPE {
return Err(ParseError::InvalidType);
}
//trace!("Header: {:?}", header);

if header.length as usize > 37 {
return Err(ParseError::InvalidLength);
}

let (first, second) = pdu.split_at(6);

let first = Address::new_le(
first.try_into().unwrap(),
first.try_into().map_err(|_| ParseError::InvalidLength)?,
Header::bit_to_address_type(header.flags.tx_add),
);
//trace!("First: {:?}", first);

let second = Address::new_le(
second.try_into().unwrap(),
second[0..6]
.try_into()
.map_err(|_| ParseError::InvalidLength)?,
Header::bit_to_address_type(header.flags.rx_add),
);

Expand Down Expand Up @@ -557,8 +562,8 @@ mod scan_req {

#[derive(Debug, Clone, PartialEq, Eq, Format)]
pub struct ScanReq {
scan_address: Address,
adv_address: Address,
pub(crate) scan_address: Address,
pub(crate) adv_address: Address,
}

impl ScanReq {
Expand Down
Loading