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;