use thiserror_no_std::Error;
use crate::io::shared_i2c::SharedI2cBus;
pub const IP5306_ADDR: u8 = 0x75;
const REG_READ0: u8 = 0x70; const REG_READ1: u8 = 0x71; const REG_READ4: u8 = 0x78;
const CHARGE_BIT: u8 = 1 << 3; const CHARGE_FULL_BIT: u8 = 1 << 3; const GAUGE_MASK: u8 = 0xF0;
#[derive(Debug, Error)]
pub enum Ip5306Error {
#[error("I2C error: {0:?}")]
I2cError(#[from] esp_hal::i2c::master::Error),
}
pub struct Ip5306Driver {
i2c: &'static SharedI2cBus,
address: u8,
}
impl Ip5306Driver {
pub fn new(i2c: &'static SharedI2cBus, address: u8) -> Self {
Self { i2c, address }
}
async fn read_reg(&mut self, reg: u8) -> Result<u8, Ip5306Error> {
let mut buf = [0u8; 1];
self.i2c
.lock()
.await
.write_read_async(self.address, &[reg], &mut buf)
.await?;
debug!("IP5306 rd 0x{:02x} = 0x{:02x}", reg, buf[0]);
Ok(buf[0])
}
pub async fn present(&mut self) -> bool {
self.read_reg(REG_READ0).await.is_ok()
}
pub async fn battery_level(&mut self) -> Result<u8, Ip5306Error> {
let gauge = self.read_reg(REG_READ4).await? & GAUGE_MASK;
Ok(match gauge {
0xE0 => 25,
0xC0 => 50,
0x80 => 75,
0x00 => 100,
_ => 0, })
}
pub async fn is_charging(&mut self) -> Result<bool, Ip5306Error> {
Ok(self.read_reg(REG_READ0).await? & CHARGE_BIT != 0)
}
pub async fn is_charge_full(&mut self) -> Result<bool, Ip5306Error> {
Ok(self.read_reg(REG_READ1).await? & CHARGE_FULL_BIT != 0)
}
}