axp2101_dd/
lib.rs

1#![cfg_attr(not(any(test, feature = "std")), no_std)]
2//! # AXP2101 Power Management Chip Interface
3//!
4//! This crate provides a bisync-based driver for the AXP2101 power management 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 voltages)
15//!     and a generated low-level API (`ll`) for direct register access.
16//! *   **Comprehensive Register Coverage:** Aims to support the full feature set of the AXP2101.
17//! *   **`defmt` and `log` Integration:** Optional support for logging and debugging.
18//!
19//! ## Getting Started
20//!
21//! To use the driver, instantiate `Axp2101` (blocking) or `Axp2101Async` (async) with your I2C bus implementation:
22//!
23//! ```rust,no_run
24//! # use embedded_hal::i2c::I2c;
25//! # use axp2101_dd::{Axp2101, DcId};
26//! let i2c_bus = todo!();
27//! let mut axp = Axp2101::new(i2c_bus);
28//!
29//! axp.set_dcdc_voltage(DcId::Dcdc1, 3300)?;
30//! # Ok(())
31//! ```
32//!
33//! For async environments, use `Axp2101Async` (re-exported from the `asynchronous` module):
34//!
35//! ```rust,no_run
36//! # use embedded_hal_async::i2c::I2c;
37//! # use axp2101_dd::{Axp2101Async, DcId};
38//! let i2c_bus = todo!();
39//! let mut axp = Axp2101Async::new(i2c_bus);
40//!
41//! axp.set_dcdc_voltage(DcId::Dcdc1, 3300).await?;
42//! # Ok(())
43//! ```
44//!
45//! For a detailed register map, please refer to the `device.yaml` file in the
46//! [repository](https://github.com/okhsunrog/axp2101-dd).
47//!
48//! ## Supported Devices
49//!
50//! The AXP2101 is found in various embedded devices and development boards.
51//!
52//! ## Warning!
53//!
54//! ***Caution!*** This chip controls power to the microcontroller and other critical
55//! components. Incorrect configuration can potentially damage or brick your device.
56//! Proceed with care and always consult the AXP2101 datasheet.
57//!
58
59#[macro_use]
60pub(crate) mod fmt;
61mod adc_helpers;
62
63use thiserror::Error;
64
65device_driver::create_device!(device_name: AxpLowLevel, manifest: "device.yaml");
66pub const AXP2101_I2C_ADDRESS: u8 = 0x34;
67
68#[derive(Debug, Error)]
69#[cfg_attr(feature = "defmt", derive(defmt::Format))]
70pub enum AxpError<I2cErr> {
71    #[error("I2C error")]
72    I2c(I2cErr),
73    #[error("Invalid voltage: {0}mV for setting")]
74    InvalidVoltage(u16),
75    #[error("Invalid current: {0}mA for setting")]
76    InvalidCurrent(u16),
77    #[error("Feature or specific mode not supported/implemented: {0}")]
78    NotSupported(&'static str),
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
82#[cfg_attr(feature = "defmt", derive(defmt::Format))]
83pub enum DcId {
84    Dcdc1,
85    Dcdc2,
86    Dcdc3,
87    Dcdc4,
88    Dcdc5,
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq)]
92#[cfg_attr(feature = "defmt", derive(defmt::Format))]
93pub enum LdoId {
94    Aldo1,
95    Aldo2,
96    Aldo3,
97    Aldo4,
98    Bldo1,
99    Bldo2,
100    Dldo1,
101    Dldo2,
102    Cpusldo,
103}
104
105/// ADC channels available on AXP2101
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))]
108pub enum AdcChannel {
109    /// Battery voltage measurement (VBAT)
110    BatteryVoltage,
111    /// TS pin measurement (temperature sensor)
112    TsPin,
113    /// VBUS voltage measurement
114    VbusVoltage,
115    /// System voltage measurement (VSYS)
116    VsysVoltage,
117    /// Die temperature measurement
118    DieTemperature,
119    /// General purpose ADC
120    Gpadc,
121}
122
123pub struct AxpInterface<I2CBus> {
124    i2c_bus: I2CBus,
125}
126
127impl<I2CBus> AxpInterface<I2CBus> {
128    pub fn new(i2c_bus: I2CBus) -> Self {
129        Self { i2c_bus }
130    }
131}
132
133#[path = "."]
134mod asynchronous {
135    use bisync::asynchronous::*;
136    use device_driver::AsyncRegisterInterface as RegisterInterface;
137    use embedded_hal_async::i2c::I2c;
138    mod driver;
139    pub use driver::*;
140}
141pub use asynchronous::Axp2101 as Axp2101Async;
142
143#[path = "."]
144mod blocking {
145    use bisync::synchronous::*;
146    use device_driver::RegisterInterface;
147    use embedded_hal::i2c::I2c;
148    #[allow(clippy::duplicate_mod)]
149    mod driver;
150    pub use driver::*;
151}
152pub use blocking::Axp2101;