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}