omnitiles/drivers/
drv8873.rs1use crate::hw::{ChipSelect, SpiBus};
10use stm32f7xx_hal::spi;
11
12pub mod reg {
14 pub const FAULT: u8 = 0x00;
15 pub const DIAG: u8 = 0x01;
16 pub const IC1: u8 = 0x02;
17 pub const IC2: u8 = 0x03;
18 pub const IC3: u8 = 0x04;
19 pub const IC4: u8 = 0x05;
20}
21
22#[derive(Copy, Clone, Debug)]
24pub struct Status {
25 raw: u8,
26}
27
28impl Status {
29 #[inline]
30 pub fn raw(&self) -> u8 {
31 self.raw
32 }
33
34 #[inline]
36 pub fn otw(&self) -> bool {
37 (self.raw & (1 << 5)) != 0
38 }
39
40 #[inline]
42 pub fn uvlo(&self) -> bool {
43 (self.raw & (1 << 4)) != 0
44 }
45
46 #[inline]
48 pub fn cpuv(&self) -> bool {
49 (self.raw & (1 << 3)) != 0
50 }
51
52 #[inline]
54 pub fn ocp(&self) -> bool {
55 (self.raw & (1 << 2)) != 0
56 }
57
58 #[inline]
60 pub fn tsd(&self) -> bool {
61 (self.raw & (1 << 1)) != 0
62 }
63
64 #[inline]
66 pub fn old(&self) -> bool {
67 (self.raw & (1 << 0)) != 0
68 }
69}
70
71#[derive(Copy, Clone, Debug)]
73pub struct Fault {
74 raw: u8,
75}
76
77impl Fault {
78 #[inline]
79 pub fn raw(&self) -> u8 {
80 self.raw
81 }
82
83 #[inline]
85 pub fn fault(&self) -> bool {
86 (self.raw & (1 << 6)) != 0
87 }
88
89 #[inline]
91 pub fn otw(&self) -> bool {
92 (self.raw & (1 << 5)) != 0
93 }
94
95 #[inline]
97 pub fn uvlo(&self) -> bool {
98 (self.raw & (1 << 4)) != 0
99 }
100
101 #[inline]
103 pub fn cpuv(&self) -> bool {
104 (self.raw & (1 << 3)) != 0
105 }
106
107 #[inline]
109 pub fn ocp(&self) -> bool {
110 (self.raw & (1 << 2)) != 0
111 }
112
113 #[inline]
115 pub fn tsd(&self) -> bool {
116 (self.raw & (1 << 1)) != 0
117 }
118
119 #[inline]
121 pub fn old(&self) -> bool {
122 (self.raw & (1 << 0)) != 0
123 }
124}
125
126#[derive(Copy, Clone, Debug)]
128pub struct Diag {
129 raw: u8,
130}
131
132impl Diag {
133 #[inline]
134 pub fn raw(&self) -> u8 {
135 self.raw
136 }
137
138 #[inline]
140 pub fn ol1(&self) -> bool {
141 (self.raw & (1 << 7)) != 0
142 }
143
144 #[inline]
146 pub fn ol2(&self) -> bool {
147 (self.raw & (1 << 6)) != 0
148 }
149
150 #[inline]
154 pub fn itrip1(&self) -> bool {
155 (self.raw & (1 << 5)) != 0
156 }
157
158 #[inline]
162 pub fn itrip2(&self) -> bool {
163 (self.raw & (1 << 4)) != 0
164 }
165
166 #[inline]
168 pub fn ocp_h1(&self) -> bool {
169 (self.raw & (1 << 3)) != 0
170 }
171
172 #[inline]
174 pub fn ocp_l1(&self) -> bool {
175 (self.raw & (1 << 2)) != 0
176 }
177
178 #[inline]
180 pub fn ocp_h2(&self) -> bool {
181 (self.raw & (1 << 1)) != 0
182 }
183
184 #[inline]
186 pub fn ocp_l2(&self) -> bool {
187 (self.raw & 1) != 0
188 }
189}
190
191#[derive(Copy, Clone, Debug)]
195pub struct Response {
196 pub status: Status,
197 pub data: u8,
198}
199
200pub struct Drv8873<const P: char, const N: u8> {
205 cs: ChipSelect<P, N>,
206}
207
208impl<const P: char, const N: u8> Drv8873<P, N> {
209 pub fn new(cs: ChipSelect<P, N>) -> Self {
211 Self { cs }
212 }
213
214 pub fn free(self) -> ChipSelect<P, N> {
216 self.cs
217 }
218
219 #[inline]
224 fn build_word(is_read: bool, addr: u8, data: u8) -> u16 {
225 let mut word: u16 = 0;
226
227 if is_read {
230 word |= 1 << 14;
231 }
232
233 word |= ((addr as u16) & 0x1F) << 9;
235
236 word |= data as u16;
239
240 word
241 }
242
243 pub fn transfer_word<I, PINS>(
247 &mut self,
248 spi: &mut SpiBus<I, PINS>,
249 word: u16,
250 ) -> Result<Response, spi::Error>
251 where
252 I: spi::Instance,
253 PINS: spi::Pins<I>,
254 {
255 let mut buf = [(word >> 8) as u8, word as u8];
256
257 self.cs.select();
258 spi.transfer_in_place(&mut buf)?;
259 self.cs.deselect();
260
261 let status = Status { raw: buf[0] };
262 let data = buf[1];
263
264 Ok(Response { status, data })
265 }
266
267 pub fn write_reg<I, PINS>(
269 &mut self,
270 spi: &mut SpiBus<I, PINS>,
271 addr: u8,
272 value: u8,
273 ) -> Result<Response, spi::Error>
274 where
275 I: spi::Instance,
276 PINS: spi::Pins<I>,
277 {
278 let word = Self::build_word(false, addr, value);
279 self.transfer_word(spi, word)
280 }
281
282 pub fn read_reg<I, PINS>(
284 &mut self,
285 spi: &mut SpiBus<I, PINS>,
286 addr: u8,
287 ) -> Result<Response, spi::Error>
288 where
289 I: spi::Instance,
290 PINS: spi::Pins<I>,
291 {
292 let word = Self::build_word(true, addr, 0x00);
293 self.transfer_word(spi, word)
294 }
295
296 pub fn read_fault<I, PINS>(&mut self, spi: &mut SpiBus<I, PINS>) -> Result<Fault, spi::Error>
300 where
301 I: spi::Instance,
302 PINS: spi::Pins<I>,
303 {
304 Ok(Fault {
305 raw: self.read_reg(spi, reg::FAULT)?.data,
306 })
307 }
308
309 pub fn read_diag<I, PINS>(&mut self, spi: &mut SpiBus<I, PINS>) -> Result<Diag, spi::Error>
313 where
314 I: spi::Instance,
315 PINS: spi::Pins<I>,
316 {
317 Ok(Diag {
318 raw: self.read_reg(spi, reg::DIAG)?.data,
319 })
320 }
321}