1use core::fmt::Debug;
6
7use embedded_hal::i2c;
8use log::trace;
9
10use crate::device::*;
11use crate::Error;
12
13pub trait Base<Err> {
16 fn write_command(&mut self, command: Command, data: Option<u16>) -> Result<(), Error<Err>>;
18 fn read_command(&mut self, command: Command, data: &mut [u8]) -> Result<(), Error<Err>>;
20}
21
22pub fn crc8(data: &[u8]) -> u8 {
24 let mut crc = CRC_INIT;
25
26 for v in data {
28 crc ^= v;
30
31 for _bit in 0..8 {
33 if crc & 0x80 != 0 {
34 crc = (crc << 1) ^ CRC_POLY;
35 } else {
36 crc = crc << 1;
37 }
38 }
39 }
40
41 crc ^ CRC_XOR
43}
44
45impl<Conn, Err> Base<Err> for Conn
47where
48 Conn: i2c::I2c<Error = Err>,
49 Err: Debug,
50{
51 fn write_command(&mut self, command: Command, data: Option<u16>) -> Result<(), Error<Err>> {
52 let c = command as u16;
53
54 let mut buff: [u8; 5] = [(c >> 8) as u8, (c & 0xFF) as u8, 0, 0, 0];
55
56 let len = match data {
57 Some(d) => {
58 buff[2] = (d >> 8) as u8;
59 buff[3] = (d & 0xFF) as u8;
60 buff[4] = crc8(&buff[2..4]);
61 5
62 }
63 None => 2,
64 };
65
66 trace!("Writing command: {:?} data: {:?}", c, data);
67
68 self.write(DEFAULT_ADDRESS | I2C_WRITE_FLAG, &buff[..len])
69 .map_err(|e| Error::Conn(e))
70 }
71
72 fn read_command(&mut self, command: Command, data: &mut [u8]) -> Result<(), Error<Err>> {
73 let c = command as u16;
75 let cmd = [(c >> 8) as u8, (c & 0xFF) as u8];
76
77 trace!("Writing command: {:x?}", cmd);
78
79 self.write(DEFAULT_ADDRESS | I2C_WRITE_FLAG, &cmd)
81 .map_err(|e| Error::Conn(e))?;
82
83 self.read(DEFAULT_ADDRESS | I2C_READ_FLAG, data)
85 .map_err(|e| Error::Conn(e))?;
86
87 trace!("Read data: {:x?}", data);
90
91 Ok(())
92 }
93}
94
95#[cfg(test)]
96mod test {
97 use super::*;
98
99 #[test]
100 fn test_crc() {
101 let tests = &[
103 ([0xbe, 0xef], 0x92),
104 ([0x00, 0x00], 0x81),
105 ([0x43, 0xDB], 0xCB),
106 ];
107
108 for t in tests {
109 let v = crc8(&t.0);
110 assert_eq!(v, t.1);
111 }
112 }
113}