ra4e2_pac/
common.rs

1/*
2DISCLAIMER
3This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products.
4No other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
5applicable laws, including copyright laws.
6THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING THIS SOFTWARE, WHETHER EXPRESS, IMPLIED
7OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
8NON-INFRINGEMENT.  ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY
9LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE FOR ANY DIRECT,
10INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR
11ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
12Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability
13of this software. By using this software, you agree to the additional terms and conditions found by accessing the
14following link:
15http://www.renesas.com/disclaimer
16
17*/
18// Generated from SVD 1.30.00, with svd2pac 0.4.0 on Sat, 12 Apr 2025 22:15:35 +0000
19
20use core::convert::From;
21use core::marker::PhantomData;
22
23#[cfg(feature = "tracing")]
24use crate::tracing;
25
26#[derive(Copy, Clone, PartialEq, Eq)]
27pub struct RW;
28#[derive(Copy, Clone, PartialEq, Eq)]
29pub struct R;
30#[derive(Copy, Clone, PartialEq, Eq)]
31pub struct W;
32
33pub(crate) mod sealed {
34    use super::*;
35    pub trait Access {}
36    impl Access for R {}
37    impl Access for W {}
38    impl Access for RW {}
39    use core::ops::{BitAnd, BitAndAssign, BitOrAssign, Not, Shl, Shr};
40
41    // It would be better with const fn
42    // waiting for RFC: const functions in traits #3490
43    pub trait CastFrom<A> {
44        fn cast_from(val: A) -> Self;
45    }
46
47    impl CastFrom<u64> for u8 {
48        #[inline(always)]
49        fn cast_from(val: u64) -> Self {
50            val as Self
51        }
52    }
53
54    impl CastFrom<u64> for u16 {
55        #[inline(always)]
56        fn cast_from(val: u64) -> Self {
57            val as Self
58        }
59    }
60
61    impl CastFrom<u64> for u32 {
62        #[inline(always)]
63        fn cast_from(val: u64) -> Self {
64            val as Self
65        }
66    }
67
68    impl CastFrom<u64> for u64 {
69        #[inline(always)]
70        fn cast_from(val: u64) -> Self {
71            val as Self
72        }
73    }
74
75    pub trait RegNumberT:
76        Copy
77        + From<u8>
78        + Into<u64>
79        + CastFrom<u64>
80        + Shr<usize, Output = Self>
81        + Shl<usize, Output = Self>
82        + BitAndAssign
83        + BitAnd<Output = Self>
84        + Not<Output = Self>
85        + BitOrAssign
86    {
87    }
88    impl RegNumberT for u8 {}
89    impl RegNumberT for u16 {}
90    impl RegNumberT for u32 {}
91    impl RegNumberT for u64 {}
92
93    pub trait RegSpec {
94        type DataType: RegNumberT;
95    }
96}
97
98pub trait Access: sealed::Access + Copy {}
99impl Access for R {}
100impl Access for W {}
101impl Access for RW {}
102
103pub trait Read: Access {}
104impl Read for RW {}
105impl Read for R {}
106
107pub trait Write: Access {}
108impl Write for RW {}
109impl Write for W {}
110
111#[derive(Copy, Clone, PartialEq, Eq)]
112pub struct Reg<T, A: Access> {
113    phantom: PhantomData<*mut (T, A)>,
114}
115unsafe impl<T, A: Access> Send for Reg<T, A> {}
116unsafe impl<T, A: Access> Sync for Reg<T, A> {}
117
118use sealed::CastFrom;
119
120use sealed::{RegNumberT, RegSpec};
121#[doc(hidden)]
122#[derive(Copy, Clone)]
123pub struct RegValueT<Reg: sealed::RegSpec> {
124    pub(crate) data: Reg::DataType,
125    pub(crate) mask: Reg::DataType,
126}
127
128pub trait RegisterValue<T: RegSpec> {
129    /// Create a register value that could be written to a register from raw integer
130    ///
131    /// ```rust, ignore
132    /// // example with generic names
133    /// // needs: use test_pac::{timer, RegisterValue, TIMER}
134    /// let to_write = timer::BitfieldReg::new(0xdeadbeef);
135    /// TIMER.bitfield_reg().write(to_write);
136    /// let to_write = to_write.boolw().set(true);
137    /// TIMER.bitfield_reg().write(to_write);
138    /// ```
139    #[must_use]
140    fn new(data: T::DataType) -> Self;
141
142    /// Get raw integer from value read from register
143    ///
144    /// ```rust,ignore
145    /// // example with generic names
146    /// // needs: use pac::{RegisterValue, TIMER}
147    /// let x = TIMER.bitfield_reg().read().get_raw();
148    /// ```
149    #[must_use]
150    fn get_raw(&self) -> T::DataType;
151
152    /// Prepare a register value that could be written to a register with an arbitrary value
153    ///
154    /// Use this function for setting a register to a custom value, independent
155    /// of bitfields, enumerations, etc. No checks are performed on the passed
156    /// value. The whole register is updated on write.
157    ///
158    /// ```rust,ignore
159    /// // example with generic names
160    /// // needs: use pac::{RegisterValue, TIMER}
161    /// TIMER.bitfield_reg().init(|r| r.set_raw(0xdeadbeef))
162    /// ```
163    #[must_use]
164    fn set_raw(self, value: T::DataType) -> Self;
165}
166
167impl<T: RegSpec> RegisterValue<T> for RegValueT<T> {
168    /// Create a register value that could be written to a register from raw integer
169    ///
170    /// ```rust, ignore
171    /// // example with generic names
172    /// // needs: use pac::{timer, RegisterValue, TIMER}
173    /// let to_write = timer::BitfieldReg::new(0xdeadbeef);
174    /// TIMER.bitfield_reg().write(to_write);
175    /// let to_write = to_write.boolw().set(true);
176    /// TIMER.bitfield_reg().write(to_write);
177    /// ```
178    #[inline(always)]
179    fn new(data: T::DataType) -> RegValueT<T> {
180        Self {
181            data,
182            mask: 0x0u8.into(),
183        }
184    }
185
186    /// Get raw integer from value read from register
187    ///
188    /// ```rust,ignore
189    /// // example with generic names
190    /// // needs: use pac::{RegisterValue, TIMER}
191    /// let x = TIMER.bitfield_reg().read().get_raw();
192    /// ```
193    #[inline(always)]
194    fn get_raw(&self) -> T::DataType {
195        self.data
196    }
197
198    /// Prepare a register value that could be written to a register with an arbitrary value
199    ///
200    /// Use this function for setting a register to a custom value, independent
201    /// of bitfields, enumerations, etc. No checks are performed on the passed
202    /// value.
203    ///
204    /// ```rust,ignore
205    /// // example with generic names
206    /// // needs: use pac::{RegisterValue, TIMER}
207    /// TIMER.bitfield_reg().init(|r| r.set_raw(0xdeadbeef))
208    /// ```
209    #[inline(always)]
210    fn set_raw(mut self, value: T::DataType) -> Self {
211        self.data = value;
212        self.mask = !(Into::<T::DataType>::into(0x0u8));
213        self
214    }
215}
216
217pub trait NoBitfieldReg<Reg: RegSpec>: RegisterValue<Reg>
218where
219    Self: Sized,
220{
221    /// Get value read from register
222    ///
223    /// ```rust,ignore
224    /// // example with generic names
225    /// // needs: use pac::{NoBitfieldReg, TIMER}
226    /// let x = TIMER.nobitfield_reg().read().get();
227    /// ```
228    #[inline(always)]
229    #[must_use]
230    fn get(&self) -> Reg::DataType {
231        self.get_raw()
232    }
233
234    /// Prepare value to be written to register
235    ///
236    /// ```rust,ignore
237    /// // example with generic names
238    /// // needs: use pac::{NoBitfieldReg, TIMER}
239    /// TIMER.nobitfield_reg().init(|r| r.set(0xc0ffee));
240    /// ```
241    #[inline(always)]
242    #[must_use]
243    fn set(self, value: Reg::DataType) -> Self {
244        self.set_raw(value)
245    }
246}
247
248impl<T, A> Reg<T, A>
249where
250    T: RegSpec,
251    A: Access,
252{
253    #[inline(always)]
254    #[must_use]
255    pub(crate) const fn from_ptr(ptr: *mut u8) -> &'static Self {
256        unsafe { &*(ptr as *const Self) }
257    }
258
259    #[inline(always)]
260    #[must_use]
261    pub const fn ptr(&self) -> *mut T::DataType {
262        self as *const _ as *mut T::DataType
263    }
264
265    /// Returns the address of the register.
266    pub fn addr(&self) -> usize {
267        unsafe { (self as *const _) as usize }
268    }
269}
270
271impl<T, A> Reg<T, A>
272where
273    T: RegSpec,
274    A: Read,
275{
276    /// Read register and return a register value
277    ///
278    /// # Safety
279    /// Read operation could cause undefined behavior for some peripheral. Developer shall read device user manual.
280    /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread.
281    ///
282    /// # Example
283    /// ```rust,ignore
284    /// // example with generic names
285    /// let reg = unsafe { TIMER.bitfield_reg().read() };
286    /// if reg.boolr().get() { /* ... */ }
287    /// ```
288    #[inline(always)]
289    #[must_use]
290    pub unsafe fn read(&self) -> RegValueT<T> {
291        #[cfg(feature = "tracing")]
292        let val = {
293            let mut buf: u64 = 0x0;
294            tracing::READ_FN.with(|rf| {
295                if let Some(rf) = rf.get() {
296                    buf = rf(self.addr(), std::mem::size_of::<T::DataType>());
297                } else {
298                    #[cfg(not(feature = "tracing_dummy"))]
299                    panic!(
300                        "Please, provide an handler for read with tracing::set_read_fn(callback);"
301                    );
302                }
303            });
304            T::DataType::cast_from(buf)
305        };
306        #[cfg(not(feature = "tracing"))]
307        let val = self.ptr().read_volatile();
308        RegValueT::<T>::new(val)
309    }
310}
311
312impl<T, A> Reg<T, A>
313where
314    T: RegSpec,
315    A: Write,
316{
317    /// Write register value back to register
318    ///
319    /// # Arguments
320    ///
321    /// * `reg_value` - A string slice that holds the name of the person
322    ///
323    /// # Safety
324    /// Write operation could cause undefined behavior for some peripheral. Developers shall read the device user manual.
325    /// Register is Send and Sync to allow complete freedom. Developers are responsible of proper use in interrupt and thread.
326    ///
327    /// # Example
328    /// ```rust,ignore
329    /// // example with generic names
330    /// // write with a previously read value
331    /// let reg = unsafe { TIMER.bitfield_reg().read() };
332    /// // or start with a known value
333    /// let reg = timer::BitfieldReg::new(0).bitfieldw().set(0x55);
334    /// // or start with the register default
335    /// let reg = timer::BitfieldReg::default();
336    ///
337    /// let reg = reg.bitfieldrw().set(0x77);
338    ///
339    /// // no change has taken place to the register due to `set` calls - do that now by writing back the result
340    /// unsafe { TIMER.bitfield_reg().write(reg) }
341    /// ```
342    /// See also: [`Reg<T, A>::init`] which provides the default value to a closure
343    #[inline(always)]
344    pub unsafe fn write(&self, reg_value: RegValueT<T>) {
345        #[cfg(feature = "tracing")]
346        tracing::WRITE_FN.with(|wf| {
347            if let Some(wf) = wf.get() {
348                wf(
349                    self.addr(),
350                    std::mem::size_of::<T::DataType>(),
351                    reg_value.data.into(),
352                )
353            } else {
354                #[cfg(not(feature = "tracing_dummy"))]
355                panic!("Please, provide an handler for read with tracing::set_read_fn(callback);");
356            }
357        });
358        #[cfg(not(feature = "tracing"))]
359        self.ptr().write_volatile(reg_value.data);
360    }
361
362    /// Write an arbitrary integer to register
363    ///
364    /// Use this function when e.g. loading data to be written from a config-page.
365    /// For normal use prefer either [`Reg<T, A>::write`] if the value was read before, or [`Reg<T, A>::init`],
366    /// both of which provide some restrictions available register fields, enums, etc.
367    ///
368    /// # Arguments
369    ///
370    /// * `value` - The unchecked value to be written to the register
371    ///
372    /// # Safety
373    ///
374    /// Write operation could cause undefined behavior for some peripheral. Developers shall read the device user manual.
375    /// Register is Send and Sync to allow complete freedom. Developers are responsible of proper use in interrupt and thread.
376    ///
377    /// # Example
378    /// ```rust,ignore
379    /// // example with generic names
380    /// unsafe { TIMER.bitfield_reg().write_raw(0xdead) }
381    /// ```
382    /// See also [`Reg<T, A>::init`] and [`Reg<T, A>::write`] both of which are the safe, preferred functions.
383    #[inline(always)]
384    pub unsafe fn write_raw(&self, value: T::DataType) {
385        #[cfg(feature = "tracing")]
386        tracing::WRITE_FN.with(|wf| {
387            if let Some(wf) = wf.get() {
388                wf(
389                    self.addr(),
390                    std::mem::size_of::<T::DataType>(),
391                    value.into(),
392                )
393            } else {
394                #[cfg(not(feature = "tracing_dummy"))]
395                panic!("Please, provide an handler for read with tracing::set_read_fn(callback);");
396            }
397        });
398        #[cfg(not(feature = "tracing"))]
399        self.ptr().write_volatile(value);
400    }
401}
402
403impl<T, A> Reg<T, A>
404where
405    T: RegSpec,
406    A: Write,
407    RegValueT<T>: Default,
408{
409    /// Write register with register value built from default register value
410    ///
411    /// # Arguments
412    ///
413    /// * `f` - Closure that receive as input a register value initialized with register value at Power On Reset.
414    ///
415    /// # Safety
416    /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual.
417    /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread.
418    ///
419    /// # Example
420    /// ```rust,ignore
421    /// // example with generic names
422    /// TIMER
423    ///     .bitfield_reg()
424    ///     .init(|r| r.bitfieldw().set(0b1010).boolw().set(true));
425    /// ```
426    #[inline(always)]
427    /// Write value computed by closure that receive as input the reset value of register
428    pub unsafe fn init(&self, f: impl FnOnce(RegValueT<T>) -> RegValueT<T>) {
429        let val = RegValueT::<T>::default();
430        let res = f(val);
431        self.write(res);
432    }
433}
434
435impl<T, A> Reg<T, A>
436where
437    T: RegSpec,
438    A: Read + Write,
439{
440    /// Read/modify/write register
441    ///
442    /// # Arguments
443    ///
444    /// * `f` - Closure that receive as input a register value read from register. The result of the closure
445    ///   is written back to the register.
446    ///
447    /// # Safety
448    /// Write operation could cause undefined behavior for some peripheral. Developer shall read device user manual.
449    /// Register is Send and Sync to allow complete freedom. Developer is responsible of proper use in interrupt and thread.
450    ///
451    /// # Example
452    /// ```rust,ignore
453    /// // example with generic names
454    /// TIMER
455    ///     .bitfield_reg()
456    ///     .modify(|r| r.boolrw().set(!r.boolrw().get()));
457    /// ```
458    #[inline(always)]
459    pub unsafe fn modify(&self, f: impl FnOnce(RegValueT<T>) -> RegValueT<T>) {
460        let val = self.read();
461        let res = f(val);
462        self.write(res);
463    }
464}
465
466/// Proxy struct for enumerated bitfields
467#[repr(transparent)]
468#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
469pub struct EnumBitfieldStruct<Q: RegNumberT, T>(pub Q, PhantomData<T>);
470
471impl<Q: RegNumberT, T> EnumBitfieldStruct<Q, T> {
472    pub const fn new(value: Q) -> Self {
473        Self(value, PhantomData)
474    }
475}
476
477impl<Q: RegNumberT, T> From<EnumBitfieldStruct<Q, T>> for u64 {
478    #[inline(always)]
479    fn from(value: EnumBitfieldStruct<Q, T>) -> Self {
480        value.0.into()
481    }
482}
483impl<Q: RegNumberT, T> CastFrom<u64> for EnumBitfieldStruct<Q, T> {
484    #[inline(always)]
485    fn cast_from(val: u64) -> Self {
486        Self(Q::cast_from(val), PhantomData)
487    }
488}
489
490impl<Q: RegNumberT, T> From<Q> for EnumBitfieldStruct<Q, T> {
491    #[inline(always)]
492    fn from(value: Q) -> Self {
493        Self(value, PhantomData)
494    }
495}
496
497/// Proxy struct for numeric bitfields
498pub struct RegisterField<
499    const START_OFFSET: usize,
500    const MASK: u64,
501    const DIM: u8,
502    const DIM_INCREMENT: u8,
503    ValueType,
504    T,
505    A,
506> where
507    T: RegSpec,
508    A: Access,
509{
510    data: RegValueT<T>,
511    index: u8,
512    marker: PhantomData<(ValueType, A)>,
513}
514
515impl<
516        const START_OFFSET: usize,
517        const MASK: u64,
518        const DIM: u8,
519        const DIM_INCREMENT: u8,
520        ValueType,
521        T,
522        A,
523    > RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>
524where
525    T: RegSpec,
526    A: Access,
527{
528    #[allow(dead_code)]
529    #[inline(always)]
530    pub(crate) fn from_register(data: RegValueT<T>, index: u8) -> Self {
531        Self {
532            data,
533            index,
534            marker: PhantomData,
535        }
536    }
537
538    /// Get mask for bitfield, the mask is unshifted and at offset 0
539    ///
540    /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>::get()`] to
541    /// extract a bitfield value.
542    #[inline(always)]
543    #[must_use]
544    pub fn mask(&self) -> T::DataType {
545        T::DataType::cast_from(MASK)
546    }
547
548    /// Get offset of bitfield in containing register
549    ///
550    /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>::get()`] to
551    /// extract a bitfield value.
552    #[inline(always)]
553    #[must_use]
554    pub const fn offset(&self) -> usize {
555        START_OFFSET + (self.index * DIM_INCREMENT) as usize
556    }
557}
558
559impl<
560        const START_OFFSET: usize,
561        const MASK: u64,
562        const DIM: u8,
563        const DIM_INCREMENT: u8,
564        ValueType,
565        T,
566        A,
567    > RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>
568where
569    T: RegSpec,
570    A: Read,
571    ValueType: CastFrom<u64>,
572{
573    /// Extract bitfield from read register value
574    #[inline(always)]
575    pub fn get(&self) -> ValueType {
576        let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
577        let filtered: T::DataType = (self.data.data >> offset) & T::DataType::cast_from(MASK);
578        ValueType::cast_from(filtered.into())
579    }
580}
581
582impl<
583        const START_OFFSET: usize,
584        const MASK: u64,
585        const DIM: u8,
586        const DIM_INCREMENT: u8,
587        ValueType,
588        T,
589        A,
590    > RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>
591where
592    T: RegSpec,
593    A: Write,
594    u64: From<ValueType>,
595{
596    /// Prepare bitfield value that could be written to register
597    ///
598    /// # Example
599    /// ```rust,ignore
600    /// // example with generic names
601    /// // get an instance by reading
602    /// let values = TIMER.bitfield_reg().read();
603    /// // or by starting with a known value
604    /// let value = timer::BitfieldReg::new(0);
605    /// // or by starting with the default
606    /// let value = timer::BitfieldReg::default();
607    ///
608    /// // set bitfields
609    /// let value = value
610    ///     // set numeric bitfield
611    ///     .bitfieldw()
612    ///     .set(0x55)
613    ///     // set enumerated bitfield with enumeration
614    ///     .bitfieldenumerated()
615    ///     .set(timer::bitfield_reg::BitfieldEnumerated::GPIOA_0)
616    ///     // set enumerated bitfield from integer
617    ///     .bitfieldenumerated()
618    ///     .set(1.into());
619    ///
620    /// // up until now no hardware change has taken place, do that now by writing
621    /// TIMER.bitfield_reg().write(value);
622    /// ```
623    #[inline(always)]
624    #[must_use]
625    pub fn set(mut self, value: ValueType) -> RegValueT<T> {
626        let mask = T::DataType::cast_from(MASK);
627        let value: T::DataType = T::DataType::cast_from(Into::<u64>::into(value)) & mask;
628        let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
629        let masked_offset: T::DataType = mask << offset;
630        self.data.mask |= masked_offset;
631        self.data.data &= !masked_offset;
632        self.data.data |= value << offset;
633        self.data
634    }
635}
636
637/// Proxy struct for boolean bitfields
638pub struct RegisterFieldBool<
639    const START_OFFSET: usize,
640    const DIM: u8,
641    const DIM_INCREMENT: u8,
642    T,
643    A,
644> where
645    T: RegSpec,
646    A: Access,
647{
648    data: RegValueT<T>,
649    index: u8,
650    marker: PhantomData<A>,
651}
652
653impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
654    RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
655where
656    T: RegSpec,
657    A: Read,
658{
659    /// Extract bitfield from read register value
660    #[inline(always)]
661    pub fn get(&self) -> bool {
662        let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
663        let filtered = (self.data.data.into() >> offset) & 1;
664        filtered == 1
665    }
666}
667
668impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
669    RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
670where
671    T: RegSpec,
672    A: Write,
673{
674    /// Prepare bitfield value to be written to register
675    ///
676    /// # Example
677    /// ```rust,ignore
678    /// // example with generic names
679    /// // get an instance by reading
680    /// let values = TIMER.bitfield_reg().read();
681    /// // or by starting with a known value
682    /// let value = timer::BitfieldReg::new(0);
683    /// // or by starting with the default
684    /// let value = timer::BitfieldReg::default();
685    ///
686    /// // set bitfield
687    /// let value = value
688    ///     .boolrw()
689    ///     .set(true);
690    ///
691    /// // up until now no hardware change has taken place, do that now by writing
692    /// TIMER.bitfield_reg().write(value);
693    /// ```
694    #[inline(always)]
695    #[must_use]
696    pub fn set(mut self, value: bool) -> RegValueT<T> {
697        let value: T::DataType = if value {
698            T::DataType::cast_from(1u64)
699        } else {
700            T::DataType::cast_from(0u64)
701        };
702        let offset = START_OFFSET + (self.index * DIM_INCREMENT) as usize;
703        let masked_offset = T::DataType::cast_from(0x1u64) << offset;
704        self.data.mask |= masked_offset;
705        self.data.data &= !masked_offset;
706        self.data.data |= value << offset;
707        self.data
708    }
709}
710
711impl<const START_OFFSET: usize, const DIM: u8, const DIM_INCREMENT: u8, T, A>
712    RegisterFieldBool<START_OFFSET, DIM, DIM_INCREMENT, T, A>
713where
714    T: RegSpec,
715    A: Access,
716{
717    #[inline(always)]
718    #[allow(dead_code)]
719    pub(crate) fn from_register(data: RegValueT<T>, index: u8) -> Self {
720        Self {
721            data,
722            index,
723            marker: PhantomData,
724        }
725    }
726
727    /// Get mask for bitfield, the mask is unshifted and at offset 0
728    ///
729    /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>::get()`] to
730    /// extract a bitfield value.
731    #[inline(always)]
732    #[must_use]
733    pub fn mask(&self) -> T::DataType {
734        T::DataType::cast_from(1)
735    }
736
737    /// Get offset of bitfield in containing register
738    ///
739    /// Prefer the use of [`RegisterField<START_OFFSET, MASK, DIM, DIM_INCREMENT, ValueType, T, A>::get()`] to
740    /// extract a bitfield value.
741    #[inline(always)]
742    #[must_use]
743    pub const fn offset(&self) -> usize {
744        START_OFFSET + (self.index * DIM_INCREMENT) as usize
745    }
746}
747
748/// An array of identical register clusters.
749pub struct ClusterRegisterArray<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> {
750    _t: ::core::marker::PhantomData<T>,
751}
752
753impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize>
754    ClusterRegisterArray<T, DIM, DIM_INCREMENT>
755{
756    /// Returns the number of register blocks in the cluster.
757    #[inline(always)]
758    pub const fn len(&self) -> usize {
759        DIM
760    }
761
762    /// Returns whether the cluster is empty (DIM == 0).
763    #[inline(always)]
764    pub const fn is_empty(&self) -> bool {
765        DIM == 0
766    }
767
768    /// Returns an iterator over the elements of this cluster.
769    #[inline(always)]
770    pub fn iter(&self) -> impl ::core::iter::ExactSizeIterator<Item = &T> {
771        self.into_iter()
772    }
773
774    /// Returns the cluster element with the specified index.
775    ///
776    /// Panics if the index is out of bounds.
777    #[inline]
778    pub const fn get(&self, index: usize) -> &T {
779        assert!(index < DIM);
780        unsafe { self.get_unchecked(index) }
781    }
782
783    /// Returns the cluster element with the specified index.
784    ///
785    /// # Safety
786    ///
787    /// `index` must be less than `DIM`.
788    #[inline(always)]
789    pub const unsafe fn get_unchecked(&self, index: usize) -> &T {
790        &*(self.as_ptr().add(index * DIM_INCREMENT) as *const _)
791    }
792
793    #[inline(always)]
794    pub(crate) const unsafe fn from_ptr(ptr: *mut u8) -> &'static Self {
795        &*(ptr as *const Self)
796    }
797
798    #[inline(always)]
799    const fn as_ptr(&self) -> *mut u8 {
800        self as *const _ as *mut _
801    }
802}
803
804impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ::core::ops::Index<usize>
805    for ClusterRegisterArray<T, DIM, DIM_INCREMENT>
806{
807    type Output = T;
808
809    #[inline(always)]
810    fn index(&self, index: usize) -> &T {
811        self.get(index)
812    }
813}
814
815impl<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> IntoIterator
816    for &'a ClusterRegisterArray<T, DIM, DIM_INCREMENT>
817{
818    type Item = &'a T;
819    type IntoIter = ClusterRegisterArrayIterator<'a, T, DIM, DIM_INCREMENT>;
820
821    #[inline(always)]
822    fn into_iter(self) -> Self::IntoIter {
823        ClusterRegisterArrayIterator {
824            array: self,
825            index: 0,
826        }
827    }
828}
829
830pub struct ClusterRegisterArrayIterator<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize>
831{
832    array: &'a ClusterRegisterArray<T, DIM, DIM_INCREMENT>,
833    index: usize,
834}
835
836impl<'a, T: Sized, const DIM: usize, const DIM_INCREMENT: usize> Iterator
837    for ClusterRegisterArrayIterator<'a, T, DIM, DIM_INCREMENT>
838{
839    type Item = &'a T;
840    #[inline(always)]
841    fn next(&mut self) -> Option<&'a T> {
842        if self.index < self.array.len() {
843            let result = &self.array[self.index];
844            self.index += 1;
845            Some(result)
846        } else {
847            None
848        }
849    }
850
851    #[inline(always)]
852    fn size_hint(&self) -> (usize, Option<usize>) {
853        let len = self.array.len() - self.index;
854        (len, Some(len))
855    }
856}
857
858impl<T: Sized, const DIM: usize, const DIM_INCREMENT: usize> ExactSizeIterator
859    for ClusterRegisterArrayIterator<'_, T, DIM, DIM_INCREMENT>
860{
861}