1use embedded_hal_async::spi::SpiDevice;
4
5use crate::{diagnostics::Diagnostics, error::Error, register::Register, utils};
6
7const READ_BIT: u16 = 0x4000;
8const PARITY_BIT: u16 = 0x8000;
9const ERROR_FLAG: u16 = 0x4000;
10const DATA_MASK: u16 = 0x3FFF;
11const NOP_COMMAND: u16 = 0x0000;
12
13pub const ANGLE_MAX: u16 = 0x3FFF + 1;
15
16#[derive(Debug)]
18#[cfg_attr(feature = "defmt", derive(defmt::Format))]
19pub struct As5048a<SPI> {
20 spi: SPI,
21}
22
23impl<SPI, E> As5048a<SPI>
24where
25 SPI: SpiDevice<u8, Error = E>,
26{
27 pub fn new(spi: SPI) -> Self {
29 Self { spi }
30 }
31
32 pub fn release(self) -> SPI {
34 self.spi
35 }
36
37 async fn read_register(&mut self, register: Register) -> Result<u16, Error<E>> {
43 let address = u16::from(register);
44
45 let command = READ_BIT | address;
46
47 let command = if utils::calculate_parity(command) {
48 PARITY_BIT | command
49 } else {
50 command
51 };
52
53 #[cfg(feature = "defmt")]
54 defmt::trace!(
55 "Reading register 0x{:04X}, command: 0x{:04X}",
56 address,
57 command
58 );
59
60 let tx_cmd = command.to_be_bytes();
61 let mut rx_cmd = [0u8; 2];
62 self.spi
63 .transfer(&mut rx_cmd, &tx_cmd)
64 .await
65 .map_err(Error::Communication)?;
66
67 let tx_nop = NOP_COMMAND.to_be_bytes();
68 let mut rx_data = [0u8; 2];
69 self.spi
70 .transfer(&mut rx_data, &tx_nop)
71 .await
72 .map_err(Error::Communication)?;
73
74 let response = u16::from_be_bytes(rx_data);
75
76 #[cfg(feature = "defmt")]
77 defmt::trace!("Received response: 0x{:04X}", response);
78
79 if !utils::verify_parity(response) {
80 #[cfg(feature = "defmt")]
81 defmt::warn!("Parity error in response: 0x{:04X}", response);
82 return Err(Error::ParityError);
83 }
84
85 if response & ERROR_FLAG != 0 {
86 #[cfg(feature = "defmt")]
87 defmt::warn!("Sensor error flag set in response");
88 return Err(Error::SensorError);
89 }
90
91 let data = response & DATA_MASK;
92 #[cfg(feature = "defmt")]
93 defmt::debug!("Register 0x{:04X} value: 0x{:04X}", address, data);
94
95 Ok(data)
96 }
97
98 #[allow(dead_code)]
112 async fn write_register(&mut self, register: Register, data: u16) -> Result<(), Error<E>> {
113 let address = u16::from(register);
114
115 #[cfg(feature = "defmt")]
116 defmt::debug!("Writing 0x{:04X} to register 0x{:04X}", data, address);
117
118 let command = address;
119
120 let command = if utils::calculate_parity(command) {
121 PARITY_BIT | command
122 } else {
123 command
124 };
125
126 let tx_cmd = command.to_be_bytes();
127 let mut rx_cmd = [0u8; 2];
128 self.spi
129 .transfer(&mut rx_cmd, &tx_cmd)
130 .await
131 .map_err(Error::Communication)?;
132
133 let data_frame = data & DATA_MASK;
134 let data_frame = if utils::calculate_parity(data_frame) {
135 PARITY_BIT | data_frame
136 } else {
137 data_frame
138 };
139
140 let tx_data = data_frame.to_be_bytes();
141 let mut rx_old = [0u8; 2];
142 self.spi
143 .transfer(&mut rx_old, &tx_data)
144 .await
145 .map_err(Error::Communication)?;
146
147 let tx_nop = NOP_COMMAND.to_be_bytes();
148 let mut rx_verify = [0u8; 2];
149 self.spi
150 .transfer(&mut rx_verify, &tx_nop)
151 .await
152 .map_err(Error::Communication)?;
153
154 let response = u16::from_be_bytes(rx_verify);
155
156 if !utils::verify_parity(response) {
157 #[cfg(feature = "defmt")]
158 defmt::warn!("Parity error in write verification: 0x{:04X}", response);
159 return Err(Error::ParityError);
160 }
161
162 if response & ERROR_FLAG != 0 {
163 #[cfg(feature = "defmt")]
164 defmt::warn!("Sensor error flag set during write");
165 return Err(Error::SensorError);
166 }
167
168 #[cfg(feature = "defmt")]
169 defmt::trace!("Write to register 0x{:04X} successful", address);
170
171 Ok(())
172 }
173
174 pub async fn angle(&mut self) -> Result<u16, Error<E>> {
185 self.read_register(Register::Angle).await
186 }
187
188 pub async fn angle_degrees(&mut self) -> Result<u16, Error<E>> {
197 let angle = self.angle().await?;
198 let degrees = (u32::from(angle).saturating_mul(360)) / u32::from(ANGLE_MAX);
199 #[allow(clippy::cast_possible_truncation)]
200 Ok(degrees as u16)
201 }
202
203 pub async fn magnitude(&mut self) -> Result<u16, Error<E>> {
211 self.read_register(Register::Magnitude).await
212 }
213
214 pub async fn diagnostics(&mut self) -> Result<Diagnostics, Error<E>> {
248 self.read_register(Register::DiagAgc)
249 .await
250 .map(Diagnostics::new)
251 }
252
253 pub async fn clear_error_flag(&mut self) -> Result<(), Error<E>> {
259 self.read_register(Register::ClearErrorFlag).await?;
260 Ok(())
261 }
262}