async_ltc681x/driver/
communication.rs1use super::registers::base::RegisterBlock;
2use super::{
3 adi_isospi_pec::{calc_pec, cmd_calc_pec},
4 command::IsCmd,
5};
6use embedded_hal::digital::{InputPin, OutputPin};
7use embedded_hal_async::spi::SpiBus;
8
9pub struct Ltc681xSpi<SPI: SpiBus, CS: OutputPin, MISO: InputPin> {
11 spi_hdl: SPI,
12 cs: CS,
13 miso_pin: MISO,
14}
15
16#[derive(Debug, Copy, Clone)]
18pub enum Error<SPI: SpiBus> {
19 PecError,
21 SpiError(SPI::Error),
23}
24impl<SPI: SpiBus, CS: OutputPin, MISO: InputPin> super::Driver for Ltc681xSpi<SPI, CS, MISO> {
25 type ErrorType = Error<SPI>;
26
27 async fn send_cmd(&mut self, cmd: &dyn IsCmd) -> Result<(), Error<SPI>> {
28 self.send_cmd_internal(cmd.as_cmd_header(), cmd.has_poll_status())
29 .await
30 }
31 async fn wake(&mut self, nr_of_bytes: usize) -> Result<(), Error<SPI>> {
32 for _i in 0..nr_of_bytes {
33 self.write_byte().await?;
34 }
35 Ok(())
36 }
37 async fn write_register(&mut self, payload: RegisterBlock) -> Result<(), Error<SPI>> {
38 let mut buf = get_write_buffer(payload);
39 self.transfer(&mut buf).await?;
40 Ok(())
42 }
43
44 async fn read_register(&mut self) -> Result<RegisterBlock, Error<SPI>> {
45 let mut buf = [0; 8];
46 self.transfer(&mut buf).await?;
47 Self::get_payload_from_buffer(&buf)
48 }
49 async fn drive_stcomm(&mut self) -> Result<(), Self::ErrorType> {
50 unimplemented!()
51 }
52 fn enable_cs(&mut self) {
53 self.cs.set_low().unwrap_or_default();
54 }
55 fn disable_cs(&mut self) {
56 self.cs.set_high().unwrap_or_default();
57 }
58}
59
60impl<SPI: SpiBus, CS: OutputPin, MISO: InputPin> Ltc681xSpi<SPI, CS, MISO> {
61 pub fn new(spi: SPI, mut cs: CS, miso: MISO) -> Self {
68 cs.set_high().unwrap_or_default();
70 Self {
71 spi_hdl: spi,
72 cs,
73 miso_pin: miso,
74 }
75 }
76
77 async fn send_cmd_internal(&mut self, cmd: u16, with_poll: bool) -> Result<(), Error<SPI>> {
78 let mut buf = get_cmd_buffer(cmd);
79 self.transfer(&mut buf).await?;
80 if with_poll {
81 self.poll().await?;
82 }
83 Ok(())
84 }
85 async fn transfer(&mut self, buffer: &mut [u8]) -> Result<(), Error<SPI>> {
90 match self.spi_hdl.transfer_in_place(buffer).await {
91 Ok(()) => Ok(()),
92 Err(err) => Err(Error::SpiError(err)),
93 }
94 }
95 async fn write_byte(&mut self) -> Result<(), Error<SPI>> {
96 let mut buf = [0xFF; 1];
97 self.transfer(&mut buf).await?;
98 Ok(())
99 }
100 async fn poll(&mut self) -> Result<(), Error<SPI>> {
101 self.write_byte().await?;
102 loop {
103 if let Ok(is_high) = self.miso_pin.is_high() {
104 if is_high {
105 break;
106 }
107 }
108 self.write_byte().await?;
109 #[cfg(test)]
112 embassy_futures::yield_now().await;
113 }
114 Ok(())
115 }
116 fn get_payload_from_buffer(buf: &[u8]) -> Result<RegisterBlock, Error<SPI>> {
117 let pec = u16::from_be_bytes([buf[6], buf[7]]);
118 if pec != calc_pec(&buf[0..=5]) {
119 return Err(Error::PecError);
120 }
121 Ok(RegisterBlock {
122 reg_1: u16::from_le_bytes([buf[0], buf[1]]),
123 reg_2: u16::from_le_bytes([buf[2], buf[3]]),
124 reg_3: u16::from_le_bytes([buf[4], buf[5]]),
125 })
126 }
127}
128
129pub(crate) fn get_write_buffer(reg: RegisterBlock) -> [u8; 8] {
130 let mut buf = [0; 8];
131 copy_payload_to_buffer(reg, &mut buf);
132 buf
133}
134fn get_cmd_buffer(write_cmd: u16) -> [u8; 4] {
135 let mut buf = [0; 4];
136 copy_cmd_to_buffer(write_cmd, &mut buf);
137 buf
138}
139pub(crate) fn copy_cmd_to_buffer(cmd: u16, buf: &mut [u8]) {
140 let pec = cmd_calc_pec(cmd).to_be_bytes();
141 let cmd = cmd.to_be_bytes();
142 buf[0] = cmd[0];
143 buf[1] = cmd[1];
144 buf[2] = pec[0];
145 buf[3] = pec[1];
146}
147fn copy_payload_to_buffer(reg: RegisterBlock, buf: &mut [u8]) {
148 let reg_1 = reg.reg_1.to_le_bytes();
149 let reg_2 = reg.reg_2.to_le_bytes();
150 let reg_3 = reg.reg_3.to_le_bytes();
151
152 buf[0] = reg_1[0];
153 buf[1] = reg_1[1];
154 buf[2] = reg_2[0];
155 buf[3] = reg_2[1];
156 buf[4] = reg_3[0];
157 buf[5] = reg_3[1];
158 let pec = calc_pec(&buf[0..=5]).to_be_bytes();
159 buf[6] = pec[0];
160 buf[7] = pec[1];
161}