Skip to content

Commit 2816eb9

Browse files
committed
Expose more fields in beacon as pub
This allows to not just parse but also generate these frames.
1 parent c57fb7e commit 2816eb9

File tree

4 files changed

+82
-93
lines changed

4 files changed

+82
-93
lines changed

Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[package]
22
name = "ieee802154"
3-
version = "0.6.1"
3+
version = "0.7.0"
44
authors = [
55
"Erik Henriksson <[email protected]>",
66
"Hanno Braun <[email protected]>",
77
"Ryan Kurte <[email protected]>",
88
]
9-
edition = "2018"
9+
edition = "2021"
1010

1111
description = "Partial implementation of the IEEE 802.15.4 standard for low-rate wireless personal area networks"
1212
documentation = "https://docs.rs/ieee802154"
@@ -17,11 +17,14 @@ categories = ["embedded", "network-programming", "no-std"]
1717
keywords = ["WPAN"]
1818

1919
[features]
20+
defmt = ["dep:defmt", "heapless/defmt-03"]
21+
serde = ["dep:serde"]
2022

2123
[dependencies]
2224
hash32 = "0.2.1"
2325
hash32-derive = "0.1"
2426
byte = "0.2.7"
27+
heapless = "0.8.0"
2528
defmt = { version = ">=0.2.0,<0.4", optional = true }
2629

2730
[dependencies.ccm]

src/mac/beacon.rs

Lines changed: 72 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
55
use byte::{check_len, BytesExt, TryRead, TryWrite};
66
use core::convert::From;
7-
use core::mem;
87

98
use crate::mac::{ExtendedAddress, ShortAddress};
109

@@ -40,11 +39,11 @@ impl From<BeaconOrder> for u8 {
4039
}
4140
}
4241

43-
/// Superframe order, amount of time during wich this superframe is active
42+
/// Superframe order, amount of time during which this superframe is active
4443
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
4544
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
4645
pub enum SuperframeOrder {
47-
/// Ammount of time that the superframe is active
46+
/// Amount of time that the superframe is active
4847
///
4948
/// superframe duration = base superframe duration × (2 ^ superframe order)
5049
SuperframeOrder(u8),
@@ -83,15 +82,15 @@ pub struct SuperframeSpecification {
8382
///
8483
/// Beacon interval = BaseSuperframeDuration × (2 ^ BeaconOrder)
8584
pub beacon_order: BeaconOrder,
86-
/// Superframe order, amount of time during wich this superframe is active
85+
/// Superframe order, amount of time during which this superframe is active
8786
pub superframe_order: SuperframeOrder,
8887
/// final contention access period slot used
8988
pub final_cap_slot: u8,
9089
/// Limit receiving of beacons for a period. Not used if beacon_order is OnDemand.
9190
pub battery_life_extension: bool,
9291
/// Frame sent by a coordinator
9392
pub pan_coordinator: bool,
94-
/// The coordinator acceppts associations to the PAN
93+
/// The coordinator accepts associations to the PAN
9594
pub association_permit: bool,
9695
}
9796

@@ -156,7 +155,7 @@ impl TryWrite for SuperframeSpecification {
156155
/// Direction of data
157156
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
158157
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
159-
enum Direction {
158+
pub enum Direction {
160159
/// Receive data
161160
Receive,
162161
/// Transmit data
@@ -168,13 +167,13 @@ enum Direction {
168167
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
169168
pub struct GuaranteedTimeSlotDescriptor {
170169
/// Device short address used by this slot
171-
short_address: ShortAddress,
170+
pub short_address: ShortAddress,
172171
/// Slot start
173-
starting_slot: u8,
172+
pub starting_slot: u8,
174173
/// Slot length
175-
length: u8,
174+
pub length: u8,
176175
/// Direction of the slot, either transmit or receive
177-
direction: Direction,
176+
pub direction: Direction,
178177
}
179178

180179
impl GuaranteedTimeSlotDescriptor {
@@ -234,46 +233,44 @@ const COUNT_MASK: u8 = 0b0000_0111;
234233
const PERMIT: u8 = 0b1000_0000;
235234

236235
/// Information of the guaranteed time slots (GTSs)
237-
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
236+
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
238237
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
239238
pub struct GuaranteedTimeSlotInformation {
240239
/// Permit GTS
241240
pub permit: bool,
242-
slot_count: usize,
243-
slots: [GuaranteedTimeSlotDescriptor; 7],
241+
/// Time slot information
242+
pub slots: heapless::Vec<GuaranteedTimeSlotDescriptor, 7>,
244243
}
245244

246245
impl GuaranteedTimeSlotInformation {
247246
/// Create a new empty GTS information
248247
pub fn new() -> Self {
249248
GuaranteedTimeSlotInformation {
250249
permit: false,
251-
slot_count: 0,
252-
slots: [GuaranteedTimeSlotDescriptor::new(); 7],
250+
slots: heapless::Vec::new(),
253251
}
254252
}
255253

256254
/// Get the slots as a slice
257255
pub fn slots(&self) -> &[GuaranteedTimeSlotDescriptor] {
258-
&self.slots[..self.slot_count]
256+
self.slots.as_slice()
259257
}
260258
}
261259

262260
impl TryWrite for GuaranteedTimeSlotInformation {
263261
fn try_write(self, bytes: &mut [u8], _ctx: ()) -> byte::Result<usize> {
264262
let offset = &mut 0;
265-
assert!(self.slot_count <= 7);
263+
assert!(self.slots.capacity() <= 7);
266264
let permit = if self.permit { PERMIT } else { 0 };
267265

268-
let header = ((self.slot_count as u8) & COUNT_MASK) | permit;
266+
let header = ((self.slots.len() as u8) & COUNT_MASK) | permit;
269267
bytes.write(offset, header)?;
270268

271-
if self.slot_count > 0 {
269+
if !self.slots.is_empty() {
272270
let direction_mask = {
273271
let mut dir = 0x01;
274272
let mut direction_mask = 0u8;
275-
for n in 0..self.slot_count {
276-
let slot = self.slots[n];
273+
for slot in &self.slots {
277274
if slot.direction_transmit() {
278275
direction_mask = direction_mask | dir;
279276
}
@@ -284,8 +281,8 @@ impl TryWrite for GuaranteedTimeSlotInformation {
284281

285282
bytes.write(offset, direction_mask)?;
286283

287-
for n in 0..self.slot_count {
288-
bytes.write(offset, self.slots[n])?;
284+
for slot in self.slots {
285+
bytes.write(offset, slot)?;
289286
}
290287
}
291288
Ok(*offset)
@@ -298,16 +295,12 @@ impl TryRead<'_> for GuaranteedTimeSlotInformation {
298295
let byte: u8 = bytes.read(offset)?;
299296
let slot_count = (byte & COUNT_MASK) as usize;
300297
let permit = (byte & PERMIT) == PERMIT;
301-
let mut slots = [GuaranteedTimeSlotDescriptor {
302-
short_address: ShortAddress::broadcast(),
303-
starting_slot: 0,
304-
length: 0,
305-
direction: Direction::Receive,
306-
}; 7];
298+
let mut slots = heapless::Vec::new();
299+
assert!(slot_count <= slots.capacity());
307300
if slot_count > 0 {
308301
check_len(&bytes[*offset..], 2 + (3 * slot_count))?;
309302
let mut direction_mask: u8 = bytes.read(offset)?;
310-
for n in 0..slot_count {
303+
for _ in 0..slot_count {
311304
let mut slot: GuaranteedTimeSlotDescriptor =
312305
bytes.read(offset)?;
313306
let direction = if direction_mask & 0b1 == 0b1 {
@@ -317,17 +310,12 @@ impl TryRead<'_> for GuaranteedTimeSlotInformation {
317310
};
318311
slot.set_direction(direction);
319312
direction_mask = direction_mask >> 1;
320-
slots[n] = slot;
313+
slots.push(slot).expect(
314+
"slot_count can never be larger than Vec::capacity",
315+
);
321316
}
322317
}
323-
Ok((
324-
Self {
325-
permit,
326-
slot_count,
327-
slots,
328-
},
329-
*offset,
330-
))
318+
Ok((Self { permit, slots }, *offset))
331319
}
332320
}
333321

@@ -338,7 +326,7 @@ const EXTENDED_MASK: u8 = 0b0111_0000;
338326
///
339327
/// Addresses to devices that has pending messages with the coordinator
340328
///
341-
/// ```notrust
329+
/// ```txt
342330
/// +--------+-----------------+--------------------+
343331
/// | Header | Short Addresses | Extended Addresses |
344332
/// +--------+-----------------+--------------------+
@@ -347,64 +335,66 @@ const EXTENDED_MASK: u8 = 0b0111_0000;
347335
///
348336
/// ## Header
349337
///
350-
/// ```notrust
338+
/// ```txt
351339
/// +-------------+----------+----------------+----------+
352340
/// | Short Count | Reserved | Extended Count | Reserved |
353341
/// +-------------+----------+----------------+----------+
354342
/// 0 - 2 3 4 - 6 7 bit
355343
/// ```
356-
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
344+
#[derive(Clone, Default, Debug, Eq, Hash, PartialEq)]
357345
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
358346
pub struct PendingAddress {
359-
short_address_count: usize,
360-
short_addresses: [ShortAddress; 7],
361-
extended_address_count: usize,
362-
extended_addresses: [ExtendedAddress; 7],
347+
/// List of pending [`ShortAddress`]es
348+
pub short_addresses: heapless::Vec<ShortAddress, 7>,
349+
/// List of pending [`ExtendedAddress`]es
350+
pub extended_addresses: heapless::Vec<ExtendedAddress, 7>,
363351
}
364352

365353
impl PendingAddress {
366354
/// Create a new empty PendingAddress struct
367-
pub fn new() -> Self {
368-
PendingAddress {
369-
short_address_count: 0,
370-
short_addresses: [ShortAddress::broadcast(); 7],
371-
extended_address_count: 0,
372-
extended_addresses: [ExtendedAddress::broadcast(); 7],
355+
pub const fn new() -> Self {
356+
Self {
357+
short_addresses: heapless::Vec::new(),
358+
extended_addresses: heapless::Vec::new(),
373359
}
374360
}
375361

376362
/// Get the short addresses
377363
pub fn short_addresses(&self) -> &[ShortAddress] {
378-
&self.short_addresses[..self.short_address_count]
364+
self.short_addresses.as_slice()
379365
}
380366
/// Get the extended address
381367
pub fn extended_addresses(&self) -> &[ExtendedAddress] {
382-
&self.extended_addresses[..self.extended_address_count]
368+
self.extended_addresses.as_slice()
383369
}
384370
}
385371

386372
impl TryRead<'_> for PendingAddress {
387373
fn try_read(bytes: &[u8], _ctx: ()) -> byte::Result<(Self, usize)> {
388374
let offset = &mut 0;
389-
let ss = mem::size_of::<ShortAddress>();
390-
let es = mem::size_of::<ExtendedAddress>();
375+
let ss = size_of::<ShortAddress>();
376+
let es = size_of::<ExtendedAddress>();
391377
let byte: u8 = bytes.read(offset)?;
392378
let sl = (byte & SHORT_MASK) as usize;
393379
let el = ((byte & EXTENDED_MASK) >> 4) as usize;
394380
check_len(&bytes[*offset..], (sl * ss) + (el * es))?;
395-
let mut short_addresses = [ShortAddress::broadcast(); 7];
396-
for n in 0..sl {
397-
short_addresses[n] = bytes.read(offset)?;
381+
let mut short_addresses = heapless::Vec::new();
382+
assert!(sl <= short_addresses.capacity());
383+
for _ in 0..sl {
384+
short_addresses
385+
.push(bytes.read(offset)?)
386+
.expect("sl can never be larger than 7");
398387
}
399-
let mut extended_addresses = [ExtendedAddress::broadcast(); 7];
400-
for n in 0..el {
401-
extended_addresses[n] = bytes.read(offset)?;
388+
let mut extended_addresses = heapless::Vec::new();
389+
assert!(el <= extended_addresses.capacity());
390+
for _ in 0..el {
391+
extended_addresses
392+
.push(bytes.read(offset)?)
393+
.expect("el can never be larger than 7");
402394
}
403395
Ok((
404396
Self {
405-
short_address_count: sl,
406397
short_addresses,
407-
extended_address_count: el,
408398
extended_addresses,
409399
},
410400
*offset,
@@ -415,31 +405,30 @@ impl TryRead<'_> for PendingAddress {
415405
impl TryWrite for PendingAddress {
416406
fn try_write(self, bytes: &mut [u8], _ctx: ()) -> byte::Result<usize> {
417407
let offset = &mut 0;
418-
assert!(self.short_address_count <= 7);
419-
assert!(self.extended_address_count <= 7);
408+
assert!(self.short_addresses.capacity() <= 7);
409+
assert!(self.extended_addresses.capacity() <= 7);
420410

421-
let sl = self.short_address_count;
422-
let el = self.extended_address_count;
411+
let sl = self.short_addresses.len();
412+
let el = self.extended_addresses.len();
423413

424-
let it_s_magic =
425-
(((el as u8) << 4) & EXTENDED_MASK) | ((sl as u8) & SHORT_MASK); //FIXME give variable meaningful name
426-
bytes.write(offset, it_s_magic)?;
414+
// Combine list lengths into one field, see Table 45 of IEEE 802.15.4-2011
415+
let combined_lengths =
416+
(((el as u8) << 4) & EXTENDED_MASK) | ((sl as u8) & SHORT_MASK);
417+
bytes.write(offset, combined_lengths)?;
427418

428-
for n in 0..self.short_address_count {
429-
let addr = self.short_addresses[n];
419+
for addr in self.short_addresses {
430420
bytes.write(offset, addr)?;
431421
}
432422

433-
for n in 0..self.extended_address_count {
434-
let addr = self.extended_addresses[n];
423+
for addr in self.extended_addresses {
435424
bytes.write(offset, addr)?;
436425
}
437426
Ok(*offset)
438427
}
439428
}
440429

441430
/// Beacon frame
442-
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
431+
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
443432
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
444433
pub struct Beacon {
445434
/// Superframe specification
@@ -477,6 +466,7 @@ impl TryWrite for Beacon {
477466
#[cfg(test)]
478467
mod tests {
479468
use super::*;
469+
use heapless::Vec;
480470

481471
#[test]
482472
fn decode_superframe_specification() {
@@ -632,29 +622,25 @@ mod tests {
632622
association_permit: true,
633623
};
634624

635-
let mut slots = [GuaranteedTimeSlotDescriptor::new(); 7];
636-
slots[0] = GuaranteedTimeSlotDescriptor {
625+
let slots = Vec::from_slice(&[GuaranteedTimeSlotDescriptor {
637626
short_address: ShortAddress(0x1234),
638627
starting_slot: 1,
639628
length: 1,
640629
direction: Direction::Transmit,
641-
};
630+
}])
631+
.unwrap();
642632

643633
let guaranteed_time_slot_info = GuaranteedTimeSlotInformation {
644634
permit: true,
645-
slot_count: 1,
646635
slots,
647636
};
648637

649-
let mut short_addresses = [ShortAddress::broadcast(); 7];
650-
short_addresses[0] = ShortAddress(0x7856);
651-
let mut extended_addresses = [ExtendedAddress::broadcast(); 7];
652-
extended_addresses[0] = ExtendedAddress(0xaec24a1c2116e260);
638+
let short_addresses = Vec::from_slice(&[ShortAddress(0x7856)]).unwrap();
639+
let extended_addresses =
640+
Vec::from_slice(&[ExtendedAddress(0xaec24a1c2116e260)]).unwrap();
653641

654642
let pending_address = PendingAddress {
655-
short_address_count: 1,
656643
short_addresses,
657-
extended_address_count: 1,
658644
extended_addresses,
659645
};
660646

0 commit comments

Comments
 (0)