Просмотр исходного кода

Merge branch 'dev' into double-acks

Scott Powell 1 год назад
Родитель
Сommit
70252b010c

+ 25 - 2
examples/companion_radio/DataStore.cpp

@@ -44,6 +44,20 @@ void DataStore::begin() {
   #include <InternalFileSystem.h>
 #endif
 
+#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
+int _countLfsBlock(void *p, lfs_block_t block){
+  lfs_size_t *size = (lfs_size_t*) p;
+  *size += 1;
+  return 0;
+}
+
+lfs_ssize_t _getLfsUsedBlockCount() {
+  lfs_size_t size = 0;
+  lfs_traverse(InternalFS._getFS(), _countLfsBlock, &size);
+  return size;
+}
+#endif
+
 uint32_t DataStore::getStorageUsedKb() const {
 #if defined(ESP32)
   return SPIFFS.usedBytes() / 1024;
@@ -52,8 +66,13 @@ uint32_t DataStore::getStorageUsedKb() const {
   info.usedBytes = 0;
   _fs->info(info);
   return info.usedBytes / 1024;
+#elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
+  const lfs_config* config = InternalFS._getFS()->cfg;
+  int usedBlockCount = _getLfsUsedBlockCount();
+  int usedBytes = config->block_size * usedBlockCount;
+  return usedBytes / 1024;
 #else
-  return 0;  // TODO:  InternalFS. method?
+  return 0;
 #endif
 }
 
@@ -65,8 +84,12 @@ uint32_t DataStore::getStorageTotalKb() const {
   info.totalBytes = 0;
   _fs->info(info);
   return info.totalBytes / 1024;
+#elif defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
+  const lfs_config* config = InternalFS._getFS()->cfg;
+  int totalBytes = config->block_size * config->block_count;
+  return totalBytes / 1024;
 #else
-  return 0;  // TODO:  InternalFS. method?
+  return 0;
 #endif
 }
 

+ 1 - 1
examples/companion_radio/MyMesh.h

@@ -7,7 +7,7 @@
 #endif
 
 /*------------ Frame Protocol --------------*/
-#define FIRMWARE_VER_CODE 5
+#define FIRMWARE_VER_CODE 6
 
 #ifndef FIRMWARE_BUILD_DATE
 #define FIRMWARE_BUILD_DATE "7 Jun 2025"

+ 8 - 4
examples/simple_room_server/main.cpp

@@ -123,6 +123,8 @@ struct PostInfo {
 #define PUSH_TIMEOUT_BASE          4000
 #define PUSH_ACK_TIMEOUT_FACTOR    2000
 
+#define POST_SYNC_DELAY_SECS       6
+
 #define CLIENT_KEEP_ALIVE_SECS     0     // Now Disabled (was 128)
 
 #define REQ_TYPE_GET_STATUS          0x01   // same as _GET_STATS
@@ -864,13 +866,15 @@ public:
       bool did_push = false;
       if (client->pending_ack == 0 && client->last_activity != 0 && client->push_failures < 3) {  // not already waiting for ACK, AND not evicted, AND retries not max
         MESH_DEBUG_PRINTLN("loop - checking for client %02X", (uint32_t) client->id.pub_key[0]);
+        uint32_t now = getRTCClock()->getCurrentTime();
         for (int k = 0, idx = next_post_idx; k < MAX_UNSYNCED_POSTS; k++) {
-          if (posts[idx].post_timestamp > client->sync_since   // is new post for this Client?
-            && !posts[idx].author.matches(client->id)) {    // don't push posts to the author
+          auto p = &posts[idx];
+          if (now >= p->post_timestamp + POST_SYNC_DELAY_SECS && p->post_timestamp > client->sync_since   // is new post for this Client?
+            && !p->author.matches(client->id)) {    // don't push posts to the author
             // push this post to Client, then wait for ACK
-            pushPostToClient(client, posts[idx]);
+            pushPostToClient(client, *p);
             did_push = true;
-            MESH_DEBUG_PRINTLN("loop - pushed to client %02X: %s", (uint32_t) client->id.pub_key[0], posts[idx].text);
+            MESH_DEBUG_PRINTLN("loop - pushed to client %02X: %s", (uint32_t) client->id.pub_key[0], p->text);
             break;
           }
           idx = (idx + 1) % MAX_UNSYNCED_POSTS;   // wrap to start of cyclic queue

+ 1 - 1
src/helpers/AdvertDataHelpers.h

@@ -57,7 +57,7 @@ public:
   bool hasName() const { return _name[0] != 0; }
   const char* getName() const { return _name; }
 
-  bool hasLatLon() const { return !(_lat == 0 && _lon == 0); }
+  bool hasLatLon() const { return (_flags & ADV_LATLON_MASK) != 0; }
   int32_t getIntLat() const { return _lat; }
   int32_t getIntLon() const { return _lon; }
   double getLat() const { return ((double)_lat) / 1000000.0; }

+ 0 - 87
src/helpers/TBeamBoard.h

@@ -1,87 +0,0 @@
-#pragma once
-
-
-#include <Wire.h>
-#include <Arduino.h>
-#include "XPowersLib.h"
-
-// Defined using AXP2102
-#define XPOWERS_CHIP_AXP2101
-#define PIN_BOARD_SDA1 42  //SDA for PMU and PFC8563 (RTC)
-#define PIN_BOARD_SCL1 41  //SCL for PMU and PFC8563 (RTC)
-#define PIN_PMU_IRQ 40     //IRQ pin for PMU
-
-// LoRa radio module pins for TBeam
-#define  P_LORA_DIO_0   26
-#define  P_LORA_DIO_2   32
-#define  P_LORA_DIO_1   33
-#define  P_LORA_NSS     18
-#define  P_LORA_RESET   14
-#define  P_LORA_BUSY    RADIOLIB_NC
-#define  P_LORA_SCLK     5
-#define  P_LORA_MISO    19
-#define  P_LORA_MOSI    27
-
-// built-ins
-//#define  PIN_VBAT_READ   37
-//#define  PIN_LED_BUILTIN 25
-
-#include "ESP32Board.h"
-
-#include <driver/rtc_io.h>
-
-class TBeamBoard : public ESP32Board {
-  XPowersLibInterface *PMU = NULL;
-public:
-  bool power_init();
-  void printPMU();
-
-  void begin() {
-    ESP32Board::begin();
-    pinMode(38, INPUT_PULLUP);
-
-    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);
-    }
-    power_init();
-  }
-
-  void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1) {
-    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
-
-    // Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
-    rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
-    rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
-
-    rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
-
-    if (pin_wake_btn < 0) {
-      esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH);  // wake up on: recv LoRa packet
-    } else {
-      esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH);  // wake up on: recv LoRa packet OR wake btn
-    }
-
-    if (secs > 0) {
-      esp_sleep_enable_timer_wakeup(secs * 1000000);
-    }
-
-    // Finally set ESP32 into sleep
-    esp_deep_sleep_start();   // CPU halts here and never returns!
-  }
-
-  uint16_t getBattMilliVolts() override {
-    if(PMU) return PMU->getBattVoltage();
-    else return 0;
-  }
-
-  const char* getManufacturerName() const override {
-    return "LilyGo T-Beam";
-  }
-};

+ 0 - 79
src/helpers/TBeamBoardSX1262.h

@@ -1,79 +0,0 @@
-#pragma once
-
-
-#include <Wire.h>
-#include <Arduino.h>
-#include "XPowersLib.h"
-
-#define XPOWERS_CHIP_AXP192
-
-// LoRa radio module pins for TBeam
-#define  P_LORA_DIO_1   33 // SX1262 IRQ pin
-#define  P_LORA_NSS     18
-#define  P_LORA_RESET   23
-#define  P_LORA_BUSY    32 // SX1262 Busy pin
-#define  P_LORA_SCLK     5
-#define  P_LORA_MISO    19
-#define  P_LORA_MOSI    27
-
-#include "ESP32Board.h"
-
-#include <driver/rtc_io.h>
-
-class TBeamBoardSX1262 : public ESP32Board {
-  XPowersAXP192 power;
-
-public:
-  void begin() {
-    ESP32Board::begin();
-
-    power.setLDO2Voltage(3300);
-    power.enableLDO2();
-
-    power.enableBattVoltageMeasure();
-
-    pinMode(38, INPUT_PULLUP);
-
-    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);
-    }
-  }
-
-  void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1) {
-    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
-
-    // Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
-    rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
-    rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
-
-    rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
-
-    if (pin_wake_btn < 0) {
-      esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH);  // wake up on: recv LoRa packet
-    } else {
-      esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH);  // wake up on: recv LoRa packet OR wake btn
-    }
-
-    if (secs > 0) {
-      esp_sleep_enable_timer_wakeup(secs * 1000000);
-    }
-
-    // Finally set ESP32 into sleep
-    esp_deep_sleep_start();   // CPU halts here and never returns!
-  }
-
-  uint16_t getBattMilliVolts() override  {
-    return power.getBattVoltage();
-  }
-
-  const char* getManufacturerName() const override {
-    return "LilyGo T-Beam SX1262";
-  }
-};

+ 0 - 116
src/helpers/TBeamS3SupremeBoard.h

@@ -1,116 +0,0 @@
-#pragma once
-
-#include "ESP32Board.h"
-#include <driver/rtc_io.h>
-#include <Wire.h>
-#include <Arduino.h>
-#include "XPowersLib.h"
-
-// LoRa radio module pins for TBeam S3 Supreme
-#define  P_LORA_DIO_1   1   //SX1262 IRQ pin
-#define  P_LORA_NSS     10  //SX1262 SS pin
-#define  P_LORA_RESET   5   //SX1262 Rest pin
-#define  P_LORA_BUSY    4   //SX1262 Busy pin
-#define  P_LORA_SCLK    12  //SX1262 SCLK pin
-#define  P_LORA_MISO    13  //SX1262 MISO pin
-#define  P_LORA_MOSI    11  //SX1262 MOSI pin
-
-//#define PIN_BOARD_SDA 17  //SDA for OLED, BME280, and QMC6310U (0x1C)
-//#define PIN_BOARD_SCL 18  //SCL for OLED, BME280, and QMC6310U (0x1C)
-
-#define PIN_BOARD_SDA1 42  //SDA for PMU and PFC8563 (RTC)
-#define PIN_BOARD_SCL1 41  //SCL for PMU and PFC8563 (RTC)
-#define PIN_PMU_IRQ 40     //IRQ pin for PMU
-
-//#define PIN_USER_BTN 0
-
-#define P_BOARD_SPI_MOSI 35  //SPI for SD Card and QMI8653 (IMU)
-#define P_BOARD_SPI_MISO 37  //SPI for SD Card and QMI8653 (IMU)
-#define P_BOARD_SPI_SCK  36  //SPI for SD Card and QMI8653 (IMU)
-#define P_BPARD_SPI_CS   47  //Pin for SD Card CS
-#define P_BOARD_IMU_CS   34  //Pin for QMI8653 (IMU) CS
-
-#define P_BOARD_IMU_INT  33  //IMU Int pin
-#define P_BOARD_RTC_INT  14  //RTC Int pin
-
-#define P_GPS_RX    9   //GPS RX pin
-#define P_GPS_TX    8   //GPS TX pin
-#define P_GPS_WAKE  7   //GPS Wakeup pin
-//#define P_GPS_1PPS  6   //GPS 1PPS pin - repurposed for lora tx led
-#define GPS_BAUD_RATE 9600
-
-//I2C Wire addresses
-#define I2C_BME280_ADD    0x76  //BME280 sensor I2C address on Wire
-#define I2C_OLED_ADD      0x3C  //SH1106 OLED I2C address on Wire
-#define I2C_QMC6310U_ADD  0x1C  //QMC6310U mag sensor I2C address on Wire
-
-//I2C Wire1 addresses
-#define I2C_RTC_ADD       0x51  //RTC I2C address on Wire1
-#define I2C_PMU_ADD       0x34  //AXP2101 I2C address on Wire1
-
-#define PMU_WIRE_PORT               Wire1
-#define XPOWERS_CHIP_AXP2101
-
-class TBeamS3SupremeBoard : public ESP32Board {
-  XPowersAXP2101 PMU;
-public:
-#ifdef MESH_DEBUG
-  void printPMU();
-#endif
-  bool power_init();
-
-  void begin() {
-
-    ESP32Board::begin();
-
-    power_init();
-
-    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);
-    }
-    power_init();
-  }
-
-  void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1) {
-    esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
-
-    // Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
-    rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
-    rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
-
-    rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
-
-    if (pin_wake_btn < 0) {
-      esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH);  // wake up on: recv LoRa packet
-    } else {
-      esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH);  // wake up on: recv LoRa packet OR wake btn
-    }
-
-    if (secs > 0) {
-      esp_sleep_enable_timer_wakeup(secs * 1000000);
-    }
-
-    // Finally set ESP32 into sleep
-    esp_deep_sleep_start();   // CPU halts here and never returns!
-  }
-
-  uint16_t getBattMilliVolts() override {
-    return PMU.getBattVoltage();
-  }
-
-  uint16_t getBattPercent() {
-    //Read the PMU fuel guage for battery %
-    uint16_t battPercent = PMU.getBatteryPercent();
-    return battPercent;
-  }
-  const char* getManufacturerName() const override {
-    return "LilyGo T-Beam S3 Supreme SX1262";
-  }
-};

+ 346 - 0
src/helpers/esp32/TBeamBoard.cpp

@@ -0,0 +1,346 @@
+#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

+ 164 - 0
src/helpers/esp32/TBeamBoard.h

@@ -0,0 +1,164 @@
+#pragma once
+
+#include <Wire.h>
+#include <Arduino.h>
+#include "XPowersLib.h"
+#include "helpers/ESP32Board.h"
+#include <driver/rtc_io.h>
+//#include <RadioLib.h>
+//#include <helpers/RadioLibWrappers.h>
+//#include <helpers/CustomSX1262Wrapper.h>
+//#include <helpers/CustomSX1276Wrapper.h>
+
+#ifdef TBEAM_SUPREME_SX1262
+  // LoRa radio module pins for TBeam S3 Supreme SX1262
+  #define  P_LORA_DIO_0   -1   //NC
+  #define  P_LORA_DIO_1    1   //SX1262 IRQ pin
+  #define  P_LORA_NSS      10  //SX1262 SS pin
+  #define  P_LORA_RESET    5   //SX1262 Rest pin
+  #define  P_LORA_BUSY     4   //SX1262 Busy pin
+  #define  P_LORA_SCLK     12   //SX1262 SCLK pin
+  #define  P_LORA_MISO     13   //SX1262 MISO pin
+  #define  P_LORA_MOSI     11   //SX1262 MOSI pin
+
+  #define PIN_BOARD_SDA1  42  //SDA for PMU and PFC8563 (RTC)
+  #define PIN_BOARD_SCL1  41  //SCL for PMU and PFC8563 (RTC)
+
+  #define PIN_PMU_IRQ  40     //IRQ pin for PMU
+
+  // #define PIN_GPS_RX      9
+  // #define PIN_GPS_TX      8
+  // #define PIN_GPS_EN      7
+
+  #define P_BOARD_SPI_MOSI  35  //SPI for SD Card and QMI8653 (IMU)
+  #define P_BOARD_SPI_MISO  37  //SPI for SD Card and QMI8653 (IMU)
+  #define P_BOARD_SPI_SCK   36  //SPI for SD Card and QMI8653 (IMU)
+  #define P_BPARD_SPI_CS    47  //Pin for SD Card CS
+  #define P_BOARD_IMU_CS    34  //Pin for QMI8653 (IMU) CS
+
+  #define P_BOARD_IMU_INT  33  //IMU Int pin
+  #define P_BOARD_RTC_INT  14  //RTC Int pin
+
+  //I2C Wire addresses
+  #define I2C_BME280_ADD     0x76  //BME280 sensor I2C address on Wire
+  #define I2C_OLED_ADD       0x3C  //SH1106 OLED I2C address on Wire
+  #define I2C_QMC6310U_ADD   0x1C  //QMC6310U mag sensor I2C address on Wire
+
+  //I2C Wire1 addresses
+  #define I2C_RTC_ADD  0x51  //RTC I2C address on Wire1
+  #define I2C_PMU_ADD  0x34  //AXP2101 I2C address on Wire1
+  
+  #define PMU_WIRE_PORT  Wire1
+  #define RTC_WIRE_PORT  Wire1
+#endif
+
+#ifdef TBEAM_SX1262
+  #define  P_LORA_BUSY    32
+#endif
+
+#ifdef TBEAM_SX1276
+  #define  P_LORA_DIO_2    32
+  #define  P_LORA_BUSY    RADIOLIB_NC
+#endif
+
+#if defined(TBEAM_SX1262) || defined(TBEAM_SX1276)
+  // LoRa radio module pins for TBeam
+  // uint32_t  P_LORA_BUSY  = 0;   //shared, so define at run
+  // uint32_t  P_LORA_DIO_2 = 0;   //SX1276 only, so define at run
+
+  #define  P_LORA_DIO_0  26
+  #define  P_LORA_DIO_1  33
+  #define  P_LORA_NSS    18
+  #define  P_LORA_RESET  23
+  #define  P_LORA_SCLK    5
+  #define  P_LORA_MISO   19
+  #define  P_LORA_MOSI   27
+
+  // #define PIN_GPS_RX      34
+  // #define PIN_GPS_TX      12
+
+  #define PIN_PMU_IRQ   35
+  #define PMU_WIRE_PORT  Wire
+  #define RTC_WIRE_PORT  Wire
+  #define I2C_PMU_ADD    0x34
+#endif
+
+// enum RadioType {
+//   SX1262, 
+//   SX1276
+// };
+
+class TBeamBoard : public ESP32Board {
+XPowersLibInterface *PMU = NULL;
+//PhysicalLayer * pl;
+//RadioType * radio = NULL;
+// int radioVersions = 2;
+
+enum {
+  POWERMANAGE_ONLINE  = _BV(0),
+  DISPLAY_ONLINE      = _BV(1),
+  RADIO_ONLINE        = _BV(2),
+  GPS_ONLINE          = _BV(3),
+  PSRAM_ONLINE        = _BV(4),
+  SDCARD_ONLINE       = _BV(5),
+  AXDL345_ONLINE      = _BV(6),
+  BME280_ONLINE       = _BV(7),
+  BMP280_ONLINE       = _BV(8),
+  BME680_ONLINE       = _BV(9),
+  QMC6310_ONLINE      = _BV(10),
+  QMI8658_ONLINE      = _BV(11),
+  PCF8563_ONLINE      = _BV(12),
+  OSC32768_ONLINE      = _BV(13),
+};
+
+bool power_init();
+//void radiotype_detect();
+
+public:
+
+#ifdef MESH_DEBUG
+  void printPMU();
+  void scanDevices(TwoWire *w);
+#endif
+  void begin();
+
+  #ifndef TBEAM_SUPREME_SX1262
+  void onBeforeTransmit() override{
+    digitalWrite(P_LORA_TX_LED, LOW);   // turn TX LED on - invert pin for SX1276
+  }
+  void onAfterTransmit() override{
+    digitalWrite(P_LORA_TX_LED, HIGH);   // turn TX LED off - invert pin for SX1276
+  }
+  #endif
+
+  void enterDeepSleep(uint32_t secs, int pin_wake_btn) {
+  esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
+
+  // Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
+  rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
+  rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
+
+  rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
+
+  if (pin_wake_btn < 0) {
+    esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH);  // wake up on: recv LoRa packet
+  } else {
+    esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH);  // wake up on: recv LoRa packet OR wake btn
+  }
+
+  if (secs > 0) {
+    esp_sleep_enable_timer_wakeup(secs * 1000000);
+  }
+
+  // Finally set ESP32 into sleep
+  esp_deep_sleep_start();   // CPU halts here and never returns!
+}
+
+  uint16_t getBattMilliVolts(){
+    return PMU->getBattVoltage();
+  }
+
+  const char* getManufacturerName() const{
+    return "LilyGo T-Beam";
+  }
+};

+ 39 - 9
src/helpers/sensors/EnvironmentSensorManager.cpp

@@ -7,7 +7,9 @@ static Adafruit_AHTX0 AHTX0;
 #endif
 
 #if ENV_INCLUDE_BME280
+#ifndef TELEM_BME280_ADDRESS
 #define TELEM_BME280_ADDRESS    0x76      // BME280 environmental sensor I2C address
+#endif
 #define TELEM_BME280_SEALEVELPRESSURE_HPA (1013.25)    // Athmospheric pressure at sea level
 #include <Adafruit_BME280.h>
 static Adafruit_BME280 BME280;
@@ -84,7 +86,7 @@ bool EnvironmentSensorManager::begin() {
 bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
   next_available_channel = TELEM_CHANNEL_SELF + 1;
 
-  if (requester_permissions & TELEM_PERM_LOCATION) {
+  if (requester_permissions & TELEM_PERM_LOCATION && gps_active) {
     telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, 0.0f); // allow lat/lon via telemetry even if no GPS is detected
   }
 
@@ -180,13 +182,25 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val
 
 #if ENV_INCLUDE_GPS
 void EnvironmentSensorManager::initBasicGPS() {
+
   Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX);
+  
+  #ifdef GPS_BAUD_RATE
+  Serial1.begin(GPS_BAUD_RATE);
+  #else
   Serial1.begin(9600);
+  #endif
 
   // Try to detect if GPS is physically connected to determine if we should expose the setting
-  pinMode(PIN_GPS_EN, OUTPUT);
-  digitalWrite(PIN_GPS_EN, HIGH);  // Power on GPS
+  #ifdef PIN_GPS_EN
+    pinMode(PIN_GPS_EN, OUTPUT);
+    digitalWrite(PIN_GPS_EN, HIGH);   // Power on GPS
+  #endif
 
+  #ifndef PIN_GPS_EN
+    MESH_DEBUG_PRINTLN("No GPS wake/reset pin found for this board. Continuing on...");
+  #endif
+  
   // Give GPS a moment to power up and send data
   delay(1000);
 
@@ -195,23 +209,39 @@ void EnvironmentSensorManager::initBasicGPS() {
 
   if (gps_detected) {
     MESH_DEBUG_PRINTLN("GPS detected");
-    digitalWrite(PIN_GPS_EN, LOW);  // Power off GPS until the setting is changed
+    #ifdef PERSISTANT_GPS
+      gps_active = true;
+      return;
+    #endif
   } else {
     MESH_DEBUG_PRINTLN("No GPS detected");
-    digitalWrite(PIN_GPS_EN, LOW);
   }
+  #ifdef PIN_GPS_EN
+    digitalWrite(PIN_GPS_EN, LOW);  // Power off GPS until the setting is changed
+  #endif
+  gps_active = false; //Set GPS visibility off until setting is changed
 }
 
 void EnvironmentSensorManager::start_gps() {
   gps_active = true;
-  pinMode(PIN_GPS_EN, OUTPUT);
-  digitalWrite(PIN_GPS_EN, HIGH);
+  #ifdef PIN_GPS_EN
+    pinMode(PIN_GPS_EN, OUTPUT);
+    digitalWrite(PIN_GPS_EN, HIGH);  
+    return;
+  #endif
+
+  MESH_DEBUG_PRINTLN("Start GPS is N/A on this board. Actual GPS state unchanged");
 }
 
 void EnvironmentSensorManager::stop_gps() {
   gps_active = false;
-  pinMode(PIN_GPS_EN, OUTPUT);
-  digitalWrite(PIN_GPS_EN, LOW);
+  #ifdef PIN_GPS_EN
+    pinMode(PIN_GPS_EN, OUTPUT);
+    digitalWrite(PIN_GPS_EN, LOW);
+    return;
+  #endif
+
+  MESH_DEBUG_PRINTLN("Stop GPS is N/A on this board. Actual GPS state unchanged");  
 }
 
 void EnvironmentSensorManager::loop() {

+ 0 - 1
variants/heltec_v3/target.cpp

@@ -32,7 +32,6 @@ bool radio_init() {
   rtc_clock.begin(Wire);
   
 #if defined(P_LORA_SCLK)
-  spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
   return radio.std_init(&spi);
 #else
   return radio.std_init();

+ 0 - 203
variants/lilygo_tbeam/target.cpp

@@ -1,203 +0,0 @@
-#include <Arduino.h>
-#include "target.h"
-
-TBeamBoard board;
-
-// Using PMU AXP2102
-#define PMU_WIRE_PORT               Wire
-
-bool pmuIntFlag = false;
-static void setPMUIntFlag(){
-  pmuIntFlag = true;
-}
-
-#if defined(P_LORA_SCLK)
-  static SPIClass spi;
-  RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
-#else
-  RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1);
-#endif
-
-WRAPPER_CLASS radio_driver(radio, board);
-
-ESP32RTCClock fallback_clock;
-AutoDiscoverRTCClock rtc_clock(fallback_clock);
-SensorManager sensors;
-
-#ifdef DISPLAY_CLASS
-  DISPLAY_CLASS display;
-#endif
-
-#ifndef LORA_CR
-  #define LORA_CR      5
-#endif
-
-bool TBeamBoard::power_init()
-{
-  if (!PMU)
-  {
-    PMU = new XPowersAXP2101(PMU_WIRE_PORT);
-    if (!PMU->init())
-    {
-      // Serial.println("Warning: Failed to find AXP2101 power management");
-      delete PMU;
-      PMU = NULL;
-    }
-    else
-    {
-      // Serial.println("AXP2101 PMU init succeeded, using AXP2101 PMU");
-    }
-  }
-  if (!PMU)
-  {
-    PMU = new XPowersAXP192(PMU_WIRE_PORT);
-    if (!PMU->init())
-    {
-      // Serial.println("Warning: Failed to find AXP192 power management");
-      delete PMU;
-      PMU = NULL;
-    }
-    else
-    {
-      // Serial.println("AXP192 PMU init succeeded, using AXP192 PMU");
-    }
-  }
-
-  if (!PMU)
-  {
-    MESH_DEBUG_PRINTLN("PMU init failed.");
-    return false;
-  }
-
-  // Serial.printf("PMU  ID:0x%x\n", PMU->getChipID());
-  // printPMU();
-  if (PMU->getChipModel() == XPOWERS_AXP192)
-  {
-    // lora radio power channel
-    PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300);
-    PMU->enablePowerOutput(XPOWERS_LDO2);
-    // oled module power channel,
-    // disable it will cause abnormal communication between boot and AXP power supply,
-    // do not turn it off
-    PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300);
-    // enable oled power
-    PMU->enablePowerOutput(XPOWERS_DCDC1);
-    // gnss module power channel
-    PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300);
-    // power->enablePowerOutput(XPOWERS_LDO3);
-    // protected oled power source
-    PMU->setProtectedChannel(XPOWERS_DCDC1);
-    // protected esp32 power source
-    PMU->setProtectedChannel(XPOWERS_DCDC3);
-    // disable not use channel
-    PMU->disablePowerOutput(XPOWERS_DCDC2);
-    // disable all axp chip interrupt
-    PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ);
-    PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_550MA);
-  }
-  else if (PMU->getChipModel() == XPOWERS_AXP2101)
-  {
-    // gnss module power channel
-    PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
-    PMU->enablePowerOutput(XPOWERS_ALDO4);
-    // lora radio power channel
-    PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
-    PMU->enablePowerOutput(XPOWERS_ALDO3);
-    // m.2 interface
-    PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
-    PMU->enablePowerOutput(XPOWERS_DCDC3);
-    // power->setPowerChannelVoltage(XPOWERS_DCDC4, 3300);
-    // power->enablePowerOutput(XPOWERS_DCDC4);
-    // not use channel
-    PMU->disablePowerOutput(XPOWERS_DCDC2); // not elicited
-    PMU->disablePowerOutput(XPOWERS_DCDC5); // not elicited
-    PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist
-    PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist
-    PMU->disablePowerOutput(XPOWERS_VBACKUP);
-    // disable all axp chip interrupt
-    PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
-    PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
-
-    // Set up PMU interrupts
-    // Serial.println("Setting up PMU interrupts");
-    pinMode(PIN_PMU_IRQ, INPUT_PULLUP);
-    attachInterrupt(PIN_PMU_IRQ, setPMUIntFlag, FALLING);
-
-    // Reset and re-enable PMU interrupts
-    // Serial.println("Re-enable interrupts");
-    PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
-    PMU->clearIrqStatus();
-    PMU->enableIRQ(
-        XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ |    // Battery interrupts
-        XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ |  // VBUS interrupts
-        XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ |     // Power Key interrupts
-        XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ // Charging interrupts
-    );
-  }
-
-  return true;
-}
-
-bool radio_init() {
-  fallback_clock.begin();
-  rtc_clock.begin(Wire);
-
-#if defined(P_LORA_SCLK)
-  spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
-#endif
-  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: radio init failed: ");
-    Serial.println(status);
-    return false;  // fail
-  }
-
-#ifdef SX127X_CURRENT_LIMIT
-  radio.setCurrentLimit(SX127X_CURRENT_LIMIT);
-#endif
-
-  radio.setCRC(1);
-
-  return true;  // success
-}
-
-uint32_t radio_get_rng_seed() {
-  return radio.random(0x7FFFFFFF);
-}
-
-void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
-  radio.setFrequency(freq);
-  radio.setSpreadingFactor(sf);
-  radio.setBandwidth(bw);
-  radio.setCodingRate(cr);
-}
-
-void radio_set_tx_power(uint8_t dbm) {
-  radio.setOutputPower(dbm);
-}
-
-mesh::LocalIdentity radio_new_identity() {
-  RadioNoiseListener rng(radio);
-  return mesh::LocalIdentity(&rng);  // create new random identity
-}
-
-#ifdef MESH_DEBUG
-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

+ 9 - 5
variants/lilygo_tbeam_SX1262/platformio.ini

@@ -4,32 +4,39 @@ board = ttgo-t-beam
 build_flags =
   ${esp32_base.build_flags}
   -I variants/lilygo_tbeam_SX1262
-  -D LILYGO_TBEAM_SX1262
+  -D TBEAM_SX1262
   -D SX126X_DIO2_AS_RF_SWITCH=true
   -D SX126X_DIO3_TCXO_VOLTAGE=1.8
   -D SX126X_CURRENT_LIMIT=140
   -D SX126X_RX_BOOSTED_GAIN=1
   -D RADIO_CLASS=CustomSX1262
   -D WRAPPER_CLASS=CustomSX1262Wrapper
+  -D DISPLAY_CLASS=SSD1306Display
   -D LORA_TX_POWER=22
   -D P_LORA_TX_LED=4
   -D PIN_BOARD_SDA=21
   -D PIN_BOARD_SCL=22
+  -D PIN_GPS_RX=12
+  -D PIN_GPS_TX=34
   -D PIN_USER_BTN=38
+  -D ENV_INCLUDE_GPS=1
 build_src_filter = ${esp32_base.build_src_filter}
   +<../variants/lilygo_tbeam_SX1262>
+  +<helpers/ui/SSD1306Display.cpp>
+  +<helpers/esp32/TBeamBoard.cpp>
+  +<helpers/sensors> 
 board_build.partitions = min_spiffs.csv ; get around 4mb flash limit
 lib_deps =
   ${esp32_base.lib_deps}
   lewisxhe/XPowersLib@^0.2.7
   adafruit/Adafruit SSD1306 @ ^2.5.13
+  stevemarple/MicroNMEA @ ^2.0.6
 
 [env:Tbeam_SX1262_companion_radio_ble]
 extends = LilyGo_TBeam_SX1262
 board_build.upload.maximum_ram_size=2000000
 build_flags =
   ${LilyGo_TBeam_SX1262.build_flags}
-  -D DISPLAY_CLASS=SSD1306Display
   -D MAX_CONTACTS=100
   -D MAX_GROUP_CHANNELS=8
   -D BLE_PIN_CODE=123456
@@ -42,7 +49,6 @@ build_flags =
 ;  -D MESH_DEBUG=1
 build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter}
   +<helpers/esp32/*.cpp>
-  +<helpers/ui/SSD1306Display.cpp>
   +<../examples/companion_radio>
 lib_deps =
   ${LilyGo_TBeam_SX1262.lib_deps}
@@ -52,7 +58,6 @@ lib_deps =
 extends = LilyGo_TBeam_SX1262
 build_flags =
   ${LilyGo_TBeam_SX1262.build_flags}
-  -D DISPLAY_CLASS=SSD1306Display
   -D ADVERT_NAME='"Tbeam SX1262 Repeater"'
   -D ADVERT_LAT=0.0
   -D ADVERT_LON=0.0
@@ -61,7 +66,6 @@ build_flags =
 ;  -D MESH_PACKET_LOGGING=1
 ;  -D MESH_DEBUG=1
 build_src_filter = ${LilyGo_TBeam_SX1262.build_src_filter}
-  +<helpers/ui/SSD1306Display.cpp>
   +<../examples/simple_repeater>
 lib_deps =
   ${LilyGo_TBeam_SX1262.lib_deps}

+ 9 - 2
variants/lilygo_tbeam_SX1262/target.cpp

@@ -1,7 +1,7 @@
 #include <Arduino.h>
 #include "target.h"
 
-TBeamBoardSX1262 board;
+TBeamBoard board;
 
 #if defined(P_LORA_SCLK)
   static SPIClass spi;
@@ -14,7 +14,14 @@ WRAPPER_CLASS radio_driver(radio, board);
 
 ESP32RTCClock fallback_clock;
 AutoDiscoverRTCClock rtc_clock(fallback_clock);
-SensorManager sensors;
+
+#if ENV_INCLUDE_GPS
+  #include <helpers/sensors/MicroNMEALocationProvider.h>
+  MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
+  EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
+#else
+  EnvironmentSensorManager sensors;
+#endif
 
 #ifdef DISPLAY_CLASS
   DISPLAY_CLASS display;

+ 4 - 4
variants/lilygo_tbeam_SX1262/target.h

@@ -3,18 +3,18 @@
 #define RADIOLIB_STATIC_ONLY 1
 #include <RadioLib.h>
 #include <helpers/RadioLibWrappers.h>
-#include <helpers/TBeamBoardSX1262.h>
+#include <helpers/esp32/TBeamBoard.h>
 #include <helpers/CustomSX1262Wrapper.h>
 #include <helpers/AutoDiscoverRTCClock.h>
-#include <helpers/SensorManager.h>
+#include <helpers/sensors/EnvironmentSensorManager.h>
 #ifdef DISPLAY_CLASS
   #include <helpers/ui/SSD1306Display.h>
 #endif
 
-extern TBeamBoardSX1262 board;
+extern TBeamBoard board;
 extern WRAPPER_CLASS radio_driver;
 extern AutoDiscoverRTCClock rtc_clock;
-extern SensorManager sensors;
+extern EnvironmentSensorManager sensors;
 
 #ifdef DISPLAY_CLASS
   extern DISPLAY_CLASS display;

+ 27 - 20
variants/lilygo_tbeam/platformio.ini → variants/lilygo_tbeam_SX1276/platformio.ini

@@ -1,63 +1,70 @@
-[LilyGo_TBeam]
+[LilyGo_TBeam_SX1276]
 extends = esp32_base
 board = ttgo-t-beam
 build_flags =
   ${esp32_base.build_flags}
-  -I variants/lilygo_tbeam
-  -D LILYGO_TBEAM
+  -I variants/lilygo_tbeam_SX1276
+  -D TBEAM_SX1276
+  -D SX127X_CURRENT_LIMIT=120
   -D RADIO_CLASS=CustomSX1276
   -D WRAPPER_CLASS=CustomSX1276Wrapper
-  -D SX127X_CURRENT_LIMIT=120
+  -D DISPLAY_CLASS=SSD1306Display
   -D LORA_TX_POWER=20
   -D P_LORA_TX_LED=4
   -D PIN_BOARD_SDA=21
   -D PIN_BOARD_SCL=22
+  -D PIN_GPS_RX=12
+  -D PIN_GPS_TX=34
   -D PIN_USER_BTN=38
+  -D ENV_INCLUDE_GPS=1
+  ;-D ENV_INCLUDE_BME680
 build_src_filter = ${esp32_base.build_src_filter}
-  +<../variants/lilygo_tbeam>
+  +<../variants/lilygo_tbeam_SX1276>
+  +<helpers/ui/SSD1306Display.cpp>
+  +<helpers/esp32/TBeamBoard.cpp>
+  +<helpers/sensors> 
 board_build.partitions = min_spiffs.csv ; get around 4mb flash limit
 lib_deps =
   ${esp32_base.lib_deps}
   lewisxhe/XPowersLib@^0.2.7
   adafruit/Adafruit SSD1306 @ ^2.5.13
+  stevemarple/MicroNMEA @ ^2.0.6
+  boschsensortec/BSEC Software Library @ ^1.8.1492
 
-[env:Tbeam_companion_radio_ble]
-extends = LilyGo_TBeam
+[env:Tbeam_SX1276_companion_radio_ble]
+extends = LilyGo_TBeam_SX1276
 board_build.upload.maximum_ram_size=2000000
 build_flags =
-  ${LilyGo_TBeam.build_flags}
-  -D DISPLAY_CLASS=SSD1306Display
+  ${LilyGo_TBeam_SX1276.build_flags}
   -D MAX_CONTACTS=100
   -D MAX_GROUP_CHANNELS=8
   -D BLE_PIN_CODE=123456
-  -D BLE_DEBUG_LOGGING=1
+;  -D BLE_DEBUG_LOGGING=1
   -D OFFLINE_QUEUE_SIZE=256
 ;  -D RADIOLIB_DEBUG_BASIC=1
 ;  -D MESH_PACKET_LOGGING=1
 ;  -D MESH_DEBUG=1
-build_src_filter = ${LilyGo_TBeam.build_src_filter}
+build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter}
   +<helpers/esp32/*.cpp>
-  +<helpers/ui/SSD1306Display.cpp>
   +<../examples/companion_radio>
 lib_deps =
-  ${LilyGo_TBeam.lib_deps}
+  ${LilyGo_TBeam_SX1276.lib_deps}
   densaugeo/base64 @ ~1.4.0
 
-[env:Tbeam_repeater]
-extends = LilyGo_TBeam
+[env:Tbeam_SX1276_repeater]
+extends = LilyGo_TBeam_SX1276
 build_flags =
-  ${LilyGo_TBeam.build_flags}
-  -D DISPLAY_CLASS=SSD1306Display
+  ${LilyGo_TBeam_SX1276.build_flags}
   -D ADVERT_NAME='"Tbeam Repeater"'
   -D ADVERT_LAT=0.0
   -D ADVERT_LON=0.0
   -D ADMIN_PASSWORD='"password"'
   -D MAX_NEIGHBOURS=8
+  -D PERSISTANT_GPS=1
 ;  -D MESH_PACKET_LOGGING=1
 ;  -D MESH_DEBUG=1
-build_src_filter = ${LilyGo_TBeam.build_src_filter}
-  +<helpers/ui/SSD1306Display.cpp>
+build_src_filter = ${LilyGo_TBeam_SX1276.build_src_filter}
   +<../examples/simple_repeater>
 lib_deps =
-  ${LilyGo_TBeam.lib_deps}
+  ${LilyGo_TBeam_SX1276.lib_deps}
   ${esp32_ota.lib_deps}

+ 75 - 0
variants/lilygo_tbeam_SX1276/target.cpp

@@ -0,0 +1,75 @@
+#include <Arduino.h>
+#include "target.h"
+
+TBeamBoard board;
+
+#if defined(P_LORA_SCLK)
+  static SPIClass spi;
+  RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
+#else
+  RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1);
+#endif
+
+WRAPPER_CLASS radio_driver(radio, board);
+
+ESP32RTCClock fallback_clock;
+AutoDiscoverRTCClock rtc_clock(fallback_clock);
+
+#if ENV_INCLUDE_GPS
+  #include <helpers/sensors/MicroNMEALocationProvider.h>
+  MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
+  EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
+#else
+  EnvironmentSensorManager sensors;
+#endif
+
+#ifdef DISPLAY_CLASS
+  DISPLAY_CLASS display;
+#endif
+
+#ifndef LORA_CR
+  #define LORA_CR      5
+#endif
+
+bool radio_init() {
+  fallback_clock.begin();
+  rtc_clock.begin(Wire);
+
+#if defined(P_LORA_SCLK)
+  spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
+#endif
+  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: radio init failed: ");
+    Serial.println(status);
+    return false;  // fail
+  }
+
+#ifdef SX127X_CURRENT_LIMIT
+  radio.setCurrentLimit(SX127X_CURRENT_LIMIT);
+#endif
+
+  radio.setCRC(1);
+
+  return true;  // success
+}
+
+uint32_t radio_get_rng_seed() {
+  return radio.random(0x7FFFFFFF);
+}
+
+void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
+  radio.setFrequency(freq);
+  radio.setSpreadingFactor(sf);
+  radio.setBandwidth(bw);
+  radio.setCodingRate(cr);
+}
+
+void radio_set_tx_power(uint8_t dbm) {
+  radio.setOutputPower(dbm);
+}
+
+mesh::LocalIdentity radio_new_identity() {
+  RadioNoiseListener rng(radio);
+  return mesh::LocalIdentity(&rng);  // create new random identity
+}

+ 4 - 4
variants/lilygo_tbeam/target.h → variants/lilygo_tbeam_SX1276/target.h

@@ -1,12 +1,12 @@
 #pragma once
 
 #define RADIOLIB_STATIC_ONLY 1
-#include <RadioLib.h>
+//#include <RadioLib.h>
 #include <helpers/RadioLibWrappers.h>
-#include <helpers/TBeamBoard.h>
+#include <helpers/esp32/TBeamBoard.h>
 #include <helpers/CustomSX1276Wrapper.h>
 #include <helpers/AutoDiscoverRTCClock.h>
-#include <helpers/SensorManager.h>
+#include <helpers/sensors/EnvironmentSensorManager.h>
 #ifdef DISPLAY_CLASS
   #include <helpers/ui/SSD1306Display.h>
 #endif
@@ -14,7 +14,7 @@
 extern TBeamBoard board;
 extern WRAPPER_CLASS radio_driver;
 extern AutoDiscoverRTCClock rtc_clock;
-extern SensorManager sensors;
+extern EnvironmentSensorManager sensors;
 
 #ifdef DISPLAY_CLASS
   extern DISPLAY_CLASS display;

+ 14 - 5
variants/lilygo_tbeam_supreme_SX1262/platformio.ini

@@ -4,19 +4,28 @@ board = t_beams3_supreme  ; LILYGO T-Beam Supreme ESP32S3 with SX1262
 build_flags =
   ${esp32_base.build_flags}
   -I variants/lilygo_tbeam_supreme_SX1262
+  -D TBEAM_SUPREME_SX1262
+  -D SX126X_CURRENT_LIMIT=140
+  -D SX126X_RX_BOOSTED_GAIN=1
+  -D RADIO_CLASS=CustomSX1262
+  -D WRAPPER_CLASS=CustomSX1262Wrapper
+  -D DISPLAY_CLASS=SH1106Display
   -D LORA_TX_POWER=22
   -D P_LORA_TX_LED=6
   -D PIN_BOARD_SDA=17
   -D PIN_BOARD_SCL=18
+  -D PIN_GPS_RX=8
+  -D PIN_GPS_TX=9
+  -D PIN_GPS_EN=7
   -D PIN_USER_BTN=0
-  -D RADIO_CLASS=CustomSX1262
-  -D WRAPPER_CLASS=CustomSX1262Wrapper
-  -D DISPLAY_CLASS=SH1106Display
-  -D SX126X_RX_BOOSTED_GAIN=1
-  -D SX126X_CURRENT_LIMIT=140
+  -D TELEM_BME280_ADDRESS=0x77
+  -D ENV_INCLUDE_GPS=1
+  -D ENV_INCLUDE_BME280=1
 build_src_filter = ${esp32_base.build_src_filter}
   +<../variants/lilygo_tbeam_supreme_SX1262>
   +<helpers/ui/SH1106Display.cpp>
+  +<helpers/esp32/TBeamBoard.cpp>
+  +<helpers/sensors> 
 board_build.partitions = min_spiffs.csv ; get around 4mb flash limit
 lib_deps =
   ${esp32_base.lib_deps}

+ 9 - 358
variants/lilygo_tbeam_supreme_SX1262/target.cpp

@@ -1,265 +1,33 @@
 #include <Arduino.h>
 #include "target.h"
-#include <helpers/sensors/MicroNMEALocationProvider.h>
 
-TBeamS3SupremeBoard board;
+TBeamBoard board;
 
 #ifdef DISPLAY_CLASS
   DISPLAY_CLASS display;
 #endif
 
-bool pmuIntFlag;
+static SPIClass spi;
 
-#if defined(P_LORA_SCLK)
-  static SPIClass spi;
-  RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
-#else
-  RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY);
-#endif
+RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
 
 WRAPPER_CLASS radio_driver(radio, board);
 
 ESP32RTCClock fallback_clock;
 AutoDiscoverRTCClock rtc_clock(fallback_clock);
-MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
-TbeamSupSensorManager sensors = TbeamSupSensorManager(nmea);
-
-static void setPMUIntFlag(){
-  pmuIntFlag = true;
-}
-
-#ifdef MESH_DEBUG
-uint32_t deviceOnline = 0x00;
-void 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 dispaly");
-                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");
-}
-void TBeamS3SupremeBoard::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();
-}
-void TbeamSupSensorManager::printBMEValues() {  
-  Serial.print("Temperature = ");
-  Serial.print(bme.readTemperature());
-  Serial.println(" *C");
-
-  Serial.print("Pressure = ");
-
-  Serial.print(bme.readPressure() / 100.0F);
-  Serial.println(" hPa");
-
-  Serial.print("Approx. Altitude = ");
-  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));
-  Serial.println(" m");
-
-  Serial.print("Humidity = ");
-  Serial.print(bme.readHumidity());
-  Serial.println(" %");
-
-  Serial.println();
-}
-#endif
-
-bool TBeamS3SupremeBoard::power_init()
-{
-  bool result = PMU.begin(PMU_WIRE_PORT, I2C_PMU_ADD, PIN_BOARD_SDA1, PIN_BOARD_SCL1);
-  if (result == false) {
-    MESH_DEBUG_PRINTLN("power is not online..."); while (1)delay(50);
-  }
-  MESH_DEBUG_PRINTLN("Setting charge led");
-  PMU.setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
-
-  // Set up PMU interrupts
-  MESH_DEBUG_PRINTLN("Setting up PMU interrupts");
-  pinMode(PIN_PMU_IRQ, INPUT_PULLUP);
-  attachInterrupt(PIN_PMU_IRQ, setPMUIntFlag, FALLING);
-
-  // GPS
-  MESH_DEBUG_PRINTLN("Setting and enabling a-ldo4 for GPS");
-  PMU.setALDO4Voltage(3300);
-  PMU.enableALDO4(); // disable to save power
-
-  // Lora
-  MESH_DEBUG_PRINTLN("Setting and enabling a-ldo3 for LoRa");
-  PMU.setALDO3Voltage(3300);
-  PMU.enableALDO3();
-
-  // To avoid SPI bus issues during power up, reset OLED, sensor, and SD card supplies
-  // MESH_DEBUG_PRINTLN("Reset a-ldo1&2 and b-ldo1");
-  // if (ESP_SLEEP_WAKEUP_UNDEFINED == esp_sleep_get_wakeup_cause())
-  // {
-  //   PMU.disableALDO1();
-  //   PMU.disableALDO2();
-  //   PMU.disableBLDO1();
-  //   delay(250);
-  // }
-
-  // m.2 interface
-  MESH_DEBUG_PRINTLN("Setting and enabling dcdc3 for m.2 interface");
-  PMU.setDC3Voltage(3300); // doesn't go anywhere in the schematic??
-  PMU.enableDC3();
-
-  // QMC6310U
-  MESH_DEBUG_PRINTLN("Setting and enabling a-ldo2 for QMC");
-  PMU.setALDO2Voltage(3300);
-  PMU.enableALDO2(); // disable to save power
-
-  // BME280 and OLED
-  MESH_DEBUG_PRINTLN("Setting and enabling a-ldo1 for oled");
-  PMU.setALDO1Voltage(3300);
-  PMU.enableALDO1();
-
-  // SD card
-  MESH_DEBUG_PRINTLN("Setting and enabling b-ldo2 for SD card");
-  PMU.setBLDO1Voltage(3300);
-  PMU.enableBLDO1();
-
-  // Out to header pins
-  MESH_DEBUG_PRINTLN("Setting and enabling b-ldo2 for output to header");
-  PMU.setBLDO2Voltage(3300);
-  PMU.enableBLDO2();
-
-  MESH_DEBUG_PRINTLN("Setting and enabling dcdc4 for output to header");
-  PMU.setDC4Voltage(XPOWERS_AXP2101_DCDC4_VOL2_MAX); // 1.8V
-  PMU.enableDC4();
-
-  MESH_DEBUG_PRINTLN("Setting and enabling dcdc5 for output to header");
-  PMU.setDC5Voltage(3300);
-  PMU.enableDC5();
-
-  // Unused power rails
-  MESH_DEBUG_PRINTLN("Disabling unused supplies dcdc2, dcdc5, dldo1 and dldo2");
-  PMU.disableDC2();
-  //PMU.disableDC5();
-  PMU.disableDLDO1();
-  PMU.disableDLDO2();
-
-  PMU.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
-
-  // Set charge current to 500mA
-  MESH_DEBUG_PRINTLN("Setting battery charge current limit and voltage");
-  PMU.setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
-  PMU.setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
 
-  PMU.clearIrqStatus();
-  PMU.disableTSPinMeasure();
-
-  // enable battery voltage measurement
-  MESH_DEBUG_PRINTLN("Enabling battery measurement");
-  PMU.enableBattVoltageMeasure();
-  PMU.enableVbusVoltageMeasure();
-
-  // Reset and re-enable PMU interrupts
-  MESH_DEBUG_PRINTLN("Re-enable interrupts");
-  PMU.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
-  PMU.clearIrqStatus();
-  PMU.enableIRQ(
-      XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ |    // Battery interrupts
-      XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ |  // VBUS interrupts
-      XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ |     // Power Key interrupts
-      XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ // Charging interrupts
-  );
-#ifdef MESH_DEBUG
-  scanDevices(&Wire); 
-  scanDevices(&Wire1);
-  printPMU();
+#if ENV_INCLUDE_GPS
+  #include <helpers/sensors/MicroNMEALocationProvider.h>
+  MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
+  EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
+#else
+  EnvironmentSensorManager sensors;
 #endif
 
-  // Set the power key off press time
-  PMU.setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
-  return true;
-}
-
-static bool readStringUntil(Stream& s, char dest[], size_t max_len, char term, unsigned int timeout_millis) {
-  unsigned long timeout = millis() + timeout_millis;
-  char *dp = dest;
-  while (millis() < timeout && dp - dest < max_len - 1) {
-    if (s.available()) {
-      char c = s.read();
-      if (c == term) break;
-      *dp++ = c;  // append to dest[]
-    } else {
-      delay(1);
-    }
-  }
-  *dp = 0;  // null terminator
-  return millis() < timeout;   // false, if timed out
-}
-
 bool radio_init() {
   fallback_clock.begin();
   rtc_clock.begin(Wire1);
   return radio.std_init(&spi);
-#endif
 }
 
 uint32_t radio_get_rng_seed() {
@@ -277,123 +45,6 @@ void radio_set_tx_power(uint8_t dbm) {
   radio.setOutputPower(dbm);
 }
 
-void TbeamSupSensorManager::start_gps()
-{
-  gps_active = true;
-  pinMode(P_GPS_WAKE, OUTPUT);
-  digitalWrite(P_GPS_WAKE, HIGH);
-}
-
-void TbeamSupSensorManager::sleep_gps() {
-  gps_active = false;
-  pinMode(P_GPS_WAKE, OUTPUT);
-  digitalWrite(P_GPS_WAKE, LOW);
-}
-
-bool TbeamSupSensorManager::begin() {
-  //init BME280
-    if (! bme.begin(0x77, &Wire)) {
-        MESH_DEBUG_PRINTLN("Could not find a valid BME280 sensor");
-        bme_active = false;
-    }
-    else
-      MESH_DEBUG_PRINTLN("BME280 found and init!");
-      bme_active = true;
-  
-  // init GPS port
-  Serial1.begin(GPS_BAUD_RATE, SERIAL_8N1, P_GPS_RX, P_GPS_TX);
-
-  MESH_DEBUG_PRINTLN("Sleeping GPS for initial state");
-  sleep_gps();
-  return true;
-}
-
-bool TbeamSupSensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
-  if (requester_permissions & TELEM_PERM_LOCATION && gps_active) {   // does requester have permission?
-    telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
-  }
-  if (requester_permissions & TELEM_PERM_ENVIRONMENT && bme_active) {   // does requester have permission?
-    telemetry.addTemperature(TELEM_CHANNEL_SELF, node_temp);
-    telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, node_hum);
-    telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, node_pres);
-    //telemetry.addAltitude(TELEM_CHANNEL_SELF, node_alt);
-  }
-  return true;
-}
-
-void TbeamSupSensorManager::loop() {
-  static long next_update = 0;
-
-  _nmea->loop();
-
-  if (millis() > next_update) {
-    if (_nmea->isValid() && gps_active) {
-      node_lat = ((double)_nmea->getLatitude())/1000000.;
-      node_lon = ((double)_nmea->getLongitude())/1000000.;
-      node_altitude = ((double)_nmea->getAltitude()) / 1000.0;
-      MESH_DEBUG_PRINT("lat %f lon %f alt %f\r\n", node_lat, node_lon, node_altitude);
-    }
-
-    //read BME280 values
-    if(bme_active){
-      //node_alt = bme.readAltitude(SEALEVELPRESSURE_HPA);
-      node_temp = bme.readTemperature();
-      node_hum = bme.readHumidity();
-      node_pres = (bme.readPressure() / 100.0F);
-    
-      #ifdef MESH_DEBUG
-      // Serial.print("Temperature = ");
-      // Serial.print(node_temp);
-      // Serial.println(" *C");
-
-      // Serial.print("Humidity = ");
-      // Serial.print(node_hum);
-      // Serial.println(" %");
-
-      // Serial.print("Pressure = ");
-      // Serial.print(node_pres);
-      // Serial.println(" hPa");
-
-      // Serial.print("Approx. Altitude = ");
-      // Serial.print(node_alt);
-      // Serial.println(" m");
-      #endif
-    }
-
-    next_update = millis() + 1000;
-  }
-}
-
-int TbeamSupSensorManager::getNumSettings() const {
-  return 1; 
-}
-
-const char* TbeamSupSensorManager::getSettingName(int i) const {
-  switch(i){
-    case 0: return "gps";
-    default: NULL;
-  }
-}
-
-const char* TbeamSupSensorManager::getSettingValue(int i) const {
-  switch(i){
-    case 0: return gps_active == true ? "1" : "0";
-    default: NULL;
-  }
-}
-
-bool TbeamSupSensorManager::setSettingValue(const char* name, const char* value) {
-  if (strcmp(name, "gps") == 0) {
-    if (strcmp(value, "0") == 0) {
-      sleep_gps();
-    } else {
-      start_gps();
-    }
-    return true;
-  }
-  return false;  // not supported
-}
-
 mesh::LocalIdentity radio_new_identity() {
   RadioNoiseListener rng(radio);
   return mesh::LocalIdentity(&rng);  // create new random identity

+ 6 - 52
variants/lilygo_tbeam_supreme_SX1262/target.h

@@ -3,66 +3,20 @@
 #define RADIOLIB_STATIC_ONLY 1
 #include <RadioLib.h>
 #include <helpers/RadioLibWrappers.h>
-#include <helpers/TBeamS3SupremeBoard.h>
+#include <helpers/esp32/TBeamBoard.h>
 #include <helpers/CustomSX1262Wrapper.h>
 #include <helpers/AutoDiscoverRTCClock.h>
-#include <helpers/SensorManager.h>
-#include <helpers/sensors/LocationProvider.h>
-#include <Adafruit_BME280.h>
-
-class TbeamSupSensorManager: public SensorManager {
-    bool gps_active = false;
-    bool bme_active = false;
-    LocationProvider * _nmea;
-    Adafruit_BME280 bme;
-    double node_temp, node_hum, node_pres;
-    
-    #define SEALEVELPRESSURE_HPA (1013.25)
-    
-    void start_gps();
-    void sleep_gps();
-  public:
-    TbeamSupSensorManager(LocationProvider &nmea): _nmea(&nmea) {node_temp = 0; node_hum = 0; node_pres = 0;}
-    bool begin() override;
-    bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override;
-    void loop() override;
-    int getNumSettings() const override;
-    const char* getSettingName(int i) const override;
-    const char* getSettingValue(int i) const override;
-    bool setSettingValue(const char* name, const char* value) override;
-
-    #ifdef MESH_DEBUG
-    void printBMEValues();
-    #endif
-
-  };
-
-extern TBeamS3SupremeBoard board;
-extern WRAPPER_CLASS radio_driver;
-extern AutoDiscoverRTCClock rtc_clock;
-extern TbeamSupSensorManager sensors;
+#include <helpers/sensors/EnvironmentSensorManager.h>
 
 #ifdef DISPLAY_CLASS
   #include <helpers/ui/SH1106Display.h>
   extern DISPLAY_CLASS display;
 #endif
 
-enum {
-  POWERMANAGE_ONLINE  = _BV(0),
-  DISPLAY_ONLINE      = _BV(1),
-  RADIO_ONLINE        = _BV(2),
-  GPS_ONLINE          = _BV(3),
-  PSRAM_ONLINE        = _BV(4),
-  SDCARD_ONLINE       = _BV(5),
-  AXDL345_ONLINE      = _BV(6),
-  BME280_ONLINE       = _BV(7),
-  BMP280_ONLINE       = _BV(8),
-  BME680_ONLINE       = _BV(9),
-  QMC6310_ONLINE      = _BV(10),
-  QMI8658_ONLINE      = _BV(11),
-  PCF8563_ONLINE      = _BV(12),
-  OSC32768_ONLINE      = _BV(13),
-};
+extern TBeamBoard board;
+extern WRAPPER_CLASS radio_driver;
+extern AutoDiscoverRTCClock rtc_clock;
+extern EnvironmentSensorManager sensors;
 
 bool radio_init();
 uint32_t radio_get_rng_seed();

+ 1 - 34
variants/nano_g2_ultra/target.cpp

@@ -18,43 +18,10 @@ NanoG2UltraSensorManager sensors = NanoG2UltraSensorManager(nmea);
 DISPLAY_CLASS display;
 #endif
 
-#ifndef LORA_CR
-#define LORA_CR 5
-#endif
-
 bool radio_init()
 {
   rtc_clock.begin(Wire);
-
-#ifdef SX126X_DIO3_TCXO_VOLTAGE
-  float tcxo = SX126X_DIO3_TCXO_VOLTAGE;
-#else
-  float tcxo = 1.6f;
-#endif
-
-  SPI.setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI);
-  SPI.begin();
-  int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo);
-  if (status != RADIOLIB_ERR_NONE)
-  {
-    Serial.print("ERROR: radio init failed: ");
-    Serial.println(status);
-    return false; // fail
-  }
-
-  radio.setCRC(1);
-
-#ifdef SX126X_CURRENT_LIMIT
-  radio.setCurrentLimit(SX126X_CURRENT_LIMIT);
-#endif
-#ifdef SX126X_DIO2_AS_RF_SWITCH
-  radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH);
-#endif
-#ifdef SX126X_RX_BOOSTED_GAIN
-  radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN);
-#endif
-
-  return true; // success
+  return radio.std_init(&SPI);
 }
 
 uint32_t radio_get_rng_seed()