SensorLib 0.5.0
Multi-platform sensor driver library for Arduino, PlatformIO, and ESP-IDF
Loading...
Searching...
No Matches
AXP2101Adc.cpp
Go to the documentation of this file.
1
31#include "../../../SensorBuildOpt.h"
32#if !SENSORLIB_EXCLUDE_PMIC_AXP2101
33
34#include "AXP2101Adc.hpp"
35#include "AXP2101Regs.hpp"
36#include <math.h>
37
38
40{
41}
42
43static uint8_t axp2101_channelToMask(PmicAdcBase::Channel ch)
44{
45 switch (ch) {
46 case PmicAdcBase::Channel::BAT_VOLTAGE: return 0x01;
48 case PmicAdcBase::Channel::VBUS_VOLTAGE: return 0x04;
49 case PmicAdcBase::Channel::VSYS_VOLTAGE: return 0x08;
51 default: return 0;
52 }
53}
54
55bool AXP2101Adc::enableChannels(uint32_t mask)
56{
57 uint8_t hwMask = 0;
58 forEachChannel(mask, [&](uint32_t bit) {
59 auto ch = static_cast<Channel>(bit);
60 hwMask |= axp2101_channelToMask(ch);
61 });
62 if (hwMask == 0) return false;
63
64 // TS pin special handling
65 if (hwMask & 0x02) {
66 int tsCtrl = _core.readReg(axp2101_regs::ts::TS_PIN_CTRL);
67 if (tsCtrl < 0) return false;
68 tsCtrl &= 0xE0;
69 tsCtrl |= 0x07;
70 if (_core.writeReg(axp2101_regs::ts::TS_PIN_CTRL, static_cast<uint8_t>(tsCtrl)) < 0) return false;
71 }
72
73 int regVal = _core.readReg(axp2101_regs::adc::CHANNEL_CTRL);
74 if (regVal < 0) return false;
75 regVal |= hwMask;
76 return _core.writeReg(axp2101_regs::adc::CHANNEL_CTRL, static_cast<uint8_t>(regVal)) >= 0;
77}
78
79bool AXP2101Adc::disableChannels(uint32_t mask)
80{
81 uint8_t hwMask = 0;
82 forEachChannel(mask, [&](uint32_t bit) {
83 auto ch = static_cast<Channel>(bit);
84 hwMask |= axp2101_channelToMask(ch);
85 });
86 if (hwMask == 0) return false;
87
88 if (hwMask & 0x02) {
89 int tsCtrl = _core.readReg(axp2101_regs::ts::TS_PIN_CTRL);
90 if (tsCtrl < 0) return false;
91 tsCtrl &= 0xF0;
92 tsCtrl |= 0x10;
93 if (_core.writeReg(axp2101_regs::ts::TS_PIN_CTRL, static_cast<uint8_t>(tsCtrl)) < 0) return false;
94 }
95
96 int regVal = _core.readReg(axp2101_regs::adc::CHANNEL_CTRL);
97 if (regVal < 0) return false;
98 regVal &= ~hwMask;
99 return _core.writeReg(axp2101_regs::adc::CHANNEL_CTRL, static_cast<uint8_t>(regVal)) >= 0;
100}
101
102bool AXP2101Adc::read(Channel ch, float &out)
103{
104 uint8_t buffer[2] = {0, 0};
105 out = NAN;
106
107 if (ch == Channel::VBUS_VOLTAGE || ch == Channel::VBUS_CURRENT ||
109 int status1 = _core.readReg(axp2101_regs::bmu::STATUS1);
110 if (status1 < 0) return false;
111 bool vbusPresent = (status1 >> 5) & 0x01;
112 bool batPresent = (status1 >> 3) & 0x01;
113 if (ch == Channel::VBUS_VOLTAGE || ch == Channel::VBUS_CURRENT) {
114 if (!vbusPresent) {
115 out = 0.0f;
116 return true;
117 }
118 }
119 if (ch == Channel::BAT_VOLTAGE || ch == Channel::BAT_CURRENT) {
120 if (!batPresent) {
121 out = 0.0f;
122 return true;
123 }
124 }
125 }
126
127 switch (ch) {
129 if (_core.readRegBuff(axp2101_regs::adc::VBUS_VOLT_H, buffer, 2) < 0)
130 return false;
131 out = static_cast<float>(((buffer[0] & 0x3F) << 8 | buffer[1])) * axp2101_regs::factory::VBUS_STEP;
132 break;
134 out = 0.0f;
135 return true;
137 if (_core.readRegBuff(axp2101_regs::adc::BAT_VOLT_H, buffer, 2) < 0)
138 return false;
139 out = static_cast<float>(((buffer[0] & 0x1F) << 8 | buffer[1])) * axp2101_regs::factory::VBAT_STEP;
140 break;
142 out = 0.0f;
143 return true;
145 if (_core.readRegBuff(axp2101_regs::adc::VSYS_VOLT_H, buffer, 2) < 0)
146 return false;
147 out = static_cast<float>(((buffer[0] & 0x3F) << 8 | buffer[1])) * axp2101_regs::factory::VSYS_STEP;
148 break;
150 if (_core.readRegBuff(axp2101_regs::adc::DIE_TEMP_H, buffer, 2) < 0)
151 return false;
152 {
153 uint16_t raw = ((buffer[0] & 0x3F) << 8) | buffer[1];
154 // formula: (22.0 + (7274 - raw) / 20.0)
155 out = 22.0f + (7274.0f - static_cast<float>(raw)) / 20.0f;
156 }
157 break;
159 if (_core.readRegBuff(axp2101_regs::adc::TS_VOLT_H, buffer, 2) < 0)
160 return false;
161 out = static_cast<float>(((buffer[0] & 0x3F) << 8 | buffer[1])) * axp2101_regs::factory::TS_STEP;
162 break;
165 if (val < 0) return false;
166 out = static_cast<float>(val);
167 }
168 break;
169 default:
170 return false;
171 }
172 return true;
173}
174
175// ---- TS Temperature (Steinhart-Hart) ----
176
177float AXP2101Adc::getTsTemperature(float SteinhartA, float SteinhartB, float SteinhartC)
178{
179 float voltage_mV = 0.0f;
180 if (!read(Channel::BAT_TEMPERATURE, voltage_mV)) return 0.0f;
181
182 if (voltage_mV == 4095.0f) return 0.0f;
183
184 float voltage_V = voltage_mV / 1000.0f;
185 float resistance = voltage_V / 5e-5f;
186 float ln_r = logf(resistance);
187 float t_inv = SteinhartA + SteinhartB * ln_r + SteinhartC * powf(ln_r, 3.0f);
188 return (1.0f / t_inv) - 273.15f;
189}
190
191#endif
@license MIT License
bool disableChannels(uint32_t mask) override
Disable one or more ADC channels (REG 0x30).
float getTsTemperature(float SteinhartA=1.126e-3f, float SteinhartB=2.38e-4f, float SteinhartC=8.5e-8f)
Read TS pin temperature using Steinhart-Hart equation.
bool enableChannels(uint32_t mask) override
Enable one or more ADC channels.
bool read(Channel ch, float &out) override
Read an ADC channel value.
AXP2101Adc(AXP2101Core &core)
Core I2C communication layer for the AXP2101 PMIC.
static void forEachChannel(uint32_t mask, Func fn)
Helper to iterate over set bits in a bitmask.
Channel
ADC channel bitmask.
@ BAT_PERCENTAGE
Battery percentage.
@ DIE_TEMPERATURE
Die temperature.
@ BAT_VOLTAGE
Battery voltage.
@ BAT_TEMPERATURE
Battery temperature.
@ BAT_CURRENT
Battery current.
@ VBUS_CURRENT
VBUS current.
@ VBUS_VOLTAGE
VBUS voltage.
@ VSYS_VOLTAGE
VSYS voltage.
int readReg(uint8_t reg) const
int writeReg(uint8_t reg, uint8_t val)
int readRegBuff(uint8_t reg, uint8_t *buf, size_t len) const
static constexpr uint8_t DIE_TEMP_H
static constexpr uint8_t TS_VOLT_H
static constexpr uint8_t VSYS_VOLT_H
static constexpr uint8_t VBUS_VOLT_H
static constexpr uint8_t BAT_VOLT_H
static constexpr uint8_t CHANNEL_CTRL
static constexpr uint8_t STATUS1
static constexpr float TS_STEP
static constexpr float VBAT_STEP
static constexpr float VSYS_STEP
static constexpr float VBUS_STEP
static constexpr uint8_t BAT_PERCENT
static constexpr uint8_t TS_PIN_CTRL