Skip to main content

device_driver/
register.rs

1use core::marker::PhantomData;
2
3use crate::{
4    Address, AddressMode, Append, ArrayRepeating, Block, Fieldset, FieldsetMetadata, NotRepeating,
5    RO, RW, ReadCapability, Repeating, ToTuple, WO, WriteCapability,
6};
7
8#[cfg(feature = "defmt")]
9use defmt::panic;
10
11/// Common properties shared by [`RegisterInterface`] & [`AsyncRegisterInterface`]
12pub trait RegisterInterfaceBase {
13    /// The error type
14    type Error;
15    /// The address type used by this interface
16    type AddressType: Address;
17}
18
19impl<T: RegisterInterfaceBase> RegisterInterfaceBase for &mut T {
20    type Error = T::Error;
21    type AddressType = T::AddressType;
22}
23
24#[diagnostic::on_unimplemented(
25    label = "cannot use blocking register operations when the device interface doesn't know how to read and write registers",
26    note = "to enable register operations, implement the trait on this type"
27)]
28/// A trait to represent the interface to the device.
29///
30/// This is called to write to and read from registers.
31pub trait RegisterInterface: RegisterInterfaceBase {
32    /// Write the given data to the register located at the given address
33    fn write_register(
34        &mut self,
35        address: Self::AddressType,
36        data: &mut [u8],
37        _metadata: &FieldsetMetadata,
38    ) -> Result<(), Self::Error>;
39
40    /// Read the register located at the given address to the given data slice
41    fn read_register(
42        &mut self,
43        address: Self::AddressType,
44        data: &mut [u8],
45        _metadata: &FieldsetMetadata,
46    ) -> Result<(), Self::Error>;
47}
48
49#[diagnostic::do_not_recommend]
50impl<T: RegisterInterface> RegisterInterface for &mut T {
51    fn write_register(
52        &mut self,
53        address: Self::AddressType,
54        data: &mut [u8],
55        metadata: &FieldsetMetadata,
56    ) -> Result<(), Self::Error> {
57        (*self).write_register(address, data, metadata)
58    }
59
60    fn read_register(
61        &mut self,
62        address: Self::AddressType,
63        data: &mut [u8],
64        metadata: &FieldsetMetadata,
65    ) -> Result<(), Self::Error> {
66        (*self).read_register(address, data, metadata)
67    }
68}
69
70#[diagnostic::on_unimplemented(
71    label = "cannot use async register operations when the device interface doesn't know how to read and write registers",
72    note = "to enable register operations, implement the trait on this type"
73)]
74/// A trait to represent the interface to the device.
75///
76/// This is called to asynchronously write to and read from registers.
77pub trait AsyncRegisterInterface: RegisterInterfaceBase {
78    /// Write the given data to the register located at the given address
79    async fn write_register(
80        &mut self,
81        address: Self::AddressType,
82        data: &mut [u8],
83        _metadata: &FieldsetMetadata,
84    ) -> Result<(), Self::Error>;
85
86    /// Read the register located at the given address to the given data slice
87    async fn read_register(
88        &mut self,
89        address: Self::AddressType,
90        data: &mut [u8],
91        _metadata: &FieldsetMetadata,
92    ) -> Result<(), Self::Error>;
93}
94
95#[diagnostic::do_not_recommend]
96impl<T: AsyncRegisterInterface> AsyncRegisterInterface for &mut T {
97    fn write_register(
98        &mut self,
99        address: Self::AddressType,
100        data: &mut [u8],
101        metadata: &FieldsetMetadata,
102    ) -> impl Future<Output = Result<(), Self::Error>> {
103        (*self).write_register(address, data, metadata)
104    }
105
106    fn read_register(
107        &mut self,
108        address: Self::AddressType,
109        data: &mut [u8],
110        metadata: &FieldsetMetadata,
111    ) -> impl Future<Output = Result<(), Self::Error>> {
112        (*self).read_register(address, data, metadata)
113    }
114}
115
116/// Object that performs actions on the device in the context of a register
117pub struct RegisterOperation<'b, B, RegisterFs, AddressType, Access, Repeat>
118where
119    B: Block,
120    B::Interface: RegisterInterfaceBase<AddressType = AddressType>,
121    RegisterFs: Fieldset,
122    AddressType: Address,
123{
124    block: &'b mut B,
125    address: AddressType,
126    register_new_with_reset: fn() -> RegisterFs,
127    _phantom: PhantomData<(RegisterFs, Access, Repeat)>,
128}
129
130impl<'b, B, RegisterFs, AddressType, Access, Repeat>
131    RegisterOperation<'b, B, RegisterFs, AddressType, Access, Repeat>
132where
133    RegisterFs: Fieldset,
134    B: Block,
135    B::Interface: RegisterInterfaceBase<AddressType = AddressType>,
136    AddressType: Address,
137{
138    #[doc(hidden)]
139    pub fn new(
140        block: &'b mut B,
141        address: AddressType,
142        register_new_with_reset: fn() -> RegisterFs,
143    ) -> Self {
144        Self {
145            block,
146            address,
147            register_new_with_reset,
148            _phantom: PhantomData,
149        }
150    }
151
152    /// Get the register's address.
153    pub fn address(&self) -> AddressType {
154        self.address
155    }
156
157    /// Get the register's reset value.
158    pub fn reset_value(&self) -> RegisterFs {
159        (self.register_new_with_reset)()
160    }
161
162    /// Get a plan to read, write or modify for bulk register operations
163    pub fn plan(&self) -> Plan<AddressType, RegisterFs, Access>
164    where
165        Repeat: NotRepeating,
166    {
167        Plan {
168            address: self.address(),
169            value: self.reset_value(),
170            _phantom: PhantomData,
171        }
172    }
173
174    /// Get a plan to read, write or modify for bulk register operations at a given index
175    #[track_caller]
176    pub fn plan_at(&self, index: Repeat::Index) -> Plan<AddressType, RegisterFs, Access>
177    where
178        Repeat: Repeating,
179    {
180        Plan {
181            address: Repeat::calc_address(self.address, index),
182            value: self.reset_value(),
183            _phantom: PhantomData,
184        }
185    }
186
187    /// Same as [`Self::plan`], but initialize the fieldset with all zeroes
188    #[track_caller]
189    pub fn plan_with_zero(&self) -> Plan<AddressType, RegisterFs, Access>
190    where
191        Repeat: NotRepeating,
192        Access: WriteCapability,
193    {
194        Plan {
195            address: self.address(),
196            value: RegisterFs::ZERO,
197            _phantom: PhantomData,
198        }
199    }
200
201    /// Same as [`Self::plan_at`], but initialize the fieldset with all zeroes
202    #[track_caller]
203    pub fn plan_with_zero_at(&self, index: Repeat::Index) -> Plan<AddressType, RegisterFs, Access>
204    where
205        Repeat: Repeating,
206        Access: WriteCapability,
207    {
208        Plan {
209            address: Repeat::calc_address(self.address, index),
210            value: RegisterFs::ZERO,
211            _phantom: PhantomData,
212        }
213    }
214
215    /// Get a plan to read, write or modify an array of registers for bulk register operations with a given start index and length
216    #[track_caller]
217    pub fn plan_array_at<const N: usize>(
218        self,
219        index: Repeat::Index,
220    ) -> Plan<AddressType, [RegisterFs; N], Access>
221    where
222        Repeat: ArrayRepeating,
223        B::RegisterAddressMode: AddressMode,
224    {
225        Repeat::assert_len_and_index(N, index.clone());
226
227        let address = Repeat::calc_address(self.address, index);
228        Self::assert_array_op_legal(address);
229
230        Plan {
231            address,
232            value: core::array::from_fn(|_| self.reset_value()),
233            _phantom: PhantomData,
234        }
235    }
236
237    /// Same as [`Self::plan_array_at`], but initialize the fieldsets with all zeroes
238    #[track_caller]
239    pub fn plan_array_with_zero_at<const N: usize>(
240        self,
241        index: Repeat::Index,
242    ) -> Plan<AddressType, [RegisterFs; N], Access>
243    where
244        Repeat: ArrayRepeating,
245        B::RegisterAddressMode: AddressMode,
246        Access: WriteCapability,
247    {
248        Repeat::assert_len_and_index(N, index.clone());
249
250        let address = Repeat::calc_address(self.address, index);
251        Self::assert_array_op_legal(address);
252
253        Plan {
254            address,
255            value: Fieldset::ZERO,
256            _phantom: PhantomData,
257        }
258    }
259
260    /// Write to the register.
261    ///
262    /// The closure is given the write object initialized to the reset value of the register.
263    /// If no reset value is specified for this register, this function is the same as [`Self::write_with_zero`].
264    #[track_caller]
265    pub fn write(
266        self,
267        f: impl FnOnce(&mut RegisterFs),
268    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
269    where
270        Repeat: NotRepeating,
271        B::Interface: RegisterInterface,
272        Access: WriteCapability,
273    {
274        let mut register = (self.register_new_with_reset)();
275        f(&mut register);
276
277        self.block.interface().write_register(
278            self.address,
279            register.as_slice_mut(),
280            &RegisterFs::METADATA,
281        )
282    }
283
284    /// Write to the register at a given index.
285    ///
286    /// The closure is given the write object initialized to the reset value of the register.
287    /// If no reset value is specified for this register, this function is the same as [`Self::write_with_zero_at`].
288    #[track_caller]
289    pub fn write_at(
290        self,
291        index: Repeat::Index,
292        f: impl FnOnce(&mut RegisterFs),
293    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
294    where
295        Repeat: Repeating,
296        B::Interface: RegisterInterface,
297        Access: WriteCapability,
298    {
299        let mut register = (self.register_new_with_reset)();
300        f(&mut register);
301
302        self.block.interface().write_register(
303            Repeat::calc_address(self.address, index),
304            register.as_slice_mut(),
305            &RegisterFs::METADATA,
306        )
307    }
308
309    /// Write to an array of register at the given index and N length.
310    ///
311    /// The closure is given the write object initialized to the reset value of the register.
312    /// If no reset value is specified for this register, this function is the same as [`Self::write_array_with_zero_at`].
313    #[track_caller]
314    pub fn write_array_at<const N: usize>(
315        self,
316        index: Repeat::Index,
317        f: impl FnOnce(&mut [RegisterFs; N]),
318    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
319    where
320        Repeat: ArrayRepeating,
321        B::Interface: RegisterInterface,
322        B::RegisterAddressMode: AddressMode,
323        Access: WriteCapability,
324    {
325        Repeat::assert_len_and_index(N, index.clone());
326
327        let mut register = core::array::from_fn(|_| (self.register_new_with_reset)());
328        f(&mut register);
329
330        let address = Repeat::calc_address(self.address, index);
331        Self::assert_array_op_legal(address);
332
333        self.block.interface().write_register(
334            address,
335            register.as_slice_mut(),
336            &RegisterFs::METADATA,
337        )
338    }
339
340    /// Write to the register.
341    ///
342    /// The closure is given the write object initialized to the reset value of the register.
343    /// If no reset value is specified for this register, this function is the same as [`Self::write_with_zero`].
344    #[track_caller]
345    pub fn write_async(
346        self,
347        f: impl FnOnce(&mut RegisterFs),
348    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
349    where
350        Repeat: NotRepeating,
351        B::Interface: AsyncRegisterInterface,
352        Access: WriteCapability,
353    {
354        let mut register = (self.register_new_with_reset)();
355        f(&mut register);
356
357        async move {
358            self.block
359                .interface()
360                .write_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
361                .await
362        }
363    }
364
365    /// Write to the register at a given index.
366    ///
367    /// The closure is given the write object initialized to the reset value of the register.
368    /// If no reset value is specified for this register, this function is the same as [`Self::write_with_zero_at_async`].
369    #[track_caller]
370    pub fn write_at_async(
371        self,
372        index: Repeat::Index,
373        f: impl FnOnce(&mut RegisterFs),
374    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
375    where
376        Repeat: Repeating,
377        B::Interface: AsyncRegisterInterface,
378        Access: WriteCapability,
379    {
380        let mut register = (self.register_new_with_reset)();
381        f(&mut register);
382
383        let address = Repeat::calc_address(self.address, index);
384
385        async move {
386            self.block
387                .interface()
388                .write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
389                .await
390        }
391    }
392
393    /// Write to an array of register at the given index and N length.
394    ///
395    /// The closure is given the write object initialized to the reset value of the register.
396    /// If no reset value is specified for this register, this function is the same as [`Self::write_array_with_zero_at_async`].
397    #[track_caller]
398    pub fn write_array_at_async<const N: usize>(
399        self,
400        index: Repeat::Index,
401        f: impl FnOnce(&mut [RegisterFs; N]),
402    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
403    where
404        Repeat: ArrayRepeating,
405        B::Interface: AsyncRegisterInterface,
406        B::RegisterAddressMode: AddressMode,
407        Access: WriteCapability,
408    {
409        Repeat::assert_len_and_index(N, index.clone());
410
411        let mut register = core::array::from_fn(|_| (self.register_new_with_reset)());
412        f(&mut register);
413
414        let address = Repeat::calc_address(self.address, index);
415        Self::assert_array_op_legal(address);
416
417        async move {
418            self.block
419                .interface()
420                .write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
421                .await
422        }
423    }
424
425    /// Write to the register.
426    ///
427    /// The closure is given the write object initialized to all zero.
428    #[track_caller]
429    pub fn write_with_zero(
430        self,
431        f: impl FnOnce(&mut RegisterFs),
432    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
433    where
434        Repeat: NotRepeating,
435        B::Interface: RegisterInterface,
436        Access: WriteCapability,
437    {
438        let mut register = RegisterFs::ZERO;
439        f(&mut register);
440
441        self.block.interface().write_register(
442            self.address,
443            register.as_slice_mut(),
444            &RegisterFs::METADATA,
445        )
446    }
447
448    /// Write to the register at a given index.
449    ///
450    /// The closure is given the write object initialized to all zero.
451    #[track_caller]
452    pub fn write_with_zero_at(
453        self,
454        index: Repeat::Index,
455        f: impl FnOnce(&mut RegisterFs),
456    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
457    where
458        Repeat: Repeating,
459        B::Interface: RegisterInterface,
460        Access: WriteCapability,
461    {
462        let mut register = RegisterFs::ZERO;
463        f(&mut register);
464
465        self.block.interface().write_register(
466            Repeat::calc_address(self.address, index),
467            register.as_slice_mut(),
468            &RegisterFs::METADATA,
469        )
470    }
471
472    /// Write to an array of registers at a given index and length.
473    ///
474    /// The closure is given the write object initialized to all zero.
475    #[track_caller]
476    pub fn write_array_with_zero_at<const N: usize>(
477        self,
478        index: Repeat::Index,
479        f: impl FnOnce(&mut [RegisterFs; N]),
480    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
481    where
482        Repeat: ArrayRepeating,
483        B::Interface: RegisterInterface,
484        B::RegisterAddressMode: AddressMode,
485        Access: WriteCapability,
486    {
487        Repeat::assert_len_and_index(N, index.clone());
488
489        let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
490        f(&mut register);
491
492        let address = Repeat::calc_address(self.address, index);
493        Self::assert_array_op_legal(address);
494
495        self.block.interface().write_register(
496            address,
497            register.as_slice_mut(),
498            &RegisterFs::METADATA,
499        )
500    }
501
502    /// Write to the register.
503    ///
504    /// The closure is given the write object initialized to all zero.
505    #[track_caller]
506    pub fn write_with_zero_async(
507        self,
508        f: impl FnOnce(&mut RegisterFs),
509    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
510    where
511        Repeat: NotRepeating,
512        B::Interface: AsyncRegisterInterface,
513        Access: WriteCapability,
514    {
515        let mut register = RegisterFs::ZERO;
516        f(&mut register);
517
518        async move {
519            self.block
520                .interface()
521                .write_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
522                .await
523        }
524    }
525
526    /// Write to the register at a given index.
527    ///
528    /// The closure is given the write object initialized to all zero.
529    #[track_caller]
530    pub fn write_with_zero_at_async(
531        self,
532        index: Repeat::Index,
533        f: impl FnOnce(&mut RegisterFs),
534    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
535    where
536        Repeat: Repeating,
537        B::Interface: AsyncRegisterInterface,
538        Access: WriteCapability,
539    {
540        let mut register = RegisterFs::ZERO;
541        f(&mut register);
542
543        let address = Repeat::calc_address(self.address, index);
544
545        async move {
546            self.block
547                .interface()
548                .write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
549                .await
550        }
551    }
552
553    /// Write to an array of registers at a given index and length.
554    ///
555    /// The closure is given the write object initialized to all zero.
556    #[track_caller]
557    pub fn write_array_with_zero_at_async<const N: usize>(
558        self,
559        index: Repeat::Index,
560        f: impl FnOnce(&mut [RegisterFs; N]),
561    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
562    where
563        Repeat: ArrayRepeating,
564        B::Interface: AsyncRegisterInterface,
565        B::RegisterAddressMode: AddressMode,
566        Access: WriteCapability,
567    {
568        Repeat::assert_len_and_index(N, index.clone());
569
570        let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
571        f(&mut register);
572
573        let address = Repeat::calc_address(self.address, index);
574        Self::assert_array_op_legal(address);
575
576        async move {
577            self.block
578                .interface()
579                .write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
580                .await
581        }
582    }
583
584    /// Read the register from the device
585    #[track_caller]
586    pub fn read(self) -> Result<RegisterFs, <B::Interface as RegisterInterfaceBase>::Error>
587    where
588        Repeat: NotRepeating,
589        B::Interface: RegisterInterface,
590        Access: ReadCapability,
591    {
592        let mut register = RegisterFs::ZERO;
593
594        self.block
595            .interface()
596            .read_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
597            .map(|_| register)
598    }
599
600    /// Read the register from the device at a given index
601    #[track_caller]
602    pub fn read_at(
603        self,
604        index: Repeat::Index,
605    ) -> Result<RegisterFs, <B::Interface as RegisterInterfaceBase>::Error>
606    where
607        Repeat: Repeating,
608        B::Interface: RegisterInterface,
609        Access: ReadCapability,
610    {
611        let mut register = RegisterFs::ZERO;
612
613        self.block
614            .interface()
615            .read_register(
616                Repeat::calc_address(self.address, index),
617                register.as_slice_mut(),
618                &RegisterFs::METADATA,
619            )
620            .map(|_| register)
621    }
622
623    /// Read an array of registers from the device at a given index and length
624    #[track_caller]
625    pub fn read_array_at<const N: usize>(
626        self,
627        index: Repeat::Index,
628    ) -> Result<[RegisterFs; N], <B::Interface as RegisterInterfaceBase>::Error>
629    where
630        Repeat: ArrayRepeating,
631        B::Interface: RegisterInterface,
632        B::RegisterAddressMode: AddressMode,
633        Access: ReadCapability,
634    {
635        Repeat::assert_len_and_index(N, index.clone());
636
637        let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
638        let address = Repeat::calc_address(self.address, index);
639        Self::assert_array_op_legal(address);
640
641        self.block
642            .interface()
643            .read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
644            .map(|_| register)
645    }
646
647    /// Read the register from the device
648    #[track_caller]
649    pub fn read_async(
650        self,
651    ) -> impl Future<Output = Result<RegisterFs, <B::Interface as RegisterInterfaceBase>::Error>>
652    where
653        Repeat: NotRepeating,
654        B::Interface: AsyncRegisterInterface,
655        Access: ReadCapability,
656    {
657        let mut register = RegisterFs::ZERO;
658
659        async move {
660            self.block
661                .interface()
662                .read_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
663                .await
664                .map(|_| register)
665        }
666    }
667
668    /// Read the register from the device at a given index
669    pub fn read_at_async(
670        self,
671        index: Repeat::Index,
672    ) -> impl Future<Output = Result<RegisterFs, <B::Interface as RegisterInterfaceBase>::Error>>
673    where
674        Repeat: Repeating,
675        B::Interface: AsyncRegisterInterface,
676        B::RegisterAddressMode: AddressMode,
677        Access: ReadCapability,
678    {
679        let mut register = RegisterFs::ZERO;
680        let address = Repeat::calc_address(self.address, index);
681
682        async move {
683            self.block
684                .interface()
685                .read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
686                .await
687                .map(|_| register)
688        }
689    }
690
691    /// Read an array of registers from the device at a given index and length
692    pub fn read_array_at_async<const N: usize>(
693        self,
694        index: Repeat::Index,
695    ) -> impl Future<Output = Result<[RegisterFs; N], <B::Interface as RegisterInterfaceBase>::Error>>
696    where
697        Repeat: ArrayRepeating,
698        B::Interface: AsyncRegisterInterface,
699        B::RegisterAddressMode: AddressMode,
700        Access: ReadCapability,
701    {
702        Repeat::assert_len_and_index(N, index.clone());
703
704        let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
705        let address = Repeat::calc_address(self.address, index);
706        Self::assert_array_op_legal(address);
707
708        async move {
709            self.block
710                .interface()
711                .read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
712                .await
713                .map(|_| register)
714        }
715    }
716
717    /// Modify the existing register value.
718    ///
719    /// The register is read, the value is then passed to the closure for making changes.
720    /// The result is then written back to the device.
721    #[track_caller]
722    pub fn modify(
723        self,
724        f: impl FnOnce(&mut RegisterFs),
725    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
726    where
727        Repeat: NotRepeating,
728        B::Interface: RegisterInterface,
729        Access: ReadCapability + WriteCapability,
730    {
731        let mut register = RegisterFs::ZERO;
732
733        self.block.interface().read_register(
734            self.address,
735            register.as_slice_mut(),
736            &RegisterFs::METADATA,
737        )?;
738
739        f(&mut register);
740
741        self.block.interface().write_register(
742            self.address,
743            register.as_slice_mut(),
744            &RegisterFs::METADATA,
745        )
746    }
747
748    /// Modify the existing register value at a given index.
749    ///
750    /// The register is read, the value is then passed to the closure for making changes.
751    /// The result is then written back to the device.
752    #[track_caller]
753    pub fn modify_at(
754        self,
755        index: Repeat::Index,
756        f: impl FnOnce(&mut RegisterFs),
757    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
758    where
759        Repeat: Repeating,
760        B::Interface: RegisterInterface,
761        Access: ReadCapability + WriteCapability,
762    {
763        let mut register = RegisterFs::ZERO;
764        let address = Repeat::calc_address(self.address, index);
765
766        self.block.interface().read_register(
767            address,
768            register.as_slice_mut(),
769            &RegisterFs::METADATA,
770        )?;
771
772        f(&mut register);
773
774        self.block.interface().write_register(
775            address,
776            register.as_slice_mut(),
777            &RegisterFs::METADATA,
778        )
779    }
780
781    /// Modify an array of existing register values at a given start index and length.
782    ///
783    /// The registers are read, the values are then passed to the closure for making changes.
784    /// The result is then written back to the device.
785    #[track_caller]
786    pub fn modify_array_at<const N: usize>(
787        self,
788        index: Repeat::Index,
789        f: impl FnOnce(&mut [RegisterFs; N]),
790    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
791    where
792        Repeat: ArrayRepeating,
793        B::Interface: RegisterInterface,
794        B::RegisterAddressMode: AddressMode,
795        Access: ReadCapability + WriteCapability,
796    {
797        Repeat::assert_len_and_index(N, index.clone());
798
799        let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
800
801        let address = Repeat::calc_address(self.address, index);
802        Self::assert_array_op_legal(address);
803
804        self.block.interface().read_register(
805            address,
806            register.as_slice_mut(),
807            &RegisterFs::METADATA,
808        )?;
809
810        f(&mut register);
811
812        self.block.interface().write_register(
813            address,
814            register.as_slice_mut(),
815            &RegisterFs::METADATA,
816        )
817    }
818
819    /// Modify the existing register value.
820    ///
821    /// The register is read, the value is then passed to the closure for making changes.
822    /// The result is then written back to the device.
823    #[track_caller]
824    pub fn modify_async(
825        self,
826        f: impl FnOnce(&mut RegisterFs),
827    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
828    where
829        Repeat: NotRepeating,
830        B::Interface: AsyncRegisterInterface,
831        Access: ReadCapability + WriteCapability,
832    {
833        let mut register = RegisterFs::ZERO;
834
835        async move {
836            self.block
837                .interface()
838                .read_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
839                .await?;
840
841            f(&mut register);
842
843            self.block
844                .interface()
845                .write_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
846                .await
847        }
848    }
849
850    /// Modify the existing register value at a given index.
851    ///
852    /// The register is read, the value is then passed to the closure for making changes.
853    /// The result is then written back to the device.
854    #[track_caller]
855    pub fn modify_at_async(
856        self,
857        index: Repeat::Index,
858        f: impl FnOnce(&mut RegisterFs),
859    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
860    where
861        Repeat: Repeating,
862        B::Interface: AsyncRegisterInterface,
863        Access: ReadCapability + WriteCapability,
864    {
865        let mut register = RegisterFs::ZERO;
866        let address = Repeat::calc_address(self.address, index);
867
868        async move {
869            self.block
870                .interface()
871                .read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
872                .await?;
873
874            f(&mut register);
875
876            self.block
877                .interface()
878                .write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
879                .await
880        }
881    }
882
883    /// Modify an array of existing register values at a given starting index and length.
884    ///
885    /// The registers are read, the values are then passed to the closure for making changes.
886    /// The result is then written back to the device.
887    #[track_caller]
888    pub fn modify_array_at_async<const N: usize>(
889        self,
890        index: Repeat::Index,
891        f: impl FnOnce(&mut [RegisterFs; N]),
892    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
893    where
894        Repeat: ArrayRepeating,
895        B::Interface: AsyncRegisterInterface,
896        B::RegisterAddressMode: AddressMode,
897        Access: ReadCapability + WriteCapability,
898    {
899        Repeat::assert_len_and_index(N, index.clone());
900
901        let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
902
903        let address = Repeat::calc_address(self.address, index);
904        Self::assert_array_op_legal(address);
905
906        async move {
907            self.block
908                .interface()
909                .read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
910                .await?;
911
912            f(&mut register);
913
914            self.block
915                .interface()
916                .write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
917                .await
918        }
919    }
920
921    #[track_caller]
922    fn assert_array_op_legal(address: AddressType)
923    where
924        B::RegisterAddressMode: AddressMode,
925        Repeat: ArrayRepeating,
926    {
927        if address.add(Repeat::STRIDE)
928            != B::RegisterAddressMode::next_address(address, core::mem::size_of::<RegisterFs>())
929        {
930            panic!(
931                "array operations can't be used with this register due to the `register-address-map` rule. Used stride: {}, accepted stride: {}",
932                Repeat::STRIDE,
933                B::RegisterAddressMode::next_address(
934                    AddressType::ZERO,
935                    core::mem::size_of::<RegisterFs>()
936                )
937            );
938        }
939    }
940}
941
942/// A plan that is used for bulk-reads and writes.
943pub struct Plan<AddressType: Copy, FS, Access> {
944    /// The address of the register
945    pub address: AddressType,
946    /// The starting value of the register. This is either the reset value or all-0's
947    pub value: FS,
948    _phantom: PhantomData<Access>,
949}
950
951/// A register operation for reading or writing multiple registers in one transaction
952pub struct BulkRegisterOperation<'b, B, AddressType: Address, Fieldsets, Access> {
953    pub(crate) block: &'b mut B,
954    pub(crate) start_address: Option<AddressType>,
955    pub(crate) next_address: Option<AddressType>,
956    pub(crate) field_sets: Fieldsets,
957    pub(crate) _phantom: PhantomData<Access>,
958}
959
960impl<B, AddressType, FieldSets, Access> BulkRegisterOperation<'_, B, AddressType, FieldSets, Access>
961where
962    B: Block,
963    B::RegisterAddressMode: AddressMode,
964    AddressType: Address,
965{
966    #[track_caller]
967    fn assert_legal(&self, address: AddressType) {
968        if let Some(next_address) = self.next_address
969            && address != next_address
970        {
971            panic!(
972                "order of registers not valid according to the address mode rules. Expected address: {}, got: {}",
973                next_address, address
974            );
975        }
976    }
977}
978
979impl<'b, B, AddressType, FieldSets> BulkRegisterOperation<'b, B, AddressType, FieldSets, WO>
980where
981    B: Block,
982    B::RegisterAddressMode: AddressMode,
983    AddressType: Address,
984{
985    /// Chain an extra write onto the bulk-write.
986    ///
987    /// The closure must return a plan for the register you want to write.
988    /// The plan is created by calling [`RegisterOperation::plan`] or [`RegisterOperation::plan_with_zero`].
989    ///
990    /// After chaining, call [`Self::execute`].
991    #[track_caller]
992    #[inline]
993    pub fn with<FS: Fieldset, LocalAccess: WriteCapability>(
994        self,
995        f: impl FnOnce(&mut B) -> Plan<AddressType, FS, LocalAccess>,
996    ) -> BulkRegisterOperation<'b, B, AddressType, FieldSets::Appended, WO>
997    where
998        FieldSets: Append<FS>,
999    {
1000        let Plan { address, value, .. } = f(self.block);
1001        self.assert_legal(address);
1002
1003        BulkRegisterOperation {
1004            block: self.block,
1005            start_address: self.start_address.or(Some(address)),
1006            next_address: Some(B::RegisterAddressMode::next_address(
1007                address,
1008                core::mem::size_of::<FS>(),
1009            )),
1010            field_sets: self.field_sets.append(value),
1011            _phantom: PhantomData,
1012        }
1013    }
1014}
1015
1016impl<'b, B, AddressType, FieldSets> BulkRegisterOperation<'b, B, AddressType, FieldSets, RO>
1017where
1018    B: Block,
1019    B::RegisterAddressMode: AddressMode,
1020    AddressType: Address,
1021{
1022    /// Chain an extra read onto the bulk-read.
1023    ///
1024    /// The closure must return a plan for the register you want to read.
1025    /// The plan is created by calling [`RegisterOperation::plan`].
1026    ///
1027    /// After chaining, call [`Self::execute`].
1028    #[track_caller]
1029    #[inline]
1030    pub fn with<FS: Fieldset, LocalAccess: ReadCapability>(
1031        self,
1032        f: impl FnOnce(&mut B) -> Plan<AddressType, FS, LocalAccess>,
1033    ) -> BulkRegisterOperation<'b, B, AddressType, FieldSets::Appended, RO>
1034    where
1035        FieldSets: Append<FS>,
1036    {
1037        let Plan { address, value, .. } = f(self.block);
1038        self.assert_legal(address);
1039
1040        BulkRegisterOperation {
1041            block: self.block,
1042            start_address: self.start_address.or(Some(address)),
1043            next_address: Some(B::RegisterAddressMode::next_address(
1044                address,
1045                core::mem::size_of::<FS>(),
1046            )),
1047            field_sets: self.field_sets.append(value),
1048            _phantom: PhantomData,
1049        }
1050    }
1051}
1052
1053impl<'b, B, AddressType, FieldSets> BulkRegisterOperation<'b, B, AddressType, FieldSets, RW>
1054where
1055    B: Block,
1056    B::RegisterAddressMode: AddressMode,
1057    AddressType: Address,
1058{
1059    /// Chain an extra modify onto the bulk-modify.
1060    ///
1061    /// The closure must return a plan for the register you want to modify.
1062    /// The plan is created by calling [`RegisterOperation::plan`].
1063    ///
1064    /// After chaining, call [`Self::execute`].
1065    #[track_caller]
1066    #[inline]
1067    pub fn with<FS: Fieldset, LocalAccess: ReadCapability + WriteCapability>(
1068        self,
1069        f: impl FnOnce(&mut B) -> Plan<AddressType, FS, LocalAccess>,
1070    ) -> BulkRegisterOperation<'b, B, AddressType, FieldSets::Appended, RW>
1071    where
1072        FieldSets: Append<FS>,
1073    {
1074        let Plan { address, value, .. } = f(self.block);
1075        self.assert_legal(address);
1076
1077        BulkRegisterOperation {
1078            block: self.block,
1079            start_address: self.start_address.or(Some(address)),
1080            next_address: Some(B::RegisterAddressMode::next_address(
1081                address,
1082                core::mem::size_of::<FS>(),
1083            )),
1084            field_sets: self.field_sets.append(value),
1085            _phantom: PhantomData,
1086        }
1087    }
1088}
1089
1090impl<B, Fieldsets>
1091    BulkRegisterOperation<
1092        '_,
1093        B,
1094        <B::Interface as RegisterInterfaceBase>::AddressType,
1095        Fieldsets,
1096        RO,
1097    >
1098where
1099    B: Block,
1100    B::Interface: RegisterInterfaceBase,
1101    Fieldsets: Fieldset + ToTuple,
1102{
1103    /// Execute the read.
1104    ///
1105    /// If ok, the fieldset values are returned as a tuple.
1106    /// If the bulk-read was illegal or the read failed, an error is returned.
1107    #[inline]
1108    pub fn execute(
1109        mut self,
1110    ) -> Result<Fieldsets::Tuple, <B::Interface as RegisterInterfaceBase>::Error>
1111    where
1112        B::Interface: RegisterInterface,
1113    {
1114        self.block
1115            .interface()
1116            .read_register(
1117                self.start_address.unwrap(),
1118                self.field_sets.as_slice_mut(),
1119                &Fieldsets::METADATA,
1120            )
1121            .map(|_| self.field_sets.to_tuple())
1122    }
1123
1124    /// Execute the read.
1125    ///
1126    /// If ok, the fieldset values are returned as a tuple.
1127    /// If the bulk-read was illegal or the read failed, an error is returned.
1128    #[inline]
1129    pub async fn execute_async(
1130        mut self,
1131    ) -> Result<Fieldsets::Tuple, <B::Interface as RegisterInterfaceBase>::Error>
1132    where
1133        B::Interface: AsyncRegisterInterface,
1134    {
1135        self.block
1136            .interface()
1137            .read_register(
1138                self.start_address.unwrap(),
1139                self.field_sets.as_slice_mut(),
1140                &Fieldsets::METADATA,
1141            )
1142            .await
1143            .map(|_| self.field_sets.to_tuple())
1144    }
1145}
1146
1147impl<B, Fieldsets>
1148    BulkRegisterOperation<
1149        '_,
1150        B,
1151        <B::Interface as RegisterInterfaceBase>::AddressType,
1152        Fieldsets,
1153        WO,
1154    >
1155where
1156    B: Block,
1157    B::Interface: RegisterInterfaceBase,
1158    Fieldsets: Fieldset,
1159    for<'a> &'a mut Fieldsets: ToTuple,
1160{
1161    /// Execute the write.
1162    ///
1163    /// Use the closure to change contents of the fieldset values that will be written.
1164    /// The fieldset values are either the reset value or all-0's based on which plan was used in the chaining phase.
1165    ///
1166    /// If ok, the return value of the closure is returned.
1167    /// If the bulk-write was illegal or the read failed, an error is returned.
1168    #[inline]
1169    pub fn execute(
1170        mut self,
1171        f: impl FnOnce(<&mut Fieldsets as ToTuple>::Tuple),
1172    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
1173    where
1174        B::Interface: RegisterInterface,
1175    {
1176        f(self.field_sets.to_tuple());
1177
1178        self.block.interface().write_register(
1179            self.start_address.unwrap(),
1180            self.field_sets.as_slice_mut(),
1181            &Fieldsets::METADATA,
1182        )
1183    }
1184
1185    /// Execute the write.
1186    ///
1187    /// Use the closure to change contents of the fieldset values that will be written.
1188    /// The fieldset values are either the reset value or all-0's based on which plan was used in the chaining phase.
1189    ///
1190    /// If ok, the return value of the closure is returned.
1191    /// If the bulk-write was illegal or the read failed, an error is returned.
1192    #[inline]
1193    pub fn execute_async(
1194        mut self,
1195        f: impl FnOnce(<&mut Fieldsets as ToTuple>::Tuple),
1196    ) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
1197    where
1198        B::Interface: AsyncRegisterInterface,
1199    {
1200        f(self.field_sets.to_tuple());
1201
1202        async move {
1203            self.block
1204                .interface()
1205                .write_register(
1206                    self.start_address.unwrap(),
1207                    self.field_sets.as_slice_mut(),
1208                    &Fieldsets::METADATA,
1209                )
1210                .await
1211        }
1212    }
1213}
1214
1215impl<B, Fieldsets>
1216    BulkRegisterOperation<
1217        '_,
1218        B,
1219        <B::Interface as RegisterInterfaceBase>::AddressType,
1220        Fieldsets,
1221        RW,
1222    >
1223where
1224    B: Block,
1225    B::Interface: RegisterInterfaceBase,
1226    Fieldsets: Fieldset,
1227    for<'a> &'a mut Fieldsets: ToTuple,
1228{
1229    /// Execute the modify.
1230    ///
1231    /// Use the closure to change contents of the fieldset values that have been read.
1232    /// The modified values will be written back to the device.
1233    ///
1234    /// If ok, the return value of the closure is returned.
1235    /// If the bulk-modify was illegal or the read failed, an error is returned.
1236    #[inline]
1237    pub fn execute(
1238        mut self,
1239        f: impl FnOnce(<&mut Fieldsets as ToTuple>::Tuple),
1240    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
1241    where
1242        B::Interface: RegisterInterface,
1243    {
1244        self.block.interface().read_register(
1245            self.start_address.unwrap(),
1246            self.field_sets.as_slice_mut(),
1247            &Fieldsets::METADATA,
1248        )?;
1249
1250        f(self.field_sets.to_tuple());
1251
1252        self.block.interface().write_register(
1253            self.start_address.unwrap(),
1254            self.field_sets.as_slice_mut(),
1255            &Fieldsets::METADATA,
1256        )
1257    }
1258
1259    /// Execute the modify.
1260    ///
1261    /// Use the closure to change contents of the fieldset values that have been read.
1262    /// The modified values will be written back to the device.
1263    ///
1264    /// If ok, the return value of the closure is returned.
1265    /// If the bulk-modify was illegal or the read failed, an error is returned.
1266    #[inline]
1267    pub async fn execute_async(
1268        mut self,
1269        f: impl FnOnce(<&mut Fieldsets as ToTuple>::Tuple),
1270    ) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
1271    where
1272        B::Interface: AsyncRegisterInterface,
1273    {
1274        self.block
1275            .interface()
1276            .read_register(
1277                self.start_address.unwrap(),
1278                self.field_sets.as_slice_mut(),
1279                &Fieldsets::METADATA,
1280            )
1281            .await?;
1282
1283        f(self.field_sets.to_tuple());
1284
1285        self.block
1286            .interface()
1287            .write_register(
1288                self.start_address.unwrap(),
1289                self.field_sets.as_slice_mut(),
1290                &Fieldsets::METADATA,
1291            )
1292            .await
1293    }
1294}