mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-27 13:25:13 +00:00
351 lines
12 KiB
C++
351 lines
12 KiB
C++
#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276)
|
|
|
|
#include <Arduino.h>
|
|
#include "TBeamBoard.h"
|
|
//#include <RadioLib.h>
|
|
|
|
uint32_t deviceOnline = 0x00;
|
|
|
|
bool pmuInterrupt;
|
|
static void setPmuFlag()
|
|
{
|
|
pmuInterrupt = true;
|
|
}
|
|
|
|
void TBeamBoard::begin() {
|
|
|
|
ESP32Board::begin();
|
|
|
|
power_init();
|
|
|
|
//Configure user button
|
|
pinMode(PIN_USER_BTN, INPUT);
|
|
|
|
#ifndef TBEAM_SUPREME_SX1262
|
|
digitalWrite(P_LORA_TX_LED, HIGH); //inverted pin for SX1276 - HIGH for off
|
|
#endif
|
|
|
|
//radiotype_detect();
|
|
|
|
esp_reset_reason_t reason = esp_reset_reason();
|
|
if (reason == ESP_RST_DEEPSLEEP) {
|
|
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
|
|
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
|
|
startup_reason = BD_STARTUP_RX_PACKET;
|
|
}
|
|
|
|
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
|
|
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
|
|
}
|
|
}
|
|
|
|
#ifdef MESH_DEBUG
|
|
void TBeamBoard::scanDevices(TwoWire *w)
|
|
{
|
|
uint8_t err, addr;
|
|
int nDevices = 0;
|
|
uint32_t start = 0;
|
|
|
|
Serial.println("Scanning I2C for Devices");
|
|
for (addr = 1; addr < 127; addr++) {
|
|
start = millis();
|
|
w->beginTransmission(addr); delay(2);
|
|
err = w->endTransmission();
|
|
if (err == 0) {
|
|
nDevices++;
|
|
switch (addr) {
|
|
case 0x77:
|
|
case 0x76:
|
|
Serial.println("\tFound BME280 Sensor");
|
|
deviceOnline |= BME280_ONLINE;
|
|
break;
|
|
case 0x34:
|
|
Serial.println("\tFound AXP192/AXP2101 PMU");
|
|
deviceOnline |= POWERMANAGE_ONLINE;
|
|
break;
|
|
case 0x3C:
|
|
Serial.println("\tFound SSD1306/SH1106 display");
|
|
deviceOnline |= DISPLAY_ONLINE;
|
|
break;
|
|
case 0x51:
|
|
Serial.println("\tFound PCF8563 RTC");
|
|
deviceOnline |= PCF8563_ONLINE;
|
|
break;
|
|
case 0x1C:
|
|
Serial.println("\tFound QMC6310 MAG Sensor");
|
|
deviceOnline |= QMC6310_ONLINE;
|
|
break;
|
|
default:
|
|
Serial.print("\tI2C device found at address 0x");
|
|
if (addr < 16) {
|
|
Serial.print("0");
|
|
}
|
|
Serial.print(addr, HEX);
|
|
Serial.println(" !");
|
|
break;
|
|
}
|
|
|
|
} else if (err == 4) {
|
|
Serial.print("Unknow error at address 0x");
|
|
if (addr < 16) {
|
|
Serial.print("0");
|
|
}
|
|
Serial.println(addr, HEX);
|
|
}
|
|
}
|
|
if (nDevices == 0)
|
|
Serial.println("No I2C devices found\n");
|
|
|
|
Serial.println("Scan for devices is complete.");
|
|
Serial.println("\n");
|
|
|
|
Serial.printf("GPS RX pin: %d", PIN_GPS_RX);
|
|
Serial.printf(" GPS TX pin: %d", PIN_GPS_TX);
|
|
Serial.println();
|
|
}
|
|
void TBeamBoard::printPMU()
|
|
{
|
|
Serial.print("isCharging:"); Serial.println(PMU->isCharging() ? "YES" : "NO");
|
|
Serial.print("isDischarge:"); Serial.println(PMU->isDischarge() ? "YES" : "NO");
|
|
Serial.print("isVbusIn:"); Serial.println(PMU->isVbusIn() ? "YES" : "NO");
|
|
Serial.print("getBattVoltage:"); Serial.print(PMU->getBattVoltage()); Serial.println("mV");
|
|
Serial.print("getVbusVoltage:"); Serial.print(PMU->getVbusVoltage()); Serial.println("mV");
|
|
Serial.print("getSystemVoltage:"); Serial.print(PMU->getSystemVoltage()); Serial.println("mV");
|
|
|
|
// The battery percentage may be inaccurate at first use, the PMU will automatically
|
|
// learn the battery curve and will automatically calibrate the battery percentage
|
|
// after a charge and discharge cycle
|
|
if (PMU->isBatteryConnect()) {
|
|
Serial.print("getBatteryPercent:"); Serial.print(PMU->getBatteryPercent()); Serial.println("%");
|
|
}
|
|
|
|
Serial.println();
|
|
}
|
|
#endif
|
|
|
|
bool TBeamBoard::power_init()
|
|
{
|
|
if (!PMU) {
|
|
#ifdef TBEAM_SUPREME_SX1262
|
|
PMU = new XPowersAXP2101(PMU_WIRE_PORT, PIN_BOARD_SDA1, PIN_BOARD_SCL1, I2C_PMU_ADD);
|
|
#else
|
|
PMU = new XPowersAXP2101(PMU_WIRE_PORT, PIN_BOARD_SDA, PIN_BOARD_SCL, I2C_PMU_ADD);
|
|
#endif
|
|
if (!PMU->init()) {
|
|
MESH_DEBUG_PRINTLN("Warning: Failed to find AXP2101 power management");
|
|
delete PMU;
|
|
PMU = NULL;
|
|
} else {
|
|
MESH_DEBUG_PRINTLN("AXP2101 PMU init succeeded, using AXP2101 PMU");
|
|
}
|
|
}
|
|
if (!PMU) {
|
|
PMU = new XPowersAXP192(PMU_WIRE_PORT, PIN_BOARD_SDA, PIN_BOARD_SCL, I2C_PMU_ADD);
|
|
if (!PMU->init()) {
|
|
MESH_DEBUG_PRINTLN("Warning: Failed to find AXP192 power management");
|
|
delete PMU;
|
|
PMU = NULL;
|
|
} else {
|
|
MESH_DEBUG_PRINTLN("AXP192 PMU init succeeded, using AXP192 PMU");
|
|
}
|
|
}
|
|
|
|
if (!PMU) {
|
|
return false;
|
|
}
|
|
|
|
deviceOnline |= POWERMANAGE_ONLINE;
|
|
|
|
PMU->setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
|
|
|
|
// Set up PMU interrupts
|
|
pinMode(PIN_PMU_IRQ, INPUT_PULLUP);
|
|
attachInterrupt(PIN_PMU_IRQ, setPmuFlag, FALLING);
|
|
|
|
if (PMU->getChipModel() == XPOWERS_AXP192) {
|
|
|
|
PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300); //Set up LoRa power rail
|
|
PMU->enablePowerOutput(XPOWERS_LDO2); //Enable the LoRa power rail
|
|
|
|
PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300); //Set up OLED power rail
|
|
PMU->enablePowerOutput(XPOWERS_DCDC1); //Enable the OLED power rail
|
|
|
|
PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300); //Set up GPS power rail
|
|
PMU->enablePowerOutput(XPOWERS_LDO3); //Enable the GPS power rail
|
|
|
|
PMU->setProtectedChannel(XPOWERS_DCDC1); //Protect the OLED power rail
|
|
PMU->setProtectedChannel(XPOWERS_DCDC3); //Protect the ESP32 power rail
|
|
|
|
PMU->disablePowerOutput(XPOWERS_DCDC2); //Disable unsused power rail DC2
|
|
|
|
PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ); //Disable PMU IRQ
|
|
|
|
PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_450MA); //Set battery charging current
|
|
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2); //Set battery charge-stop voltage
|
|
}
|
|
else if(PMU->getChipModel() == XPOWERS_AXP2101){
|
|
#ifdef TBEAM_SUPREME_SX1262
|
|
//Set up the GPS power rail
|
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
|
|
PMU->enablePowerOutput(XPOWERS_ALDO4);
|
|
|
|
//Set up the LoRa power rail
|
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
|
|
PMU->enablePowerOutput(XPOWERS_ALDO3);
|
|
|
|
//Set up power rail for the M.2 interface
|
|
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
|
|
PMU->enablePowerOutput(XPOWERS_DCDC3);
|
|
|
|
if (ESP_SLEEP_WAKEUP_UNDEFINED == esp_sleep_get_wakeup_cause()) {
|
|
MESH_DEBUG_PRINTLN("Power off and restart ALDO BLDO..");
|
|
PMU->disablePowerOutput(XPOWERS_ALDO1);
|
|
PMU->disablePowerOutput(XPOWERS_ALDO2);
|
|
PMU->disablePowerOutput(XPOWERS_BLDO1);
|
|
delay(250);
|
|
}
|
|
|
|
//Set up power rail for QMC6310U
|
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
|
|
PMU->enablePowerOutput(XPOWERS_ALDO2);
|
|
|
|
//Set up power rail for BME280 and OLED
|
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
|
|
PMU->enablePowerOutput(XPOWERS_ALDO1);
|
|
|
|
//Set up pwer rail for SD Card
|
|
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
|
|
PMU->enablePowerOutput(XPOWERS_BLDO1);
|
|
|
|
//Set up power rail BLDO2 to headers
|
|
PMU->setPowerChannelVoltage(XPOWERS_BLDO2, 3300);
|
|
PMU->enablePowerOutput(XPOWERS_BLDO2);
|
|
|
|
//Set up power rail DCDC4 to headers
|
|
PMU->setPowerChannelVoltage(XPOWERS_DCDC4, XPOWERS_AXP2101_DCDC4_VOL2_MAX);
|
|
PMU->enablePowerOutput(XPOWERS_DCDC4);
|
|
|
|
//Set up power rail DCDC5 to headers
|
|
PMU->setPowerChannelVoltage(XPOWERS_DCDC5, 3300);
|
|
PMU->enablePowerOutput(XPOWERS_DCDC5);
|
|
|
|
//Disable unused power rails
|
|
PMU->disablePowerOutput(XPOWERS_DCDC2);
|
|
PMU->disablePowerOutput(XPOWERS_DLDO1);
|
|
PMU->disablePowerOutput(XPOWERS_DLDO2);
|
|
PMU->disablePowerOutput(XPOWERS_VBACKUP);
|
|
#else
|
|
//Turn off unused power rails
|
|
PMU->disablePowerOutput(XPOWERS_DCDC2);
|
|
PMU->disablePowerOutput(XPOWERS_DCDC3);
|
|
PMU->disablePowerOutput(XPOWERS_DCDC4);
|
|
PMU->disablePowerOutput(XPOWERS_DCDC5);
|
|
PMU->disablePowerOutput(XPOWERS_ALDO1);
|
|
PMU->disablePowerOutput(XPOWERS_ALDO4);
|
|
PMU->disablePowerOutput(XPOWERS_BLDO1);
|
|
PMU->disablePowerOutput(XPOWERS_BLDO2);
|
|
PMU->disablePowerOutput(XPOWERS_DLDO1);
|
|
PMU->disablePowerOutput(XPOWERS_DLDO2);
|
|
//PMU->disablePowerOutput(XPOWERS_CPULDO);
|
|
|
|
PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300); //Set up GPS RTC power
|
|
PMU->enablePowerOutput(XPOWERS_VBACKUP); //Turn on GPS RTC power
|
|
|
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); //Set up LoRa power rail
|
|
PMU->enablePowerOutput(XPOWERS_ALDO2); //Enable LoRa power rail
|
|
|
|
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); //Set up GPS power rail
|
|
PMU->enablePowerOutput(XPOWERS_ALDO3); //Enable GPS power rail
|
|
|
|
#endif
|
|
|
|
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); //Disable all PMU interrupts
|
|
|
|
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA); //Set battery charging current to 500mA
|
|
PMU->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2); //Set battery charging cutoff voltage to 4.2V
|
|
|
|
}
|
|
|
|
PMU->clearIrqStatus(); //Clear interrupt flags
|
|
|
|
PMU->disableTSPinMeasure(); //Disable TS detection, since it is not used
|
|
|
|
//Enable voltage measurements
|
|
PMU->enableSystemVoltageMeasure();
|
|
PMU->enableVbusVoltageMeasure();
|
|
PMU->enableBattVoltageMeasure();
|
|
|
|
#ifdef MESH_DEBUG
|
|
scanDevices(&Wire);
|
|
printPMU();
|
|
#endif
|
|
|
|
// Set the power key off press time
|
|
PMU->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
|
|
return true;
|
|
}
|
|
|
|
#pragma region "Debug code"
|
|
// void TBeamBoard::radiotype_detect(){
|
|
|
|
// static SPIClass spi;
|
|
// char chipTypeInfo;
|
|
|
|
// #if defined(P_LORA_SCLK)
|
|
// spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
|
|
// #endif
|
|
|
|
// for(int i = 0; i<radioVersions; i++){
|
|
// switch(i){
|
|
// case 0:
|
|
// CustomSX1262 radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
|
|
// int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8);
|
|
// if (status != RADIOLIB_ERR_NONE) {
|
|
// Serial.print("ERROR: SX1262 not found: ");
|
|
// Serial.println(status);
|
|
// //delete radio;
|
|
// radio = NULL;
|
|
// break;
|
|
// }
|
|
// else{
|
|
// MESH_DEBUG_PRINTLN("SX1262 detected");
|
|
// P_LORA_BUSY = 32;
|
|
// RADIO_CLASS = CustomSX1262;
|
|
// WRAPPER_CLASS = CustomSX1262Wrapper;
|
|
// SX126X_RX_BOOSTED_GAIN = true;
|
|
// SX126X_CURRENT_LIMIT = 140;
|
|
// //delete radio;
|
|
// radio = NULL;
|
|
// break;
|
|
// }
|
|
// case 1:
|
|
// SX1276 radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
|
|
// int status1 = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8);
|
|
// if (status1 != RADIOLIB_ERR_NONE) {
|
|
// Serial.print("ERROR: SX1272 not found: ");
|
|
// Serial.println(status1);
|
|
// //delete radio;
|
|
// radio = NULL;
|
|
// }
|
|
// else{
|
|
// MESH_DEBUG_PRINTLN("SX1272 detected");
|
|
// P_LORA_BUSY = RADIOLIB_NC;
|
|
// P_LORA_DIO_2 = 32;
|
|
// RADIO_CLASS = CustomSX1272;
|
|
// WRAPPER_CLASS = CustomSX1272Wrapper;
|
|
// SX127X_CURRENT_LIMIT = 120;
|
|
// //delete radio;
|
|
// radio = NULL;
|
|
// return;
|
|
// }
|
|
// default:
|
|
// }
|
|
// }
|
|
|
|
|
|
|
|
// }
|
|
#pragma endregion
|
|
|
|
#endif
|