drv8301_dd/
lib.rs

1#![cfg_attr(not(any(test, feature = "std")), no_std)]
2//! # DRV8301 Gate Driver Interface
3//!
4//! This crate provides a bisync-based driver for the DRV8301 three-phase gate driver IC,
5//! built upon the `device-driver` crate for robust, declarative register
6//! definitions via a YAML manifest. It supports both asynchronous (`async`)
7//! and blocking operation through a unified API, using the [`bisync`](https://docs.rs/bisync) crate
8//! for seamless compatibility with both `embedded-hal` and `embedded-hal-async` traits.
9//!
10//! ## Features
11//!
12//! *   **Declarative Register Map:** Full device configuration defined in `device.yaml`.
13//! *   **Unified Async/Blocking Support:** Write your code once and use it in both async and blocking contexts via bisync.
14//! *   **Type-Safe API:** High-level functions for common operations (e.g., setting overcurrent thresholds)
15//!     and a generated low-level API (`ll`) for direct register access.
16//! *   **Comprehensive Register Coverage:** Supports the full feature set of the DRV8301.
17//! *   **`defmt` and `log` Integration:** Optional support for logging and debugging.
18//!
19//! ## Getting Started
20//!
21//! To use the driver, instantiate `Drv8301` (blocking) or `Drv8301Async` (async) with your SPI bus implementation:
22//!
23//! ```rust,no_run
24//! # use embedded_hal::spi::SpiDevice;
25//! # use drv8301_dd::Drv8301;
26//! let spi_device = todo!();
27//! let mut drv = Drv8301::new(spi_device);
28//!
29//! // Check for faults
30//! let has_fault = drv.has_fault()?;
31//! # Ok::<(), drv8301_dd::DrvError<()>>(())
32//! ```
33//!
34//! For async environments, use `Drv8301Async` (re-exported from the `asynchronous` module):
35//!
36//! ```rust,no_run
37//! # use embedded_hal_async::spi::SpiDevice;
38//! # use drv8301_dd::Drv8301Async;
39//! let spi_device = todo!();
40//! let mut drv = Drv8301Async::new(spi_device);
41//!
42//! // Check for faults
43//! let has_fault = drv.has_fault().await?;
44//! # Ok::<(), drv8301_dd::DrvError<()>>(())
45//! ```
46//!
47//! For a detailed register map, please refer to the `device.yaml` file in the
48//! [repository](https://github.com/okhsunrog/drv8301-dd).
49//!
50//! ## Warning!
51//!
52//! ***Caution!*** This chip controls power FETs that can handle high voltages and currents.
53//! Incorrect configuration can potentially damage FETs, motors, or other components.
54//! Proceed with care and always consult the DRV8301 datasheet.
55
56#[macro_use]
57pub(crate) mod fmt;
58
59use thiserror::Error;
60
61device_driver::create_device!(device_name: DrvLowLevel, manifest: "device.yaml");
62
63#[derive(Debug, Error)]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65pub enum DrvError<SpiErr> {
66    #[error("SPI error")]
67    Spi(SpiErr),
68    #[error("SPI frame error detected in response")]
69    FrameError,
70    #[error("Feature or specific mode not supported/implemented: {0}")]
71    NotSupported(&'static str),
72}
73
74/// Complete fault status from both DRV8301 status registers
75///
76/// This struct provides a comprehensive view of all fault conditions
77/// reported by the DRV8301 gate driver IC.
78#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
79#[cfg_attr(feature = "defmt", derive(defmt::Format))]
80pub struct FaultStatus {
81    /// Master fault indicator (OR of all fault conditions)
82    pub fault: bool,
83    /// GVDD undervoltage fault (GVDD < ~8V)
84    pub gvdd_uv: bool,
85    /// GVDD overvoltage fault (GVDD > ~16V)
86    pub gvdd_ov: bool,
87    /// PVDD undervoltage fault (PVDD < ~5.9V)
88    pub pvdd_uv: bool,
89    /// Overtemperature shutdown (die temp > ~150°C)
90    pub otsd: bool,
91    /// Overtemperature warning (die temp > ~130°C)
92    pub otw: bool,
93    /// Phase A high-side FET overcurrent
94    pub fetha_oc: bool,
95    /// Phase A low-side FET overcurrent
96    pub fetla_oc: bool,
97    /// Phase B high-side FET overcurrent
98    pub fethb_oc: bool,
99    /// Phase B low-side FET overcurrent
100    pub fetlb_oc: bool,
101    /// Phase C high-side FET overcurrent
102    pub fethc_oc: bool,
103    /// Phase C low-side FET overcurrent
104    pub fetlc_oc: bool,
105}
106
107impl FaultStatus {
108    /// Returns true if any overcurrent fault is active on any phase
109    pub fn has_overcurrent(&self) -> bool {
110        self.fetha_oc
111            || self.fetla_oc
112            || self.fethb_oc
113            || self.fetlb_oc
114            || self.fethc_oc
115            || self.fetlc_oc
116    }
117
118    /// Returns true if any thermal condition (warning or shutdown) is active
119    pub fn has_thermal(&self) -> bool {
120        self.otsd || self.otw
121    }
122
123    /// Returns true if any voltage fault (UV or OV) is active
124    pub fn has_voltage_fault(&self) -> bool {
125        self.gvdd_uv || self.gvdd_ov || self.pvdd_uv
126    }
127
128    /// Returns true if no faults are active
129    pub fn is_ok(&self) -> bool {
130        !self.fault
131    }
132
133    /// Returns true if any phase A FET has an overcurrent fault
134    pub fn phase_a_overcurrent(&self) -> bool {
135        self.fetha_oc || self.fetla_oc
136    }
137
138    /// Returns true if any phase B FET has an overcurrent fault
139    pub fn phase_b_overcurrent(&self) -> bool {
140        self.fethb_oc || self.fetlb_oc
141    }
142
143    /// Returns true if any phase C FET has an overcurrent fault
144    pub fn phase_c_overcurrent(&self) -> bool {
145        self.fethc_oc || self.fetlc_oc
146    }
147}
148
149pub struct DrvInterface<SpiBus> {
150    spi_bus: SpiBus,
151}
152
153impl<SpiBus> DrvInterface<SpiBus> {
154    pub fn new(spi_bus: SpiBus) -> Self {
155        Self { spi_bus }
156    }
157}
158
159#[path = "."]
160mod asynchronous {
161    use bisync::asynchronous::*;
162    use device_driver::AsyncRegisterInterface as RegisterInterface;
163    use embedded_hal_async::spi::SpiDevice;
164    mod driver;
165    pub use driver::*;
166}
167pub use asynchronous::Drv8301 as Drv8301Async;
168
169#[path = "."]
170mod blocking {
171    use bisync::synchronous::*;
172    use device_driver::RegisterInterface;
173    use embedded_hal::spi::SpiDevice;
174    #[allow(clippy::duplicate_mod)]
175    mod driver;
176    pub use driver::*;
177}
178pub use blocking::Drv8301;