use core::marker::PhantomData;
use crate::{
Address, AddressMode, Append, ArrayRepeating, Block, Fieldset, FieldsetMetadata, NotRepeating,
RO, RW, ReadCapability, Repeating, ToTuple, WO, WriteCapability,
};
#[cfg(feature = "defmt")]
use defmt::panic;
pub trait RegisterInterfaceBase {
type Error;
type AddressType: Address;
}
impl<T: RegisterInterfaceBase> RegisterInterfaceBase for &mut T {
type Error = T::Error;
type AddressType = T::AddressType;
}
#[diagnostic::on_unimplemented(
label = "cannot use blocking register operations when the device interface doesn't know how to read and write registers",
note = "to enable register operations, implement the trait on this type"
)]
pub trait RegisterInterface: RegisterInterfaceBase {
fn write_register(
&mut self,
address: Self::AddressType,
data: &mut [u8],
_metadata: &FieldsetMetadata,
) -> Result<(), Self::Error>;
fn read_register(
&mut self,
address: Self::AddressType,
data: &mut [u8],
_metadata: &FieldsetMetadata,
) -> Result<(), Self::Error>;
}
#[diagnostic::do_not_recommend]
impl<T: RegisterInterface> RegisterInterface for &mut T {
fn write_register(
&mut self,
address: Self::AddressType,
data: &mut [u8],
metadata: &FieldsetMetadata,
) -> Result<(), Self::Error> {
(*self).write_register(address, data, metadata)
}
fn read_register(
&mut self,
address: Self::AddressType,
data: &mut [u8],
metadata: &FieldsetMetadata,
) -> Result<(), Self::Error> {
(*self).read_register(address, data, metadata)
}
}
#[diagnostic::on_unimplemented(
label = "cannot use async register operations when the device interface doesn't know how to read and write registers",
note = "to enable register operations, implement the trait on this type"
)]
pub trait AsyncRegisterInterface: RegisterInterfaceBase {
async fn write_register(
&mut self,
address: Self::AddressType,
data: &mut [u8],
_metadata: &FieldsetMetadata,
) -> Result<(), Self::Error>;
async fn read_register(
&mut self,
address: Self::AddressType,
data: &mut [u8],
_metadata: &FieldsetMetadata,
) -> Result<(), Self::Error>;
}
#[diagnostic::do_not_recommend]
impl<T: AsyncRegisterInterface> AsyncRegisterInterface for &mut T {
fn write_register(
&mut self,
address: Self::AddressType,
data: &mut [u8],
metadata: &FieldsetMetadata,
) -> impl Future<Output = Result<(), Self::Error>> {
(*self).write_register(address, data, metadata)
}
fn read_register(
&mut self,
address: Self::AddressType,
data: &mut [u8],
metadata: &FieldsetMetadata,
) -> impl Future<Output = Result<(), Self::Error>> {
(*self).read_register(address, data, metadata)
}
}
pub struct RegisterOperation<'b, B, RegisterFs, AddressType, Access, Repeat>
where
B: Block,
B::Interface: RegisterInterfaceBase<AddressType = AddressType>,
RegisterFs: Fieldset,
AddressType: Address,
{
block: &'b mut B,
address: AddressType,
register_new_with_reset: fn() -> RegisterFs,
_phantom: PhantomData<(RegisterFs, Access, Repeat)>,
}
impl<'b, B, RegisterFs, AddressType, Access, Repeat>
RegisterOperation<'b, B, RegisterFs, AddressType, Access, Repeat>
where
RegisterFs: Fieldset,
B: Block,
B::Interface: RegisterInterfaceBase<AddressType = AddressType>,
AddressType: Address,
{
#[doc(hidden)]
pub fn new(
block: &'b mut B,
address: AddressType,
register_new_with_reset: fn() -> RegisterFs,
) -> Self {
Self {
block,
address,
register_new_with_reset,
_phantom: PhantomData,
}
}
pub fn address(&self) -> AddressType {
self.address
}
pub fn reset_value(&self) -> RegisterFs {
(self.register_new_with_reset)()
}
pub fn plan(&self) -> Plan<AddressType, RegisterFs, Access>
where
Repeat: NotRepeating,
{
Plan {
address: self.address(),
value: self.reset_value(),
_phantom: PhantomData,
}
}
#[track_caller]
pub fn plan_at(&self, index: Repeat::Index) -> Plan<AddressType, RegisterFs, Access>
where
Repeat: Repeating,
{
Plan {
address: Repeat::calc_address(self.address, index),
value: self.reset_value(),
_phantom: PhantomData,
}
}
#[track_caller]
pub fn plan_with_zero(&self) -> Plan<AddressType, RegisterFs, Access>
where
Repeat: NotRepeating,
Access: WriteCapability,
{
Plan {
address: self.address(),
value: RegisterFs::ZERO,
_phantom: PhantomData,
}
}
#[track_caller]
pub fn plan_with_zero_at(&self, index: Repeat::Index) -> Plan<AddressType, RegisterFs, Access>
where
Repeat: Repeating,
Access: WriteCapability,
{
Plan {
address: Repeat::calc_address(self.address, index),
value: RegisterFs::ZERO,
_phantom: PhantomData,
}
}
#[track_caller]
pub fn plan_array_at<const N: usize>(
self,
index: Repeat::Index,
) -> Plan<AddressType, [RegisterFs; N], Access>
where
Repeat: ArrayRepeating,
B::RegisterAddressMode: AddressMode,
{
Repeat::assert_len_and_index(N, index.clone());
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
Plan {
address,
value: core::array::from_fn(|_| self.reset_value()),
_phantom: PhantomData,
}
}
#[track_caller]
pub fn plan_array_with_zero_at<const N: usize>(
self,
index: Repeat::Index,
) -> Plan<AddressType, [RegisterFs; N], Access>
where
Repeat: ArrayRepeating,
B::RegisterAddressMode: AddressMode,
Access: WriteCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
Plan {
address,
value: Fieldset::ZERO,
_phantom: PhantomData,
}
}
#[track_caller]
pub fn write(
self,
f: impl FnOnce(&mut RegisterFs),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: NotRepeating,
B::Interface: RegisterInterface,
Access: WriteCapability,
{
let mut register = (self.register_new_with_reset)();
f(&mut register);
self.block.interface().write_register(
self.address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn write_at(
self,
index: Repeat::Index,
f: impl FnOnce(&mut RegisterFs),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: Repeating,
B::Interface: RegisterInterface,
Access: WriteCapability,
{
let mut register = (self.register_new_with_reset)();
f(&mut register);
self.block.interface().write_register(
Repeat::calc_address(self.address, index),
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn write_array_at<const N: usize>(
self,
index: Repeat::Index,
f: impl FnOnce(&mut [RegisterFs; N]),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: ArrayRepeating,
B::Interface: RegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: WriteCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let mut register = core::array::from_fn(|_| (self.register_new_with_reset)());
f(&mut register);
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
self.block.interface().write_register(
address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn write_async(
self,
f: impl FnOnce(&mut RegisterFs),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: NotRepeating,
B::Interface: AsyncRegisterInterface,
Access: WriteCapability,
{
let mut register = (self.register_new_with_reset)();
f(&mut register);
async move {
self.block
.interface()
.write_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
pub fn write_at_async(
self,
index: Repeat::Index,
f: impl FnOnce(&mut RegisterFs),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: Repeating,
B::Interface: AsyncRegisterInterface,
Access: WriteCapability,
{
let mut register = (self.register_new_with_reset)();
f(&mut register);
let address = Repeat::calc_address(self.address, index);
async move {
self.block
.interface()
.write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
pub fn write_array_at_async<const N: usize>(
self,
index: Repeat::Index,
f: impl FnOnce(&mut [RegisterFs; N]),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: ArrayRepeating,
B::Interface: AsyncRegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: WriteCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let mut register = core::array::from_fn(|_| (self.register_new_with_reset)());
f(&mut register);
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
async move {
self.block
.interface()
.write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
pub fn write_with_zero(
self,
f: impl FnOnce(&mut RegisterFs),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: NotRepeating,
B::Interface: RegisterInterface,
Access: WriteCapability,
{
let mut register = RegisterFs::ZERO;
f(&mut register);
self.block.interface().write_register(
self.address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn write_with_zero_at(
self,
index: Repeat::Index,
f: impl FnOnce(&mut RegisterFs),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: Repeating,
B::Interface: RegisterInterface,
Access: WriteCapability,
{
let mut register = RegisterFs::ZERO;
f(&mut register);
self.block.interface().write_register(
Repeat::calc_address(self.address, index),
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn write_array_with_zero_at<const N: usize>(
self,
index: Repeat::Index,
f: impl FnOnce(&mut [RegisterFs; N]),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: ArrayRepeating,
B::Interface: RegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: WriteCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
f(&mut register);
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
self.block.interface().write_register(
address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn write_with_zero_async(
self,
f: impl FnOnce(&mut RegisterFs),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: NotRepeating,
B::Interface: AsyncRegisterInterface,
Access: WriteCapability,
{
let mut register = RegisterFs::ZERO;
f(&mut register);
async move {
self.block
.interface()
.write_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
pub fn write_with_zero_at_async(
self,
index: Repeat::Index,
f: impl FnOnce(&mut RegisterFs),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: Repeating,
B::Interface: AsyncRegisterInterface,
Access: WriteCapability,
{
let mut register = RegisterFs::ZERO;
f(&mut register);
let address = Repeat::calc_address(self.address, index);
async move {
self.block
.interface()
.write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
pub fn write_array_with_zero_at_async<const N: usize>(
self,
index: Repeat::Index,
f: impl FnOnce(&mut [RegisterFs; N]),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: ArrayRepeating,
B::Interface: AsyncRegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: WriteCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
f(&mut register);
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
async move {
self.block
.interface()
.write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
pub fn read(self) -> Result<RegisterFs, <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: NotRepeating,
B::Interface: RegisterInterface,
Access: ReadCapability,
{
let mut register = RegisterFs::ZERO;
self.block
.interface()
.read_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
.map(|_| register)
}
#[track_caller]
pub fn read_at(
self,
index: Repeat::Index,
) -> Result<RegisterFs, <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: Repeating,
B::Interface: RegisterInterface,
Access: ReadCapability,
{
let mut register = RegisterFs::ZERO;
self.block
.interface()
.read_register(
Repeat::calc_address(self.address, index),
register.as_slice_mut(),
&RegisterFs::METADATA,
)
.map(|_| register)
}
#[track_caller]
pub fn read_array_at<const N: usize>(
self,
index: Repeat::Index,
) -> Result<[RegisterFs; N], <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: ArrayRepeating,
B::Interface: RegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: ReadCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
self.block
.interface()
.read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.map(|_| register)
}
#[track_caller]
pub fn read_async(
self,
) -> impl Future<Output = Result<RegisterFs, <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: NotRepeating,
B::Interface: AsyncRegisterInterface,
Access: ReadCapability,
{
let mut register = RegisterFs::ZERO;
async move {
self.block
.interface()
.read_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
.map(|_| register)
}
}
pub fn read_at_async(
self,
index: Repeat::Index,
) -> impl Future<Output = Result<RegisterFs, <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: Repeating,
B::Interface: AsyncRegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: ReadCapability,
{
let mut register = RegisterFs::ZERO;
let address = Repeat::calc_address(self.address, index);
async move {
self.block
.interface()
.read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
.map(|_| register)
}
}
pub fn read_array_at_async<const N: usize>(
self,
index: Repeat::Index,
) -> impl Future<Output = Result<[RegisterFs; N], <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: ArrayRepeating,
B::Interface: AsyncRegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: ReadCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
async move {
self.block
.interface()
.read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
.map(|_| register)
}
}
#[track_caller]
pub fn modify(
self,
f: impl FnOnce(&mut RegisterFs),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: NotRepeating,
B::Interface: RegisterInterface,
Access: ReadCapability + WriteCapability,
{
let mut register = RegisterFs::ZERO;
self.block.interface().read_register(
self.address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)?;
f(&mut register);
self.block.interface().write_register(
self.address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn modify_at(
self,
index: Repeat::Index,
f: impl FnOnce(&mut RegisterFs),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: Repeating,
B::Interface: RegisterInterface,
Access: ReadCapability + WriteCapability,
{
let mut register = RegisterFs::ZERO;
let address = Repeat::calc_address(self.address, index);
self.block.interface().read_register(
address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)?;
f(&mut register);
self.block.interface().write_register(
address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn modify_array_at<const N: usize>(
self,
index: Repeat::Index,
f: impl FnOnce(&mut [RegisterFs; N]),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
Repeat: ArrayRepeating,
B::Interface: RegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: ReadCapability + WriteCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
self.block.interface().read_register(
address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)?;
f(&mut register);
self.block.interface().write_register(
address,
register.as_slice_mut(),
&RegisterFs::METADATA,
)
}
#[track_caller]
pub fn modify_async(
self,
f: impl FnOnce(&mut RegisterFs),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: NotRepeating,
B::Interface: AsyncRegisterInterface,
Access: ReadCapability + WriteCapability,
{
let mut register = RegisterFs::ZERO;
async move {
self.block
.interface()
.read_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
.await?;
f(&mut register);
self.block
.interface()
.write_register(self.address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
pub fn modify_at_async(
self,
index: Repeat::Index,
f: impl FnOnce(&mut RegisterFs),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: Repeating,
B::Interface: AsyncRegisterInterface,
Access: ReadCapability + WriteCapability,
{
let mut register = RegisterFs::ZERO;
let address = Repeat::calc_address(self.address, index);
async move {
self.block
.interface()
.read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await?;
f(&mut register);
self.block
.interface()
.write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
pub fn modify_array_at_async<const N: usize>(
self,
index: Repeat::Index,
f: impl FnOnce(&mut [RegisterFs; N]),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
Repeat: ArrayRepeating,
B::Interface: AsyncRegisterInterface,
B::RegisterAddressMode: AddressMode,
Access: ReadCapability + WriteCapability,
{
Repeat::assert_len_and_index(N, index.clone());
let mut register = <[RegisterFs; N] as Fieldset>::ZERO;
let address = Repeat::calc_address(self.address, index);
Self::assert_array_op_legal(address);
async move {
self.block
.interface()
.read_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await?;
f(&mut register);
self.block
.interface()
.write_register(address, register.as_slice_mut(), &RegisterFs::METADATA)
.await
}
}
#[track_caller]
fn assert_array_op_legal(address: AddressType)
where
B::RegisterAddressMode: AddressMode,
Repeat: ArrayRepeating,
{
if address.add(Repeat::STRIDE)
!= B::RegisterAddressMode::next_address(address, core::mem::size_of::<RegisterFs>())
{
panic!(
"array operations can't be used with this register due to the `register-address-map` rule. Used stride: {}, accepted stride: {}",
Repeat::STRIDE,
B::RegisterAddressMode::next_address(
AddressType::ZERO,
core::mem::size_of::<RegisterFs>()
)
);
}
}
}
pub struct Plan<AddressType: Copy, FS, Access> {
pub address: AddressType,
pub value: FS,
_phantom: PhantomData<Access>,
}
pub struct BulkRegisterOperation<'b, B, AddressType: Address, Fieldsets, Access> {
pub(crate) block: &'b mut B,
pub(crate) start_address: Option<AddressType>,
pub(crate) next_address: Option<AddressType>,
pub(crate) field_sets: Fieldsets,
pub(crate) _phantom: PhantomData<Access>,
}
impl<B, AddressType, FieldSets, Access> BulkRegisterOperation<'_, B, AddressType, FieldSets, Access>
where
B: Block,
B::RegisterAddressMode: AddressMode,
AddressType: Address,
{
#[track_caller]
fn assert_legal(&self, address: AddressType) {
if let Some(next_address) = self.next_address
&& address != next_address
{
panic!(
"order of registers not valid according to the address mode rules. Expected address: {}, got: {}",
next_address, address
);
}
}
}
impl<'b, B, AddressType, FieldSets> BulkRegisterOperation<'b, B, AddressType, FieldSets, WO>
where
B: Block,
B::RegisterAddressMode: AddressMode,
AddressType: Address,
{
#[track_caller]
#[inline]
pub fn with<FS: Fieldset, LocalAccess: WriteCapability>(
self,
f: impl FnOnce(&mut B) -> Plan<AddressType, FS, LocalAccess>,
) -> BulkRegisterOperation<'b, B, AddressType, FieldSets::Appended, WO>
where
FieldSets: Append<FS>,
{
let Plan { address, value, .. } = f(self.block);
self.assert_legal(address);
BulkRegisterOperation {
block: self.block,
start_address: self.start_address.or(Some(address)),
next_address: Some(B::RegisterAddressMode::next_address(
address,
core::mem::size_of::<FS>(),
)),
field_sets: self.field_sets.append(value),
_phantom: PhantomData,
}
}
}
impl<'b, B, AddressType, FieldSets> BulkRegisterOperation<'b, B, AddressType, FieldSets, RO>
where
B: Block,
B::RegisterAddressMode: AddressMode,
AddressType: Address,
{
#[track_caller]
#[inline]
pub fn with<FS: Fieldset, LocalAccess: ReadCapability>(
self,
f: impl FnOnce(&mut B) -> Plan<AddressType, FS, LocalAccess>,
) -> BulkRegisterOperation<'b, B, AddressType, FieldSets::Appended, RO>
where
FieldSets: Append<FS>,
{
let Plan { address, value, .. } = f(self.block);
self.assert_legal(address);
BulkRegisterOperation {
block: self.block,
start_address: self.start_address.or(Some(address)),
next_address: Some(B::RegisterAddressMode::next_address(
address,
core::mem::size_of::<FS>(),
)),
field_sets: self.field_sets.append(value),
_phantom: PhantomData,
}
}
}
impl<'b, B, AddressType, FieldSets> BulkRegisterOperation<'b, B, AddressType, FieldSets, RW>
where
B: Block,
B::RegisterAddressMode: AddressMode,
AddressType: Address,
{
#[track_caller]
#[inline]
pub fn with<FS: Fieldset, LocalAccess: ReadCapability + WriteCapability>(
self,
f: impl FnOnce(&mut B) -> Plan<AddressType, FS, LocalAccess>,
) -> BulkRegisterOperation<'b, B, AddressType, FieldSets::Appended, RW>
where
FieldSets: Append<FS>,
{
let Plan { address, value, .. } = f(self.block);
self.assert_legal(address);
BulkRegisterOperation {
block: self.block,
start_address: self.start_address.or(Some(address)),
next_address: Some(B::RegisterAddressMode::next_address(
address,
core::mem::size_of::<FS>(),
)),
field_sets: self.field_sets.append(value),
_phantom: PhantomData,
}
}
}
impl<B, Fieldsets>
BulkRegisterOperation<
'_,
B,
<B::Interface as RegisterInterfaceBase>::AddressType,
Fieldsets,
RO,
>
where
B: Block,
B::Interface: RegisterInterfaceBase,
Fieldsets: Fieldset + ToTuple,
{
#[inline]
pub fn execute(
mut self,
) -> Result<Fieldsets::Tuple, <B::Interface as RegisterInterfaceBase>::Error>
where
B::Interface: RegisterInterface,
{
self.block
.interface()
.read_register(
self.start_address.unwrap(),
self.field_sets.as_slice_mut(),
&Fieldsets::METADATA,
)
.map(|_| self.field_sets.to_tuple())
}
#[inline]
pub async fn execute_async(
mut self,
) -> Result<Fieldsets::Tuple, <B::Interface as RegisterInterfaceBase>::Error>
where
B::Interface: AsyncRegisterInterface,
{
self.block
.interface()
.read_register(
self.start_address.unwrap(),
self.field_sets.as_slice_mut(),
&Fieldsets::METADATA,
)
.await
.map(|_| self.field_sets.to_tuple())
}
}
impl<B, Fieldsets>
BulkRegisterOperation<
'_,
B,
<B::Interface as RegisterInterfaceBase>::AddressType,
Fieldsets,
WO,
>
where
B: Block,
B::Interface: RegisterInterfaceBase,
Fieldsets: Fieldset,
for<'a> &'a mut Fieldsets: ToTuple,
{
#[inline]
pub fn execute(
mut self,
f: impl FnOnce(<&mut Fieldsets as ToTuple>::Tuple),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
B::Interface: RegisterInterface,
{
f(self.field_sets.to_tuple());
self.block.interface().write_register(
self.start_address.unwrap(),
self.field_sets.as_slice_mut(),
&Fieldsets::METADATA,
)
}
#[inline]
pub fn execute_async(
mut self,
f: impl FnOnce(<&mut Fieldsets as ToTuple>::Tuple),
) -> impl Future<Output = Result<(), <B::Interface as RegisterInterfaceBase>::Error>>
where
B::Interface: AsyncRegisterInterface,
{
f(self.field_sets.to_tuple());
async move {
self.block
.interface()
.write_register(
self.start_address.unwrap(),
self.field_sets.as_slice_mut(),
&Fieldsets::METADATA,
)
.await
}
}
}
impl<B, Fieldsets>
BulkRegisterOperation<
'_,
B,
<B::Interface as RegisterInterfaceBase>::AddressType,
Fieldsets,
RW,
>
where
B: Block,
B::Interface: RegisterInterfaceBase,
Fieldsets: Fieldset,
for<'a> &'a mut Fieldsets: ToTuple,
{
#[inline]
pub fn execute(
mut self,
f: impl FnOnce(<&mut Fieldsets as ToTuple>::Tuple),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
B::Interface: RegisterInterface,
{
self.block.interface().read_register(
self.start_address.unwrap(),
self.field_sets.as_slice_mut(),
&Fieldsets::METADATA,
)?;
f(self.field_sets.to_tuple());
self.block.interface().write_register(
self.start_address.unwrap(),
self.field_sets.as_slice_mut(),
&Fieldsets::METADATA,
)
}
#[inline]
pub async fn execute_async(
mut self,
f: impl FnOnce(<&mut Fieldsets as ToTuple>::Tuple),
) -> Result<(), <B::Interface as RegisterInterfaceBase>::Error>
where
B::Interface: AsyncRegisterInterface,
{
self.block
.interface()
.read_register(
self.start_address.unwrap(),
self.field_sets.as_slice_mut(),
&Fieldsets::METADATA,
)
.await?;
f(self.field_sets.to_tuple());
self.block
.interface()
.write_register(
self.start_address.unwrap(),
self.field_sets.as_slice_mut(),
&Fieldsets::METADATA,
)
.await
}
}