dw3000_ng/ll.rs
1//! Low-level interface to the DW3000
2//!
3//! This module implements a register-level interface to the DW3000. Users of
4//! this library should typically not need to use this. Please consider using
5//! the [high-level interface] instead.
6//!
7//! If you're using the low-level interface because the high-level interface
8//! doesn't cover your use case, please consider [filing an issue].
9//!
10//! **NOTE**: Many field access methods accept types that have a larger number
11//! of bits than the field actually consists of. If you use such a method to
12//! pass a value that is too large to be written to the field, it will be
13//! silently truncated.
14//!
15//! [high-level interface]: ../hl/index.html
16//! [filing an issue]: https://github.com/braun-robotics/rust-dw3000/issues/new
17
18use core::fmt::{Display, Formatter};
19use core::{fmt, marker::PhantomData};
20
21use crate::{maybe_async_attr, spi_type};
22
23/// Entry point to the DW3000 driver's low-level API
24///
25/// Please consider using [hl::DW3000] instead.
26///
27/// [hl::DW3000]: ../hl/struct.DW3000.html
28#[derive(Copy, Clone)]
29pub struct DW3000<SPI> {
30 /// SPI device
31 pub spi: SPI,
32}
33
34impl<SPI> DW3000<SPI> {
35 /// Create a new instance of `DW3000`
36 ///
37 /// Requires the SPI device
38 pub fn new(spi: SPI) -> Self {
39 DW3000 { spi }
40 }
41
42 /// DW3000 fast command
43 #[maybe_async_attr]
44 pub async fn fast_command(&mut self, fast: u8) -> Result<(), Error<SPI>>
45 where
46 SPI: spi_type::spi::SpiDevice<u8>,
47 {
48 let mut buffer = [0];
49 buffer[0] = (0x1 << 7) | ((fast << 1) & 0x3e) | 0x1;
50
51 SPI::write(&mut self.spi, &buffer)
52 .await
53 .map_err(Error::Transfer)?;
54
55 Ok(())
56 }
57
58 /// Allow direct access to the SPI bus
59 pub fn bus(&mut self) -> &mut SPI {
60 &mut self.spi
61 }
62}
63
64/// Provides access to a register
65///
66/// You can get an instance for a given register using one of the methods on
67/// [`DW3000`].
68pub struct RegAccessor<'s, R, SPI>(&'s mut DW3000<SPI>, PhantomData<R>);
69
70impl<R, SPI> RegAccessor<'_, R, SPI>
71where
72 SPI: spi_type::spi::SpiDevice<u8>,
73{
74 /// Read from the register
75 #[inline]
76 #[maybe_async_attr]
77 pub async fn read(&mut self) -> Result<R::Read, Error<SPI>>
78 where
79 R: Register + Readable,
80 {
81 let mut r = R::read();
82 let buffer = R::buffer(&mut r);
83
84 init_header::<R>(false, buffer);
85 self.0
86 .spi
87 .transfer_in_place(buffer)
88 .await
89 .map_err(Error::Transfer)?;
90
91 Ok(r)
92 }
93
94 /// Write to the register
95 #[inline]
96 #[maybe_async_attr]
97 pub async fn write<F>(&mut self, f: F) -> Result<(), Error<SPI>>
98 where
99 R: Register + Writable,
100 F: FnOnce(&mut R::Write) -> &mut R::Write,
101 {
102 let mut w = R::write();
103 f(&mut w);
104
105 let buffer = R::buffer(&mut w);
106 init_header::<R>(true, buffer);
107
108 SPI::write(&mut self.0.spi, buffer)
109 .await
110 .map_err(Error::Transfer)?;
111
112 Ok(())
113 }
114
115 /// Modify the register
116 #[inline]
117 #[maybe_async_attr]
118 pub async fn modify<F>(&mut self, f: F) -> Result<(), Error<SPI>>
119 where
120 R: Register + Readable + Writable,
121 F: for<'r> FnOnce(&mut R::Read, &'r mut R::Write) -> &'r mut R::Write,
122 {
123 let mut r = self.read().await?;
124 let mut w = R::write();
125
126 <R as Writable>::buffer(&mut w).copy_from_slice(<R as Readable>::buffer(&mut r));
127
128 f(&mut r, &mut w);
129
130 let buffer = <R as Writable>::buffer(&mut w);
131 init_header::<R>(true, buffer);
132
133 SPI::write(&mut self.0.spi, buffer)
134 .await
135 .map_err(Error::Transfer)?;
136
137 Ok(())
138 }
139}
140
141/// An SPI error that can occur when communicating with the DW3000
142pub enum Error<SPI>
143where
144 SPI: spi_type::spi::ErrorType,
145{
146 /// SPI error occured during a transfer transaction
147 Transfer(SPI::Error),
148}
149
150impl<SPI> Display for Error<SPI>
151where
152 SPI: spi_type::spi::ErrorType,
153 SPI::Error: core::fmt::Debug,
154{
155 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
156 write!(f, "{:?}", self)
157 }
158}
159
160#[cfg(feature = "std")]
161impl<SPI> std::error::Error for Error<SPI> where SPI: spi_type::spi::ErrorType {}
162
163// We can't derive this implementation, as the compiler will complain that the
164// associated error type doesn't implement `Debug`.
165impl<SPI> fmt::Debug for Error<SPI>
166where
167 SPI: spi_type::spi::ErrorType,
168 SPI::Error: fmt::Debug,
169{
170 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
171 match self {
172 Error::Transfer(error) => write!(f, "Transfer({:?})", error),
173 }
174 }
175}
176
177#[cfg(feature = "defmt")]
178impl<SPI> defmt::Format for Error<SPI>
179where
180 SPI: spi_type::spi::SpiDevice<u8>,
181{
182 fn format(&self, f: defmt::Formatter) {
183 match self {
184 Error::Transfer(_) => defmt::write!(f, "Transfer()"),
185 }
186 }
187}
188
189/// Initializes the SPI message header
190///
191/// Initializes the SPI message header for accessing a given register, writing
192/// the header directly into the provided buffer. Returns the length of the
193/// header that was written.
194///
195/// TODO: Here we always use the full address, but we should also support the
196/// short address mode and masked write mode.
197#[inline(always)]
198fn init_header<R: Register>(write: bool, buffer: &mut [u8]) -> usize {
199 // bool write defines if we are in read or write mode (first bit)
200 // sub_id is a bool that defines if we are in full or short command
201 // we start with full address!
202 buffer[0] = (((write as u8) << 7) & 0x80)
203 | (1u8 << 6) // We always use 2-octet addressing
204 | ((R::ID << 1) & 0x3e) // 5-bit base address
205 | ((R::SUB_ID >> 6) & 0x01); // MSB of the 7-bit sub-address
206
207 buffer[1] = R::SUB_ID << 2; // last two bits M1 M0 are always 0
208
209 2
210}
211
212/// Implemented for all registers
213///
214/// This is a mostly internal crate that should not be implemented or used
215/// directly by users of this crate. It is exposed through the public API
216/// though, so it can't be made private.
217///
218/// The DW3000 user manual, section 7.1, specifies what the values of the
219/// constant should be for each register.
220pub trait Register {
221 /// The register index
222 const ID: u8;
223
224 /// The registers's sub-index
225 const SUB_ID: u8;
226
227 /// The lenght of the register
228 const LEN: usize;
229}
230
231/// Marker trait for registers that can be read from
232///
233/// This is a mostly internal crate that should not be implemented or used
234/// directly by users of this crate. It is exposed through the public API
235/// though, so it can't be made private.
236pub trait Readable {
237 /// The type that is used to read from the register
238 type Read;
239
240 /// Return the read type for this register
241 fn read() -> Self::Read;
242
243 /// Return the read type's internal buffer
244 fn buffer(r: &mut Self::Read) -> &mut [u8];
245}
246
247/// Marker trait for registers that can be written to
248///
249/// This is a mostly internal crate that should not be implemented or used
250/// directly by users of this crate. It is exposed through the public API
251/// though, so it can't be made private.
252pub trait Writable {
253 /// The type that is used to write to the register
254 type Write;
255
256 /// Return the write type for this register
257 fn write() -> Self::Write;
258
259 /// Return the write type's internal buffer
260 fn buffer(w: &mut Self::Write) -> &mut [u8];
261}
262
263/// Generates register implementations
264macro_rules! impl_register {
265 (
266 $(
267 $id:expr,
268 $sub_id:expr,
269 $len:expr,
270 $rw:tt,
271 $name:ident($name_lower:ident) {
272 #[$doc:meta]
273 $(
274 $field:ident,
275 $first_bit:expr,
276 $last_bit:expr,
277 $ty:ty;
278 #[$field_doc:meta]
279 )*
280 }
281 )*
282 ) => {
283 $(
284 #[$doc]
285 #[allow(non_camel_case_types)]
286 pub struct $name;
287
288 impl Register for $name {
289 const ID: u8 = $id;
290 const SUB_ID: u8 = $sub_id;
291 const LEN: usize = $len;
292 }
293
294 impl $name {
295 // You know what would be neat? Using `if` in constant
296 // expressions! But that's not possible, so we're left with the
297 // following hack.
298 // const SUB_INDEX_IS_NONZERO: usize =
299 // (Self::SUB_ID > 0) as usize;
300 // const SUB_INDEX_NEEDS_SECOND_BYTE: usize =
301 // (Self::SUB_ID > 127) as usize;
302 const HEADER_LEN: usize = 2;
303 // 1
304 // + Self::SUB_INDEX_IS_NONZERO
305 // + Self::SUB_INDEX_NEEDS_SECOND_BYTE;
306 }
307
308 #[$doc]
309 pub mod $name_lower {
310 use core::fmt;
311
312
313 const HEADER_LEN: usize = super::$name::HEADER_LEN;
314
315
316 /// Used to read from the register
317 pub struct R(pub(crate) [u8; HEADER_LEN + $len]);
318
319 impl R {
320 $(
321 #[$field_doc]
322 #[inline(always)]
323 pub fn $field(&self) -> $ty {
324 use core::mem::size_of;
325 use crate::ll::FromBytes;
326
327 // The index (in the register data) of the first
328 // byte that contains a part of this field.
329 const START: usize = $first_bit / 8;
330
331 // The index (in the register data) of the byte
332 // after the last byte that contains a part of this
333 // field.
334 const END: usize = $last_bit / 8 + 1;
335
336 // The number of bytes in the register data that
337 // contain part of this field.
338 const LEN: usize = END - START;
339
340 // Get all bytes that contain our field. The field
341 // might fill out these bytes completely, or only
342 // some bits in them.
343 let mut bytes = [0; LEN];
344 bytes[..LEN].copy_from_slice(
345 &self.0[START+HEADER_LEN .. END+HEADER_LEN]
346 );
347
348 // Before we can convert the field into a number and
349 // return it, we need to shift it, to make sure
350 // there are no other bits to the right of it. Let's
351 // start by determining the offset of the field
352 // within a byte.
353 const OFFSET_IN_BYTE: usize = $first_bit % 8;
354
355 if OFFSET_IN_BYTE > 0 {
356 // Shift the first byte. We always have at least
357 // one byte here, so this always works.
358 bytes[0] >>= OFFSET_IN_BYTE;
359
360 // If there are more bytes, let's shift those
361 // too.
362 // We need to allow exceeding bitshifts in this
363 // loop, as we run into that if `OFFSET_IN_BYTE`
364 // equals `0`. Please note that we never
365 // actually encounter that at runtime, due to
366 // the if condition above.
367 let mut i = 1;
368 #[allow(arithmetic_overflow)]
369 while i < LEN {
370 bytes[i - 1] |=
371 bytes[i] << 8 - OFFSET_IN_BYTE;
372 bytes[i] >>= OFFSET_IN_BYTE;
373 i += 1;
374 }
375 }
376
377 // If the field didn't completely fill out its last
378 // byte, we might have bits from unrelated fields
379 // there. Let's erase those before doing the final
380 // conversion into the field's data type.
381 const SIZE_IN_BITS: usize =
382 $last_bit - $first_bit + 1;
383 const BITS_ABOVE_FIELD: usize =
384 8 - (SIZE_IN_BITS % 8);
385 const SIZE_IN_BYTES: usize =
386 (SIZE_IN_BITS - 1) / 8 + 1;
387 const LAST_INDEX: usize =
388 SIZE_IN_BYTES - 1;
389 if BITS_ABOVE_FIELD < 8 {
390 // Need to allow exceeding bitshifts to make the
391 // compiler happy. They're never actually
392 // encountered at runtime, due to the if
393 // condition.
394 #[allow(arithmetic_overflow)]
395 {
396 bytes[LAST_INDEX] <<= BITS_ABOVE_FIELD;
397 bytes[LAST_INDEX] >>= BITS_ABOVE_FIELD;
398 }
399 }
400
401 // Now all that's left is to convert the bytes into
402 // the field's type. Please note that methods for
403 // converting numbers to/from bytes are coming to
404 // stable Rust, so we might be able to remove our
405 // custom infrastructure here. Tracking issue:
406 // https://github.com/rust-lang/rust/issues/52963
407 let bytes = if bytes.len() > size_of::<$ty>() {
408 &bytes[..size_of::<$ty>()]
409 }
410 else {
411 &bytes
412 };
413 <$ty as FromBytes>::from_bytes(bytes)
414 }
415 )*
416 }
417
418 impl fmt::Debug for R {
419 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
420 write!(f, "0x")?;
421 for i in (0 .. $len).rev() {
422 write!(f, "{:02x}", self.0[HEADER_LEN + i])?;
423 }
424
425 Ok(())
426 }
427 }
428
429 #[cfg(feature = "defmt")]
430 impl defmt::Format for R {
431 fn format(&self, f: defmt::Formatter) {
432 defmt::write!(f, "0x");
433 for i in (0 .. $len).rev() {
434 defmt::write!(f, "{:02x}", self.0[HEADER_LEN + i]);
435 }
436 }
437 }
438
439 /// Used to write to the register
440 #[allow(unused)]
441 pub struct W(pub(crate) [u8; HEADER_LEN + $len]);
442
443 impl W {
444 $(
445 #[$field_doc]
446 #[inline(always)]
447 pub fn $field(&mut self, value: $ty) -> &mut Self {
448 use crate::ll::ToBytes;
449
450 // Convert value into bytes
451 let source = <$ty as ToBytes>::to_bytes(value);
452
453 // Now, let's figure out where the bytes are located
454 // within the register array.
455 const START: usize = $first_bit / 8;
456 const END: usize = $last_bit / 8 + 1;
457 const OFFSET_IN_BYTE: usize = $first_bit % 8;
458
459 // Also figure out the length of the value in bits.
460 // That's going to come in handy.
461 const LEN: usize = $last_bit - $first_bit + 1;
462
463
464 // We need to track how many bits are left in the
465 // value overall, and in the value's current byte.
466 let mut bits_left = LEN;
467 let mut bits_left_in_byte = 8;
468
469 // We also need to track how many bits have already
470 // been written to the current target byte.
471 let mut bits_written_to_byte = 0;
472
473 // Now we can take the bytes from the value, shift
474 // them, mask them, and write them into the target
475 // array.
476 let mut source_i = 0;
477 let mut target_i = START;
478 while target_i < END {
479 // Values don't always end at byte boundaries,
480 // so we need to mask the bytes when writing to
481 // the slice.
482 // Let's start out assuming we can write to the
483 // whole byte of the slice. This will be true
484 // for the middle bytes of our value.
485 let mut mask = 0xff;
486
487 // Let's keep track of the offset we're using to
488 // write to this byte. We're going to need it.
489 let mut offset_in_this_byte = 0;
490
491 // If this is the first byte we're writing to
492 // the slice, we need to remove the lower bits
493 // of the mask.
494 if target_i == START {
495 mask <<= OFFSET_IN_BYTE;
496 offset_in_this_byte = OFFSET_IN_BYTE;
497 }
498
499 // If this is the last byte we're writing to the
500 // slice, we need to remove the higher bits of
501 // the mask. Please note that we could be
502 // writing to _both_ the first and the last
503 // byte.
504 if target_i == END - 1 {
505 let shift =
506 8 - bits_left - offset_in_this_byte;
507 mask <<= shift;
508 mask >>= shift;
509 }
510
511 mask <<= bits_written_to_byte;
512
513 // Read the value from `source`
514 let value = source[source_i]
515 >> 8 - bits_left_in_byte
516 << offset_in_this_byte
517 << bits_written_to_byte;
518
519 // Zero the target bits in the slice, then write
520 // the value.
521 self.0[HEADER_LEN + target_i] &= !mask;
522 self.0[HEADER_LEN + target_i] |= value & mask;
523
524 // The number of bits that were expected to be
525 // written to the target byte.
526 let bits_needed = mask.count_ones() as usize;
527
528 // The number of bits we actually wrote to the
529 // target byte.
530 let bits_used = bits_needed.min(
531 bits_left_in_byte - offset_in_this_byte
532 );
533
534 bits_left -= bits_used;
535 bits_written_to_byte += bits_used;
536
537 // Did we use up all the bits in the source
538 // byte? If so, we can move on to the next one.
539 if bits_left_in_byte > bits_used {
540 bits_left_in_byte -= bits_used;
541 }
542 else {
543 bits_left_in_byte =
544 8 - (bits_used - bits_left_in_byte);
545
546 source_i += 1;
547 }
548
549 // Did we write all the bits in the target byte?
550 // If so, we can move on to the next one.
551 if bits_used == bits_needed {
552 target_i += 1;
553 bits_written_to_byte = 0;
554 }
555 }
556
557 self
558 }
559 )*
560 }
561 }
562
563 impl_rw!($rw, $name, $name_lower, $len);
564 )*
565
566
567 impl<SPI> DW3000<SPI> {
568 $(
569 #[$doc]
570 pub fn $name_lower(&mut self) -> RegAccessor<$name, SPI> {
571 RegAccessor(self, PhantomData)
572 }
573 )*
574 }
575 }
576}
577
578// Helper macro, used internally by `impl_register!`
579macro_rules! impl_rw {
580 (RO, $name:ident, $name_lower:ident, $len:expr) => {
581 impl_rw!(@R, $name, $name_lower, $len);
582 };
583 (RW, $name:ident, $name_lower:ident, $len:expr) => {
584 impl_rw!(@R, $name, $name_lower, $len);
585 impl_rw!(@W, $name, $name_lower, $len);
586 };
587
588 (@R, $name:ident, $name_lower:ident, $len:expr) => {
589 impl Readable for $name {
590 type Read = $name_lower::R;
591
592 fn read() -> Self::Read {
593 $name_lower::R([0; Self::HEADER_LEN + $len])
594 }
595
596 fn buffer(r: &mut Self::Read) -> &mut [u8] {
597 &mut r.0
598 }
599 }
600 };
601 (@W, $name:ident, $name_lower:ident, $len:expr) => {
602 impl Writable for $name {
603 type Write = $name_lower::W;
604
605 fn write() -> Self::Write {
606 $name_lower::W([0; Self::HEADER_LEN + $len])
607 }
608
609 fn buffer(w: &mut Self::Write) -> &mut [u8] {
610 &mut w.0
611 }
612 }
613 };
614}
615
616// All register are implemented in this macro invocation. It follows the
617// following syntax:
618// <id>, <sub-id>, <size-bytes>, <RO/RW>, <name-upper>(name-lower) { /// <doc>
619// <field 1>
620// <field 2>
621// ...
622// }
623//
624
625/************************************************************************ */
626/********** DWM3000 MODIFICATIONS *********** */
627/************************************************************************ */
628// registers for DWM3000
629// Each field follows the following syntax:
630// <Id>, <Offset>, <Length>, <Access>, <NAME(name)>
631// <name>, <first-bit-index>, <last-bit-index>, <type>; /// <doc>
632
633impl_register! {
634
635 0x00, 0x00, 4, RO, DEV_ID(dev_id) { /// Device identifier
636 rev, 0, 3, u8; /// Revision
637 ver, 4, 7, u8; /// Version
638 model, 8, 15, u8; /// Model
639 ridtag, 16, 31, u16; /// Register Identification Tag
640 }
641 0x00, 0x04, 8, RW, EUI(eui) { /// Extended Unique Identifier
642 value, 0, 63, u64; /// Extended Unique Identifier
643 }
644 0x00, 0x0C, 4, RW, PANADR(panadr) { /// PAN Identifier and Short Address
645 short_addr, 0, 15, u16; /// Short Address
646 pan_id, 16, 31, u16; /// PAN Identifier
647 }
648 0x00, 0x10, 4, RW, SYS_CFG(sys_cfg) { /// System Configuration
649 ffen, 0, 0, u8; /// Frame Filtering Enable
650 dis_fcs_tx, 1, 1, u8; /// disable auto-FCS Transmission
651 dis_fce, 2, 2, u8; /// Disable frame check error handling
652 dis_drxb, 3, 3, u8; /// Disable Double RX Buffer
653 phr_mode, 4, 4, u8; /// PHR Mode
654 phr_6m8, 5, 5, u8; /// Sets the PHR rate to match the data rate
655 spi_crcen, 6, 6, u8; /// Enable SPI CRC functionnality
656 cia_ipatov, 7, 7, u8; /// Select CIA processing preamble CIR
657 cia_sts, 8, 8, u8; /// Select CIA processing STS CIR
658 rxwtoe, 9, 9, u8; /// Receive Wait Timeout Enable
659 rxautr, 10, 10, u8; /// Receiver Auto Re-enable
660 auto_ack, 11, 11, u8; /// Automatic Acknowledge Enable
661 cp_spc, 12, 13, u8; /// STS Packet Configuration
662 cp_sdc, 15, 15, u8; /// configures the SDC
663 pdoa_mode, 16, 17, u8; /// configure PDoA
664 fast_aat, 18, 18, u8; /// enable fast RX to TX turn around mode
665 }
666 0x00, 0x14, 2, RW, FF_CFG(ff_cfg) { /// comments
667 ffab, 0, 0, u8; /// Frame Filtering Allow Beacon
668 ffad, 1, 1, u8; /// Frame Filtering Allow Data
669 ffaa, 2, 2, u8; /// Frame Filtering Allow Acknowledgement
670 ffam, 3, 3, u8; /// Frame Filtering Allow MAC Command Frame
671 ffar, 4, 4, u8; /// Frame Filtering Allow Reserved
672 ffamulti, 5, 5, u8; /// Frame Filtering Allow Multipurpose
673 ffaf, 6, 6, u8; /// Frame Filtering Allow Fragmented
674 ffae, 7, 7, u8; /// Frame Filtering Allow extended frame
675 ffbc, 8, 8, u8; /// Frame Filtering Behave As Coordinator
676 ffib, 9, 9, u8; /// Frame Filtering Allow MAC
677 le0_pend, 10, 10, u8; /// Data pending for device at led0 addr
678 le1_pend, 11, 11, u8; /// Data pending for device at led1 addr
679 le2_pend, 12, 12, u8; /// Data pending for device at led2 addr
680 le3_pend, 13, 13, u8; /// Data pending for device at led3 addr
681 ssadrap, 14, 14, u8; /// Short Source Address Data Request
682 lsadrape, 15, 15, u8; /// Long Source Address Data Request
683 }
684 0x00, 0x18, 1, RO, SPI_RD_CRC(spi_rd_crc) { /// SPI CRC read status
685 value, 0, 7, u8; /// SPI CRC read status
686 }
687 0x00, 0x1C, 4, RO, SYS_TIME(sys_time) { /// System Time Counter register
688 value, 0, 31, u32; /// System Time Counter register
689 }
690 0x00, 0x24, 6, RW, TX_FCTRL(tx_fctrl) { /// TX Frame Control
691 txflen, 0, 9, u16; /// TX Frame Length
692 txbr, 10, 10, u8; /// Transmit Bit Rate
693 tr, 11, 11, u8; /// Transmit Ranging enable
694 txpsr, 12, 15, u8; /// Transmit Preamble Symbol Repetitions
695 txb_offset, 16, 25, u16; /// Transmit buffer index offset
696 fine_plen, 40, 47, u8; /// Fine PSR control
697 }
698 0x00, 0x2C, 4, RW, DX_TIME(dx_time) { /// Delayed Send or Receive Time
699 value, 0, 31, u32; /// Delayed Send or Receive Time
700 }
701 0x00, 0x30, 4, RW, DREF_TIME(dref_time) { /// Delayed send or receive reference time
702 value, 0, 31, u32; /// Delayed send or receive reference time
703 }
704 0x00, 0x34, 3, RW, RX_FWTO(rx_fwto) { /// Receive frame wait timeout period
705 value, 0, 23, u32; /// Receive frame wait timeout period
706 }
707 0x00, 0x38, 1, RW, SYS_CTRL(sys_ctrl) { /// System Control Register
708 value, 0, 7, u8; /// System control
709 }
710 0x00, 0x3C, 6, RW, SYS_ENABLE(sys_enable) { /// System event enable mask register
711 cplock_en, 1, 1, u8; /// Mask clock PLL lock event
712 spicrce_en, 2, 2, u8; /// Mask SPI CRC Error event
713 aat_en, 3, 3, u8; /// Mask automatic acknowledge trigger event
714 txfrb_en, 4, 4, u8; /// Mask transmit frame begins event
715 txprs_en, 5, 5, u8; /// Mask transmit preamble sent event
716 txphs_en, 6, 6, u8; /// Mask transmit PHY Header Sent event
717 txfrs_en, 7, 7, u8; /// Mask transmit frame sent event
718 rxprd_en, 8, 8, u8; /// Mask receiver preamble detected event
719 rxsfdd_en, 9, 9, u8; /// Mask receiver SFD detected event
720 ciadone_en, 10, 10, u8; /// Mask CIA processing done event
721 rxphd_en, 11, 11, u8; /// Mask receiver PHY header detect event
722 rxphe_en, 12, 12, u8; /// Mask receiver PHY header error event
723 rxfr_en, 13, 13, u8; /// Mask receiver data frame ready event
724 rxfcg_en, 14, 14, u8; /// Mask receiver FCS good event
725 rxfce_en, 15, 15, u8; /// Mask receiver FCS error event
726 rxrfsl_en, 16, 16, u8; /// Mask receiver Reed Solomon Frame Sync Loss event
727 rxfto_en, 17, 17, u8; /// Mask Receive Frame Wait Timeout event
728 ciaerr_en, 18, 18, u8; /// Mask leading edge detection processing error event
729 vwarn_en, 19, 19, u8; /// Mask Voltage warning event
730 rxovrr_en, 20, 20, u8; /// Receiver overrun
731 rxpto_en, 21, 21, u8; /// Mask Preamble detection timeout event
732 spirdy_en, 23, 23, u8; /// Mask SPI ready event
733 rcinit_en, 24, 24, u8; /// Mask IDLE RC event
734 pll_hilo_en, 25, 25, u8; /// Mask PLL Losing Lock warning event
735 rxsto_en, 26, 26, u8; /// Mask Receive SFD timeout event
736 hpdwarn_en, 27, 27, u8; /// Mask Half Period Delay Warning event
737 cperr_en, 28, 28, u8; /// Mask Scramble Timestamp Sequence (STS) error event
738 arfe_en, 29, 29, u8; /// Mask Automatic Frame Filtering rejection event
739 rxprej_en, 33, 33, u8; /// Mask Receiver Preamble Rejection event
740 vt_det_en, 36, 36, u8; /// Mask Voltage/Temperature variation dtection interrupt event
741 gpioirq_en, 37, 37, u8; /// Mask GPIO interrupt event
742 aes_done_en, 38, 38, u8; /// Mask AES done interrupt event
743 aes_err_en, 39, 39, u8; /// Mask AES error interrupt event
744 cdm_err_en, 40, 40, u8; /// Mask CMD error interrupt event
745 spi_ovf_en, 41, 41, u8; /// Mask SPI overflow interrupt event
746 spi_unf_en, 42, 42, u8; /// Mask SPI underflow interrupt event
747 spi_err_en, 43, 43, u8; /// Mask SPI error interrupt event
748 cca_fail_en, 44, 44, u8; /// Mask CCA fail interrupt event
749 }
750 0x00, 0x44, 6, RW, SYS_STATUS(sys_status) { /// System Event Status Register
751 irqs, 0, 0, u8; /// Interrupt Request Status
752 cplock, 1, 1, u8; /// Clock PLL Lock
753 spicrce, 2, 2, u8; /// External Sync Clock Reset
754 aat, 3, 3, u8; /// Automatic Acknowledge Trigger
755 txfrb, 4, 4, u8; /// TX Frame Begins
756 txprs, 5, 5, u8; /// TX Preamble Sent
757 txphs, 6, 6, u8; /// TX PHY Header Sent
758 txfrs, 7, 7, u8; /// TX Frame Sent
759 rxprd, 8, 8, u8; /// RX Preamble Detected
760 rxsfdd, 9, 9, u8; /// RX SFD Detected
761 ciadone, 10, 10, u8; /// LDE Processing Done
762 rxphd, 11, 11, u8; /// RX PHY Header Detect
763 rxphe, 12, 12, u8; /// RX PHY Header Error
764 rxfr, 13, 13, u8; /// RX Data Frame Ready
765 rxfcg, 14, 14, u8; /// RX FCS Good
766 rxfce, 15, 15, u8; /// RX FCS Error
767 rxfsl, 16, 16, u8; /// RX Reed-Solomon Frame Sync Loss
768 rxfto, 17, 17, u8; /// RX Frame Wait Timeout
769 ciaerr, 18, 18, u8; /// Leading Edge Detection Error
770 vwarn, 19, 19, u8; /// Low voltage warning
771 rxovrr, 20, 20, u8; /// RX Overrun
772 rxpto, 21, 21, u8; /// Preamble detection timeout
773 spirdy, 23, 23, u8; /// SPI ready for host access
774 rcinit, 24, 24, u8; /// RC INIT
775 pll_hilo, 25, 25, u8; /// lock PLL Losing Lock
776 rxsto, 26, 26, u8; /// Receive SFD timeout
777 hpdwarn, 27, 27, u8; /// Half Period Delay Warning
778 cperr, 28, 28, u8; /// Scramble Timestamp Sequence (STS) error
779 arfe, 29, 29, u8; /// Automatic Frame Filtering rejection
780 rxprej, 29, 29, u8; /// Receiver Preamble Rejection
781 vt_det, 33, 33, u8; /// Voltage or temperature variation detected
782 gpioirq, 36, 36, u8; /// GPIO interrupt
783 aes_done, 37, 37, u8; /// AES-DMA operation complete
784 aes_err, 38, 38, u8; /// AES-DMA error
785 cmd_err, 39, 39, u8; /// Command error
786 spi_ovf, 40, 40, u8; /// SPI overflow error
787 spi_unf, 41, 41, u8; /// SPI underflow error
788 spierr, 42, 42, u8; /// SPI collision error
789 cca_fail, 43, 43, u8; /// This event will be set as a result of failure of CMD_CCA_TX to transmit a packet
790 }
791 0x00, 0x4C, 4, RO, RX_FINFO(rx_finfo) { /// RX Frame Information
792 rxflen, 0, 9, u16; /// Receive Frame Length
793 rxnspl, 11, 12, u8; /// Receive Non-Standard Preamble Length
794 rxbr, 13, 13, u8; /// Receive Bit Rate Report
795 rng, 15, 15, u8; /// Receiver Ranging
796 rxprf, 16, 17, u8; /// RX Pulse Repetition Rate Report
797 rxpsr, 18, 19, u8; /// RX Preamble Repetition
798 rxpacc, 20, 31, u16; /// Preamble Accumulation Count
799 }
800 0x00, 0x64, 5, RO, RX_TIME(rx_time) { /// Receive Time Stamp
801 rx_stamp, 0, 39, u64; /// Fully adjusted time stamp
802 }
803 0x00, 0x70, 4, RO, RX_RAWST(rx_rawst) { /// Raw receive time stamp
804 value, 0, 31, u32; /// Raw receive time stamp
805 }
806 0x00, 0x74, 5, RO, TX_TIME(tx_time) { /// Transmit Time Stamp
807 tx_stamp, 0, 39, u64; /// Fully adjusted time stamp
808 }
809 0x01, 0x00, 4, RO, TX_RAWST(tx_rawst) { /// Transmit time stamp raw
810 value, 0, 31, u32; /// Transmit time stamp raw
811 }
812 0x01, 0x04, 2, RW, TX_ANTD(tx_antd) { /// Transmitter antenna delay
813 value, 0, 15, u16; /// Transmitter antenna delay
814 }
815 0x01, 0x08, 4, RW, ACK_RESP(ack_resp) { /// Acknowledgement delay time and response time
816 w4r_tim, 0, 19, u32; /// Wait-for-Response turn-around Time
817 ack_tim, 24, 31, u8; /// Auto-Acknowledgement turn-around TimeC
818 }
819 0x01, 0x0C, 4, RW, TX_POWER(tx_power) { /// TX Power Control
820 value, 0, 31, u32; /// TX Power Control value
821 }
822 0x01, 0x14, 2, RW, CHAN_CTRL(chan_ctrl) { /// Channel Control Register
823 rf_chan, 0, 0, u8; /// Selects the receive channel.
824 sfd_type, 1, 2, u8; /// Enables the non-standard Decawave proprietary SFD sequence.
825 tx_pcode, 3, 7, u8; /// This field selects the preamble code used in the transmitter.
826 rx_pcode, 8, 12, u8; /// This field selects the preamble code used in the receiver.
827 }
828 0x01, 0x18, 4, RW, LE_PEND_01(le_pend_01) { /// Low Energy device address 0 and 1
829 le_addr0, 0, 15, u16; /// Low Energy device 16-bit address
830 le_addr1, 16, 31, u16; /// Low Energy device 16-bit address
831 }
832 0x01, 0x1C, 4, RW, LE_PEND_23(le_pend_23) { /// Low Energy device address 2 and 3
833 le_addr2, 0, 15, u16; /// Low Energy device 16-bit address
834 le_addr3, 16, 31, u16; /// Low Energy device 16-bit address
835 }
836 0x01, 0x20, 1, RW, SPI_COLLISION(spi_collision) { /// SPI collision status
837 value, 0, 7, u8; /// SPI collision status
838 }
839 0x01, 0x24, 1, RW, RDB_STATUS(rdb_status) { /// RX double buffer status
840 rxfcg0, 0, 0, u8; /// Receiver FCS Good
841 rxfr0, 1, 1, u8; /// Receiver Data Frame Ready
842 ciadone0, 2, 2, u8; /// CIA processing done on the CIR relating to a message in RX_BUFFER_0 when operating in double buffer mode
843 cp_err0, 3, 3, u8; /// Scramble Timestamp Sequence (STS) error
844 rxfcg1, 4, 4, u8; /// Receiver FCS Good
845 rxfr1, 5, 5, u8; /// Receiver Data Frame Ready
846 ciadone1, 6, 6, u8; /// CIA processing done on the CIR relating to a message in RX_BUFFER_1 when operating in double buffer mode
847 cp_err1, 7, 7, u8; /// Scramble Timestamp Sequence (STS) error
848 }
849 0x01, 0x28, 1, RW, RDB_DIAG(rdb_diag) { /// RX double buffer diagnostic configuration
850 rdb_dmode, 0, 2, u8; /// RX double buffer diagnostic mode
851 }
852 0x01, 0x30, 2, RW, AES_CFG(aes_cfg) { /// AES configuration
853 mode, 0, 0, u8; /// Mode of operation of AES core
854 key_size, 1, 2, u8; /// AES Key Size
855 key_addr, 3, 5, u8; /// Address offset of AES KEY
856 key_load, 6, 6, u8; /// Load the AES KEY from AES KEY source
857 key_src, 7, 7, u8; /// AES key source
858 tag_size, 8, 10, u8; /// Size of AES tag field
859 core_sel, 11, 11, u8; /// AES Core select
860 key_otp, 12, 12, u8; /// AES key Memory source
861 }
862 0x01, 0x34, 4, RW, AES_IV0(aes_iv0) { /// AES GCM core mode
863 value, 0, 31, u32; /// AES GCM core mode
864 }
865 0x01, 0x38, 4, RW, AES_IV1(aes_iv1) { /// AES GCM core mode
866 value, 0, 31, u32; /// AES GCM core mode
867 }
868 0x01, 0x3C, 4, RW, AES_IV2(aes_iv2) { /// AES GCM core mode
869 value, 0, 31, u32; /// AES GCM core mode
870 }
871 0x01, 0x40, 2, RW, AES_IV3(aes_iv3) { /// AES GCM core mode
872 value, 0, 15, u16; /// AES GCM core mode
873 }
874 0x01, 0x42, 2, RW, AES_IV4(aes_iv4) { /// AES GCM core mode
875 value, 0, 15, u16; /// AES GCM core mode
876 }
877 0x01, 0x44, 8, RW, DMA_CFG(dma_cfg) { /// DMA configuration register
878 src_port, 0, 2, u8; /// Source memory port for DMA transfer
879 src_addr, 3, 12, u16; /// Address offset within source memory for DMA transfer
880 dst_port, 13, 15, u8; /// Destination memory port for DMA transfer
881 dst_addr, 16, 25, u16; /// Address offset within destination memory for DMA transfer
882 cp_end_sel, 26, 26, u8; /// Select the endianess of the CP seed port
883 hdr_size, 32, 38, u8; /// Size of header field in the packet to be transferred via the DMA
884 pyld_size, 39, 48, u8; /// Size of payload field in the packet to be transferred via the DMA
885 }
886 0x01, 0x4C, 1, RW, AES_START(aes_start) { /// Start AES operation
887 value, 0, 0, u8; /// Start AES operation
888 }
889 0x01, 0x50, 4, RW, AES_STS(aes_sts) { /// The AES Status
890 aes_done, 0, 0, u8; /// AES operation complete. Write 1 to clear
891 auth_err, 1, 1, u8; /// AES authentication error. Write 1 to clear.
892 trans_err, 2, 2, u8; /// Indicates error with DMA transfer to memory. Write 1 to clear
893 mem_conf, 3, 3, u8; /// Indicates access conflict between multiple masters (SPI host, CIA engine and AES-DMA engine) trying to access same memory
894 ram_empty, 4, 4, u8; /// Indicates AES scratch RAM is empty
895 ram_full, 5, 5, u8; /// Indicates AES scratch RAM is full
896 }
897 0x01, 0x54, 16, RW, AES_KEY(aes_key) { /// The 128-bit KEY for the AES GCM/CCM* core
898 value, 0x0, 0x7F, u128; /// value
899 }
900
901 /*******************************************************************/
902 /************** STS CONFIG REGISTER ***************************/
903 /*******************************************************************/
904 0x02, 0x00, 2, RW, STS_CFG(sts_cfg) { /// STS configuration
905 cps_len, 0, 7, u8; /// STS length
906 }
907 0x02, 0x04, 1, RW, STS_CTRL(sts_ctrl) { /// STS control
908 load_iv, 0, 0, u8; /// Load STS_IV bit into the AES-128 block for the generation of STS
909 rst_last, 1, 1, u8; /// Start from last, when it is set to 1 the STS generation starts from the last count that was used by the AES-128 block for the generation of the previous STS.
910 }
911 0x02, 0x08, 2, RW, STS_STS(sts_sts) { /// STS status
912 acc_qual, 0, 11, u16; /// STS accumulation quality
913 }
914 0x02, 0x0C, 16, RW, STS_KEY(sts_key) { /// STS 128-bit KEY
915 value, 0x0, 0x7F, u128; /// value
916 }
917 0x02, 0x1C, 16, RW, STS_IV(sts_iv) { /// STS 128-bit IV
918 value, 0x0, 0x7F, u128; /// value
919 }
920
921 /*******************************************************************/
922 /***************** RX_TUNE REGISTER ***************************/
923 /*******************************************************************/
924 0x03, 0x18, 2, RW, DGC_CFG(dgc_cfg) { /// RX tuning configuration register
925 rx_tune_en, 0, 0, u8; /// RX tuning enable bit
926 thr_64, 9, 14, u8; /// RX tuning threshold configuration for 64 MHz PRF
927 }
928 0x03, 0x1C, 4, RW, DGC_CFG0(dgc_cfg0) { /// DGC_CFG0
929 value, 0, 31, u32; /// Value
930 }
931 0x03, 0x20, 4, RW, DGC_CFG1(dgc_cfg1) { /// DGC_CFG1
932 value, 0, 31, u32; /// Value
933 }
934 0x03, 0x38, 4, RW, DGC_LUT_0(dgc_lut_0) { /// DGC_LUT_0
935 value, 0, 31, u32; /// Value
936 }
937 0x03, 0x3C, 4, RW, DGC_LUT_1(dgc_lut_1) { /// DGC_LUT_1
938 value, 0, 31, u32; /// Value
939 }
940 0x03, 0x40, 4, RW, DGC_LUT_2(dgc_lut_2) { /// DGC_LUT_2
941 value, 0, 31, u32; /// Value
942 }
943 0x03, 0x44, 4, RW, DGC_LUT_3(dgc_lut_3) { /// DGC_LUT_3
944 value, 0, 31, u32; /// Value
945 }
946 0x03, 0x48, 4, RW, DGC_LUT_4(dgc_lut_4) { /// DGC_LUT_4
947 value, 0, 31, u32; /// Value
948 }
949 0x03, 0x4C, 4, RW, DGC_LUT_5(dgc_lut_5) { /// DGC_LUT_5
950 value, 0, 31, u32; /// Value
951 }
952 0x03, 0x50, 4, RW, DGC_LUT_6(dgc_lut_6) { /// DGC_LUT_6
953 value, 0, 31, u32; /// Value
954 }
955 0x03, 0x60, 4, RW, DGC_DBG(dgc_dbg) { /// Reports DGC information
956 dgc_decision, 28, 30, u8; /// DGC decision index.
957 }
958
959 /*******************************************************************/
960 /***************** EXT_SYNC REGISTER **************************/
961 /*******************************************************************/
962 0x04, 0x00, 4, RW, EC_CTRL(ec_ctrl) { /// External clock synchronisation counter configuration
963 osts_wait, 3, 10, u8; /// Wait counter used for external timebase reset
964 ostr_mode, 11, 11, u8; /// External timebase reset mode enable bit
965 }
966 0x04, 0x0C, 4, RW, RX_CAL(rx_cal) { /// RX calibration block configuration
967 cal_mode, 0, 1, u8; /// RX calibration mode
968 cal_en, 4, 7, u8; /// RX calibration enable
969 comp_dly, 16, 19, u8; /// RX calibration tuning value
970 }
971 0x04, 0x14, 4, RW, RX_CAL_RESI(rx_cal_resi) { /// RX calibration block result
972 value, 0, 28, u32; /// reports the result once the RX calibration is complete
973 }
974 0x04, 0x1C, 4, RW, RX_CAL_RESQ(rx_cal_resq) { /// RX calibration block result
975 value, 0, 28, u32; /// reports the result once the RX calibration is complete
976 }
977 0x04, 0x20, 1, RW, RX_CAL_STS(rx_cal_sts) { /// RX calibration block status
978 value, 0, 0, u8; /// reports the status once the RX calibration is complete
979 }
980
981 /*******************************************************************/
982 /***************** GPIO_CTRL REGISTER *************************/
983 /*******************************************************************/
984 0x05, 0x00, 4, RW, GPIO_MODE(gpio_mode) { /// GPIO Mode Control Register
985 msgp0, 0, 2, u8; /// Mode Selection for GPIO0/RXOKLED
986 msgp1, 3, 5, u8; /// Mode Selection for GPIO1/SFDLED
987 msgp2, 6, 8, u8; /// Mode Selection for GPIO2/RXLED
988 msgp3, 9, 11, u8; /// Mode Selection for GPIO3/TXLED
989 msgp4, 12, 14, u8; /// Mode Selection for GPIO4/EXTPA
990 msgp5, 15, 17, u8; /// Mode Selection for GPIO5/EXTTXE
991 msgp6, 18, 20, u8; /// Mode Selection for GPIO6/EXTRXE
992 msgp7, 21, 23, u8; /// Mode Selection for GPIO7
993 msgp8, 24, 26, u8; /// Mode Selection for GPIO8
994 }
995 0x05, 0x04, 2, RW, GPIO_PULL_EN(gpio_pull_en) { /// GPIO Drive Strength and Pull Control
996 mgpen0, 0, 0, u8; /// Setting to 0 will lower the drive strength
997 mgpen1, 1, 1, u8; /// Setting to 0 will lower the drive strength
998 mgpen2, 2, 2, u8; /// Setting to 0 will lower the drive strength
999 mgpen3, 3, 3, u8; /// Setting to 0 will lower the drive strength
1000 mgpen4, 4, 4, u8; /// Setting to 0 will lower the drive strength
1001 mgpen5, 5, 5, u8; /// Setting to 0 will lower the drive strength
1002 mgpen6, 6, 6, u8; /// Setting to 0 will lower the drive strength
1003 mgpen7, 7, 7, u8; /// Setting to 0 will lower the drive strength
1004 mgpen8, 8, 8, u8; /// Setting to 0 will lower the drive strength
1005 }
1006 0x05, 0x08, 2, RW, GPIO_DIR(gpio_dir) { /// GPIO Direction Control Register
1007 gpd0, 0, 0, u8; /// value of 0 means the pin is an output
1008 gpd1, 1, 1, u8; /// value of 0 means the pin is an output
1009 gpd2, 2, 2, u8; /// value of 0 means the pin is an output
1010 gpd3, 3, 3, u8; /// value of 0 means the pin is an output
1011 gpd4, 4, 4, u8; /// value of 0 means the pin is an output
1012 gpd5, 5, 5, u8; /// value of 0 means the pin is an output
1013 gpd6, 6, 6, u8; /// value of 0 means the pin is an output
1014 gpd7, 7, 7, u8; /// value of 0 means the pin is an output
1015 gpd8, 8, 8, u8; /// value of 0 means the pin is an output
1016 }
1017 0x05, 0x0C, 2, RW, GPIO_OUT(gpio_out) { /// GPIO Data Output Register
1018 gop0, 0, 0, u8; /// show the current output setting
1019 gop1, 1, 1, u8; /// show the current output setting
1020 gop2, 2, 2, u8; /// show the current output setting
1021 gop3, 3, 3, u8; /// show the current output setting
1022 gop4, 4, 4, u8; /// show the current output setting
1023 gop5, 5, 5, u8; /// show the current output setting
1024 gop6, 6, 6, u8; /// show the current output setting
1025 gop7, 7, 7, u8; /// show the current output setting
1026 gop8, 8, 8, u8; /// show the current output setting
1027 }
1028 0x05, 0x10, 2, RW, GPIO_IRQE(gpio_irqe) { /// GPIO Interrupt Enable
1029 girqe0, 0, 0, u8; /// selected as interrupt source
1030 girqe1, 1, 1, u8; /// selected as interrupt source
1031 girqe2, 2, 2, u8; /// selected as interrupt source
1032 girqe3, 3, 3, u8; /// selected as interrupt source
1033 girqe4, 4, 4, u8; /// selected as interrupt source
1034 girqe5, 5, 5, u8; /// selected as interrupt source
1035 girqe6, 6, 6, u8; /// selected as interrupt source
1036 girqe7, 7, 7, u8; /// selected as interrupt source
1037 girqe8, 8, 8, u8; /// selected as interrupt source
1038 }
1039 0x05, 0x14, 2, RW, GPIO_ISTS(gpio_ists) { /// GPIO Interrupt Status
1040 gists0, 0, 0, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1041 gists1, 1, 1, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1042 gists2, 2, 2, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1043 gists3, 3, 3, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1044 gists4, 4, 4, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1045 gists5, 5, 5, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1046 gists6, 6, 6, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1047 gists7, 7, 7, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1048 gists8, 8, 8, u8; /// Value 1 means GPIO gave rise to the GPIOIRQ SYS_STATUS event
1049 }
1050 0x05, 0x18, 2, RW, GPIO_ISEN(gpio_isen) { /// GPIO Interrupt Sense Selection
1051 gisen0, 0, 0, u8; /// GPIO IRQ Sense selection GPIO input
1052 gisen1, 1, 1, u8; /// GPIO IRQ Sense selection GPIO input
1053 gisen2, 2, 2, u8; /// GPIO IRQ Sense selection GPIO input
1054 gisen3, 3, 3, u8; /// GPIO IRQ Sense selection GPIO input
1055 gisen4, 4, 4, u8; /// GPIO IRQ Sense selection GPIO input
1056 gisen5, 5, 5, u8; /// GPIO IRQ Sense selection GPIO input
1057 gisen6, 6, 6, u8; /// GPIO IRQ Sense selection GPIO input
1058 gisen7, 7, 7, u8; /// GPIO IRQ Sense selection GPIO input
1059 gisen8, 8, 8, u8; /// GPIO IRQ Sense selection GPIO input
1060 }
1061 0x05, 0x1C, 2, RW, GPIO_IMODE(gpio_imode) { /// GPIO Interrupt Mode (Level / Edge)
1062 gimod0, 0, 0, u8; /// GPIO IRQ Mode selection for GPIO input
1063 gimod1, 1, 1, u8; /// GPIO IRQ Mode selection for GPIO input
1064 gimod2, 2, 2, u8; /// GPIO IRQ Mode selection for GPIO input
1065 gimod3, 3, 3, u8; /// GPIO IRQ Mode selection for GPIO input
1066 gimod4, 4, 4, u8; /// GPIO IRQ Mode selection for GPIO input
1067 gimod5, 5, 5, u8; /// GPIO IRQ Mode selection for GPIO input
1068 gimod6, 6, 6, u8; /// GPIO IRQ Mode selection for GPIO input
1069 gimod7, 7, 7, u8; /// GPIO IRQ Mode selection for GPIO input
1070 gimod8, 8, 8, u8; /// GPIO IRQ Mode selection for GPIO input
1071 }
1072 0x05, 0x20, 2, RW, GPIO_IBES(gpio_ibes) { /// GPIO Interrupt “Both Edge” Select
1073 gibes0, 0, 0, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1074 gibes1, 1, 1, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1075 gibes2, 2, 2, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1076 gibes3, 3, 3, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1077 gibes4, 4, 4, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1078 gibes5, 5, 5, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1079 gibes6, 6, 6, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1080 gibes7, 7, 7, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1081 gibes8, 8, 8, u8; /// GPIO IRQ “Both Edge” selection for GPIO input
1082 }
1083 0x05, 0x24, 4, RW, GPIO_ICLR(gpio_iclr) { /// GPIO Interrupt Latch Clear
1084 giclr0, 0, 0, u8; /// GPIO IRQ latch clear for GPIO input
1085 giclr1, 1, 1, u8; /// GPIO IRQ latch clear for GPIO input
1086 giclr2, 2, 2, u8; /// GPIO IRQ latch clear for GPIO input
1087 giclr3, 3, 3, u8; /// GPIO IRQ latch clear for GPIO input
1088 giclr4, 4, 4, u8; /// GPIO IRQ latch clear for GPIO input
1089 giclr5, 5, 5, u8; /// GPIO IRQ latch clear for GPIO input
1090 giclr6, 6, 6, u8; /// GPIO IRQ latch clear for GPIO input
1091 giclr7, 7, 7, u8; /// GPIO IRQ latch clear for GPIO input
1092 giclr8, 8, 8, u8; /// GPIO IRQ latch clear for GPIO input
1093 }
1094 0x05, 0x28, 4, RW, GPIO_IDBE(gpio_idbe) { /// GPIO Interrupt De-bounce Enable
1095 gidbe0, 0, 0, u8; /// GPIO IRQ de-bounce enable for GPIO
1096 gidbe1, 1, 1, u8; /// GPIO IRQ de-bounce enable for GPIO
1097 gidbe2, 2, 2, u8; /// GPIO IRQ de-bounce enable for GPIO
1098 gidbe3, 3, 3, u8; /// GPIO IRQ de-bounce enable for GPIO
1099 gidbe4, 4, 4, u8; /// GPIO IRQ de-bounce enable for GPIO
1100 gidbe5, 5, 5, u8; /// GPIO IRQ de-bounce enable for GPIO
1101 gidbe6, 6, 6, u8; /// GPIO IRQ de-bounce enable for GPIO
1102 gidbe7, 7, 7, u8; /// GPIO IRQ de-bounce enable for GPIO
1103 gidbe8, 8, 8, u8; /// GPIO IRQ de-bounce enable for GPIO
1104 }
1105 0x05, 0x2C, 2, RO, GPIO_RAW(gpio_raw) { /// GPIO Raw State
1106 grawp0, 0, 0, u8; /// GPIO port raw state
1107 grawp1, 1, 1, u8; /// GPIO port raw state
1108 grawp2, 2, 2, u8; /// GPIO port raw state
1109 grawp3, 3, 3, u8; /// GPIO port raw state
1110 grawp4, 4, 4, u8; /// GPIO port raw state
1111 grawp5, 5, 5, u8; /// GPIO port raw state
1112 grawp6, 6, 6, u8; /// GPIO port raw state
1113 grawp7, 7, 7, u8; /// GPIO port raw state
1114 grawp8, 8, 8, u8; /// GPIO port raw state
1115 }
1116
1117 /*******************************************************************/
1118 /***************** DRX_CONF REGISTER *************************/
1119 /*******************************************************************/
1120 0x06, 0x00, 2, RW, DTUNE0(dtune0) { /// PAC configuration
1121 pac, 0, 1, u8; /// Preamble Acquisition Chunk size
1122 dt0b4, 4, 4, u8; /// Tuning bit 4 of digital tuning reg0
1123 }
1124 0x06, 0x02, 2, RW, RX_SFD_TOC(rx_sfd_toc) { /// SFD timeout
1125 value, 0, 15, u16; /// don't set to 0
1126 }
1127 0x06, 0x04, 2, RW, PRE_TOC(pre_toc) { /// Preamble detection timeout
1128 value, 0, 15, u16; /// digital receiver configuration
1129 }
1130 0x06, 0x0C, 4, RW, DTUNE3(dtune3) { /// Receiver tuning register
1131 value, 0, 31, u32; /// value
1132 }
1133 0x06, 0x10, 4, RW, DTUNE4(dtune4) { /// Digital Tuning Reserved register
1134 dtune4, 24, 31, u32; /// value
1135 }
1136 0x06, 0x14, 4, RO, DTUNE5(dtune5) { /// Digital Tuning Reserved register
1137 value, 0, 31, u32; /// value
1138 }
1139 0x06, 0x29, 3, RO, DRX_CAR_INT(drx_car_int) { /// Carrier recovery integrator register
1140 value, 0, 23, u32; /// value
1141 }
1142
1143 /*******************************************************************/
1144 /***************** RF_CONF REGISTER *************************/
1145 /*******************************************************************/
1146 0x07, 0x00, 4, RW, RF_ENABLE(rf_enable) { /// RF control enable
1147 value, 0, 31, u32; /// value
1148 }
1149 0x07, 0x04, 4, RW, RF_CTRL_MASK(rf_ctrl_mask) { /// RF enable mask
1150 value, 0, 31, u32; /// value
1151 }
1152 0x07, 0x14, 4, RW, RF_SWITCH(rf_switch) { /// RF switch configuration
1153 antswnotoggle, 0, 0, u8; /// When set to 1, the automatic toggling of the antenna switch is disabled when the device is operating in PDoA modes
1154 antswpdoaport, 1, 1, u8; /// Specifies the starting port for reception when the device is operating in PDoA modes
1155 antswen, 8, 8, u8; /// Setting this to 1 will enable manual control of the antenna switch
1156 antswctrl, 12, 14, u8; /// Manual control of antenna switch when ANTSWEN is set
1157 trxswen, 16, 16, u8; /// Setting this to 1 will enable manual control of the TX RX switch
1158 trxswctrl, 24, 29, u8; /// TX/RX switch control when TRXSWEN bit is set
1159 }
1160 0x07, 0x1A, 1, RW, RF_TX_CTRL_1(rf_tx_ctrl_1) { /// RF transmitter configuration
1161 value, 0, 7, u8; /// value
1162 }
1163 0x07, 0x1C, 4, RW, RF_TX_CTRL_2(rf_tx_ctrl_2) { /// RF transmitter configuration
1164 value, 0, 31, u32; /// Pulse Generator Delay value
1165 }
1166 0x07, 0x28, 1, RW, TX_TEST(tx_test) { /// Transmitter test configuration
1167 tx_entest, 0, 3, u8; /// Transmitter test enable
1168 }
1169 0x07, 0x34, 1, RW, SAR_TEST(rsar_test) { /// Transmitter Calibration – SAR temperaturesensor read enable
1170 sar_rden, 2, 2, u8; /// Writing 1 enables the SAR temperature sensor reading
1171 }
1172 0x07, 0x40, 8, RW, LDO_TUNE(ldo_tune) { /// Internal LDO voltage tuning parameter
1173 value, 0x00, 0x3C, u128; /// used to control the output voltage levels of the on chip LDOs
1174 }
1175 0x07, 0x48, 4, RW, LDO_CTRL(ldo_ctrl) { /// LDO control
1176 low, 0, 15, u16; /// LDO control
1177 high, 16, 31, u16; /// LDO control
1178 }
1179 0x07, 0x51, 1, RW, LDO_RLOAD(ldo_rload) { /// LDO tuning register
1180 value, 0, 7, u8; /// LDO tuning register
1181 }
1182
1183 /*******************************************************************/
1184 /***************** RF_CAL REGISTER **************************/
1185 /*******************************************************************/
1186 0x08, 0x00, 1, RW, SAR_CTRL(sar_ctrl) { /// Transmitter Calibration – SAR control
1187 sar_start, 0, 0, u8; /// Writing 1 sets SAR enable and writing 0 clears the enable.
1188 }
1189 0x08, 0x04, 1, RW, SAR_STATUS(sar_status) { /// Transmitter Calibration – SAR status
1190 sar_done, 0, 0, u8; /// Set to 1 when the data is ready to be read.
1191 }
1192 0x08, 0x08, 3, RO, SAR_READING(sar_reading) { /// Transmitter Calibration –Latest SAR readings
1193 sar_lvbat, 0, 7, u8; /// Latest SAR reading for Voltage level.
1194 sar_ltemp, 8, 15, u8; /// Latest SAR reading for Temperature level.
1195 }
1196 0x08, 0x0C, 2, RO, SAR_WAKE_RD(sar_wake_rd) { /// Transmitter Calibration – SAR readings at last wake-up
1197 sar_wvbat, 0, 7, u8; /// SAR reading of Voltage level taken at last wake up event.
1198 sar_wtemp, 8, 15, u8; /// To read the temp, use SAR_READING instead.
1199 }
1200 0x08, 0x10, 2, RW, PGC_CTRL(pgc_ctrl) { /// Transmitter Calibration – Pulse Generator control
1201 pg_start, 0, 0, u8; /// Start the pulse generator calibration.
1202 pgc_auto_cal, 1, 1, u8; /// Start the pulse generator auto-calibration.
1203 pgc_tmeas, 2, 5, u8; /// Number of clock cycles over which to run the pulse generator calibration counter.
1204 }
1205 0x08, 0x14, 2, RO, PGC_STATUS(pgc_status) { /// Transmitter Calibration – Pulse Generator status
1206 pg_delay_cnt, 0, 11, u16; /// Pulse generator count value
1207 autocal_done, 12, 12, u8; /// Auto-calibration of the PG_DELAY has completed.
1208 }
1209 0x08, 0x18, 2, RW, PG_TEST(pg_test) { /// Transmitter Calibration – Pulse Generator test
1210 value, 0, 15, u16; /// Pulse Generator test
1211 }
1212 0x08, 0x1C, 2, RO, PG_CAL_TARGET(pg_cal_target) { /// Transmitter Calibration – Pulse Generator count target value
1213 value, 0, 11, u16; /// Pulse generator target value of PG_COUNT at which point PG auto cal will complete.
1214 }
1215
1216 /*******************************************************************/
1217 /***************** FS_CTRL REGISTER *************************/
1218 /*******************************************************************/
1219 0x09, 0x00, 2, RW, PLL_CFG(pll_cfg) { /// PLL configuration
1220 value, 0, 15, u16; /// PLL configuration
1221 }
1222 0x09, 0x04, 4, RW, PLL_CC(pll_cc) { /// PLL coarse code – starting code for calibration procedure
1223 ch9_code, 0, 7, u8; /// PLL calibration coarse code for channel 9.
1224 ch5_code, 8, 21, u16; /// PLL calibration coarse code for channel 5.
1225 value, 0, 31, u32; /// PLL calibration coarse code.
1226 }
1227 0x09, 0x08, 2, RW, PLL_CAL(pll_cal) { /// PLL calibration configuration
1228 use_old, 1, 1, u8; /// Use the coarse code value as set in PLL_CC register as starting point for PLL calibration.
1229 pll_cfg_ld, 4, 7, u8; /// PLL calibration configuration value.
1230 cal_en, 8, 8, u8; /// PLL calibration enable bit.
1231 }
1232 0x09, 0x14, 1, RW, XTAL(xtal) { /// Frequency synthesiser – Crystal trim
1233 value, 0, 7, u8; /// Crystal Trim.
1234 }
1235
1236 /*******************************************************************/
1237 /********************* AON REGISTER *************************/
1238 /*******************************************************************/
1239 0x0A, 0x00, 3, RW, AON_DIG_CFG(aon_dig_cfg) { /// AON wake up configuration register
1240 onw_aon_dld, 0, 0, u8; /// On Wake-up download the AON array.
1241 onw_run_sar, 1, 1, u8; /// On Wake-up Run the (temperature and voltage) Analog-to-Digital Convertors.
1242 onw_go2idle, 8, 8, u8; /// On Wake-up go to IDLE_PLL state.
1243 onw_go2rx, 9, 9, u8; /// On Wake-up go to RX.
1244 onw_pgfcal, 11, 11, u8; /// On Wake-up perform RX calibration
1245 }
1246 0x0A, 0x04, 1, RW, AON_CTRL(aon_ctrl) { /// AON control register
1247 restore, 0, 0, u8; /// Copy the user configurations from the AON memory to the host interface register set.
1248 save, 1, 1, u8; /// Copy the user configurations from the host interface register set into the AON memory.
1249 cfg_upload, 2, 2, u8; /// Upload the AON block configurations to the AON.
1250 dca_read, 3, 3, u8; /// Direct AON memory access read.
1251 dca_write, 4, 4, u8; /// Direct AON memory write access
1252 dca_write_hi, 5, 5, u8; /// Direct AON memory write access. Needs to be set when using address > 0xFF
1253 dca_enab, 7, 7, u8; /// Direct AON memory access enable bit.
1254 }
1255 0x0A, 0x08, 1, RW, AON_RDATA(aon_rdata) { /// AON direct access read data result
1256 value, 0, 7, u8; /// AON direct access read data result
1257 }
1258 0x0A, 0x0C, 2, RW, AON_ADDR(aon_addr) { /// AON direct access address
1259 value, 0, 15, u16; /// AON direct access address
1260 }
1261 0x0A, 0x10, 1, RW, AON_WDATA(aon_wdata) { /// AON direct access write data
1262 value, 0, 7, u8; /// AON direct access write data
1263 }
1264 0x0A, 0x14, 1, RW, AON_CFG(aon_cfg) { /// AON configuration register
1265 sleep_en, 0, 0, u8; /// Sleep enable configuration bit.
1266 wake_cnt, 1, 1, u8; /// Wake when sleep counter elapses.
1267 brout_en, 2, 2, u8; /// Enable the BROWNOUT detector during SLEEP or DEEPSLEEP.
1268 wake_csn, 3, 3, u8; /// Wake using SPI access.
1269 wake_wup, 4, 4, u8; /// Wake using WAKEUP pin.
1270 pres_sleep, 5, 5, u8; /// Preserve Sleep.
1271 }
1272
1273 /*******************************************************************/
1274 /****************** OTP_IF REGISTER *************************/
1275 /*******************************************************************/
1276 0x0B, 0x00, 4, RW, OTP_WDATA(otp_wdata) { /// OTP data to program to a particular address
1277 value, 0, 31, u32; /// OTP data to program to a particular address
1278 }
1279 0x0B, 0x04, 4, RW, OTP_ADDR(otp_addr) { /// OTP address to which to program the data
1280 otp_addr, 0, 10, u16; /// Address within OTP memory that will be accessed read or written.
1281 }
1282 0x0B, 0x08, 2, RW, OTP_CFG(otp_cfg) { /// OTP configuration register
1283 otp_man, 0, 0, u8; /// Enable manual control over OTP interface.
1284 otp_read, 1, 1, u8; /// OTP read enable.
1285 otp_write, 2, 2, u8; /// OTP write enable.
1286 otp_write_mr, 3, 3, u8; /// OTP write mode.
1287 dgc_kick, 6, 6, u8; /// Loading of the RX_TUNE_CAL parameter
1288 ldo_kick, 7, 7, u8; /// Loading of the LDOTUNE_CAL parameter
1289 bias_kick, 8, 8, u8; /// Loading of the BIASTUNE_CAL parameter
1290 ops_kick, 10, 10, u8; /// Loading of the operating parameter set selected by the OPS_SEL configuration
1291 ops_sel, 11, 12, u8; /// Operating parameter set selection.
1292 dgc_sel, 13, 13, u8; /// RX_TUNE parameter set selection.
1293 }
1294 0x0B, 0x0C, 1, RW, OTP_STAT(otp_stat) { /// OTP memory programming status register
1295 otp_prog_done, 0, 0, u8; /// OTP Programming Done
1296 otp_vpp_ok, 1, 1, u8; /// OTP Programming Voltage OK.
1297 }
1298 0x0B, 0x10, 4, RO, OTP_RDATA(otp_rdata) { /// OTP data read from given address
1299 value, 0, 31, u32; /// OTP data read from given address
1300 }
1301 0x0B, 0x14, 4, RW, OTP_SRDATA(otp_srdata) { /// OTP Special Register (SR) read data
1302 value, 0, 31, u32; /// OTP Special Register (SR) read data
1303 }
1304
1305 /*******************************************************************/
1306 /********************* CIA REGISTER *************************/
1307 /*******************************************************************/
1308 0x0C, 0x00, 8, RO, IP_TS(ip_ts) { /// Preamble sequence receive time stamp and status
1309 ip_toa, 0, 39, u64; /// Preamble sequence Time of Arrival estimate.
1310 ip_poa, 40, 53, u16; /// Phase of arrival as computed from the preamble CIR.
1311 ip_toast, 56, 63, u8; /// Preamble sequence Time of Arrival status indicator.
1312 }
1313 0x0C, 0x08, 8, RO, STS_TS(sts_ts) { /// STS receive time stamp and status
1314 sts_toa, 0, 39, u64; /// STS Time of Arrival estimate.
1315 sts_poa, 40, 53, u16; /// Phase of arrival as computed from the STS CIR.
1316 sts_toast, 55, 63, u16; /// STS sequence Time of Arrival status indicator.
1317 }
1318 0x0C, 0x10, 8, RO, STS1_TS(sts1_ts) { /// 2nd STS receive time stamp and status
1319 sts1_toa, 0, 39, u64; /// STS second Time of Arrival estimate.
1320 sts1_poa, 40, 53, u16; /// Phase of arrival as computed from the STS based CIR estimate.
1321 sts1_toast, 55, 63, u16; /// STS second Time of Arrival status indicator.
1322 }
1323 0x0C, 0x18, 6, RO, TDOA(tdoa) { /// The TDoA between the two CIRs
1324 value, 0, 47, u64; /// The TDoA between the two CIRs
1325 }
1326 0x0C, 0x1E, 2, RO, PDOA(pdoa) { /// The PDoA between the two CIRs
1327 pdoa, 0, 13, u16; /// Phase difference result.
1328 fp_th_md, 14, 14, u8; /// First path threshold test mode.
1329 }
1330 0x0C, 0x20, 4, RO, CIA_DIAG_0(cia_diag_0) { /// CIA Diagnostic 0
1331 coe_ppm, 0, 12, u16; /// Clock offset estimate.
1332 }
1333 0x0C, 0x24, 4, RO, CIA_DIAG_1(cia_diag_1) { /// Reserved diagnostic data
1334 }
1335 0x0C, 0x28, 4, RO, IP_DIAG_0(ip_diag_0) { /// Preamble Diagnostic 0 – peak
1336 ip_peaka, 0, 20, u32; /// Amplitude of the sample accumulated using the preamble sequence.
1337 ip_peaki, 21, 30, u16; /// Index of the sample accumulated using the preamble sequence.
1338 }
1339 0x0C, 0x2C, 4, RO, IP_DIAG_1(ip_diag_1) { /// Preamble Diagnostic 1 – power indication
1340 ip_carea, 0, 16, u32; /// Channel area accumulated using the preamble sequence.
1341 }
1342 0x0C, 0x30, 4, RO, IP_DIAG_2(ip_diag_2) { /// Preamble Diagnostic 2 – magnitude @ FP + 1
1343 ip_fp1m, 0, 21, u32; /// Magnitude of the sample at the first index immediately after the estimated first path position accumulated using the preamble sequence.
1344 }
1345 0x0C, 0x34, 4, RO, IP_DIAG_3(ip_diag_3) { /// Preamble Diagnostic 3 – magnitude @ FP + 2
1346 ip_fp2m, 0, 21, u32; /// Magnitude of the sample at the second index immediately after the estimated first path position accumulated using the preamble sequence.
1347 }
1348 0x0C, 0x38, 4, RO, IP_DIAG_4(ip_diag_4) { /// Preamble Diagnostic 4 – magnitude @ FP + 3
1349 ip_fp3m, 0, 21, u32; /// Magnitude of the sample at the third index immediately after the estimated first path position accumulated using the preamble sequence.
1350 }
1351 0x0C, 0x3C, 12, RO, IP_DIAG_RES1(ip_diag_res1) { /// Reserved diagnostic data
1352 }
1353 0x0C, 0x48, 4, RO, IP_DIAG_8(ip_diag_8) { /// Preamble Diagnostic 8 – first path
1354 ip_fp, 0, 15, u16; /// Estimated first path location accumulated using the preamble sequence.
1355 }
1356 0x0C, 0x4C, 12, RO, IP_DIAG_RES2(ip_diag_res2) { /// Reserved diagnostic data
1357 }
1358 0x0C, 0x58, 4, RO, IP_DIAG_12(ip_diag_12) { /// Preamble Diagnostic 12 – symbols accumulated
1359 ip_nacc, 0, 11, u16; /// Number of preamble sequence symbols that were accumulated to form the preamble CIR.
1360 }
1361 0x0C, 0x5C, 4, RO, STS_DIAG_0(sts_diag_0) { /// STS 0 Diagnostic 0 – STS CIA peak amplitude
1362 cp0_peaka, 0, 20, u32; /// Amplitude of the sample accumulated using the STS
1363 cp0_peaki, 21, 29, u16; /// Index of the sample accumulated using the STS
1364 }
1365 0x0C, 0x60, 4, RO, STS_DIAG_1(sts_diag_1) { /// STS 0 Diagnostic 1 – STS power indication
1366 cp0_carea, 0, 15, u16; /// Channel area accumulated using the the STS
1367 }
1368 0x0C, 0x64, 4, RO, STS_DIAG_2(sts_diag_2) { /// STS 0 Diagnostic 2 – STS magnitude @ FP + 1
1369 cp0_fp1m, 0, 21, u32; /// Magnitude of the sample at the first index immediately after the estimated first path position accumulated using the STS
1370 }
1371 0x0C, 0x68, 4, RO, STS_DIAG_3(sts_diag_3) { /// STS 0 Diagnostic 3 – STS magnitude @ FP + 2
1372 cp0_fp2m, 0, 21, u32; /// Magnitude of the sample at the second index immediately after the estimated first path position accumulated using the STS
1373 }
1374 0x0D, 0x00, 4, RO, STS_DIAG_4(sts_diag_4) { /// STS 0 Diagnostic 4 – STS magnitude @ FP + 3
1375 cp0_fp3m, 0, 21, u32; /// Magnitude of the sample at the third index immediately after the estimated first path position accumulated using the STS
1376 }
1377 0x0D, 0x04, 12, RO, STS0_DIAG_RES1(sts0_diag_res1) { /// Reserved diagnostic data
1378 }
1379 0x0D, 0x10, 4, RO, STS_DIAG_8(sts_diag_8) { /// STS 0 Diagnostic 8 – STS first path
1380 cp0_fp, 0, 14, u16; /// Estimated first path location accumulated using the STS
1381 }
1382 0x0D, 0x14, 12, RO, STS0_DIAG_RES2(sts0_diag_res2) { /// Reserved diagnostic data
1383 }
1384 0x0D, 0x20, 4, RO, STS_DIAG_12(sts_diag_12) { /// STS 0 diagnostic 12 – accumulated STS length
1385 cp0_nacc, 0, 10, u16; /// Number of preamble sequence symbols that were accumulated to form the preamble CIR.
1386 }
1387 0x0D, 0x24, 20, RO, STS0_DIAG_RES3(sts0_diag_res3) { /// Reserved diagnostic data
1388 }
1389 0x0D, 0x38, 4, RO, STS1_DIAG_0(sts1_diag_0) { /// STS 1 Diagnostic 0 – STS CIA peak amplitude
1390 cp1_peaka, 0, 20, u32; /// Amplitude of the sample accumulated using the STS
1391 cp1_peaki, 21, 29, u16; /// Index of the sample accumulated using the STS
1392 }
1393 0x0D, 0x3C, 4, RO, STS1_DIAG_1(sts1_diag_1) { /// STS 1 Diagnostic 1 – STS power indication
1394 cp1_carea, 0, 15, u16; /// Channel area accumulated using the the STS
1395 }
1396 0x0D, 0x40, 4, RO, STS1_DIAG_2(sts1_diag_2) { /// STS 1 Diagnostic 2 – STS magnitude @ FP + 1
1397 cp1_fp1m, 0, 21, u32; /// Magnitude of the sample at the first index immediately after the estimated first path position accumulated using the STS
1398 }
1399 0x0D, 0x44, 4, RO, STS1_DIAG_3(sts1_diag_3) { /// STS 1 Diagnostic 3 – STS magnitude @ FP + 2
1400 cp1_fp2m, 0, 21, u32; /// Magnitude of the sample at the second index immediately after the estimated first path position accumulated using the STS
1401 }
1402 0x0D, 0x48, 4, RO, STS1_DIAG_4(sts1_diag_4) { /// STS 1 Diagnostic 4 – STS magnitude @ FP + 3
1403 cp1_fp3m, 0, 21, u32; /// Magnitude of the sample at the third index immediately after the estimated first path position accumulated using the STS
1404 }
1405 0x0D, 0x4C, 12, RO, STS1_DIAG_RES1(sts1_diag_res1) { /// Reserved diagnostic data
1406 }
1407 0x0D, 0x58, 4, RO, STS1_DIAG_8(sts1_diag_8) { /// STS 1 Diagnostic 8 – STS first path
1408 cp1_fp, 0, 14, u16; /// Estimated first path location accumulated using the STS
1409 }
1410 0x0D, 0x5C, 12, RO, STS1_DIAG_RES2(sts1_diag_res2) { /// Reserved diagnostic data
1411 }
1412 0x0D, 0x68, 4, RO, STS1_DIAG_12(sts1_diag_12) { /// STS 1 Diagnostic 12 – STS accumulated STS length
1413 cp1_nacc, 0, 10, u16; /// Number of preamble sequence symbols that were accumulated to form the preamble CIR.
1414 }
1415 0x0E, 0x00, 4, RW, CIA_CONF(cia_conf) { /// CIA general configuration
1416 rxantd, 0, 15, u16; /// Configures the receive antenna delay.
1417 mindiag, 20, 20, u8; /// Minimum Diagnostics.
1418 }
1419 0x0E, 0x04, 4, RW, FP_CONF(fp_conf) { /// First path temp adjustment and thresholds
1420 fp_agreed_th, 8, 10, u8; /// The threshold to use when performing the FP_AGREE test.
1421 cal_temp, 11, 18, u8; /// Temperature at which the device was calibrated.
1422 tc_rxdly_en, 20, 20, u8; /// Temperature compensation for RX antenna delay.
1423 }
1424 0x0E, 0x0C, 4, RW, IP_CONF_LO(ip_conf_lo) { /// Preamble Config – CIA preamble configuration
1425 ip_ntm, 0, 4, u8; /// Preamble Noise Threshold Multiplier.
1426 ip_pmult, 5, 6, u8; /// Preamble Peak Multiplier.
1427 ip_scp, 8, 9, u8; /// Undocumented bitfield for SCP mode.
1428 ip_rtm, 16, 20, u8; /// Preamble replica threshold multiplier
1429 }
1430 0x0E, 0x0E, 4, RW, IP_CONF_HI(ip_conf_hi) { /// Preamble Config – CIA preamble configuration
1431 value, 0, 31, u32; /// Undocumented IP_CONF_HI register
1432 }
1433 0x0E, 0x12, 4, RW, STS_CONF_0(sts_conf_0) { /// STS Config 0 – CIA STS configuration
1434 sts_ntm, 0, 4, u8; /// STS Noise Threshold Multiplier.
1435 sts_pmult, 5, 6, u8; /// STS Peak Multiplier.
1436 sts_scp, 8, 15, u8; /// Undocumented bitfield for SCP mode.
1437 sts_rtm, 16, 22, u8; /// STS replica threshold multiplier
1438 }
1439 0x0E, 0x16, 4, RW, STS_CONF_1(sts_conf_1) { /// STS Config 1 – CIA STS configuration
1440 res_b0, 0, 7, u8; /// Tuning value
1441 fp_agreed_en, 28, 28, u8; /// Checks to see if the two ToA estimates are within allowed tolerances.
1442 sts_cq_en, 29, 29, u8; /// Checks how consistent the impulse response stays during the accumulation of the STS.
1443 sts_ss_en, 30, 30, u8; /// Compare the sampling statistics of the STS reception to those of the earlier reception of the preamble sequence.
1444 sts_pgr_en, 31, 31, u8; /// Test the growth rate of the STS based CIR to the earlier growth rate of the preamble based CIR.
1445 }
1446 0x0E, 0x1A, 2, RW, CIA_ADJUST(cia_adjust) { /// User adjustment to the PDoA
1447 value, 0, 13, u8; /// Adjustment value to account for non-balanced antenna circuits.
1448 }
1449
1450 /*******************************************************************/
1451 /***************** DIG_DIAG REGISTER ************************/
1452 /*******************************************************************/
1453 0x0F, 0x00, 1, RW, EVC_CTRL(evc_ctrl) { /// Event counter control
1454 evc_en, 0, 0, u8; /// Event Counters Enable.
1455 evc_clr, 1, 1, u8; /// Event Counters Clear.
1456 }
1457 0x0F, 0x04, 2, RO, EVC_PHE(evc_phe) { /// PHR error counter
1458 value, 0, 11, u16; /// PHR Error Event Counter.
1459 }
1460 0x0F, 0x06, 2, RO, EVC_RSE(evc_rse) { /// RSD error counter
1461 value, 0, 11, u16; /// Reed Solomon decoder (Sync Loss) Error Event Counter.
1462 }
1463 0x0F, 0x08, 2, RO, EVC_FCG(evc_fcg) { /// Frame check sequence good counter
1464 value, 0, 11, u16; /// Frame Check Sequence Good Event Counter.
1465 }
1466 0x0F, 0x0A, 2, RO, EVC_FCE(evc_fce) { /// Frame Check Sequence error counter
1467 value, 0, 11, u16; /// Frame Check Sequence Error Event Counter.
1468 }
1469 0x0F, 0x0C, 1, RO, EVC_FFR(evc_ffr) { /// Frame filter rejection counter
1470 value, 0, 7, u8; /// Frame Filter Rejection Event Counter.
1471 }
1472 0x0F, 0x0E, 1, RO, EVC_OVR (evc_ovr) { /// RX overrun error counter
1473 value, 0, 7, u8; /// RX Overrun Error Event Counter.
1474 }
1475 0x0F, 0x10, 2, RO, EVC_STO(evc_sto) { /// SFD timeout counter
1476 value, 0, 11, u16; /// SFD timeout errors Event Counter.
1477 }
1478 0x0F, 0x12, 2, RO, EVC_PTO(evc_pto) { /// Preamble timeout counter
1479 value, 0, 11, u16; /// Preamble Detection Timeout Event Counter.
1480 }
1481 0x0F, 0x14, 1, RO, EVC_FWTO(evc_fwto) { /// RX frame wait timeout counter
1482 value, 0, 7, u8; /// RX Frame Wait Timeout Event Counter.
1483 }
1484 0x0F, 0x16, 2, RO, EVC_TXFS(evc_txfs) { /// TX frame sent counter
1485 value, 0, 11, u16; /// TX Frame Sent Event Counter.
1486 }
1487 0x0F, 0x18, 1, RO, EVC_HPW(evc_hpw) { /// Half period warning counter
1488 value, 0, 7, u8; /// Half Period Warning Event Counter.
1489 }
1490 0x0F, 0x1A, 1, RO, EVC_SWCE(evc_swce) { /// SPI write CRC error counter
1491 value, 0, 7, u8; /// SPI write CRC error counter.
1492 }
1493 0x0F, 0x1C, 8, RO, EVC_RES1(evc_res1) { /// Digital diagnostics reserved area 1
1494 value, 0, 63, u64; /// Digital diagnostics reserved area 1
1495 }
1496 0x0F, 0x24, 4, RW, DIAG_TMC(diag_tmc) { /// Test mode control register
1497 tx_pstm, 4, 4, u8; /// Transmit Power Spectrum Test Mode.
1498 hirq_pol, 21, 21, u8; /// Host interrupt polarity.
1499 cia_wden, 24, 24, u8; /// Enable the CIA watchdog.
1500 cia_run, 26, 26, u8; /// Run the CIA manually.
1501 }
1502 0x0F, 0x28, 1, RO, EVC_CPQE(evc_cpqe) { /// STS quality error counter
1503 value, 0, 7, u8; /// STS quality error counter
1504 }
1505 0x0F, 0x2A, 1, RO, EVC_VWARN(evc_vwarn) { /// Low voltage warning error counter
1506 value, 0, 7, u8; /// Low voltage warning error counter
1507 }
1508 0x0F, 0x2C, 1, RO, SPI_MODE(spi_mode) { /// SPI mode
1509 value, 0, 1, u8; /// SPI mode
1510 }
1511 0x0F, 0x30, 4, RO, SYS_STATE(sys_state) { /// System states *
1512 tx_state, 0, 3, u8; /// Current Transmit State Machine value
1513 rx_state, 8, 11, u8; /// Current Receive State Machine value
1514 pmsc_state, 16, 23, u8; /// Current PMSC State Machine value
1515 }
1516 0x0F, 0x3C, 1, RO, FCMD_STAT(fcmd_stat) { /// Fast command status
1517 value, 0, 4, u8; /// Fast command status.
1518 }
1519 0x0F, 0x48, 4, RO, CTR_DBG(ctr_dbg) { /// Current value of the low 32-bits of the STS IV
1520 value, 0, 31, u32; /// Current value of the low 32-bits of the STS IV
1521 }
1522 0x0F, 0x4C, 1, RO, SPICRCINIT(spicrcinit) { /// SPI CRC LFSR initialisation code
1523 value, 0, 7, u8; /// SPI CRC LFSR initialisation code for the SPI CRC function.
1524 }
1525
1526 /*******************************************************************/
1527 /******************** PMSC REGISTER *************************/
1528 /*******************************************************************/
1529 0x11, 0x00, 2, RW, SOFT_RST(soft_rst) { /// Soft reset of the device blocks
1530 arm_rst, 0, 0, u8; /// Soft ARM reset
1531 prgn_rst, 1, 1, u8; /// Soft PRGN reset
1532 cia_rst, 2, 2, u8; /// Soft CIA reset
1533 bist_rst, 3, 3, u8; /// Soft BIST reset
1534 rx_rst, 4, 4, u8; /// Soft RX reset
1535 tx_rst, 5, 5, u8; /// Soft TX reset
1536 hif_rst, 6, 6, u8; /// Soft HIF reset
1537 pmsc_rst, 7, 7, u8; /// Soft PMSC reset
1538 gpio_rst, 8, 8, u8; /// Soft GPIO reset
1539 }
1540 0x11, 0x04, 4, RW, CLK_CTRL(clk_ctrl) { /// PMSC clock control register
1541 sys_clk, 0, 1, u8; /// System Clock Selection field.
1542 rx_clk, 2, 3, u8; /// Receiver Clock Selection
1543 tx_clk, 4, 5, u8; /// Transmitter Clock Selection.
1544 acc_clk_en, 6, 6, u8; /// Force Accumulator Clock Enable
1545 cia_clk_en, 8, 8, u8; /// Force CIA Clock Enable
1546 sar_clk_en, 10, 10, u8; /// Analog-to-Digital Convertor Clock Enable.
1547 acc_mclk_en, 15, 15, u8; /// Accumulator Memory Clock Enable.
1548 gpio_clk_en, 16, 16, u8; /// GPIO clock Enable
1549 gpio_dclk_en, 18, 18, u8; /// GPIO De-bounce Clock Enable.
1550 gpio_drst_n, 19, 19, u8; /// GPIO de-bounce reset (NOT), active low.
1551 lp_clk_en, 23, 23, u8; /// Kilohertz clock Enable.
1552 }
1553 0x11, 0x08, 4, RW, SEQ_CTRL(seq_ctrl) { /// PMSC sequencing control register
1554 ainit2idle, 8, 8, u8; /// Automatic IDLE_RC to IDLE_PLL.
1555 atx2slp, 11, 11, u8; /// After TX automatically Sleep.
1556 arx2slp, 12, 12, u8; /// After RX automatically Sleep.
1557 pll_sync, 15, 15, u8; /// This enables a 1 GHz clock used for some external SYNC modes.
1558 ciarune, 17, 17, u8; /// CIA run enable.
1559 force2init, 23, 23, u8; /// Force to IDLE_RC state.
1560 lp_clk_div, 26, 31, u8; /// Kilohertz clock divisor.
1561 }
1562 0x11, 0x12, 4, RW, TXFSEQ(txfseq) { /// PMSC fine grain TX sequencing control
1563 value, 0, 31, u32; /// PMSC fine grain TX sequencing control
1564 }
1565 0x11, 0x16, 4, RW, LED_CTRL(led_ctrl) { /// PMSC fine grain TX sequencing control
1566 blink_tim, 0, 7, u8; /// Blink time count value.
1567 blink_en, 8, 8, u8; /// Blink Enable.
1568 force_trig, 16, 19, u8; /// Manually triggers an LED blink.
1569 }
1570 0x11, 0x1A, 4, RW, RX_SNIFF(rx_sniff) { /// Receiver SNIFF mode configuration
1571 sniff_on, 0, 3, u8; /// SNIFF Mode ON time.
1572 sniff_off, 8, 15, u8; /// SNIFF Mode OFF time specified in μs.
1573 }
1574 0x11, 0x1F, 2, RW, BIAS_CTRL(bias_ctrl) { /// Analog blocks’ calibration values
1575 value, 0, 13, u16; /// Analog blocks’ calibration values
1576 }
1577
1578 /*******************************************************************/
1579 /***************** ACC_MEM REGISTER *************************/
1580 /*******************************************************************/
1581 0x15, 0x00, 12288, RO, ACC_MEM(acc_mem) { /// Read access to accumulator data memory
1582 } // If the code doesn't run properly, reduce the length from 12288 to 8096
1583
1584 /*******************************************************************/
1585 /***************** SCRATCH_RAM REGISTER *********************/
1586 /*******************************************************************/
1587 0x16, 0x00, 127, RW, SCRATCH_RAM(scratch_ram) { /// Scratch RAM memory buffer
1588 }
1589
1590 /*******************************************************************/
1591 /***************** AES_RAM REGISTER *************************/
1592 /*******************************************************************/
1593 0x17, 0x00, 128, RW, AES_KEY_RAM(aes_key_ram) { /// storage for up to 8 x 128 bit AES KEYs
1594 aes_key1, 0x0, 0x7F, u128; /// 1st AES key
1595 aes_key2, 0x80, 0xFF, u128; /// 2nd AES key
1596 aes_key3, 0x100, 0x17F, u128; /// 3rd AES key
1597 aes_key4, 0x180, 0x1FF, u128; /// 4th AES key
1598 aes_key5, 0x200, 0x27F, u128; /// 5th AES key
1599 aes_key6, 0x280, 0x2FF, u128; /// 6th AES key
1600 aes_key7, 0x300, 0x37F, u128; /// 7th AES key
1601 aes_key8, 0x380, 0x3FF, u128; /// 8th AES key
1602 }
1603
1604 /*******************************************************************/
1605 /***************** SET_1, SET2 REGISTERS ********************/
1606 /*******************************************************************/
1607 0x18, 0x00, 464, RO, DB_DIAG(db_diag) { /// Double buffer diagnostic register set
1608 }
1609 0x18, 0x00, 232, RO, DB_DIAG_SET1(db_diag_set1) { /// Double buffer diagnostic register set 1
1610 }
1611 0x18, 0xE8, 232, RO, DB_DIAG_SET2(db_diag_set2) { /// Double buffer diagnostic register set 2
1612 }
1613
1614 /*******************************************************************/
1615 /***************** INDIRECT_PTR_A REGISTER ******************/
1616 /*******************************************************************/
1617 0x1D, 0x00, 1, RW, INDIRECT_PTR_A(indirect_ptr_a) { /// Indirect pointer A
1618 value, 0, 7, u8; /// Indirect pointer A
1619 }
1620
1621 /*******************************************************************/
1622 /***************** INDIRECT_PTR_B REGISTER ******************/
1623 /*******************************************************************/
1624 0x1E, 0x00, 1, RW, INDIRECT_PTR_B(indirect_ptr_b) { /// Indirect pointer B
1625 value, 0, 7, u8; /// Indirect pointer B
1626 }
1627
1628 /*******************************************************************/
1629 /***************** IN_PTR_CFG REGISTER **********************/
1630 /*******************************************************************/
1631 0x1F, 0x00, 1, RO, FINT_STAT(fint_stat) { /// Fast System Event Status Register
1632 txok, 0, 0, u8; /// TXFRB or TXPRS or TXPHS or TXFRS.
1633 cca_fail, 1, 1, u8; /// AAT or CCA_FAIL.
1634 rxtserr, 2, 2, u8; /// CIAERR
1635 rxok, 3, 3, u8; /// RXFR and CIADONE or RXFCG.
1636 rxerr, 4, 4, u8; /// RXFCE or RXFSL or RXPHE or ARFE or RXSTO or RXOVRR.
1637 rxto, 5, 5, u8; /// RXFTO or RXPTO.
1638 sys_event, 6, 6, u8; /// VT_DET or GPIOIRQ or RCINIT or SPIRDY.
1639 sys_panic, 7, 7, u8; /// AES_ERR or CMD_ERR or SPI_UNF or SPI_OVF or SPIERR or PLL_HILO or VWARN.
1640 }
1641 0x1F, 0x04, 1, RW, PTR_ADDR_A(ptr_addr_a) { /// Base address of the register to be accessed through indirect pointer A
1642 ptra_base, 0, 4, u8; /// Base address of the register to be accessed through indirect pointer A
1643 }
1644 0x1F, 0x08, 2, RW, PTR_OFFSET_A(ptr_offset_a) { /// Offset address of the register to be accessed through indirect pointer A
1645 ptra_ofs, 0, 14, u16; /// Offset address of the register to be accessed through indirect pointer A
1646 }
1647 0x1F, 0x0C, 1, RW, PTR_ADDR_B(ptr_addr_b) { /// Base address of the register to be accessed through indirect pointer B
1648 ptrb_base, 0, 4, u8; /// Base address of the register to be accessed through indirect pointer B
1649 }
1650 0x1F, 0x10, 2, RW, PTR_OFFSET_B(ptr_offset_b) { /// Offset address of the register to be accessed through indirect pointer B
1651 ptrb_ofs, 0, 14, u16; /// Offset address of the register to be accessed through indirect pointer B
1652 }
1653}
1654
1655/// Transmit Data Buffer
1656///
1657/// Currently only the first 127 bytes of the buffer are supported, which is
1658/// enough to support standard Standard IEEE 802.15.4 UWB frames.
1659#[allow(non_camel_case_types)]
1660pub struct TX_BUFFER;
1661
1662impl Register for TX_BUFFER {
1663 const ID: u8 = 0x14;
1664 const LEN: usize = 127;
1665 const SUB_ID: u8 = 0x00;
1666}
1667
1668impl Writable for TX_BUFFER {
1669 type Write = tx_buffer::W;
1670
1671 fn write() -> Self::Write {
1672 tx_buffer::W([0; 127 + 2])
1673 }
1674
1675 fn buffer(w: &mut Self::Write) -> &mut [u8] {
1676 &mut w.0
1677 }
1678}
1679
1680impl<SPI> DW3000<SPI> {
1681 /// Transmit Data Buffer
1682 pub fn tx_buffer(&mut self) -> RegAccessor<TX_BUFFER, SPI> {
1683 RegAccessor(self, PhantomData)
1684 }
1685}
1686
1687/// Transmit Data Buffer
1688pub mod tx_buffer {
1689
1690 const HEADER_LEN: usize = 2;
1691 const LEN: usize = 127;
1692
1693 /// Used to write to the register
1694 pub struct W(pub(crate) [u8; LEN + HEADER_LEN]);
1695
1696 impl W {
1697 /// Provides write access to the buffer contents
1698 pub fn data(&mut self) -> &mut [u8] {
1699 &mut self.0[HEADER_LEN..]
1700 }
1701 }
1702}
1703
1704/// Receive Data Buffer 0
1705///
1706/// Currently only the first 127 bytes of the buffer are supported, which is
1707/// enough to support standard Standard IEEE 802.15.4 UWB frames.
1708#[allow(non_camel_case_types)]
1709pub struct RX_BUFFER_0;
1710
1711impl Register for RX_BUFFER_0 {
1712 const ID: u8 = 0x12;
1713 const LEN: usize = 127;
1714 const SUB_ID: u8 = 0x00;
1715}
1716
1717impl Readable for RX_BUFFER_0 {
1718 type Read = rx_buffer_0::R;
1719
1720 fn read() -> Self::Read {
1721 rx_buffer_0::R([0; 127 + 2])
1722 }
1723
1724 fn buffer(w: &mut Self::Read) -> &mut [u8] {
1725 &mut w.0
1726 }
1727}
1728
1729impl<SPI> DW3000<SPI> {
1730 /// Receive Data Buffer
1731 pub fn rx_buffer_0(&mut self) -> RegAccessor<RX_BUFFER_0, SPI> {
1732 RegAccessor(self, PhantomData)
1733 }
1734}
1735
1736/// Receive Data Buffer
1737pub mod rx_buffer_0 {
1738 use core::fmt;
1739
1740 const HEADER_LEN: usize = 2;
1741 const LEN: usize = 127;
1742
1743 /// Used to read from the register
1744 pub struct R(pub(crate) [u8; HEADER_LEN + LEN]);
1745
1746 impl R {
1747 /// Provides read access to the buffer contents
1748 pub fn data(&self) -> &[u8] {
1749 &self.0[HEADER_LEN..HEADER_LEN + LEN]
1750 }
1751 }
1752
1753 impl fmt::Debug for R {
1754 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1755 write!(f, "0x")?;
1756 for i in (0..LEN).rev() {
1757 write!(f, "{:02x}", self.0[HEADER_LEN + i])?;
1758 }
1759
1760 Ok(())
1761 }
1762 }
1763}
1764
1765/// Receive Data Buffer 1
1766///
1767/// Currently only the first 127 bytes of the buffer are supported, which is
1768/// enough to support Standard IEEE 802.15.4 UWB frames.
1769#[allow(non_camel_case_types)]
1770pub struct RX_BUFFER_1;
1771
1772impl Register for RX_BUFFER_1 {
1773 const ID: u8 = 0x13;
1774 const LEN: usize = 127;
1775 const SUB_ID: u8 = 0x00;
1776}
1777
1778impl Readable for RX_BUFFER_1 {
1779 type Read = rx_buffer_1::R;
1780
1781 fn read() -> Self::Read {
1782 rx_buffer_1::R([0; 127 + 2])
1783 }
1784
1785 fn buffer(w: &mut Self::Read) -> &mut [u8] {
1786 &mut w.0
1787 }
1788}
1789
1790impl<SPI> DW3000<SPI> {
1791 /// Receive Data Buffer1
1792 pub fn rx_buffer_1(&mut self) -> RegAccessor<RX_BUFFER_1, SPI> {
1793 RegAccessor(self, PhantomData)
1794 }
1795}
1796
1797/// Receive Data Buffer
1798pub mod rx_buffer_1 {
1799 use core::fmt;
1800
1801 const HEADER_LEN: usize = 2;
1802 const LEN: usize = 127;
1803
1804 /// Used to read from the register
1805 pub struct R(pub(crate) [u8; HEADER_LEN + LEN]);
1806
1807 impl R {
1808 /// Provides read access to the buffer contents
1809 pub fn data(&self) -> &[u8] {
1810 &self.0[HEADER_LEN..HEADER_LEN + LEN]
1811 }
1812 }
1813
1814 impl fmt::Debug for R {
1815 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1816 write!(f, "0x")?;
1817 for i in (0..LEN).rev() {
1818 write!(f, "{:02x}", self.0[HEADER_LEN + i])?;
1819 }
1820
1821 Ok(())
1822 }
1823 }
1824}
1825
1826/// Internal trait used by `impl_registers!`
1827trait FromBytes {
1828 fn from_bytes(bytes: &[u8]) -> Self;
1829}
1830
1831/// Internal trait used by `impl_registers!`
1832trait ToBytes {
1833 type Bytes;
1834
1835 fn to_bytes(self) -> Self::Bytes;
1836}
1837
1838/// Internal macro used to implement `FromBytes`/`ToBytes`
1839macro_rules! impl_bytes {
1840 ($($ty:ty,)*) => {
1841 $(
1842 impl FromBytes for $ty {
1843 fn from_bytes(bytes: &[u8]) -> Self {
1844 let mut val = 0;
1845
1846 for (i, &b) in bytes.iter().enumerate() {
1847 val |= (b as $ty) << (i * 8);
1848 }
1849
1850 val
1851 }
1852 }
1853
1854 impl ToBytes for $ty {
1855 type Bytes = [u8; ::core::mem::size_of::<$ty>()];
1856
1857 fn to_bytes(self) -> Self::Bytes {
1858 let mut bytes = [0; ::core::mem::size_of::<$ty>()];
1859
1860 for (i, b) in bytes.iter_mut().enumerate() {
1861 let shift = 8 * i;
1862 let mask = 0xff << shift;
1863
1864 *b = ((self & mask) >> shift) as u8;
1865 }
1866
1867 bytes
1868 }
1869 }
1870 )*
1871 }
1872}
1873
1874impl_bytes! {
1875 u8,
1876 u16,
1877 u32,
1878 u64,
1879 u128,
1880}