1pub 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}