1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
//! Defined Traits for embedded-registers-derive.
//! For Derive Docs see [embedded-registers-derive](https://docs.rs/embedded-registers-derive/latest/embedded_registers_derive/)
#![cfg_attr(not(feature = "std"), no_std)]
use embedded_hal::i2c::Operation;
/// The basis trait for all registers. A register is a type
/// that maps to a specific register on an embedded device and
/// should own the raw data required for this register.
///
/// Additionally, a register knows the virtual address ossociated
/// to the embedded device, and a bitfield representation of the
/// data content.
pub trait Register: Default + Clone {
/// The size of the register in bytes
const REGISTER_SIZE: usize;
/// The virtual address of this register
const ADDRESS: u8;
/// The associated bondrewd bitfield type
type Bitfield;
/// Provides immutable access to the raw data.
fn data(&self) -> &[u8];
/// Provides mutable access to the raw data.
fn data_mut(&mut self) -> &mut [u8];
}
/// This trait is implemented by any register that can be read via a specific bus interface.
#[allow(async_fn_in_trait)]
pub trait RegisterRead: Register {
/// Asynchronously read this register from the given i2c bus and device address.
#[inline]
async fn read_i2c<I>(i2c: &mut I, address: u8) -> Result<Self, I::Error>
where
I: embedded_hal_async::i2c::I2c + embedded_hal_async::i2c::ErrorType,
{
let mut register = Self::default();
i2c.write_read(address, &[Self::ADDRESS], register.data_mut()).await?;
Ok(register)
}
/// Synchronously read this register from the given i2c bus and device address.
#[inline]
fn read_i2c_blocking<I>(i2c: &mut I, address: u8) -> Result<Self, I::Error>
where
I: embedded_hal::i2c::I2c + embedded_hal::i2c::ErrorType,
{
let mut register = Self::default();
i2c.write_read(address, &[Self::ADDRESS], register.data_mut())?;
Ok(register)
}
}
/// This trait is implemented by any register that can be written via a specific bus interface.
#[allow(async_fn_in_trait)]
pub trait RegisterWrite: Register {
/// Asynchronously write this register to the given i2c bus and device address.
#[inline]
async fn write_i2c<I>(&self, i2c: &mut I, address: u8) -> Result<(), I::Error>
where
I: embedded_hal_async::i2c::I2c + embedded_hal_async::i2c::ErrorType,
{
i2c.transaction(
address,
&mut [Operation::Write(&[Self::ADDRESS]), Operation::Write(self.data())],
)
.await
}
/// Synchronously write this register to the given i2c bus and device address.
#[inline]
fn write_i2c_blocking<I>(&self, i2c: &mut I, address: u8) -> Result<(), I::Error>
where
I: embedded_hal::i2c::I2c + embedded_hal::i2c::ErrorType,
{
i2c.transaction(
address,
&mut [Operation::Write(&[Self::ADDRESS]), Operation::Write(self.data())],
)
}
}
// re-export the derive stuff
#[cfg(feature = "derive")]
#[doc(hidden)]
pub use embedded_registers_derive::*;