#![cfg_attr(docsrs, feature(doc_cfg))]
#![cfg_attr(not(test), no_std)]
#![warn(missing_docs, rustdoc::broken_intra_doc_links)]
#![doc(html_root_url = "https://docs.rs/bq25887")]
use core::convert::TryFrom;
use core::result::Result;
use embedded_hal_async::i2c::I2c as I2cTrait;
pub const DEFAULT_I2C_ADDRESS: u8 = 0x6A;
const LARGEST_REG_SIZE_BYTES: usize = 0x01;
#[allow(missing_docs)]
mod generated {
device_driver::create_device!(
device_name: Bq25887,
manifest: "src/bq25887.yaml"
);
}
pub use generated::Bq25887;
pub use generated::Ichg;
pub use generated::Pn;
pub use generated::AdcRate;
pub use generated::field_sets;
#[cfg(feature = "embassy")]
#[cfg_attr(docsrs, doc(cfg(feature = "embassy")))]
pub mod embassy;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
pub enum BQ25887Error<I2cError> {
I2c(I2cError),
Conversion(device_driver::ConversionError<u8>),
}
impl<E> From<device_driver::ConversionError<u8>> for BQ25887Error<E> {
fn from(err: device_driver::ConversionError<u8>) -> Self {
BQ25887Error::Conversion(err)
}
}
impl<I2C: I2cTrait> device_driver::AsyncRegisterInterface for DeviceInterface<I2C> {
type Error = BQ25887Error<I2C::Error>;
type AddressType = u8;
async fn write_register(
&mut self,
address: Self::AddressType,
_size_bits: u32,
data: &[u8],
) -> Result<(), Self::Error> {
let mut buf = [0u8; 1 + LARGEST_REG_SIZE_BYTES];
buf[0] = address;
buf[1..=data.len()].copy_from_slice(data);
self.i2c
.write(self.address, &buf[..=data.len()])
.await
.map_err(BQ25887Error::I2c)
}
async fn read_register(
&mut self,
address: Self::AddressType,
_size_bits: u32,
data: &mut [u8],
) -> Result<(), Self::Error> {
self.i2c
.write_read(self.address, &[address], data)
.await
.map_err(BQ25887Error::I2c)
}
}
pub struct DeviceInterface<I2C: I2cTrait> {
pub i2c: I2C,
address: u8,
}
impl<I2C: I2cTrait> DeviceInterface<I2C> {
pub(crate) fn new(i2c: I2C, address: u8) -> Self {
Self { i2c, address }
}
}
#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PartInformationSummary {
pub part_number: Pn,
pub device_revision: u8,
}
impl TryFrom<crate::field_sets::PartInformation> for PartInformationSummary {
type Error = device_driver::ConversionError<u8>;
fn try_from(value: crate::field_sets::PartInformation) -> Result<Self, Self::Error> {
Ok(PartInformationSummary {
part_number: value.pn()?,
device_revision: value.dev_rev(),
})
}
}
pub struct Bq25887Driver<I2C: I2cTrait> {
device: Bq25887<DeviceInterface<I2C>>,
}
impl<I2C: I2cTrait> Bq25887Driver<I2C> {
pub fn new(i2c: I2C) -> Self {
Self::new_with_address(i2c, DEFAULT_I2C_ADDRESS)
}
pub fn new_with_address(i2c: I2C, address: u8) -> Self {
Self {
device: Bq25887::new(DeviceInterface::new(i2c, address)),
}
}
pub async fn read_voltage_regulation_limit(
&mut self,
) -> Result<crate::field_sets::CellVoltageLimit, BQ25887Error<I2C::Error>> {
self.device.cell_voltage_limit().read_async().await
}
pub async fn write_voltage_regulation_limit(
&mut self,
volt_limit: crate::field_sets::CellVoltageLimit,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.cell_voltage_limit()
.write_async(|reg| *reg = volt_limit)
.await
}
pub async fn read_charge_current_limit(
&mut self,
) -> Result<crate::field_sets::ChargeCurrentLimit, BQ25887Error<I2C::Error>> {
self.device.charge_current_limit().read_async().await
}
pub async fn write_charge_current_limit(
&mut self,
current_limit: crate::field_sets::ChargeCurrentLimit,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.charge_current_limit()
.write_async(|reg| *reg = current_limit)
.await
}
pub async fn enable_battery_connection(&mut self, setting: bool) -> Result<(), BQ25887Error<I2C::Error>> {
let mut reg = self.device.charge_current_limit().read_async().await?;
reg.set_en_hiz(!setting);
self.device.charge_current_limit().write_async(|w| *w = reg).await
}
pub async fn read_input_voltage_limit(
&mut self,
) -> Result<crate::field_sets::InputVoltageLimit, BQ25887Error<I2C::Error>> {
self.device.input_voltage_limit().read_async().await
}
pub async fn write_input_voltage_limit(
&mut self,
input_volt_limit: crate::field_sets::InputVoltageLimit,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.input_voltage_limit()
.write_async(|reg| *reg = input_volt_limit)
.await
}
pub async fn read_input_current_limit(
&mut self,
) -> Result<crate::field_sets::InputCurrentLimit, BQ25887Error<I2C::Error>> {
self.device.input_current_limit().read_async().await
}
pub async fn write_input_current_limit(
&mut self,
current_limit: crate::field_sets::InputCurrentLimit,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.input_current_limit()
.write_async(|reg| *reg = current_limit)
.await
}
pub async fn read_precharge_and_termination_current_limit(
&mut self,
) -> Result<crate::field_sets::PrechgTerminationCtrl, BQ25887Error<I2C::Error>> {
self.device.prechg_termination_ctrl().read_async().await
}
pub async fn write_precharge_and_termination_current_limit(
&mut self,
current_limit: crate::field_sets::PrechgTerminationCtrl,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.prechg_termination_ctrl()
.write_async(|reg| *reg = current_limit)
.await
}
pub async fn read_charger_control_1(
&mut self,
) -> Result<crate::field_sets::ChargerCtrl1, BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_1().read_async().await
}
pub async fn write_charger_control_1(
&mut self,
control: crate::field_sets::ChargerCtrl1,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_1().write_async(|reg| *reg = control).await
}
pub async fn read_charger_control_2(
&mut self,
) -> Result<crate::field_sets::ChargerCtrl2, BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_2().read_async().await
}
pub async fn write_charger_control_2(
&mut self,
control: crate::field_sets::ChargerCtrl2,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_2().write_async(|reg| *reg = control).await
}
pub async fn read_charger_control_3(
&mut self,
) -> Result<crate::field_sets::ChargerCtrl3, BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_3().read_async().await
}
pub async fn write_charger_control_3(
&mut self,
control: crate::field_sets::ChargerCtrl3,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_3().write_async(|reg| *reg = control).await
}
pub async fn read_charger_control_4(
&mut self,
) -> Result<crate::field_sets::ChargerCtrl4, BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_4().read_async().await
}
pub async fn write_charger_control_4(
&mut self,
control: crate::field_sets::ChargerCtrl4,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_4().write_async(|reg| *reg = control).await
}
pub async fn read_ico_current_limit_in_use(
&mut self,
) -> Result<crate::field_sets::IcoCurrentLimit, BQ25887Error<I2C::Error>> {
self.device.ico_current_limit().read_async().await
}
pub async fn read_charger_status_1(
&mut self,
) -> Result<crate::field_sets::ChargerStatus1, BQ25887Error<I2C::Error>> {
self.device.charger_status_1().read_async().await
}
pub async fn read_charger_status_2(
&mut self,
) -> Result<crate::field_sets::ChargerStatus2, BQ25887Error<I2C::Error>> {
self.device.charger_status_2().read_async().await
}
pub async fn read_ntc_status(&mut self) -> Result<crate::field_sets::NtcStatus, BQ25887Error<I2C::Error>> {
self.device.ntc_status().read_async().await
}
pub async fn read_fault_status(&mut self) -> Result<crate::field_sets::FaultStatus, BQ25887Error<I2C::Error>> {
self.device.fault_status().read_async().await
}
pub async fn read_charger_flag_1(&mut self) -> Result<crate::field_sets::ChargerFlag1, BQ25887Error<I2C::Error>> {
self.device.charger_flag_1().read_async().await
}
pub async fn read_charger_flag_2(&mut self) -> Result<crate::field_sets::ChargerFlag2, BQ25887Error<I2C::Error>> {
self.device.charger_flag_2().read_async().await
}
pub async fn read_fault_flag(&mut self) -> Result<crate::field_sets::FaultFlag, BQ25887Error<I2C::Error>> {
self.device.fault_flag().read_async().await
}
pub async fn read_charger_mask_1(&mut self) -> Result<crate::field_sets::ChargerMask1, BQ25887Error<I2C::Error>> {
self.device.charger_mask_1().read_async().await
}
pub async fn write_charger_mask_1(
&mut self,
mask: crate::field_sets::ChargerMask1,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_mask_1().write_async(|reg| *reg = mask).await
}
pub async fn read_charger_mask_2(&mut self) -> Result<crate::field_sets::ChargerMask2, BQ25887Error<I2C::Error>> {
self.device.charger_mask_2().read_async().await
}
pub async fn write_charger_mask_2(
&mut self,
mask: crate::field_sets::ChargerMask2,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_mask_2().write_async(|reg| *reg = mask).await
}
pub async fn read_fault_mask(&mut self) -> Result<crate::field_sets::FaultMask, BQ25887Error<I2C::Error>> {
self.device.fault_mask().read_async().await
}
pub async fn write_fault_mask(
&mut self,
mask: crate::field_sets::FaultMask,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.fault_mask().write_async(|reg| *reg = mask).await
}
pub async fn read_adc_control(&mut self) -> Result<crate::field_sets::AdcControl, BQ25887Error<I2C::Error>> {
self.device.adc_control().read_async().await
}
pub async fn write_adc_control(
&mut self,
control: crate::field_sets::AdcControl,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.adc_control().write_async(|reg| *reg = control).await
}
pub async fn read_adc_function_disable(
&mut self,
) -> Result<crate::field_sets::AdcFunctionDisable, BQ25887Error<I2C::Error>> {
self.device.adc_function_disable().read_async().await
}
pub async fn write_adc_function_disable(
&mut self,
function: crate::field_sets::AdcFunctionDisable,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.adc_function_disable()
.write_async(|reg| *reg = function)
.await
}
pub async fn read_ibus_adc_1(&mut self) -> Result<crate::field_sets::IbusAdc1, BQ25887Error<I2C::Error>> {
self.device.ibus_adc_1().read_async().await
}
pub async fn read_ibus_adc_0(&mut self) -> Result<crate::field_sets::IbusAdc0, BQ25887Error<I2C::Error>> {
self.device.ibus_adc_0().read_async().await
}
pub async fn read_ichg_adc_1(&mut self) -> Result<crate::field_sets::IchgAdc1, BQ25887Error<I2C::Error>> {
self.device.ichg_adc_1().read_async().await
}
pub async fn read_ichg_adc_0(&mut self) -> Result<crate::field_sets::IchgAdc0, BQ25887Error<I2C::Error>> {
self.device.ichg_adc_0().read_async().await
}
pub async fn read_vbus_adc_1(&mut self) -> Result<crate::field_sets::VbusAdc1, BQ25887Error<I2C::Error>> {
self.device.vbus_adc_1().read_async().await
}
pub async fn read_vbus_adc_0(&mut self) -> Result<crate::field_sets::VbusAdc0, BQ25887Error<I2C::Error>> {
self.device.vbus_adc_0().read_async().await
}
pub async fn read_vbat_adc_1(&mut self) -> Result<crate::field_sets::VbatAdc1, BQ25887Error<I2C::Error>> {
self.device.vbat_adc_1().read_async().await
}
pub async fn read_vbat_adc_0(&mut self) -> Result<crate::field_sets::VbatAdc0, BQ25887Error<I2C::Error>> {
self.device.vbat_adc_0().read_async().await
}
pub async fn read_vcell_top_adc_1(&mut self) -> Result<crate::field_sets::VcelltopAdc1, BQ25887Error<I2C::Error>> {
self.device.vcelltop_adc_1().read_async().await
}
pub async fn read_vcell_top_adc_0(&mut self) -> Result<crate::field_sets::VcelltopAdc0, BQ25887Error<I2C::Error>> {
self.device.vcelltop_adc_0().read_async().await
}
pub async fn read_ts_adc_1(&mut self) -> Result<crate::field_sets::TsAdc1, BQ25887Error<I2C::Error>> {
self.device.ts_adc_1().read_async().await
}
pub async fn read_ts_adc_0(&mut self) -> Result<crate::field_sets::TsAdc0, BQ25887Error<I2C::Error>> {
self.device.ts_adc_0().read_async().await
}
pub async fn read_tdie_adc_1(&mut self) -> Result<crate::field_sets::TdieAdc1, BQ25887Error<I2C::Error>> {
self.device.tdie_adc_1().read_async().await
}
pub async fn read_tdie_adc_0(&mut self) -> Result<crate::field_sets::TdieAdc0, BQ25887Error<I2C::Error>> {
self.device.tdie_adc_0().read_async().await
}
pub async fn read_part_information(&mut self) -> Result<PartInformationSummary, BQ25887Error<I2C::Error>> {
let reg = self.device.part_information().read_async().await?;
let summary = PartInformationSummary::try_from(reg).map_err(BQ25887Error::from)?;
Ok(summary)
}
pub async fn master_reset(&mut self) -> Result<(), BQ25887Error<I2C::Error>> {
let mut reg = self.device.part_information().read_async().await?;
reg.set_reg_rst(true);
self.device.part_information().write_async(|r| *r = reg).await
}
pub async fn read_vcellbot_adc_1(&mut self) -> Result<crate::field_sets::VcellbotAdc1, BQ25887Error<I2C::Error>> {
self.device.vcellbot_adc_1().read_async().await
}
pub async fn read_vcellbot_adc_0(&mut self) -> Result<crate::field_sets::VcellbotAdc0, BQ25887Error<I2C::Error>> {
self.device.vcellbot_adc_0().read_async().await
}
pub async fn read_cell_balancing_control_1(
&mut self,
) -> Result<crate::field_sets::CellBalanceCtrl1, BQ25887Error<I2C::Error>> {
self.device.cell_balance_ctrl_1().read_async().await
}
pub async fn write_cell_balancing_control_1(
&mut self,
control: crate::field_sets::CellBalanceCtrl1,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.cell_balance_ctrl_1()
.write_async(|reg| *reg = control)
.await
}
pub async fn read_cell_balancing_control_2(
&mut self,
) -> Result<crate::field_sets::CellBalanceCtrl2, BQ25887Error<I2C::Error>> {
self.device.cell_balance_ctrl_2().read_async().await
}
pub async fn write_cell_balancing_control_2(
&mut self,
control: crate::field_sets::CellBalanceCtrl2,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.cell_balance_ctrl_2()
.write_async(|reg| *reg = control)
.await
}
pub async fn read_cell_balancing_status_and_control(
&mut self,
) -> Result<crate::field_sets::CellBalanceStatCtrl, BQ25887Error<I2C::Error>> {
self.device.cell_balance_stat_ctrl().read_async().await
}
pub async fn write_cell_balancing_status_and_control(
&mut self,
control: crate::field_sets::CellBalanceStatCtrl,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device
.cell_balance_stat_ctrl()
.write_async(|reg| *reg = control)
.await
}
pub async fn read_cell_balancing_flag(
&mut self,
) -> Result<crate::field_sets::CellBalanceFlag, BQ25887Error<I2C::Error>> {
self.device.cell_balance_flag().read_async().await
}
pub async fn write_cell_balancing_flag(
&mut self,
flag: crate::field_sets::CellBalanceFlag,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.cell_balance_flag().write_async(|reg| *reg = flag).await
}
pub async fn read_cell_balancing_mask(
&mut self,
) -> Result<crate::field_sets::CellBalanceMask, BQ25887Error<I2C::Error>> {
self.device.cell_balance_mask().read_async().await
}
pub async fn write_cell_balancing_mask(
&mut self,
mask: crate::field_sets::CellBalanceMask,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.cell_balance_mask().write_async(|reg| *reg = mask).await
}
pub async fn disable_watchdog(&mut self) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_1().modify_async(|reg| {
reg.set_watchdog(crate::generated::Watchdog::WdDisable);
}).await
}
pub async fn set_watchdog_timeout(
&mut self,
timeout: crate::generated::Watchdog,
) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_1().modify_async(|reg| {
reg.set_watchdog(timeout);
}).await
}
pub async fn reset_watchdog(&mut self) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.charger_ctrl_3().modify_async(|reg| {
reg.set_wd_rst(true);
}).await
}
pub async fn is_adc_enabled(&mut self) -> Result<bool, BQ25887Error<I2C::Error>> {
let adc_control = self.device.adc_control().read_async().await?;
Ok(adc_control.adc_en())
}
pub async fn enable_adc_continuous(&mut self) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.adc_control().write_async(|reg| {
reg.set_adc_en(true);
reg.set_adc_rate(crate::generated::AdcRate::Continuous);
}).await
}
pub async fn enable_adc_oneshot(&mut self) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.adc_control().write_async(|reg| {
reg.set_adc_en(true);
reg.set_adc_rate(crate::generated::AdcRate::OneShot);
}).await
}
pub async fn disable_adc(&mut self) -> Result<(), BQ25887Error<I2C::Error>> {
self.device.adc_control().write_async(|reg| {
reg.set_adc_en(false);
}).await
}
pub async fn read_vbat_mv(&mut self) -> Result<u16, BQ25887Error<I2C::Error>> {
let msb = self.read_vbat_adc_1().await?;
let lsb = self.read_vbat_adc_0().await?;
let raw = ((msb.vbat_adc_msb() as u16) << 8) | (lsb.vbat_adc_lsb() as u16);
Ok(raw) }
pub async fn read_vbus_mv(&mut self) -> Result<u16, BQ25887Error<I2C::Error>> {
let msb = self.read_vbus_adc_1().await?;
let lsb = self.read_vbus_adc_0().await?;
let raw = ((msb.vbus_adc_msb() as u16) << 8) | (lsb.vbus_adc_lsb() as u16);
Ok(raw) }
pub async fn read_ichg_ma(&mut self) -> Result<u16, BQ25887Error<I2C::Error>> {
let msb = self.read_ichg_adc_1().await?;
let lsb = self.read_ichg_adc_0().await?;
let raw = ((msb.ichg_adc_msb() as u16) << 8) | (lsb.ichg_adc_lsb() as u16);
Ok(raw) }
pub async fn read_ibus_ma(&mut self) -> Result<u16, BQ25887Error<I2C::Error>> {
let msb = self.read_ibus_adc_1().await?;
let lsb = self.read_ibus_adc_0().await?;
let raw = ((msb.ibus_adc_msb() as u16) << 8) | (lsb.ibus_adc_lsb() as u16);
Ok(raw) }
pub async fn read_vcell_top_mv(&mut self) -> Result<u16, BQ25887Error<I2C::Error>> {
let msb = self.read_vcell_top_adc_1().await?;
let lsb = self.read_vcell_top_adc_0().await?;
let raw = ((msb.vcelltop_adc_msb() as u16) << 8) | (lsb.vcelltop_adc_lsb() as u16);
Ok(raw) }
pub async fn read_vcell_bot_mv(&mut self) -> Result<u16, BQ25887Error<I2C::Error>> {
let msb = self.read_vcellbot_adc_1().await?;
let lsb = self.read_vcellbot_adc_0().await?;
let raw = ((msb.vcellbot_adc_msb() as u16) << 8) | (lsb.vcellbot_adc_lsb() as u16);
Ok(raw) }
pub async fn read_tdie_raw(&mut self) -> Result<u16, BQ25887Error<I2C::Error>> {
let msb = self.read_tdie_adc_1().await?;
let lsb = self.read_tdie_adc_0().await?;
let raw = ((msb.tdie_adc_msb() as u16) << 8) | (lsb.tdie_adc_lsb() as u16);
Ok(raw)
}
pub async fn read_tdie_decidegrees(&mut self) -> Result<i16, BQ25887Error<I2C::Error>> {
let raw = self.read_tdie_raw().await?;
let temp = if raw & 0x8000 != 0 {
-(((!raw).wrapping_add(1) & 0x7FFF) as i16 * 5)
} else {
(raw as i16) * 5
};
Ok(temp)
}
pub async fn read_ts_raw(&mut self) -> Result<u16, BQ25887Error<I2C::Error>> {
let msb = self.read_ts_adc_1().await?;
let lsb = self.read_ts_adc_0().await?;
let raw = ((msb.ts_adc_msb() as u16) << 8) | (lsb.ts_adc_lsb() as u16);
Ok(raw)
}
}