picocalc_BIOS/Core/Src/axp2101.c
JackCarterSmith 1b288f72cc
Some fix
- Missalign PMIC IRQ flag
- Incorrect batt led
2025-05-05 21:36:42 +02:00

314 lines
9.6 KiB
C

#include "axp2101.h"
#include "main.h"
#include "stm32_assert.h"
#define AXP2101_DEV_I2C_ID 0x68
static uint8_t statusRegister[XPOWERS_AXP2101_INTSTS_CNT] = {0};
static uint8_t intRegister[XPOWERS_AXP2101_INTSTS_CNT] = {0};
__STATIC_INLINE uint8_t clrRegisterBit(uint8_t registers, uint8_t bit) {
uint8_t reg_value = 0;
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, registers, 1, &reg_value, 1, 60);
if (status != HAL_OK)
return 1;
reg_value &= (uint8_t)(~_BV(bit));
return HAL_I2C_Mem_Write(&hi2c2, AXP2101_DEV_I2C_ID, registers, 1, &reg_value, 1, 60);
}
__STATIC_INLINE uint8_t getRegisterBit(uint8_t registers, uint8_t bit) {
uint8_t reg_value = 0;
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, registers, 1, &reg_value, 1, 60);
if (status != HAL_OK)
return 1;
return reg_value & _BV(bit);
}
__STATIC_INLINE uint8_t setRegisterBit(uint8_t registers, uint8_t bit) {
uint8_t reg_value = 0;
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, registers, 1, &reg_value, 1, 60);
if (status != HAL_OK)
return 1;
reg_value |= (uint8_t)(_BV(bit));
return HAL_I2C_Mem_Write(&hi2c2, AXP2101_DEV_I2C_ID, registers, 1, &reg_value, 1, 60);
}
uint32_t setInterruptImpl(uint32_t opts, uint8_t enable) {
uint8_t reg_value = 0;
HAL_StatusTypeDef status = HAL_OK;
if (opts & 0x0000FF) {
HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_INTEN1, 1, &reg_value, 1, 60);
intRegister[0] = enable ? (uint8_t)(reg_value | (opts & 0xFF)) : (uint8_t)(reg_value & (~(opts & 0xFF)));
status |= HAL_I2C_Mem_Write(&hi2c2, 0x68, XPOWERS_AXP2101_INTEN1, 1, &intRegister[0], 1, 60);
}
if (opts & 0x00FF00) {
HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_INTEN2, 1, &reg_value, 1, 60);
intRegister[1] = enable ? (uint8_t)(reg_value | (opts >> 8)) : (uint8_t)(reg_value & (~(opts >> 8)));
status |= HAL_I2C_Mem_Write(&hi2c2, 0x68, XPOWERS_AXP2101_INTEN2, 1, &intRegister[1], 1, 60);
}
if (opts & 0xFF0000) {
HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_INTEN3, 1, &reg_value, 1, 60);
intRegister[2] = enable ? (uint8_t)(reg_value | (opts >> 16)) : (uint8_t)(reg_value & (~(opts >> 16)));
status |= HAL_I2C_Mem_Write(&hi2c2, 0x68, XPOWERS_AXP2101_INTEN3, 1, &intRegister[2], 1, 60);
}
return (uint32_t)status;
}
uint32_t AXP2101_shutdown(void) {
return setRegisterBit(XPOWERS_AXP2101_COMMON_CONFIG, 0);
}
uint32_t AXP2101_disableTSPinMeasure(void) {
return clrRegisterBit(XPOWERS_AXP2101_ADC_CHANNEL_CTRL, 1);
}
uint32_t AXP2101_enableBattDetection(void) {
return setRegisterBit(XPOWERS_AXP2101_BAT_DET_CTRL, 0);
}
uint32_t AXP2101_enableBattVoltageMeasure(void) {
return setRegisterBit(XPOWERS_AXP2101_ADC_CHANNEL_CTRL, 0);
}
uint32_t AXP2101_enableSystemVoltageMeasure(void) {
return setRegisterBit(XPOWERS_AXP2101_ADC_CHANNEL_CTRL, 3);
}
uint32_t AXP2101_enableVbusVoltageMeasure(void) {
return setRegisterBit(XPOWERS_AXP2101_ADC_CHANNEL_CTRL, 2);
}
uint32_t AXP2101_enableIRQ(uint32_t opt) {
return setInterruptImpl(opt, 1);
}
uint32_t AXP2101_disableIRQ(uint32_t opt) {
return setInterruptImpl(opt, 0);
}
uint32_t AXP2101_clearIrqStatus(void) {
HAL_StatusTypeDef status = HAL_OK;
uint8_t fbuff = 0xFF;
for (size_t i = 0; i < XPOWERS_AXP2101_INTSTS_CNT; i++) {
status |= HAL_I2C_Mem_Write(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_INTSTS1 + (uint8_t)i, 1, &fbuff, 1, 60);
statusRegister[i] = 0;
}
return (uint32_t)status;
}
uint8_t AXP2101_isDropWarningLevel1Irq(void) {
uint8_t mask = XPOWERS_AXP2101_WARNING_LEVEL1_IRQ;
if (intRegister[0] & mask)
return ((statusRegister[0] & mask) == mask);
return 0;
}
uint8_t AXP2101_isVbusRemoveIrq(void) {
uint8_t mask = XPOWERS_AXP2101_VBUS_REMOVE_IRQ >> 8;
if (intRegister[1] & mask)
return ((statusRegister[1] & mask) == mask);
return 0;
}
uint8_t AXP2101_isBatInsertIrq(void) {
uint8_t mask = XPOWERS_AXP2101_BAT_INSERT_IRQ >> 8;
if (intRegister[1] & mask)
return ((statusRegister[1] & mask) == mask);
return 0;
}
uint8_t AXP2101_isBatRemoveIrq(void) {
uint8_t mask = XPOWERS_AXP2101_BAT_REMOVE_IRQ >> 8;
if (intRegister[1] & mask)
return ((statusRegister[1] & mask) == mask);
return 0;
}
uint8_t AXP2101_isPekeyShortPressIrq(void) {
uint8_t mask = XPOWERS_AXP2101_PKEY_SHORT_IRQ >> 8;
if (intRegister[1] & mask)
return ((statusRegister[1] & mask) == mask);
return 0;
}
uint8_t AXP2101_isPekeyLongPressIrq(void) {
uint8_t mask = XPOWERS_AXP2101_PKEY_LONG_IRQ >> 8;
if (intRegister[1] & mask)
return ((statusRegister[1] & mask) == mask);
return 0;
}
uint8_t AXP2101_isBatChargeDoneIrq(void) {
uint8_t mask = XPOWERS_AXP2101_BAT_CHG_DONE_IRQ >> 16;
if (intRegister[2] & mask)
return ((statusRegister[2] & mask) == mask);
return 0;
}
uint8_t AXP2101_isBatChargeStartIrq(void) {
uint8_t mask = XPOWERS_AXP2101_BAT_CHG_START_IRQ >> 16;
if (intRegister[2] & mask)
return ((statusRegister[2] & mask) == mask);
return 0;
}
// value in mV
uint32_t AXP2101_setSysPowerDownVoltage(uint16_t value) {
uint8_t reg_value = 0;
HAL_StatusTypeDef status;
if (value % XPOWERS_AXP2101_VSYS_VOL_THRESHOLD_STEPS) {
//log_e("Mistake ! The steps is must %u mV", XPOWERS_AXP2101_VSYS_VOL_THRESHOLD_STEPS);
return 10;
}
if (value < XPOWERS_AXP2101_VSYS_VOL_THRESHOLD_MIN) {
//log_e("Mistake ! The minimum settable voltage of VSYS is %u mV", XPOWERS_AXP2101_VSYS_VOL_THRESHOLD_MIN);
return 10;
} else if (value > XPOWERS_AXP2101_VSYS_VOL_THRESHOLD_MAX) {
//log_e("Mistake ! The maximum settable voltage of VSYS is %u mV", XPOWERS_AXP2101_VSYS_VOL_THRESHOLD_MAX);
return 10;
}
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_VOFF_SET, 1, &reg_value, 1, 60);
if (status != HAL_OK)
return 1;
reg_value &= 0xF8;
reg_value |= (uint8_t)((value - XPOWERS_AXP2101_VSYS_VOL_THRESHOLD_MIN) / XPOWERS_AXP2101_VSYS_VOL_THRESHOLD_STEPS);
return (uint32_t)HAL_I2C_Mem_Write(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_VOFF_SET, 1, &reg_value, 1, 60);
}
uint32_t AXP2101_setChargingLedMode(uint8_t mode) {
uint8_t reg_value = 0;
HAL_StatusTypeDef status;
switch (mode) {
case XPOWERS_CHG_LED_OFF:
// clrRegisterBit(XPOWERS_AXP2101_CHGLED_SET_CTRL, 0);
// break;
case XPOWERS_CHG_LED_BLINK_1HZ:
case XPOWERS_CHG_LED_BLINK_4HZ:
case XPOWERS_CHG_LED_ON:
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_CHGLED_SET_CTRL, 1, &reg_value, 1, 60);
if (status != HAL_OK)
return 1;
reg_value &= 0xC8;
reg_value |= 0x05; //use manual ctrl
reg_value |= (mode << 4);
status = HAL_I2C_Mem_Write(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_CHGLED_SET_CTRL, 1, &reg_value, 1, 60);
break;
case XPOWERS_CHG_LED_CTRL_CHG:
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_CHGLED_SET_CTRL, 1, &reg_value, 1, 60);
if (status != HAL_OK)
return 1;
reg_value &= 0xF9;
reg_value |= 0x01; // use type A mode
//reg_value |= 0x02; // use type B mode
status = HAL_I2C_Mem_Write(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_CHGLED_SET_CTRL, 1, &reg_value, 1, 60);
break;
default:
status = 10;
break;
}
return (uint32_t)status;
}
/**
* @brief Low battery warning threshold 5-20%, 1% per step
* @param percentage: 5 ~ 20
* @retval Status code
*/
uint32_t AXP2101_setLowBatWarnThreshold(uint8_t percentage) {
if (percentage < 5 || percentage > 20)
return 1;
uint8_t reg_value = 0;
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_LOW_BAT_WARN_SET, 1, &reg_value, 1, 60);
if (status != HAL_OK)
return 1;
reg_value &= 0x0F;
reg_value |= (uint8_t)((percentage - 5) << 4);
return HAL_I2C_Mem_Write(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_LOW_BAT_WARN_SET, 1, &reg_value, 1, 60);
}
/**
* @brief Low battery shutdown threshold 0-15%, 1% per step
* @param opt: 0 ~ 15
* @retval Status code
*/
uint32_t AXP2101_setLowBatShutdownThreshold(uint8_t opt) {
uint8_t reg_value = 0;
HAL_StatusTypeDef status;
if (opt > 15)
opt = 15;
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_LOW_BAT_WARN_SET, 1, &reg_value, 1, 60);
if (status != HAL_OK)
return 1;
reg_value &= 0xF0;
reg_value |= opt;
return HAL_I2C_Mem_Write(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_LOW_BAT_WARN_SET, 1, &reg_value, 1, 60);
}
uint8_t AXP2101_isBatteryConnect(void) {
return getRegisterBit(XPOWERS_AXP2101_STATUS1, 3);
}
uint8_t AXP2101_isCharging(void) {
uint8_t reg_value = 0;
HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_STATUS2, 1, &reg_value, 1, 60);
return (reg_value >> 5) == 0x01;
}
uint32_t AXP2101_getIrqStatus(uint32_t* out_value) {
HAL_StatusTypeDef status = HAL_OK;
status |= HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_INTSTS1, 1, &statusRegister[0], 1, 60);
status |= HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_INTSTS2, 1, &statusRegister[1], 1, 60);
status |= HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_INTSTS3, 1, &statusRegister[2], 1, 60);
((uint8_t*)&out_value)[0] = statusRegister[0];
((uint8_t*)&out_value)[0] = statusRegister[1];
((uint8_t*)&out_value)[0] = statusRegister[2];
((uint8_t*)&out_value)[3] = 0xFF;
return (uint32_t)status;
}
uint32_t AXP2101_getBatteryPercent(uint8_t* out_value) {
if (!AXP2101_isBatteryConnect())
return 1;
return HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_BAT_PERCENT_DATA, 1, out_value, 1, 60);
}