Dominic Höglinger 61b0fd84ee + Fixup: Bq27220
* Give credit
 * Fixed scope of byte functions
 * Remove debug log
 * Update README.md
2025-07-03 19:00:29 +02:00

113 lines
4.4 KiB
C++

#pragma once
#include <Tactility/hal/i2c/I2cDevice.h>
#define BQ27220_ADDRESS 0x55
class Bq27220 final : public tt::hal::i2c::I2cDevice {
private:
uint32_t accessKey;
bool unsealDevice();
bool unsealFullAccess();
bool exitSealMode();
bool sendSubCommand(uint16_t subCmd, bool waitConfirm = false);
bool writeConfig16(uint16_t address, uint16_t value);
bool configPreamble(bool &isSealed);
bool configEpilouge(const bool isSealed);
template<typename T>
bool performConfigUpdate(T configUpdateFunc)
{
// Configuration routine lifted from
// https://github.com/Xinyuan-LilyGO/T-Echo/blob/main/lib/SensorLib/src/GaugeBQ27220.hpp
// Copyright (c) 2025 lewis he
// SPDX-License-Identifier: MIT
bool isSealed = false;
if (!configPreamble(isSealed)) {
return false;
}
bool result = configUpdateFunc();
configEpilouge(isSealed);
return result;
}
public:
// Register structures lifted from
// https://github.com/Xinyuan-LilyGO/T-Deck-Pro/blob/master/lib/BQ27220/bq27220.h
// Copyright (c) 2025 Liygo / Shenzhen Xinyuan Electronic Technology Co., Ltd
union BatteryStatus {
struct
{
// Low byte, Low bit first
uint16_t DSG : 1; /**< The device is in DISCHARGE */
uint16_t SYSDWN : 1; /**< System down bit indicating the system should shut down */
uint16_t TDA : 1; /**< Terminate Discharge Alarm */
uint16_t BATTPRES : 1; /**< Battery Present detected */
uint16_t AUTH_GD : 1; /**< Detect inserted battery */
uint16_t OCVGD : 1; /**< Good OCV measurement taken */
uint16_t TCA : 1; /**< Terminate Charge Alarm */
uint16_t RSVD : 1; /**< Reserved */
// High byte, Low bit first
uint16_t CHGING : 1; /**< Charge inhibit */
uint16_t FC : 1; /**< Full-charged is detected */
uint16_t OTD : 1; /**< Overtemperature in discharge condition is detected */
uint16_t OTC : 1; /**< Overtemperature in charge condition is detected */
uint16_t SLEEP : 1; /**< Device is operating in SLEEP mode when set */
uint16_t OCVFALL : 1; /**< Status bit indicating that the OCV reading failed due to current */
uint16_t OCVCOMP : 1; /**< An OCV measurement update is complete */
uint16_t FD : 1; /**< Full-discharge is detected */
} reg;
uint16_t full;
};
enum OperationStatusSec {
OperationStatusSecSealed = 0b11,
OperationStatusSecUnsealed = 0b10,
OperationStatusSecFull = 0b01,
};
union OperationStatus {
struct
{
// Low byte, Low bit first
bool CALMD : 1; /**< Calibration mode enabled */
uint8_t SEC : 2; /**< Current security access */
bool EDV2 : 1; /**< EDV2 threshold exceeded */
bool VDQ : 1; /**< Indicates if Current discharge cycle is NOT qualified or qualified for an FCC updated */
bool INITCOMP : 1; /**< gauge initialization is complete */
bool SMTH : 1; /**< RemainingCapacity is scaled by smooth engine */
bool BTPINT : 1; /**< BTP threshold has been crossed */
// High byte, Low bit first
uint8_t RSVD1 : 2; /**< Reserved */
bool CFGUPDATE : 1; /**< Gauge is in CONFIG UPDATE mode */
uint8_t RSVD0 : 5; /**< Reserved */
} reg;
uint16_t full;
};
std::string getName() const final { return "BQ27220"; }
std::string getDescription() const final { return "I2C-controlled CEDV battery fuel gauge"; }
explicit Bq27220(i2c_port_t port) : I2cDevice(port, BQ27220_ADDRESS), accessKey(0xFFFFFFFF) {}
bool configureCapacity(uint16_t designCapacity, uint16_t fullChargeCapacity);
bool getVoltage(uint16_t &value);
bool getCurrent(int16_t &value);
bool getBatteryStatus(BatteryStatus &batt_sta);
bool getOperationStatus(OperationStatus &oper_sta);
bool getTemperature(uint16_t &value);
bool getFullChargeCapacity(uint16_t &value);
bool getDesignCapacity(uint16_t &value);
bool getRemainingCapacity(uint16_t &value);
bool getStateOfCharge(uint16_t &value);
bool getStateOfHealth(uint16_t &value);
bool getChargeVoltageMax(uint16_t &value);
};