use core::marker::PhantomData;
use crate::{FieldSet, ReadCapability, WriteCapability};
pub trait RegisterInterface {
type Error;
type AddressType: Copy;
fn write_register(
&mut self,
address: Self::AddressType,
size_bits: u32,
data: &[u8],
) -> Result<(), Self::Error>;
fn read_register(
&mut self,
address: Self::AddressType,
size_bits: u32,
data: &mut [u8],
) -> Result<(), Self::Error>;
}
pub trait AsyncRegisterInterface {
type Error;
type AddressType: Copy;
async fn write_register(
&mut self,
address: Self::AddressType,
size_bits: u32,
data: &[u8],
) -> Result<(), Self::Error>;
async fn read_register(
&mut self,
address: Self::AddressType,
size_bits: u32,
data: &mut [u8],
) -> Result<(), Self::Error>;
}
pub struct RegisterOperation<'i, Interface, AddressType: Copy, Register: FieldSet, Access> {
interface: &'i mut Interface,
address: AddressType,
register_new_with_reset: fn() -> Register,
_phantom: PhantomData<(Register, Access)>,
}
impl<'i, Interface, AddressType: Copy, Register: FieldSet, Access>
RegisterOperation<'i, Interface, AddressType, Register, Access>
{
#[doc(hidden)]
pub fn new(
interface: &'i mut Interface,
address: AddressType,
register_new_with_reset: fn() -> Register,
) -> Self {
Self {
interface,
address,
register_new_with_reset,
_phantom: PhantomData,
}
}
}
impl<Interface, AddressType: Copy, Register: FieldSet, Access>
RegisterOperation<'_, Interface, AddressType, Register, Access>
where
Interface: RegisterInterface<AddressType = AddressType>,
Access: WriteCapability,
{
pub fn write<R>(&mut self, f: impl FnOnce(&mut Register) -> R) -> Result<R, Interface::Error> {
let mut register = (self.register_new_with_reset)();
let returned = f(&mut register);
let buffer = Register::BUFFER::from(register);
self.interface
.write_register(self.address, Register::SIZE_BITS, buffer.as_ref())?;
Ok(returned)
}
pub fn write_with_zero<R>(
&mut self,
f: impl FnOnce(&mut Register) -> R,
) -> Result<R, Interface::Error> {
let mut register = Register::new_with_zero();
let returned = f(&mut register);
self.interface.write_register(
self.address,
Register::SIZE_BITS,
Register::BUFFER::from(register).as_mut(),
)?;
Ok(returned)
}
}
impl<Interface, AddressType: Copy, Register: FieldSet, Access>
RegisterOperation<'_, Interface, AddressType, Register, Access>
where
Interface: RegisterInterface<AddressType = AddressType>,
Access: ReadCapability,
{
pub fn read(&mut self) -> Result<Register, Interface::Error> {
let mut buffer = Register::BUFFER::from(Register::new_with_zero());
self.interface
.read_register(self.address, Register::SIZE_BITS, buffer.as_mut())?;
Ok(buffer.into())
}
}
impl<Interface, AddressType: Copy, Register: FieldSet, Access>
RegisterOperation<'_, Interface, AddressType, Register, Access>
where
Interface: RegisterInterface<AddressType = AddressType>,
Access: ReadCapability + WriteCapability,
{
pub fn modify<R>(&mut self, f: impl FnOnce(&mut Register) -> R) -> Result<R, Interface::Error> {
let mut register = self.read()?;
let returned = f(&mut register);
self.interface.write_register(
self.address,
Register::SIZE_BITS,
Register::BUFFER::from(register).as_mut(),
)?;
Ok(returned)
}
}
impl<'i, Interface, AddressType: Copy, Register: FieldSet, Access>
RegisterOperation<'i, Interface, AddressType, Register, Access>
where
Interface: AsyncRegisterInterface<AddressType = AddressType>,
Access: WriteCapability,
{
pub async fn write_async<R>(
&mut self,
f: impl FnOnce(&mut Register) -> R,
) -> Result<R, Interface::Error> {
let mut register = (self.register_new_with_reset)();
let returned = f(&mut register);
let buffer = Register::BUFFER::from(register);
self.interface
.write_register(self.address, Register::SIZE_BITS, buffer.as_ref())
.await?;
Ok(returned)
}
pub async fn write_with_zero_async<R>(
&mut self,
f: impl FnOnce(&mut Register) -> R,
) -> Result<R, Interface::Error> {
let mut register = Register::new_with_zero();
let returned = f(&mut register);
self.interface
.write_register(
self.address,
Register::SIZE_BITS,
Register::BUFFER::from(register).as_mut(),
)
.await?;
Ok(returned)
}
}
impl<'i, Interface, AddressType: Copy, Register: FieldSet, Access>
RegisterOperation<'i, Interface, AddressType, Register, Access>
where
Interface: AsyncRegisterInterface<AddressType = AddressType>,
Access: ReadCapability,
{
pub async fn read_async(&mut self) -> Result<Register, Interface::Error> {
let mut buffer = Register::BUFFER::from(Register::new_with_zero());
self.interface
.read_register(self.address, Register::SIZE_BITS, buffer.as_mut())
.await?;
Ok(buffer.into())
}
}
impl<'i, Interface, AddressType: Copy, Register: FieldSet, Access>
RegisterOperation<'i, Interface, AddressType, Register, Access>
where
Interface: AsyncRegisterInterface<AddressType = AddressType>,
Access: ReadCapability + WriteCapability,
{
pub async fn modify_async<R>(
&mut self,
f: impl FnOnce(&mut Register) -> R,
) -> Result<R, Interface::Error> {
let mut register = self.read_async().await?;
let returned = f(&mut register);
self.interface
.write_register(
self.address,
Register::SIZE_BITS,
Register::BUFFER::from(register).as_mut(),
)
.await?;
Ok(returned)
}
}