1use crate::device::error::DeviceErrorInfo;
2use crate::driver::Driver;
3use crate::driver::command;
4use crate::driver::command::{HasGpioChannelConfig, HasMDOption};
5use crate::driver::registers::{AuxRegisters, CellRegisters, auxreg, cells, cfga, cfgb};
6use error::Error;
7
8pub mod error;
10#[cfg(test)]
11mod test;
12
13pub trait Device<const NUM_OF_DEVICES: usize> {
15 type Error;
16 async fn read_cfga(&mut self) -> Result<[cfga::CfgA; NUM_OF_DEVICES], Self::Error>;
21 async fn read_cfgb(&mut self) -> Result<[cfgb::CfgB; NUM_OF_DEVICES], Self::Error>;
26
27 async fn read_cva(&mut self) -> Result<[cells::CvA; NUM_OF_DEVICES], Self::Error>;
32 async fn read_cvb(&mut self) -> Result<[cells::CvB; NUM_OF_DEVICES], Self::Error>;
37 async fn read_cvc(&mut self) -> Result<[cells::CvC; NUM_OF_DEVICES], Self::Error>;
42 async fn read_cvd(&mut self) -> Result<[cells::CvD; NUM_OF_DEVICES], Self::Error>;
47 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
48 async fn read_cve(&mut self) -> Result<[cells::CvE; NUM_OF_DEVICES], Self::Error>;
53 #[cfg(feature = "ltc6813")]
54 async fn read_cvf(&mut self) -> Result<[cells::CvF; NUM_OF_DEVICES], Self::Error>;
59
60 async fn read_auxa(&mut self) -> Result<[auxreg::AuxA; NUM_OF_DEVICES], Self::Error>;
65 async fn read_auxb(&mut self) -> Result<[auxreg::AuxB; NUM_OF_DEVICES], Self::Error>;
70 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
71 async fn read_auxc(&mut self) -> Result<[auxreg::AuxC; NUM_OF_DEVICES], Self::Error>;
76 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
77 async fn read_auxd(&mut self) -> Result<[auxreg::AuxD; NUM_OF_DEVICES], Self::Error>;
82
83 async fn write_cfga(&mut self, reg: [cfga::CfgA; NUM_OF_DEVICES]) -> Result<(), Self::Error>;
92 async fn write_cfgb(&mut self, reg: [cfgb::CfgB; NUM_OF_DEVICES]) -> Result<(), Self::Error>;
100
101 async fn convert_cells(
109 &mut self,
110 cmd: command::Adcv,
111 ) -> Result<[CellRegisters; NUM_OF_DEVICES], Self::Error>;
112
113 async fn convert_gpios(
119 &mut self,
120 cmd: command::Adax,
121 ) -> Result<[AuxRegisters; NUM_OF_DEVICES], Self::Error>;
122
123 async fn perform_overlap_tests(&mut self, cmd: command::Adol) -> Result<(), Self::Error>;
133
134 async fn perform_accuracy_check(
143 &mut self,
144 conv_setting: command::MDSetting,
145 ) -> Result<(), Self::Error>;
146 async fn convert_cells_and_gpios(
152 &mut self,
153 cmd_cells: command::Adcv,
154 cmd_gpios: command::Adax,
155 ) -> Result<
156 (
157 [CellRegisters; NUM_OF_DEVICES],
158 [AuxRegisters; NUM_OF_DEVICES],
159 ),
160 Self::Error,
161 >;
162 async fn wake(&mut self) -> Result<(), Self::Error>;
172}
173
174macro_rules! read {
175 ($name:ident, $t:ty, $cmd:ident) => {
176 async fn $name(&mut self) -> Result<[$t; NUM_OF_DEVICES], Self::Error> {
177 self.driver.enable_cs();
178 Self::convert_error(self.send_cmd(&command::$cmd::default()).await)?;
179
180 let mut res: [$t; NUM_OF_DEVICES] = [<$t>::default(); NUM_OF_DEVICES];
181 for i in 0..NUM_OF_DEVICES {
182 let reg = self.driver.read_register().await;
183 match reg {
184 Ok(r) => res[i] = r.into(),
185 Err(e) => {
186 self.driver.disable_cs();
187 return Self::convert_error(Err(e));
188 }
189 }
190 }
191 self.driver.disable_cs();
192 Ok(res)
193 }
194 };
195}
196
197impl<const NUM_OF_DEVICES: usize, DRIVER: Driver> Device<NUM_OF_DEVICES>
198 for Ltc681x<DRIVER, NUM_OF_DEVICES>
199{
200 type Error = Error<DRIVER>;
201
202 read!(read_cfga, cfga::CfgA, RdCfgA);
203 read!(read_cfgb, cfgb::CfgB, RdCfgB);
204 read!(read_cva, cells::CvA, RdCvA);
205 read!(read_cvb, cells::CvB, RdCvB);
206 read!(read_cvc, cells::CvC, RdCvC);
207 read!(read_cvd, cells::CvD, RdCvD);
208 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
209 read!(read_cve, cells::CvE, RdCvE);
210 #[cfg(feature = "ltc6813")]
211 read!(read_cvf, cells::CvF, RdCvF);
212 read!(read_auxa, auxreg::AuxA, RdAuxA);
213 read!(read_auxb, auxreg::AuxB, RdAuxB);
214 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
215 read!(read_auxc, auxreg::AuxC, RdAuxC);
216 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
217 read!(read_auxd, auxreg::AuxD, RdAuxD);
218
219 async fn write_cfga(&mut self, reg: [cfga::CfgA; NUM_OF_DEVICES]) -> Result<(), Self::Error> {
221 self.driver.enable_cs();
222 Self::convert_error(self.send_cmd(&command::WrCfgA::default()).await)?;
223 for item in reg.into_iter().take(NUM_OF_DEVICES) {
224 let ret = self.driver.write_register(item.into()).await;
225 Self::convert_error(self.handle_ret(ret))?;
226 }
227 self.driver.disable_cs();
228 Ok(())
229 }
230 async fn write_cfgb(&mut self, reg: [cfgb::CfgB; NUM_OF_DEVICES]) -> Result<(), Self::Error> {
232 self.driver.enable_cs();
233 Self::convert_error(self.send_cmd(&command::WrCfgB::default()).await)?;
234 for item in reg.into_iter().take(NUM_OF_DEVICES) {
235 let ret = self.driver.write_register(item.into()).await;
236 Self::convert_error(self.handle_ret(ret))?;
237 }
238 self.driver.disable_cs();
239 Ok(())
240 }
241
242 async fn convert_cells(
244 &mut self,
245 cmd: command::Adcv,
246 ) -> Result<[CellRegisters; NUM_OF_DEVICES], Self::Error> {
247 Self::convert_error(self.convert(&cmd).await)?;
248
249 let cva = self.read_cva().await?;
250 let cvb = self.read_cvb().await?;
251 let cvc = self.read_cvc().await?;
252 let cvd = self.read_cvd().await?;
253 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
254 let cve = self.read_cve().await?;
255 #[cfg(feature = "ltc6813")]
256 let cvf = self.read_cvf().await?;
257 let mut ret: [CellRegisters; NUM_OF_DEVICES] = [CellRegisters::default(); NUM_OF_DEVICES];
258 for i in 0..NUM_OF_DEVICES {
259 ret[i] = CellRegisters::new(
260 cva[i],
261 cvb[i],
262 cvc[i],
263 cvd[i],
264 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
265 cve[i],
266 #[cfg(feature = "ltc6813")]
267 cvf[i],
268 );
269 }
270 Ok(ret)
271 }
272
273 async fn convert_gpios(
275 &mut self,
276 cmd: command::Adax,
277 ) -> Result<[AuxRegisters; NUM_OF_DEVICES], Self::Error> {
278 Self::convert_error(self.convert(&cmd).await)?;
279
280 let auxa = self.read_auxa().await?;
281 let auxb = self.read_auxb().await?;
282 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
283 let auxc = self.read_auxc().await?;
284 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
285 let auxd = self.read_auxd().await?;
286 let mut ret: [AuxRegisters; NUM_OF_DEVICES] = [AuxRegisters::default(); NUM_OF_DEVICES];
287 for i in 0..NUM_OF_DEVICES {
288 ret[i] = AuxRegisters::new(
289 auxa[i],
290 auxb[i],
291 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
292 auxc[i],
293 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
294 auxd[i],
295 );
296 }
297 Ok(ret)
298 }
299 async fn perform_overlap_tests(&mut self, cmd: command::Adol) -> Result<(), Error<DRIVER>> {
301 const ALLOWED_DEVIATION_DIGITS: u16 = 100; Self::convert_error(self.convert(&cmd).await)?;
304 let cvc = self.read_cvc().await?;
306
307 for (i, item) in cvc.iter().enumerate().take(NUM_OF_DEVICES) {
308 if item
309 .get_cell_7_voltage()
310 .abs_diff(cvc[i].get_cell_8_voltage())
311 .ge(&ALLOWED_DEVIATION_DIGITS)
312 {
313 return Err(Error::DeviceError(DeviceErrorInfo {
314 err: error::DeviceErrorKind::Overlap,
315 device_index: i,
316 }));
317 }
318 #[cfg(any(feature = "ltc6812", feature = "ltc6813"))]
319 {
320 let cve = self.read_cve().await?;
321 for (i, item) in cve.iter().enumerate().take(NUM_OF_DEVICES) {
322 if item
323 .get_cell_13_voltage()
324 .abs_diff(item.get_cell_14_voltage())
325 >= ALLOWED_DEVIATION_DIGITS
326 {
327 return Err(Error::DeviceError(DeviceErrorInfo {
328 err: error::DeviceErrorKind::Overlap,
329 device_index: i,
330 }));
331 }
332 }
333 }
334 }
335 Ok(())
336 }
337
338 async fn perform_accuracy_check(
340 &mut self,
341 conv_setting: command::MDSetting,
342 ) -> Result<(), Error<DRIVER>> {
343 const VREF_ALLOWED_UPPER_BOUND: u16 = 30140;
345 const VREF_ALLOWED_LOWER_BOUND: u16 = 29900;
346
347 Self::convert_error(
348 self.convert(
349 &command::Adax::default()
350 .set_md_option(conv_setting)
351 .set_channel_config(command::GpioChannelConfig::ScndRef),
352 )
353 .await,
354 )?;
355 let auxb = self.read_auxb().await?;
356 for (i, item) in auxb.iter().enumerate().take(NUM_OF_DEVICES) {
357 let vref = item.get_vref_voltage();
358 if !(VREF_ALLOWED_LOWER_BOUND..=VREF_ALLOWED_UPPER_BOUND).contains(&vref) {
359 let err_desc = DeviceErrorInfo {
360 err: error::DeviceErrorKind::AccuracyFailed,
361 device_index: i,
362 };
363 return Err(Error::DeviceError(err_desc));
364 }
365 }
366 Ok(())
367 }
368 async fn convert_cells_and_gpios(
370 &mut self,
371 cmd_cells: command::Adcv,
372 cmd_gpios: command::Adax,
373 ) -> Result<
374 (
375 [CellRegisters; NUM_OF_DEVICES],
376 [AuxRegisters; NUM_OF_DEVICES],
377 ),
378 Self::Error,
379 > {
380 Ok((
381 self.convert_cells(cmd_cells).await?,
382 self.convert_gpios(cmd_gpios).await?,
383 ))
384 }
385 async fn wake(&mut self) -> Result<(), Self::Error> {
387 for _i in 0..NUM_OF_DEVICES {
388 self.driver.enable_cs();
389 let ret = self.driver.wake(12).await;
391 Self::convert_error(self.handle_ret(ret))?;
392 self.driver.disable_cs();
393 }
394 Ok(())
395 }
396}
397#[derive(Debug)]
399pub struct Ltc681x<DRIVER: Driver, const NUM_OF_DEVICES: usize> {
400 driver: DRIVER,
401}
402
403impl<DRIVER: Driver, const NUM_OF_DEVICES: usize> Ltc681x<DRIVER, NUM_OF_DEVICES> {
404 async fn send_cmd(&mut self, cmd: &dyn command::IsCmd) -> Result<(), DRIVER::ErrorType> {
406 if let Err(err) = self.driver.send_cmd(cmd).await {
407 self.driver.disable_cs();
408 Err(err)
409 } else {
410 Ok(())
411 }
412 }
413 async fn convert(&mut self, cmd: &dyn command::IsCmd) -> Result<(), DRIVER::ErrorType> {
414 self.driver.enable_cs();
415 self.send_cmd(cmd).await?;
416 self.driver.disable_cs();
417 Ok(())
418 }
419 pub fn new(driver: DRIVER) -> Self {
421 Self { driver }
422 }
423
424 fn handle_ret(
425 &mut self,
426 ret: Result<(), <DRIVER as Driver>::ErrorType>,
427 ) -> Result<(), DRIVER::ErrorType> {
428 if let Err(err) = ret {
429 self.driver.disable_cs();
430 Err(err)
431 } else {
432 Ok(())
433 }
434 }
435 fn convert_error<T>(drv_err: Result<T, DRIVER::ErrorType>) -> Result<T, Error<DRIVER>> {
436 match drv_err {
437 Ok(x) => Ok(x),
438 Err(err) => Err(Error::DriverError(err)),
439 }
440 }
441}