pmu reorg, preparing for axp2101

pull/381/head
Hansi, dl9rdz 2023-08-26 17:19:38 +00:00
rodzic 082b6ccdf5
commit 60e97d917b
5 zmienionych plików z 550 dodań i 120 usunięć

Wyświetl plik

@ -1,7 +1,6 @@
#include "features.h"
#include "version.h"
#include "axp20x.h"
#include <WiFi.h>
#include <WiFiUdp.h>
#include <ESPAsyncWebServer.h>
@ -28,6 +27,8 @@
#include "src/json.h"
#include "src/posinfo.h"
#include "src/pmu.h"
/* Data exchange connectors */
#if FEATURE_CHASEMAPPER
#include "src/conn-chasemapper.h"
@ -51,11 +52,9 @@ const char *mainStateStr[5] = {"DECODER", "SPECTRUM", "WIFISCAN", "UPDATE", "TOU
AsyncWebServer server(80);
AXP20X_Class axp;
#define PMU_IRQ 35
PMU *pmu = NULL;
SemaphoreHandle_t axpSemaphore;
// 0: cleared; 1: set; 2: do not check, also query state of axp via i2c on each loop
uint8_t pmu_irq = 0;
extern uint8_t pmu_irq;
const char *updateHost = "rdzsonde.mooo.com";
int updatePort = 80;
@ -161,7 +160,7 @@ String processor(const String& var) {
lat = sonde.config.rxlat;
lon = sonde.config.rxlon;
}
if ( !isnan(lat) && !isnan(lon) ) {
//if ( !isnan(lat) && !isnan(lon) ) {
#endif
if ( posInfo.valid ) {
char p[40];
@ -318,7 +317,7 @@ const char *createQRGForm() {
return message;
}
const char *handleQRGPost(AsyncWebServerRequest *request) {
const char *handleQRGPost(AsyncWebServerRequest * request) {
char label[10];
// parameters: a_i, f_1, t_i (active/frequency/type)
File file = SPIFFS.open("/qrg.txt", "w");
@ -451,7 +450,7 @@ const char *createSondeHubMap() {
}
#endif
const char *handleWIFIPost(AsyncWebServerRequest *request) {
const char *handleWIFIPost(AsyncWebServerRequest * request) {
char label[10];
// parameters: a_i, f_1, t_i (active/frequency/type)
#if 1
@ -809,7 +808,7 @@ const char *handleConfigPost(AsyncWebServerRequest * request) {
f.close();
Serial.printf("Re-reading file file\n");
setupConfigData();
if(!gpsPos.valid) fixedToPosInfo();
if (!gpsPos.valid) fixedToPosInfo();
// TODO: Check if this is better done elsewhere?
// Use new config (whereever this is feasible without a reboot)
disp.setContrast();
@ -1595,23 +1594,10 @@ int getKeyPress() {
void handlePMUirq() {
if (sonde.config.button2_axp) {
// Use AXP power button as second button
if (pmu_irq) {
Serial.println("PMU_IRQ is set\n");
xSemaphoreTake( axpSemaphore, portMAX_DELAY );
axp.readIRQ();
if (axp.isPEKShortPressIRQ()) {
button2.pressed = KP_SHORT;
button2.keydownTime = my_millis();
}
if (axp.isPEKLongtPressIRQ()) {
button2.pressed = KP_MID;
button2.keydownTime = my_millis();
}
if (pmu_irq != 2) {
pmu_irq = 0;
}
axp.clearIRQ();
xSemaphoreGive( axpSemaphore );
int key = pmu->handleIRQ();
if (key > 0) {
button2.pressed = (KeyPress)key;
button2.keydownTime = my_millis();
}
} else {
Serial.println("handlePMIirq() called. THIS SHOULD NOT HAPPEN w/o button2_axp set");
@ -1642,7 +1628,7 @@ int getKeyPressEvent() {
#define SSD1306_ADDRESS 0x3c
bool ssd1306_found = false;
bool axp192_found = false;
bool axp_found = false;
int scanI2Cdevice(void)
{
@ -1663,9 +1649,9 @@ int scanI2Cdevice(void)
ssd1306_found = true;
Serial.println("ssd1306 display found");
}
if (addr == AXP192_SLAVE_ADDRESS) {
axp192_found = true;
Serial.println("axp192 PMU found");
if (addr == AXP192_SLAVE_ADDRESS) { // Same for AXP2101
axp_found = true;
Serial.println("axp2101 PMU found");
}
} else if (err == 4) {
Serial.print("Unknow error at address 0x");
@ -1746,71 +1732,25 @@ void setup()
delay(500);
scanI2Cdevice();
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
Serial.println("AXP192 Begin PASS");
} else {
Serial.println("AXP192 Begin FAIL");
}
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON);
if (sonde.config.type == TYPE_M5_CORE2) {
// Display backlight on M5 Core2
axp.setPowerOutPut(AXP192_DCDC3, AXP202_ON);
axp.setDCDC3Voltage(3300);
// SetBusPowerMode(0):
// #define AXP192_GPIO0_CTL (0x90)
// #define AXP192_GPIO0_VOL (0x91)
// #define AXP202_LDO234_DC23_CTL (0x12)
// The axp class lacks a functino to set GPIO0 VDO to 3.3V (as is done by original M5Stack software)
// so do this manually (default value 2.8V did not have the expected effect :))
// data = Read8bit(0x91);
// write1Byte(0x91, (data & 0X0F) | 0XF0);
uint8_t reg;
Wire.beginTransmission((uint8_t)AXP192_SLAVE_ADDRESS);
Wire.write(AXP192_GPIO0_VOL);
Wire.endTransmission();
Wire.requestFrom(AXP192_SLAVE_ADDRESS, 1);
reg = Wire.read();
reg = (reg & 0x0F) | 0xF0;
Wire.beginTransmission((uint8_t)AXP192_SLAVE_ADDRESS);
Wire.write(AXP192_GPIO0_VOL);
Wire.write(reg);
Wire.endTransmission();
// data = Read8bit(0x90);
// Write1Byte(0x90, (data & 0XF8) | 0X02)
axp.setGPIOMode(AXP_GPIO_0, AXP_IO_LDO_MODE); // disable AXP supply from VBUS
pmu_irq = 2; // IRQ pin is not connected on Core2
// data = Read8bit(0x12); //read reg 0x12
// Write1Byte(0x12, data | 0x40); // enable 3,3V => 5V booster
// this is done below anyway: axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON);
axp.adc1Enable(AXP202_ACIN_VOL_ADC1, 1);
axp.adc1Enable(AXP202_ACIN_CUR_ADC1, 1);
} else {
// GPS on T-Beam, buzzer on M5 Core2
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON);
axp.adc1Enable(AXP202_VBUS_VOL_ADC1, 1);
axp.adc1Enable(AXP202_VBUS_CUR_ADC1, 1);
}
axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON);
axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON);
axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON);
axp.setDCDC1Voltage(3300);
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
if (sonde.config.button2_axp ) {
if (pmu_irq != 2) {
pinMode(PMU_IRQ, INPUT_PULLUP);
attachInterrupt(PMU_IRQ, [] {
pmu_irq = 1;
}, FALLING);
if (!pmu) {
pmu = PMU::getInstance(Wire);
if (pmu) {
Serial.println("PMU found");
pmu->init();
}
//axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1);
axp.enableIRQ( AXP202_PEK_LONGPRESS_IRQ | AXP202_PEK_SHORTPRESS_IRQ, 1 );
axp.clearIRQ();
if (sonde.config.button2_axp ) {
//axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1);
//axp.enableIRQ( AXP202_PEK_LONGPRESS_IRQ | AXP202_PEK_SHORTPRESS_IRQ, 1 );
//axp.clearIRQ();
pmu->disableAllIRQ();
pmu->enableIRQ();
}
int ndevices = scanI2Cdevice();
if (sonde.fingerprint != 17 || ndevices > 0) break; // only retry for fingerprint 17 (startup problems of new t-beam with oled)
delay(500);
}
int ndevices = scanI2Cdevice();
if (sonde.fingerprint != 17 || ndevices > 0) break; // only retry for fingerprint 17 (startup problems of new t-beam with oled)
delay(500);
}
}
if (sonde.config.batt_adc >= 0) {
@ -2006,7 +1946,7 @@ void enterMode(int mode) {
} else if (mainState == ST_WIFISCAN) {
sonde.clearDisplay();
}
if (mode == ST_DECODER) {
// trigger activation of background task
// currentSonde should be set before enterMode()
@ -2074,7 +2014,7 @@ void loopDecoder() {
}
}
if (rdzserver.hasClient()) {
Serial.println("TCP JSON socket: new connection");
rdzclient.stop();
@ -2088,7 +2028,7 @@ void loopDecoder() {
if (c == '\n' || c == '}' || rdzDataPos >= RDZ_DATA_LEN) {
// parse GPS position from phone
rdzData[rdzDataPos] = c;
if (rdzDataPos > 2) parseGpsJson(rdzData, rdzDataPos+1);
if (rdzDataPos > 2) parseGpsJson(rdzData, rdzDataPos + 1);
rdzDataPos = 0;
}
else {
@ -2113,7 +2053,7 @@ void loopDecoder() {
connAPRS.updateSonde(s);
#endif
#if 0
// moved to conn-aprs.cpp
// moved to conn-aprs.cpp
char *str = aprs_senddata(s, sonde.config.call, sonde.config.objcall, sonde.config.udpfeed.symbol);
char raw[201];
int rawlen = aprsstr_mon2raw(str, raw, APRS_MAXLEN);
@ -2329,7 +2269,7 @@ void enableNetwork(bool enable) {
MDNS.addService("jsonrdz", "tcp", 14570);
//if (sonde.config.kisstnc.active) {
// tncserver.begin();
rdzserver.begin();
rdzserver.begin();
//}
#if FEATURE_MQTT
connMQTT.netsetup();

Wyświetl plik

@ -2,10 +2,10 @@
#include <U8x8lib.h>
#include <U8g2lib.h>
#include <SPIFFS.h>
#include <axp20x.h>
#include <MicroNMEA.h>
#include "Display.h"
#include "Sonde.h"
#include "pmu.h"
int readLine(Stream &stream, char *buffer, int maxlen);
@ -22,8 +22,7 @@ extern const char *version_id;
extern Sonde sonde;
extern AXP20X_Class axp;
extern bool axp192_found;
extern PMU *pmu;
extern SemaphoreHandle_t axpSemaphore;
extern xSemaphoreHandle globalLock;
@ -1668,13 +1667,14 @@ void Display::drawGPS(DispEntry *de) {
void Display::drawBatt(DispEntry *de) {
float val;
char buf[30];
if (!axp192_found) {
if (!pmu) {
if (sonde.config.batt_adc<0) return;
switch (de->extra[0])
{
case 'V':
val = (float)(analogRead(sonde.config.batt_adc)) / 4095 * 2 * 3.3 * 1.1;
snprintf(buf, 30, "%.2f%s", val, de->extra + 1);
Serial.printf("Batt: %s", buf);
break;
default:
*buf = 0;
@ -1685,48 +1685,65 @@ void Display::drawBatt(DispEntry *de) {
xSemaphoreTake( axpSemaphore, portMAX_DELAY );
switch(de->extra[0]) {
case 'S':
if(!axp.isBatteryConnect()) {
if(axp.isVBUSPlug()) { strcpy(buf, "U"); }
if(!pmu->isBatteryConnected()) {
if(pmu->isVbusIn()) { strcpy(buf, "U"); }
else { strcpy(buf, "N"); } // no battary
}
else if (axp.isChargeing()) { strcpy(buf, "C"); } // charging
else if (pmu->isCharging()) { strcpy(buf, "C"); } // charging
else { strcpy(buf, "B"); } // battery, but not charging
Serial.printf("Battery: %s\n", buf);
break;
case 'V':
val = axp.getBattVoltage();
val = pmu->getBattVoltage();
snprintf(buf, 30, "%.2f%s", val/1000, de->extra+1);
Serial.printf("Vbatt: %s\n", buf);
break;
case 'C':
val = axp.getBattChargeCurrent();
}
if(pmu->type==TYPE_AXP192) {
switch(de->extra[0]) {
case 'C':
val = pmu->getBattChargeCurrent();
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
Serial.printf("Icharge: %s\n", buf);
break;
case 'D':
val = axp.getBattDischargeCurrent();
case 'D':
val = pmu->getBattDischargeCurrent();
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
Serial.printf("Idischarge: %s\n", buf);
break;
case 'U':
case 'U':
if(sonde.config.type == TYPE_M5_CORE2) {
val = axp.getAcinVoltage();
val = pmu->getAcinVoltage();
} else {
val = axp.getVbusVoltage();
val = pmu->getVbusVoltage();
}
snprintf(buf, 30, "%.2f%s", val/1000, de->extra+1);
Serial.printf("Vbus: %s\n", buf);
break;
case 'I':
case 'I':
if(sonde.config.type == TYPE_M5_CORE2) {
val = axp.getAcinCurrent();
val = pmu->getAcinCurrent();
} else {
val = axp.getVbusCurrent();
val = pmu->getVbusCurrent();
}
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
Serial.printf("Ibus: %s\n", buf);
break;
case 'T':
val = axp.getTemp(); // fixed in newer versions of libraray: -144.7 no longer needed here!
case 'T':
val = pmu->getTemperature();
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
Serial.printf("temp: %s\n", buf);
break;
default:
default:
*buf=0;
}
}
} else if (pmu->type == TYPE_AXP2101) {
*buf = 0;
if(de->extra[0]=='T') {
val = pmu->getTemperature();
snprintf(buf, 30, "%.2f%s", val, de->extra+1);
}
}
xSemaphoreGive( axpSemaphore );
rdis->setFont(de->fmt);
drawString(de, buf);

370
RX_FSK/src/pmu.cpp 100644
Wyświetl plik

@ -0,0 +1,370 @@
#include <stdio.h>
#include <Wire.h>
#include "pmu.h"
#include "src/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);
}
#if 0
else if (chipid==0x4A) {
pmu = new AXP2101PMU(wire);
}
#endif
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;
}
int AXP2101PMU::init() {
// Initialize AXP2101, for T-BEAM v1.2
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

103
RX_FSK/src/pmu.h 100644
Wyświetl plik

@ -0,0 +1,103 @@
#include <inttypes.h>
#include <Wire.h>
#define AXP192_SLAVE_ADDRESS 0x34
enum { TYPE_NONE=-1, TYPE_UNKNOWN=0, TYPE_AXP192, TYPE_AXP2101 };
class PMU {
protected:
PMU(TwoWire &wire) : _wire(wire) { };
public:
TwoWire &_wire;
static PMU *getInstance(TwoWire &wire);
int type;
static int readRegisterWire(TwoWire &wire, uint8_t reg);
int readRegister(uint8_t reg);
uint16_t readRegisters_8_4(uint8_t reghi, uint8_t reglo);
uint16_t readRegisters_8_5(uint8_t reghi, uint8_t reglo);
int writeRegister(uint8_t reg, uint8_t val);
int getRegisterBit(uint8_t register, uint8_t bit);
int setRegisterBit(uint8_t register, uint8_t bit);
int clearRegisterBit(uint8_t register, uint8_t bit);
int handleIRQ();
virtual int init();
virtual void disableAllIRQ();
virtual void enableIRQ();
virtual int getIrqKeyStatus();
virtual int isBatteryConnected();
virtual int isVbusIn();
virtual int isCharging();
virtual float getBattVoltage();
virtual float getBattDischargeCurrent();
virtual float getBattChargeCurrent();
virtual float getAcinVoltage();
virtual float getAcinCurrent();
virtual float getVbusVoltage();
virtual float getVbusCurrent();
virtual float getTemperature();
};
/* Interface */
class AXP192PMU : public PMU {
public:
AXP192PMU(TwoWire &wire) : PMU(wire) { type = TYPE_AXP192; };
int init();
void disableAllIRQ();
void enableIRQ();
int getIrqKeyStatus();
int isBatteryConnected();
int isVbusIn();
int isCharging();
float getBattVoltage();
float getBattDischargeCurrent();
float getBattChargeCurrent();
float getAcinVoltage();
float getAcinCurrent();
float getVbusVoltage();
float getVbusCurrent();
float getTemperature();
protected:
void _enableIRQ(uint8_t addr, uint8_t mask);
int setVoltageReg(uint8_t reg, uint8_t regval);
int setDC1(uint16_t millivolt);
int setDC2(uint16_t millivolt);
int setDC3(uint16_t millivolt);
int setLDO2(uint16_t millivolt);
int setLDOio(uint16_t millivolt);
int enableDC1(bool onff = true);
int enableDC3(bool onoff = true);
int enableLDO2(bool onoff = true);
int enableLDO3(bool onoff = true);
int enableDC2(bool onoff = true);
int enableEXTEN(bool onoff = true);
int enableADC(uint8_t channels);
};
class AXP2101PMU : public PMU {
public:
AXP2101PMU(TwoWire &wire) : PMU(wire) { };
int init();
protected:
int setVBACKUP(uint16_t millivolt);
int setDCDC1(uint16_t millivolt);
int setALDO2(uint16_t millivolt);
int setALDO3(uint16_t millivolt);
int disableAll();
int enableVBACKUP(bool onoff = true);
int enableDC1(bool onoff = true);
int enableALDO2(bool onoff = true);
int enableALDO3(bool onoff = true);
};

Wyświetl plik

@ -18,7 +18,6 @@ lib_deps_builtin =
; src
lib_deps_external =
olikraus/U8g2 @ ^2.28.8
AXP202X_Library
stevemarple/MicroNMEA @ ^2.0.5
me-no-dev/ESP Async WebServer @ ^1.2.3
https://github.com/moononournation/Arduino_GFX#v1.1.5
@ -47,3 +46,4 @@ lib_ignore = Time
;
extra_scripts = post:scripts/makefontpartition.py
;board_build.partitions = partition-fonts.csv