1use maybe_async_cfg::maybe;
3
4#[cfg(not(feature = "async"))]
5use embedded_hal::{i2c, spi};
6#[cfg(feature = "async")]
7use embedded_hal_async::{i2c, spi};
8
9use crate::{
10 private,
11 register_address::{RegRead, RegWrite},
12 Error,
13};
14
15pub(crate) const MMC5983_ADDR: u8 = 0b0110000;
17
18#[derive(Debug)]
20pub struct I2cInterface<I2C> {
21 pub(crate) i2c: I2C,
22}
23
24#[derive(Debug)]
26pub struct SpiInterface<SPI> {
27 pub(crate) spi: SPI,
28}
29
30#[maybe(
32 sync(cfg(not(feature = "async")), keep_self,),
33 async(cfg(feature = "async"), keep_self,)
34)]
35pub trait WriteData: private::Sealed {
36 type Error;
38
39 async fn write_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error>;
41}
42
43#[maybe(
44 sync(cfg(not(feature = "async")), keep_self,),
45 async(cfg(feature = "async"), keep_self,)
46)]
47impl<I2C, E> WriteData for I2cInterface<I2C>
48where
49 I2C: i2c::I2c<Error = E>,
50{
51 type Error = Error<E>;
52
53 async fn write_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
54 let payload: [u8; 2] = [R::ADDR, reg.data()];
55 self.i2c
56 .write(MMC5983_ADDR, &payload)
57 .await
58 .map_err(Error::Comm)
59 }
60}
61
62#[maybe(
63 sync(cfg(not(feature = "async")), keep_self,),
64 async(cfg(feature = "async"), keep_self,)
65)]
66impl<SPI, CommE> WriteData for SpiInterface<SPI>
67where
68 SPI: spi::SpiDevice<u8, Error = CommE>,
69{
70 type Error = Error<CommE>;
71
72 async fn write_register<R: RegWrite>(&mut self, reg: R) -> Result<(), Self::Error> {
73 let payload: [u8; 2] = [R::ADDR & !SPI_RW, reg.data()];
74 self.spi.write(&payload).await.map_err(Error::Comm)
75 }
76}
77
78#[maybe(
80 sync(cfg(not(feature = "async")), keep_self,),
81 async(cfg(feature = "async"), keep_self,)
82)]
83pub trait ReadData: private::Sealed {
84 type Error;
86
87 async fn read_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error>;
89
90 async fn read_consecutive(
92 &mut self,
93 start_addr: u8,
94 buffer: &mut [u8],
95 ) -> Result<(), Self::Error>;
96}
97
98const SPI_RW: u8 = 1 << 7;
99
100#[maybe(
101 sync(cfg(not(feature = "async")), keep_self,),
102 async(cfg(feature = "async"), keep_self,)
103)]
104impl<I2C, E> ReadData for I2cInterface<I2C>
105where
106 I2C: i2c::I2c<Error = E>,
107{
108 type Error = Error<E>;
109
110 async fn read_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
111 let mut data = [0];
112 self.i2c
113 .write_read(MMC5983_ADDR, &[R::ADDR], &mut data)
114 .await
115 .map_err(Error::Comm)?;
116
117 Ok(R::from_data(data[0]))
118 }
119
120 async fn read_consecutive(
121 &mut self,
122 start_addr: u8,
123 buffer: &mut [u8],
124 ) -> Result<(), Self::Error> {
125 self.i2c
126 .write_read(MMC5983_ADDR, &[start_addr], buffer)
127 .await
128 .map_err(Error::Comm)
129 }
130}
131
132#[maybe(
133 sync(cfg(not(feature = "async")), keep_self,),
134 async(cfg(feature = "async"), keep_self,)
135)]
136impl<SPI, CommE> ReadData for SpiInterface<SPI>
137where
138 SPI: spi::SpiDevice<u8, Error = CommE>,
139{
140 type Error = Error<CommE>;
141
142 async fn read_register<R: RegRead>(&mut self) -> Result<R::Output, Self::Error> {
143 let mut data = [SPI_RW | R::ADDR, 0];
144 self.spi
145 .transfer_in_place(&mut data)
146 .await
147 .map_err(Error::Comm)?;
148
149 Ok(R::from_data(data[1]))
150 }
151
152 async fn read_consecutive(
153 &mut self,
154 start_addr: u8,
155 buffer: &mut [u8],
156 ) -> Result<(), Self::Error> {
157 let mut data = [0u8; 32]; if buffer.len() >= data.len() {
160 return Err(Error::InvalidInputData);
161 }
162
163 data[0] = SPI_RW | start_addr;
165
166 let data_slice = &mut data[..=buffer.len()];
168
169 self.spi
170 .transfer_in_place(data_slice)
171 .await
172 .map_err(Error::Comm)?;
173
174 buffer.copy_from_slice(&data_slice[1..]);
175 Ok(())
176 }
177}