embedded_interfaces/registers/
mod.rs

1use crate::{MaybeBitdumpFormattable, TransportError};
2
3pub mod i2c;
4pub mod spi;
5
6/// A base trait for all register codecs
7pub trait RegisterCodec {
8    /// An error type for codec specific errors
9    type Error: core::fmt::Debug;
10}
11
12/// The basis trait for all registers. A register is a type that maps to a specific register on an
13/// embedded device and should own the raw data required for this register.
14///
15/// Additionally, a register knows the virtual address ossociated to the embedded device, and a
16/// bitfield representation of the data content.
17pub trait Register: Default + Clone + bytemuck::Pod + MaybeBitdumpFormattable {
18    /// The size of the register in bytes
19    const REGISTER_SIZE: usize;
20    /// The virtual address of this register
21    const ADDRESS: u64;
22
23    /// The associated unpacked type
24    type Unpacked;
25    /// A common error type which can represent all associated codec errors
26    type CodecError: core::fmt::Debug;
27    /// The SPI codec that should be used for this register. If the device doesn't support SPI
28    /// communication, this can be ignored.
29    #[cfg(all(feature = "sync", not(feature = "async")))]
30    type SpiCodec: spi::CodecSync<Error = Self::CodecError>;
31    #[cfg(all(not(feature = "sync"), feature = "async"))]
32    type SpiCodec: spi::CodecAsync<Error = Self::CodecError>;
33    #[cfg(all(feature = "sync", feature = "async"))]
34    type SpiCodec: spi::CodecSync<Error = Self::CodecError> + spi::CodecAsync<Error = Self::CodecError>;
35    /// The I2C codec that should be used for this register. If the device doesn't support I2C
36    /// communication, this can be ignored.
37    #[cfg(all(feature = "sync", not(feature = "async")))]
38    type I2cCodec: i2c::CodecSync<Error = Self::CodecError>;
39    #[cfg(all(not(feature = "sync"), feature = "async"))]
40    type I2cCodec: i2c::CodecAsync<Error = Self::CodecError>;
41    #[cfg(all(feature = "sync", feature = "async"))]
42    type I2cCodec: i2c::CodecSync<Error = Self::CodecError> + i2c::CodecAsync<Error = Self::CodecError>;
43}
44
45/// This trait is a marker trait implemented by any register that can be read from a device.
46pub trait ReadableRegister: Register {}
47
48/// This trait is a marker trait implemented by any register that can be written to a device.
49pub trait WritableRegister: Register {}
50
51/// A trait that is implemented by any bus interface and allows devices with registers to share
52/// register read/write implementations independent of the actual interface in use.
53#[maybe_async_cfg::maybe(sync(feature = "sync"), async(feature = "async"))]
54#[allow(async_fn_in_trait)]
55pub trait RegisterInterface {
56    /// A type representing errors on the underlying bus
57    type BusError: core::fmt::Debug;
58
59    /// Reads the given register through this interface
60    async fn read_register<R>(&mut self) -> Result<R, TransportError<<R as Register>::CodecError, Self::BusError>>
61    where
62        R: ReadableRegister;
63
64    /// Writes the given register through this interface
65    async fn write_register<R>(
66        &mut self,
67        register: impl AsRef<R>,
68    ) -> Result<(), TransportError<<R as Register>::CodecError, Self::BusError>>
69    where
70        R: WritableRegister;
71}