drv8301_dd/
driver.rs

1use super::{RegisterInterface, SpiDevice, bisync, only_async, only_sync};
2use crate::{DrvError, DrvInterface, DrvLowLevel, FaultStatus};
3use crate::{GateCurrent, OcAdjSet, OcpMode, OctwMode, ShuntAmplifierGain};
4
5#[bisync]
6impl<SpiBus, E> RegisterInterface for DrvInterface<SpiBus>
7where
8    SpiBus: SpiDevice<Error = E>,
9    E: core::fmt::Debug,
10{
11    type AddressType = u8;
12    type Error = DrvError<E>;
13
14    async fn read_register(
15        &mut self,
16        address: u8,
17        _size_bits: u32,
18        data: &mut [u8],
19    ) -> Result<(), Self::Error> {
20        // Build read command: bit 15 = 1 (read), bits 14:11 = address, bits 10:0 = don't care
21        let cmd: u16 = 0x8000 | ((address as u16 & 0x0F) << 11);
22        let cmd_bytes = cmd.to_be_bytes();
23
24        // First transaction: send read command
25        let mut response_bytes = [0u8; 2];
26        self.spi_bus
27            .transfer(&mut response_bytes, &cmd_bytes)
28            .await
29            .map_err(DrvError::Spi)?;
30
31        // Second transaction: send same command to get actual data (N+1 timing)
32        let mut read_response = [0u8; 2];
33        self.spi_bus
34            .transfer(&mut read_response, &cmd_bytes)
35            .await
36            .map_err(DrvError::Spi)?;
37
38        let response = u16::from_be_bytes(read_response);
39
40        // Check for frame error (bit 15 = 1 in response)
41        if (response & 0x8000) != 0 {
42            return Err(DrvError::FrameError);
43        }
44
45        // Extract 11-bit data and store in output buffer (big-endian)
46        let reg_data = response & 0x07FF;
47        if data.len() >= 2 {
48            data[0] = (reg_data >> 8) as u8;
49            data[1] = reg_data as u8;
50        }
51
52        Ok(())
53    }
54
55    async fn write_register(
56        &mut self,
57        address: u8,
58        _size_bits: u32,
59        data: &[u8],
60    ) -> Result<(), Self::Error> {
61        // Extract 11-bit data from buffer (big-endian)
62        let reg_data = if data.len() >= 2 {
63            ((data[0] as u16) << 8) | (data[1] as u16)
64        } else if data.len() == 1 {
65            data[0] as u16
66        } else {
67            0
68        };
69
70        // Build write command: bit 15 = 0 (write), bits 14:11 = address, bits 10:0 = data
71        let cmd: u16 = ((address as u16 & 0x0F) << 11) | (reg_data & 0x07FF);
72        let cmd_bytes = cmd.to_be_bytes();
73
74        // Execute write transaction
75        let mut response_bytes = [0u8; 2];
76        self.spi_bus
77            .transfer(&mut response_bytes, &cmd_bytes)
78            .await
79            .map_err(DrvError::Spi)?;
80
81        Ok(())
82    }
83}
84
85pub struct Drv8301<
86    SpiImpl: RegisterInterface<AddressType = u8, Error = DrvError<SpiBusErr>>,
87    SpiBusErr: core::fmt::Debug = <SpiImpl as RegisterInterface>::Error,
88> {
89    pub ll: DrvLowLevel<SpiImpl>,
90    _marker: core::marker::PhantomData<SpiBusErr>,
91}
92
93impl<SpiBus, E> Drv8301<DrvInterface<SpiBus>, E>
94where
95    SpiBus: SpiDevice<Error = E>,
96    E: core::fmt::Debug,
97{
98    pub fn new(spi: SpiBus) -> Self {
99        Self {
100            ll: DrvLowLevel::new(DrvInterface::new(spi)),
101            _marker: core::marker::PhantomData,
102        }
103    }
104}
105
106pub trait CurrentDrvDriverInterface<E>:
107    RegisterInterface<AddressType = u8, Error = DrvError<E>>
108{
109}
110
111impl<T, E> CurrentDrvDriverInterface<E> for T
112where
113    T: RegisterInterface<AddressType = u8, Error = DrvError<E>>,
114    E: core::fmt::Debug,
115{
116}
117
118include!("bisync_helpers.rs");
119
120impl<SpiImpl, SpiBusErr> Drv8301<SpiImpl, SpiBusErr>
121where
122    SpiImpl: CurrentDrvDriverInterface<SpiBusErr>,
123    SpiBusErr: core::fmt::Debug,
124{
125    /// Check if any fault condition is active
126    #[bisync]
127    pub async fn has_fault(&mut self) -> Result<bool, DrvError<SpiBusErr>> {
128        let mut op = self.ll.status_register_1();
129        let status = read_internal(&mut op).await?;
130        Ok(status.fault())
131    }
132
133    /// Get device ID from Status Register 2
134    #[bisync]
135    pub async fn get_device_id(&mut self) -> Result<u8, DrvError<SpiBusErr>> {
136        let mut op = self.ll.status_register_2();
137        let status = read_internal(&mut op).await?;
138        Ok(status.device_id())
139    }
140
141    /// Get complete fault status from both status registers
142    ///
143    /// Returns a [`FaultStatus`] struct containing all fault flags from the DRV8301.
144    /// This includes voltage faults, thermal conditions, and per-phase overcurrent status.
145    ///
146    /// # Example
147    /// ```rust,no_run
148    /// # use drv8301_dd::Drv8301;
149    /// # let spi = todo!();
150    /// # let mut drv = Drv8301::new(spi);
151    /// let status = drv.get_fault_status()?;
152    /// if status.has_overcurrent() {
153    ///     // Handle overcurrent condition
154    /// }
155    /// if status.phase_a_overcurrent() {
156    ///     // Phase A specific handling
157    /// }
158    /// # Ok::<(), drv8301_dd::DrvError<()>>(())
159    /// ```
160    #[bisync]
161    pub async fn get_fault_status(&mut self) -> Result<FaultStatus, DrvError<SpiBusErr>> {
162        let mut op1 = self.ll.status_register_1();
163        let status1 = read_internal(&mut op1).await?;
164
165        let mut op2 = self.ll.status_register_2();
166        let status2 = read_internal(&mut op2).await?;
167
168        Ok(FaultStatus {
169            fault: status1.fault(),
170            gvdd_uv: status1.gvdd_uv(),
171            gvdd_ov: status2.gvdd_ov(),
172            pvdd_uv: status1.pvdd_uv(),
173            otsd: status1.otsd(),
174            otw: status1.otw(),
175            fetha_oc: status1.fetha_oc(),
176            fetla_oc: status1.fetla_oc(),
177            fethb_oc: status1.fethb_oc(),
178            fetlb_oc: status1.fetlb_oc(),
179            fethc_oc: status1.fethc_oc(),
180            fetlc_oc: status1.fetlc_oc(),
181        })
182    }
183
184    /// Set the overcurrent (VDS) threshold
185    #[bisync]
186    pub async fn set_oc_threshold(
187        &mut self,
188        threshold: OcAdjSet,
189    ) -> Result<(), DrvError<SpiBusErr>> {
190        let mut op = self.ll.control_register_1();
191        modify_internal(&mut op, |r| r.set_oc_adj_set(threshold)).await
192    }
193
194    /// Set the overcurrent protection mode
195    #[bisync]
196    pub async fn set_ocp_mode(&mut self, mode: OcpMode) -> Result<(), DrvError<SpiBusErr>> {
197        let mut op = self.ll.control_register_1();
198        modify_internal(&mut op, |r| r.set_ocp_mode(mode)).await
199    }
200
201    /// Set PWM mode (6-PWM or 3-PWM)
202    #[bisync]
203    pub async fn set_pwm_mode(&mut self, three_pwm: bool) -> Result<(), DrvError<SpiBusErr>> {
204        let mut op = self.ll.control_register_1();
205        modify_internal(&mut op, |r| r.set_pwm_mode(three_pwm)).await
206    }
207
208    /// Reset gate driver faults
209    #[bisync]
210    pub async fn reset_gate_faults(&mut self) -> Result<(), DrvError<SpiBusErr>> {
211        let mut op = self.ll.control_register_1();
212        modify_internal(&mut op, |r| r.set_gate_reset(true)).await
213    }
214
215    /// Set the peak gate drive current
216    #[bisync]
217    pub async fn set_gate_current(
218        &mut self,
219        current: GateCurrent,
220    ) -> Result<(), DrvError<SpiBusErr>> {
221        let mut op = self.ll.control_register_1();
222        modify_internal(&mut op, |r| r.set_gate_current(current)).await
223    }
224
225    /// Set the current shunt amplifier gain
226    #[bisync]
227    pub async fn set_shunt_amplifier_gain(
228        &mut self,
229        gain: ShuntAmplifierGain,
230    ) -> Result<(), DrvError<SpiBusErr>> {
231        let mut op = self.ll.control_register_2();
232        modify_internal(&mut op, |r| r.set_gain(gain)).await
233    }
234
235    /// Set the nOCTW pin reporting mode
236    #[bisync]
237    pub async fn set_octw_mode(&mut self, mode: OctwMode) -> Result<(), DrvError<SpiBusErr>> {
238        let mut op = self.ll.control_register_2();
239        modify_internal(&mut op, |r| r.set_octw_mode(mode)).await
240    }
241
242    /// Enable or disable DC calibration mode for shunt amplifier channel 1
243    #[bisync]
244    pub async fn set_dc_cal_ch1(&mut self, enable: bool) -> Result<(), DrvError<SpiBusErr>> {
245        let mut op = self.ll.control_register_2();
246        modify_internal(&mut op, |r| r.set_dc_cal_ch1(enable)).await
247    }
248
249    /// Enable or disable DC calibration mode for shunt amplifier channel 2
250    #[bisync]
251    pub async fn set_dc_cal_ch2(&mut self, enable: bool) -> Result<(), DrvError<SpiBusErr>> {
252        let mut op = self.ll.control_register_2();
253        modify_internal(&mut op, |r| r.set_dc_cal_ch2(enable)).await
254    }
255
256    /// Set overcurrent off-time control mode
257    #[bisync]
258    pub async fn set_oc_toff(&mut self, off_time_control: bool) -> Result<(), DrvError<SpiBusErr>> {
259        let mut op = self.ll.control_register_2();
260        modify_internal(&mut op, |r| r.set_oc_toff(off_time_control)).await
261    }
262}