kopia lustrzana https://github.com/dl9rdz/rdz_ttgo_sonde
546 wiersze
18 KiB
C++
546 wiersze
18 KiB
C++
#include <stdio.h>
|
|
#include <Wire.h>
|
|
#include "pmu.h"
|
|
#include "Sonde.h"
|
|
|
|
// 0: cleared; 1: set; 2: do not check, also query state of axp via i2c on each loop
|
|
uint8_t pmu_irq = 0;
|
|
#define PMU_IRQ 35
|
|
|
|
#define AXP192_VMIN 1800
|
|
#define AXP192_VSTEP 100
|
|
|
|
|
|
#define AXP192_IC_TYPE (0x03)
|
|
|
|
#define AXP192_DC_MIN 700
|
|
#define AXP192_DC_STEPS 25
|
|
|
|
#define AXP192_LDO_MIN (1800)
|
|
#define AXP192_LDO_STEPS (100)
|
|
|
|
#define AXP192_VOLTREG_DC1
|
|
|
|
// some registers:
|
|
#define AXP192_STATUS (0x00)
|
|
#define AXP192_MODE_CHGSTATUS (0x01)
|
|
|
|
// Power voltage control register
|
|
#define AXP192_DC2OUT_VOL (0x23)
|
|
#define AXP192_DC1OUT_VOL (0x26)
|
|
#define AXP192_DC3OUT_VOL (0x27)
|
|
#define AXP192_LDO23OUT_VOL (0x28)
|
|
#define AXP192_GPIO0_VOL (0x91)
|
|
|
|
// Power enable registers
|
|
#define AXP192_LDO23_DC123_EXT_CTL (0x12)
|
|
|
|
// ADC control
|
|
#define AXP192_ADC_EN1 (0x82)
|
|
|
|
// ADC results
|
|
#define AXP192_BAT_AVERVOL_H8 (0x78)
|
|
#define AXP192_BAT_AVERVOL_L4 (0x79)
|
|
#define AXP192_BAT_AVERCHGCUR_H8 (0x7A)
|
|
#define AXP192_BAT_AVERCHGCUR_L4 (0x7B)
|
|
#define AXP192_BAT_AVERCHGCUR_L5 (0x7B)
|
|
#define AXP192_ACIN_VOL_H8 (0x56)
|
|
#define AXP192_ACIN_VOL_L4 (0x57)
|
|
#define AXP192_ACIN_CUR_H8 (0x58)
|
|
#define AXP192_ACIN_CUR_L4 (0x59)
|
|
#define AXP192_VBUS_VOL_H8 (0x5A)
|
|
#define AXP192_VBUS_VOL_L4 (0x5B)
|
|
#define AXP192_VBUS_CUR_H8 (0x5C)
|
|
#define AXP192_VBUS_CUR_L4 (0x5D)
|
|
#define AXP192_INTERNAL_TEMP_H8 (0x5E)
|
|
#define AXP192_INTERNAL_TEMP_L4 (0x5F)
|
|
#define AXP192_TS_IN_H8 (0x62)
|
|
#define AXP192_TS_IN_L4 (0x63)
|
|
#define AXP192_GPIO0_VOL_ADC_H8 (0x64)
|
|
#define AXP192_GPIO0_VOL_ADC_L4 (0x65)
|
|
#define AXP192_GPIO1_VOL_ADC_H8 (0x66)
|
|
#define AXP192_GPIO1_VOL_ADC_L4 (0x67)
|
|
#define AXP192_BAT_AVERDISCHGCUR_H8 (0x7C)
|
|
#define AXP192_BAT_AVERDISCHGCUR_L5 (0x7D)
|
|
|
|
|
|
// Interrupt enable
|
|
#define AXP192_INTEN1 (0x40)
|
|
#define AXP192_INTEN2 (0x41)
|
|
#define AXP192_INTEN3 (0x42)
|
|
#define AXP192_INTEN4 (0x43)
|
|
#define AXP192_INTEN5 (0x4A)
|
|
|
|
// Int clear.
|
|
#define AXP192_INTSTS1 (0x44)
|
|
#define AXP192_INTSTS2 (0x45)
|
|
#define AXP192_INTSTS3 (0x46)
|
|
#define AXP192_INTSTS4 (0x47)
|
|
#define AXP192_INTSTS5 (0x4D)
|
|
|
|
extern SemaphoreHandle_t axpSemaphore;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////
|
|
/// High-level functions
|
|
PMU *PMU::getInstance(TwoWire &wire) {
|
|
PMU *pmu = NULL;
|
|
// Check if there is some AXP192 or AXP2101 present
|
|
uint8_t chipid = readRegisterWire(wire, AXP192_IC_TYPE);
|
|
// AXP192: 0x03 AXP2101: 0x4A
|
|
if(chipid==0x03) {
|
|
pmu = new AXP192PMU(wire);
|
|
}
|
|
else if (chipid==0x4A) {
|
|
pmu = new AXP2101PMU(wire);
|
|
}
|
|
return pmu;
|
|
}
|
|
|
|
|
|
int PMU::readRegisterWire(TwoWire &wire, uint8_t reg) {
|
|
wire.beginTransmission(AXP192_SLAVE_ADDRESS);
|
|
wire.write(reg);
|
|
if (wire.endTransmission() != 0) {
|
|
return -1;
|
|
}
|
|
wire.requestFrom(AXP192_SLAVE_ADDRESS, 1U);
|
|
return wire.read();
|
|
}
|
|
int PMU::readRegister(uint8_t reg) {
|
|
return readRegisterWire(_wire, reg);
|
|
}
|
|
uint16_t PMU::readRegisters_8_4(uint8_t regh, uint8_t regl)
|
|
{
|
|
uint8_t hi = readRegister(regh);
|
|
uint8_t lo = readRegister(regl);
|
|
return (hi << 4) | (lo & 0x0F);
|
|
}
|
|
|
|
uint16_t PMU::readRegisters_8_5(uint8_t regh, uint8_t regl)
|
|
{
|
|
uint8_t hi = readRegister(regh);
|
|
uint8_t lo = readRegister(regl);
|
|
return (hi << 5) | (lo & 0x1F);
|
|
}
|
|
|
|
int PMU::writeRegister(uint8_t reg, uint8_t val) {
|
|
_wire.beginTransmission(AXP192_SLAVE_ADDRESS);
|
|
_wire.write(reg);
|
|
_wire.write(val);
|
|
return (_wire.endTransmission() == 0) ? 0 : -1;
|
|
}
|
|
int PMU::getRegisterBit(uint8_t reg, uint8_t bit) {
|
|
int val = readRegister(reg);
|
|
if (val == -1) { return -1; }
|
|
return (val >> bit) & 0x01;
|
|
}
|
|
int PMU::setRegisterBit(uint8_t reg, uint8_t bit) {
|
|
int val = readRegister(reg);
|
|
if (val == -1) { return -1; }
|
|
return writeRegister(reg, (val | (1<<bit)));
|
|
}
|
|
int PMU::clearRegisterBit(uint8_t reg, uint8_t bit) {
|
|
int val = readRegister(reg);
|
|
if (val == -1) { return -1; }
|
|
return writeRegister(reg, (val & ( ~(1<<bit))));
|
|
}
|
|
|
|
// Returns if there was a keypress, using the following enum defined in RX_FSK.ini:
|
|
enum KeyPress { KP_NONE = 0, KP_SHORT, KP_DOUBLE, KP_MID, KP_LONG };
|
|
|
|
int PMU::handleIRQ() {
|
|
if (pmu_irq) {
|
|
Serial.println("PMU_IRQ is set\n");
|
|
} else {
|
|
return -1;
|
|
}
|
|
int keypress = -1;
|
|
xSemaphoreTake( axpSemaphore, portMAX_DELAY );
|
|
keypress = getIrqKeyStatus();
|
|
if(keypress) { Serial.printf("Keypress: %d (%s)", keypress, keypress==KP_SHORT?"short":"mid"); }
|
|
if (pmu_irq != 2) {
|
|
pmu_irq = 0;
|
|
}
|
|
xSemaphoreGive( axpSemaphore );
|
|
return keypress;
|
|
}
|
|
|
|
int AXP192PMU::init() {
|
|
// Initialize AXP192, for T-BEAM v1.1 or M5Stack
|
|
|
|
// LDO2: LoRa VCC on T-BEAM, PERI_VDD on M5Core2 (LCD)
|
|
setLDO2(3300);
|
|
enableLDO2();
|
|
if(sonde.config.type == TYPE_M5_CORE2) {
|
|
// Display backlight (LCD_BL) on M5 Core2
|
|
setDC3(3300);
|
|
enableDC3();
|
|
pmu_irq = 2; // IRQ pin not connected on Core2
|
|
// Set GPIO0 VDO to 3.3V (as is done by original M5Stack software)
|
|
// (default value 2.8V did not have the expected effect :))
|
|
setLDOio(3300);
|
|
// ADC configuration: Enable monitoring of AC [bits 4,5 in enable register]
|
|
uint8_t val = readRegister(AXP192_ADC_EN1);
|
|
writeRegister(AXP192_ADC_EN1, val | (1 << 4) | (1 << 5) );
|
|
} else {
|
|
// T-Beam specific
|
|
// GPS power on T-Beam (its the buzzer on M5 Core2, so only enable for T-Beam)
|
|
enableLDO3();
|
|
// ADC configuration: Enable monitoring of USB [bits 2,3 in enable register]
|
|
uint8_t val = readRegister(AXP192_ADC_EN1);
|
|
writeRegister(AXP192_ADC_EN1, val | (1 << 4) | (1 << 5) );
|
|
}
|
|
// Common configuration for T-Beam and M5 Core2
|
|
// DCDC2: M5Core: Unused, T-Beam: Unused, so set to disabled!! (was enabled in previous versions)
|
|
enableDC2(false);
|
|
|
|
// EXTEN: M5Core2: 5V Boost enable; T-Beam EXTEN
|
|
enableEXTEN();
|
|
|
|
// DCDC1: M5Core: MCU_VDD, T-Beam 1.1: "VCC_2.5V" == 3V3-Pin on pin header on board
|
|
setDC1(3300);
|
|
enableDC1();
|
|
|
|
// ADC configuration: Enable monitor batt current [bit 6 in eable register]
|
|
uint8_t val = readRegister(AXP192_ADC_EN1);
|
|
writeRegister(AXP192_ADC_EN1, val | (1 << 6) );
|
|
|
|
if (pmu_irq != 2) {
|
|
pinMode(PMU_IRQ, INPUT_PULLUP);
|
|
attachInterrupt(PMU_IRQ, [] {
|
|
pmu_irq = 1;
|
|
}, FALLING);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
/// Helper functions
|
|
|
|
int AXP192PMU::getIrqKeyStatus() {
|
|
int status = readRegister(AXP192_INTSTS3);
|
|
|
|
// Also clear IRQ status
|
|
writeRegister(AXP192_INTSTS1, 0xFF);
|
|
writeRegister(AXP192_INTSTS2, 0xFF);
|
|
writeRegister(AXP192_INTSTS3, 0xFF);
|
|
writeRegister(AXP192_INTSTS4, 0xFF);
|
|
writeRegister(AXP192_INTSTS5, 0xFF);
|
|
|
|
//
|
|
if ( status & 0x01 ) return KP_MID;
|
|
if ( status & 0x02 ) return KP_SHORT;
|
|
return KP_NONE;
|
|
}
|
|
|
|
|
|
void AXP192PMU::disableAllIRQ() {
|
|
writeRegister(AXP192_INTEN1, 0);
|
|
writeRegister(AXP192_INTEN2, 0);
|
|
writeRegister(AXP192_INTEN3, 0);
|
|
writeRegister(AXP192_INTEN4, 0);
|
|
writeRegister(AXP192_INTEN5, 0);
|
|
}
|
|
|
|
void AXP192PMU::_enableIRQ(uint8_t addr, uint8_t mask) {
|
|
int data = readRegister(addr);
|
|
writeRegister(addr, data | mask);
|
|
}
|
|
|
|
// we want KP_SHORT and KP_LONG interrupts...
|
|
// IRQ4, in reg 0x42h, Bit 16+17
|
|
void AXP192PMU::enableIRQ() {
|
|
//_enableIRQ( AXP192_INTEN1, mask&0xFF );
|
|
//_enableIRQ( AXP192_INTEN2, mask>>8 );
|
|
_enableIRQ( AXP192_INTEN3, 0x03 );
|
|
//_enableIRQ( AXP192_INTEN4, mask>>24 );
|
|
//_enableIRQ( AXP192_INTEN5, mask>>32 );
|
|
}
|
|
|
|
// Functions for setting voltage output levels
|
|
int AXP192PMU::setVoltageReg(uint8_t reg, uint8_t regval) {
|
|
int val = readRegister(reg);
|
|
if (val==-1) return -1;
|
|
val &= 0x80;
|
|
val |= regval;
|
|
return writeRegister(reg, val);
|
|
}
|
|
|
|
int AXP192PMU::setDC1(uint16_t millivolt) {
|
|
return setVoltageReg(AXP192_DC1OUT_VOL, (millivolt-AXP192_DC_MIN)/AXP192_DC_STEPS );
|
|
}
|
|
int AXP192PMU::setDC2(uint16_t millivolt) {
|
|
return setVoltageReg(AXP192_DC2OUT_VOL, (millivolt-AXP192_DC_MIN)/AXP192_DC_STEPS );
|
|
}
|
|
int AXP192PMU::setDC3(uint16_t millivolt) {
|
|
return setVoltageReg(AXP192_DC3OUT_VOL , (millivolt-AXP192_DC_MIN)/AXP192_DC_STEPS );
|
|
}
|
|
int AXP192PMU::setLDO2(uint16_t millivolt) {
|
|
return setVoltageReg(AXP192_LDO23OUT_VOL, (millivolt-AXP192_LDO_MIN)/AXP192_LDO_STEPS);
|
|
}
|
|
int AXP192PMU::setLDOio(uint16_t millivolt) {
|
|
return setVoltageReg(AXP192_GPIO0_VOL, (millivolt-AXP192_LDO_MIN)/AXP192_LDO_STEPS);
|
|
}
|
|
|
|
|
|
// LDO23_DC123_EXT_CTL
|
|
// 0:DC-DC1, 1:DC-DC3, 2:LDO2, 3:LDO3, 4:DC-DC2, 6:EXTEN
|
|
int AXP192PMU::enableDC1(bool onoff) {
|
|
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 0) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 0);
|
|
}
|
|
int AXP192PMU::enableDC3(bool onoff) {
|
|
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 1) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 1);
|
|
}
|
|
int AXP192PMU::enableLDO2(bool onoff) {
|
|
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 2) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 2);
|
|
}
|
|
int AXP192PMU::enableLDO3(bool onoff) {
|
|
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 3) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 3);
|
|
}
|
|
int AXP192PMU::enableDC2(bool onoff) {
|
|
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 4) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 4);
|
|
}
|
|
int AXP192PMU::enableEXTEN(bool onoff) {
|
|
return onoff ? setRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 6) : clearRegisterBit(AXP192_LDO23_DC123_EXT_CTL, 6);
|
|
}
|
|
|
|
int AXP192PMU::enableADC(uint8_t channels) {
|
|
uint8_t val = readRegister(AXP192_ADC_EN1);
|
|
return writeRegister(AXP192_ADC_EN1, val | channels );
|
|
}
|
|
|
|
int AXP192PMU::isBatteryConnected() {
|
|
return getRegisterBit(AXP192_MODE_CHGSTATUS, 5);
|
|
}
|
|
int AXP192PMU::isVbusIn() {
|
|
return getRegisterBit(AXP192_STATUS, 5);
|
|
}
|
|
int AXP192PMU::isCharging() {
|
|
return getRegisterBit(AXP192_MODE_CHGSTATUS, 6);
|
|
}
|
|
|
|
#define AXP192_BATT_VOLTAGE_STEP (1.1F)
|
|
float AXP192PMU::getBattVoltage() {
|
|
return readRegisters_8_4(AXP192_BAT_AVERVOL_H8, AXP192_BAT_AVERVOL_L4) * AXP192_BATT_VOLTAGE_STEP;
|
|
}
|
|
|
|
#define AXP192_BATT_DISCHARGE_CUR_STEP (0.5F)
|
|
float AXP192PMU::getBattDischargeCurrent() {
|
|
return readRegisters_8_5(AXP192_BAT_AVERDISCHGCUR_H8, AXP192_BAT_AVERDISCHGCUR_L5) * AXP192_BATT_DISCHARGE_CUR_STEP;
|
|
}
|
|
|
|
#define AXP192_BATT_CHARGE_CUR_STEP (0.5F)
|
|
float AXP192PMU::getBattChargeCurrent() {
|
|
return readRegisters_8_5(AXP192_BAT_AVERCHGCUR_H8, AXP192_BAT_AVERCHGCUR_L5) * AXP192_BATT_CHARGE_CUR_STEP;
|
|
}
|
|
|
|
#define AXP192_ACIN_VOLTAGE_STEP (1.7F)
|
|
float AXP192PMU::getAcinVoltage() {
|
|
return readRegisters_8_4(AXP192_ACIN_VOL_H8, AXP192_ACIN_VOL_L4) * AXP192_ACIN_VOLTAGE_STEP;
|
|
}
|
|
|
|
#define AXP192_ACIN_CUR_STEP (0.625F)
|
|
float AXP192PMU::getAcinCurrent() {
|
|
return readRegisters_8_4(AXP192_ACIN_CUR_H8, AXP192_ACIN_CUR_L4) * AXP192_ACIN_CUR_STEP;
|
|
}
|
|
|
|
#define AXP192_VBUS_VOLTAGE_STEP (1.7F)
|
|
float AXP192PMU::getVbusVoltage() {
|
|
return readRegisters_8_4(AXP192_VBUS_VOL_H8, AXP192_VBUS_VOL_L4) * AXP192_VBUS_VOLTAGE_STEP;
|
|
}
|
|
|
|
#define AXP192_VBUS_CUR_STEP (0.375F)
|
|
float AXP192PMU::getVbusCurrent() {
|
|
return readRegisters_8_4(AXP192_VBUS_CUR_H8, AXP192_VBUS_CUR_L4) * AXP192_VBUS_CUR_STEP;
|
|
}
|
|
|
|
#define AXP192_INTERNAL_TEMP_STEP (0.1F)
|
|
float AXP192PMU::getTemperature() {
|
|
return readRegisters_8_4(AXP192_INTERNAL_TEMP_H8, AXP192_INTERNAL_TEMP_L4) * AXP192_INTERNAL_TEMP_STEP - 144.7;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
/////// Functions for AXP2101
|
|
|
|
// Registers
|
|
#define AXP2101_CHARGE_GAUGE_WDT_CTRL (0x18)
|
|
#define AXP2101_BTN_BAT_CHG_VOL_SET (0x6A)
|
|
#define AXP2101_DC_ONOFF_DVM_CTRL (0x80)
|
|
#define AXP2101_LDO_ONOFF_CTRL0 (0x90)
|
|
#define AXP2101_LDO_ONOFF_CTRL1 (0x91)
|
|
|
|
#define AXP2101_LDO_VOL1_CTRL (0x93)
|
|
#define AXP2101_LDO_VOL2_CTRL (0x94)
|
|
|
|
#define AXP2101_ADC_CHANNEL_CTRL (0x30)
|
|
|
|
// vterm_cfg: Bit 2:0, 4.2V = 011 (3)
|
|
#define AXP2101_CHG_V_CFG (0x64)
|
|
// ICC_CFG: Bit 4:0: constant current charge current limit, 25*N mA (N<=8), 200+100*(N-8) (N>8)
|
|
#define AXP2101_ICC_CFG (0x62)
|
|
|
|
// Interrupt enable
|
|
#define AXP2101_INTEN1 (0x40)
|
|
#define AXP2101_INTEN2 (0x41)
|
|
#define AXP2101_INTEN3 (0x42)
|
|
|
|
// Interrupt status
|
|
#define AXP2101_INTSTS1 (0x48)
|
|
#define AXP2101_INTSTS2 (0x49)
|
|
#define AXP2101_INTSTS3 (0x4A)
|
|
|
|
// Constants
|
|
#define AXP2101_ALDO_VOL_MIN (500)
|
|
#define AXP2101_ALDO_VOL_STEPS (100)
|
|
|
|
#define AXP2101_BTN_VOL_MIN (2600)
|
|
#define AXP2101_BTN_VOL_STEPS (100)
|
|
|
|
// 200 + 100*(11-8) = 500
|
|
#define AXP2101_CHG_CUR_500MA (0x0B)
|
|
#define AXP2101_CHG_VOL_4V2 (3)
|
|
|
|
|
|
// return 0: ok, -1: error
|
|
int AXP2101PMU::init() {
|
|
// Initialize AXP2101, for T-BEAM v1.2
|
|
|
|
// Hard-coded for now, disable DC2/3/4/5 ALDO1,4 BLDO1/2 DLDO1/2
|
|
int val = readRegister(AXP2101_DC_ONOFF_DVM_CTRL);
|
|
writeRegister(AXP2101_DC_ONOFF_DVM_CTRL, val & (~0x1E)); // clear Bit 1,2,3,4 (DC2/3/4/5)
|
|
|
|
// clear bit 0 (aldo1), 3 (aldo4), 4,5(bldo1/2), 7 (dldo1)
|
|
val = readRegister(AXP2101_LDO_ONOFF_CTRL0);
|
|
writeRegister(AXP2101_LDO_ONOFF_CTRL0, val & (~0xB9));
|
|
|
|
// clear bit 0 (dldo2)
|
|
val = readRegister(AXP2101_LDO_ONOFF_CTRL1);
|
|
writeRegister(AXP2101_LDO_ONOFF_CTRL1, val & (~0x01));
|
|
|
|
// Set PowerVDD to 3100mV (GNSS RTC) -- reg 6A [MS412FE data sheet: charge volt 2.8-3.3; standard value 3.1]
|
|
val = readRegister(AXP2101_BTN_BAT_CHG_VOL_SET);
|
|
if (val == -1) return -1;
|
|
val &= 0xF8;
|
|
val |= (3100 - AXP2101_BTN_VOL_MIN) / AXP2101_BTN_VOL_STEPS;
|
|
writeRegister(AXP2101_BTN_BAT_CHG_VOL_SET, val);
|
|
|
|
setRegisterBit(AXP2101_CHARGE_GAUGE_WDT_CTRL, 2);
|
|
|
|
// ESP32 VDD 3300mV
|
|
// No need to set, automatically open , Don't close it
|
|
|
|
// LoRa VDD 3300mV on ALDO2
|
|
val = readRegister(AXP2101_LDO_VOL1_CTRL);
|
|
if (val == -1) return -1;
|
|
val &= 0xE0;
|
|
val |= (3300 - AXP2101_ALDO_VOL_MIN) / AXP2101_ALDO_VOL_STEPS;
|
|
writeRegister(AXP2101_LDO_VOL1_CTRL, val);
|
|
setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 1);
|
|
|
|
// GNSS VDD 3300mV on ALDO3
|
|
val = readRegister(AXP2101_LDO_VOL2_CTRL);
|
|
if (val == -1) return -1;
|
|
val &= 0xE0;
|
|
val |= (3300 - AXP2101_ALDO_VOL_MIN) / AXP2101_ALDO_VOL_STEPS;
|
|
writeRegister(AXP2101_LDO_VOL2_CTRL, val);
|
|
setRegisterBit(AXP2101_LDO_ONOFF_CTRL0, 2);
|
|
|
|
if (pmu_irq != 2) {
|
|
pinMode(PMU_IRQ, INPUT_PULLUP);
|
|
attachInterrupt(PMU_IRQ, [] {
|
|
pmu_irq = 1;
|
|
}, FALLING);
|
|
}
|
|
|
|
// Set charging configuration: 500mA, 4.2V cut off
|
|
|
|
// Set constant current charge limit to 500mA (reguster 0x62)
|
|
// Data sheep (7.3.3.) tells that default value is 1.024 A (which should be fine??)
|
|
// Data sheet (register table) tells that default value is "{EFUSE,0b,EFUSE}", whatever that is
|
|
// Let's set this to 500 mA manually to be sure
|
|
val = readRegister(AXP2101_ICC_CFG);
|
|
if (val == -1) return -1;
|
|
val &= 0xE0;
|
|
writeRegister(AXP2101_ICC_CFG, val | AXP2101_CHG_CUR_500MA);
|
|
|
|
#if 0
|
|
// Set cut-off voltage to 4.2V (register 0x63)
|
|
// This is the default value, so setting it should not be needed.
|
|
val = readRegister(AXP2101_CHG_V_CFG);
|
|
if (val == -1) return -1;
|
|
val &= 0xFC;
|
|
writeRegister(AXP2101_CHG_V_CFG, val | AXP2101_CHG_VOL_4V2);
|
|
#endif
|
|
|
|
// Disable TS measurement, enable vsys, vbus, vbat measurement
|
|
// Disable TS is important for T-Beam 1.2 (no TS thermistor), otherwise it will not charge.
|
|
writeRegister(AXP2101_ADC_CHANNEL_CTRL, 0x0d);
|
|
|
|
// Clear all IRQ
|
|
getIrqKeyStatus();
|
|
|
|
// precharge current (reg 0x61): default value (0101b) should be fine
|
|
// Termination current (125mA default value) should be fine as well
|
|
#if 0
|
|
// Just some debug code
|
|
Serial.println("All good \n");
|
|
|
|
for(int i=0; i<0x80; i++) {
|
|
val = readRegister(i);
|
|
Serial.printf("Reg %x: %x (%d)\n", i, val, val);
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
void AXP2101PMU::disableAllIRQ() {
|
|
writeRegister(AXP2101_INTEN1, 0);
|
|
writeRegister(AXP2101_INTEN2, 0);
|
|
writeRegister(AXP2101_INTEN3, 0);
|
|
}
|
|
|
|
void AXP2101PMU::_enableIRQ(uint8_t addr, uint8_t mask) {
|
|
int data = readRegister(addr);
|
|
writeRegister(addr, data | mask);
|
|
}
|
|
|
|
// we want KP_SHORT and KP_LONG interrupts...
|
|
// IRQen1, in req 0x41h, Bit 2(long)+3(short) (10+11 global)
|
|
void AXP2101PMU::enableIRQ() {
|
|
//_enableIRQ( AXP2101_INTEN1, mask&0xFF );
|
|
_enableIRQ( AXP2101_INTEN2, 0x0C );
|
|
//_enableIRQ( AXP2101_INTEN3, 0x03 );
|
|
}
|
|
|
|
int AXP2101PMU::getIrqKeyStatus() {
|
|
int status = readRegister(AXP2101_INTSTS2);
|
|
|
|
// Also clear IRQ status
|
|
writeRegister(AXP2101_INTSTS1, 0xFF);
|
|
writeRegister(AXP2101_INTSTS2, 0xFF);
|
|
writeRegister(AXP2101_INTSTS3, 0xFF);
|
|
|
|
//
|
|
if ( status & 0x04 ) return KP_MID;
|
|
if ( status & 0x08 ) return KP_SHORT;
|
|
return KP_NONE;
|
|
}
|
|
|
|
int AXP2101PMU::isBatteryConnected() { return -1; }
|
|
int AXP2101PMU::isVbusIn() { return -1; }
|
|
int AXP2101PMU::isCharging() { return -1; }
|
|
float AXP2101PMU::getBattVoltage() { return -1; }
|
|
float AXP2101PMU::getBattDischargeCurrent() { return -1; }
|
|
float AXP2101PMU::getBattChargeCurrent() { return -1; }
|
|
float AXP2101PMU::getAcinVoltage() { return -1; }
|
|
float AXP2101PMU::getAcinCurrent() { return -1; }
|
|
float AXP2101PMU::getVbusVoltage() { return -1; }
|
|
float AXP2101PMU::getVbusCurrent() { return -1; }
|
|
float AXP2101PMU::getTemperature() { return -1; }
|
|
|
|
|