bq2515x/
prelude.rs

1//! Strongly typed register values used by this crate.
2
3pub use crate::ll::registers::{
4    AdcReadRate, BuvloThreshold, IchargeRange, LdoSwitchConfig, PmidMode, PmidRegCtrl,
5};
6
7#[derive(Debug, PartialEq, PartialOrd, num_enum::IntoPrimitive, num_enum::FromPrimitive)]
8#[repr(u8)]
9pub enum AdcCompChannel {
10    #[num_enum(default)]
11    Disabled,
12    AdcIn,
13    TS,
14    VBat,
15    ICharge,
16    Vin,
17    PMid,
18    IIn,
19}
20
21#[derive(Debug, PartialEq, PartialOrd, num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
22#[repr(u8)]
23pub enum CurrentLimit {
24    _50mA = 0b000,
25    _100mA = 0b001,
26    _150mA = 0b010,
27    _200mA = 0b011,
28    _300mA = 0b100,
29    _400mA = 0b101,
30    _500mA = 0b110,
31    _600mA = 0b111,
32}
33
34#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
35pub struct Millivolts(pub u16);
36
37#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
38pub struct Milliampere(pub u16);
39
40#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
41#[cfg_attr(feature = "defmt", derive(defmt::Format))]
42pub struct RawVoltage<const MAX_MV: u16>(pub u16);
43
44#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
45#[cfg_attr(feature = "defmt", derive(defmt::Format))]
46pub struct IinCurrent {
47    pub raw: u16,
48    pub high_range: bool,
49}
50
51#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
52#[cfg_attr(feature = "defmt", derive(defmt::Format))]
53pub struct IChargePercentage(pub u16);
54
55#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, derive_more::From, derive_more::Into)]
56#[cfg_attr(feature = "defmt", derive(defmt::Format))]
57pub struct VBatRegulationVoltage(pub u8);
58
59#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, derive_more::From, derive_more::Into)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub struct FastChargeCurrent(pub u8);
62
63#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, derive_more::From, derive_more::Into)]
64#[cfg_attr(feature = "defmt", derive(defmt::Format))]
65pub struct LDOOutputVoltage(pub u8);
66
67#[inline(always)]
68fn scale_u16(x: u16, old_range: u16, new_range: u16) -> u16 {
69    (x as u32 * new_range as u32 / old_range as u32) as u16
70}
71
72impl<const MAX_MV: u16> From<RawVoltage<MAX_MV>> for Millivolts {
73    fn from(val: RawVoltage<MAX_MV>) -> Self {
74        Millivolts(scale_u16(val.0, u16::MAX, MAX_MV))
75    }
76}
77
78impl<const MAX_MV: u16> From<Millivolts> for RawVoltage<MAX_MV> {
79    fn from(val: Millivolts) -> Self {
80        RawVoltage(scale_u16(val.0, MAX_MV, u16::MAX))
81    }
82}
83
84impl From<VBatRegulationVoltage> for Millivolts {
85    fn from(value: VBatRegulationVoltage) -> Self {
86        let value: u16 = 3600 + value.0 as u16 * 10;
87        Millivolts(value.clamp(3600, 4600))
88    }
89}
90
91impl From<Millivolts> for VBatRegulationVoltage {
92    fn from(value: Millivolts) -> Self {
93        let value = value.0.clamp(3600, 4600);
94        let value = (value - 3600) / 10;
95        VBatRegulationVoltage(value as u8)
96    }
97}
98
99impl From<LDOOutputVoltage> for Millivolts {
100    fn from(value: LDOOutputVoltage) -> Self {
101        let value: u16 = 600 + value.0 as u16 * 100;
102        Millivolts(value.clamp(600, 3700))
103    }
104}
105
106impl From<Millivolts> for LDOOutputVoltage {
107    fn from(value: Millivolts) -> Self {
108        let value = value.0.clamp(600, 3700);
109        let value = (value - 600) / 100;
110        LDOOutputVoltage(value as u8)
111    }
112}
113
114#[cfg(feature = "defmt")]
115impl defmt::Format for Millivolts {
116    fn format(&self, fmt: defmt::Formatter) {
117        defmt::write!(fmt, "{}mV", self.0)
118    }
119}
120
121impl IinCurrent {
122    pub fn range(&self) -> Milliampere {
123        Milliampere(if self.high_range { 750 } else { 375 })
124    }
125}
126
127impl From<IinCurrent> for Milliampere {
128    fn from(val: IinCurrent) -> Self {
129        Milliampere(scale_u16(val.raw, u16::MAX, val.range().0))
130    }
131}
132
133impl From<Milliampere> for IinCurrent {
134    fn from(val: Milliampere) -> Self {
135        IinCurrent {
136            raw: scale_u16(val.0, 750, u16::MAX),
137            high_range: true,
138        }
139    }
140}
141
142impl FastChargeCurrent {
143    pub fn from_milliampere(ma: Milliampere, range: IchargeRange) -> Self {
144        let step_100 = match range {
145            IchargeRange::Step1MilliA25 => 125,
146            IchargeRange::Step2MilliA5 => 250,
147        };
148        Self((ma.0 * 100 / step_100) as u8)
149    }
150}
151
152impl IChargePercentage {
153    pub fn to_percentage(&self) -> u8 {
154        (self.0 as u32 * 80 / u16::MAX as u32) as u8
155    }
156}
157
158#[derive(Debug)]
159#[cfg_attr(feature = "defmt", derive(defmt::Format))]
160pub struct AdcData {
161    pub vin: Option<RawVoltage<6000>>,
162    pub pmid: Option<RawVoltage<6000>>,
163    pub iin: Option<IinCurrent>,
164    pub vbat: Option<RawVoltage<6000>>,
165    pub ts: Option<RawVoltage<1200>>,
166    pub adcin: Option<RawVoltage<1200>>,
167    pub icharge: Option<IChargePercentage>,
168}