From bd6bd065ac435ca8d2e62d6dae100d92819d9aa7 Mon Sep 17 00:00:00 2001 From: Quency-D Date: Fri, 15 Aug 2025 15:54:24 +0800 Subject: [PATCH 01/21] Add heltec_vision_master_t190 board. --- boards/heltec_vision_master_t190.json | 44 ++++++++++ src/helpers/ui/ST7789Display.cpp | 13 ++- src/helpers/ui/ST7789Display.h | 5 +- .../HeltecT190Board.cpp | 69 +++++++++++++++ .../HeltecT190Board.h | 30 +++++++ .../heltec_vision_master_t190/pins_arduino.h | 61 +++++++++++++ .../heltec_vision_master_t190/platformio.ini | 85 +++++++++++++++++++ variants/heltec_vision_master_t190/target.cpp | 53 ++++++++++++ variants/heltec_vision_master_t190/target.h | 27 ++++++ 9 files changed, 385 insertions(+), 2 deletions(-) create mode 100644 boards/heltec_vision_master_t190.json create mode 100644 variants/heltec_vision_master_t190/HeltecT190Board.cpp create mode 100644 variants/heltec_vision_master_t190/HeltecT190Board.h create mode 100644 variants/heltec_vision_master_t190/pins_arduino.h create mode 100644 variants/heltec_vision_master_t190/platformio.ini create mode 100644 variants/heltec_vision_master_t190/target.cpp create mode 100644 variants/heltec_vision_master_t190/target.h diff --git a/boards/heltec_vision_master_t190.json b/boards/heltec_vision_master_t190.json new file mode 100644 index 00000000..6aa674fc --- /dev/null +++ b/boards/heltec_vision_master_t190.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "psram_type": "opi", + "hwids": [ + ["0x303A", "0x1001"], + ["0x303A", "0x0002"] + ], + "mcu": "esp32s3", + "variant": "heltec_vision_master_t190" + }, + "connectivity": ["wifi", "bluetooth", "lora"], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "Heltec Vision Master T190", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 8388608, + "maximum_size": 16777216, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://heltec.org/project/vision-master-t190/", + "vendor": "Heltec" +} diff --git a/src/helpers/ui/ST7789Display.cpp b/src/helpers/ui/ST7789Display.cpp index 9e71e6bd..6a91457a 100644 --- a/src/helpers/ui/ST7789Display.cpp +++ b/src/helpers/ui/ST7789Display.cpp @@ -18,7 +18,11 @@ bool ST7789Display::begin() { pinMode(PIN_TFT_VDD_CTL, OUTPUT); pinMode(PIN_TFT_LEDA_CTL, OUTPUT); digitalWrite(PIN_TFT_VDD_CTL, LOW); + #ifdef PIN_TFT_LEDA_CTL_ACTIVE + digitalWrite(PIN_TFT_LEDA_CTL, PIN_TFT_LEDA_CTL_ACTIVE); + #else digitalWrite(PIN_TFT_LEDA_CTL, LOW); + #endif digitalWrite(PIN_TFT_RST, HIGH); display.init(); @@ -43,15 +47,22 @@ void ST7789Display::turnOn() { delay(20); // Now turn on the backlight + #ifdef PIN_TFT_LEDA_CTL_ACTIVE + digitalWrite(PIN_TFT_LEDA_CTL, PIN_TFT_LEDA_CTL_ACTIVE); + #else digitalWrite(PIN_TFT_LEDA_CTL, LOW); - + #endif _isOn = true; } } void ST7789Display::turnOff() { digitalWrite(PIN_TFT_VDD_CTL, HIGH); +#ifdef PIN_TFT_LEDA_CTL_ACTIVE + digitalWrite(PIN_TFT_LEDA_CTL, !PIN_TFT_LEDA_CTL_ACTIVE); +#else digitalWrite(PIN_TFT_LEDA_CTL, HIGH); +#endif digitalWrite(PIN_TFT_RST, LOW); _isOn = false; } diff --git a/src/helpers/ui/ST7789Display.h b/src/helpers/ui/ST7789Display.h index b267a2cb..0f7ff71b 100644 --- a/src/helpers/ui/ST7789Display.h +++ b/src/helpers/ui/ST7789Display.h @@ -14,8 +14,11 @@ class ST7789Display : public DisplayDriver { bool i2c_probe(TwoWire& wire, uint8_t addr); public: +#ifdef HELTEC_VISION_MASTER_T190 + ST7789Display() : DisplayDriver(128, 64), display(&SPI, PIN_TFT_RST, PIN_TFT_DC, PIN_TFT_CS, GEOMETRY_RAWMODE, 320, 170,PIN_TFT_SDA,-1,PIN_TFT_SCL) {_isOn = false;} +#else ST7789Display() : DisplayDriver(128, 64), display(&SPI1, PIN_TFT_RST, PIN_TFT_DC, PIN_TFT_CS, GEOMETRY_RAWMODE, 240, 135) {_isOn = false;} - +#endif bool begin(); bool isOn() override { return _isOn; } diff --git a/variants/heltec_vision_master_t190/HeltecT190Board.cpp b/variants/heltec_vision_master_t190/HeltecT190Board.cpp new file mode 100644 index 00000000..c5b03bc8 --- /dev/null +++ b/variants/heltec_vision_master_t190/HeltecT190Board.cpp @@ -0,0 +1,69 @@ +#include "HeltecT190Board.h" + +void HeltecT190Board::begin() { + ESP32Board::begin(); + + pinMode(PIN_ADC_CTRL, OUTPUT); + digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive + + periph_power.begin(); + + 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 HeltecT190Board::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! + } + + void HeltecT190Board::powerOff() { + // TODO: re-enable this when there is a definite wake-up source pin: + // enterDeepSleep(0); + } + + uint16_t HeltecT190Board::getBattMilliVolts() { + analogReadResolution(10); + digitalWrite(PIN_ADC_CTRL, HIGH); + delay(10); + uint32_t raw = 0; + for (int i = 0; i < 8; i++) { + raw += analogRead(PIN_VBAT_READ); + } + raw = raw / 8; + + digitalWrite(PIN_ADC_CTRL, LOW); + + return (5.42 * (3.3 / 1024.0) * raw) * 1000; + } + + const char* HeltecT190Board::getManufacturerName() const { + return "Heltec T190"; + } + diff --git a/variants/heltec_vision_master_t190/HeltecT190Board.h b/variants/heltec_vision_master_t190/HeltecT190Board.h new file mode 100644 index 00000000..96c09c1c --- /dev/null +++ b/variants/heltec_vision_master_t190/HeltecT190Board.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include + +// LoRa radio module pins for heltec_vision_master_e290 +#define P_LORA_DIO_1 14 +#define P_LORA_NSS 8 +#define P_LORA_RESET 12 +#define P_LORA_BUSY 13 +#define P_LORA_SCLK 9 +#define P_LORA_MISO 11 +#define P_LORA_MOSI 10 + +class HeltecT190Board : public ESP32Board { + +public: + RefCountedDigitalPin periph_power; + + HeltecT190Board() : periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE) { } + + void begin(); + void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1); + void powerOff() override; + uint16_t getBattMilliVolts() override; + const char* getManufacturerName() const override ; + +}; diff --git a/variants/heltec_vision_master_t190/pins_arduino.h b/variants/heltec_vision_master_t190/pins_arduino.h new file mode 100644 index 00000000..56856106 --- /dev/null +++ b/variants/heltec_vision_master_t190/pins_arduino.h @@ -0,0 +1,61 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +static const uint8_t LED_BUILTIN = 45; // LED is not populated on earliest board variant +#define BUILTIN_LED LED_BUILTIN // Backward compatibility +#define LED_BUILTIN LED_BUILTIN + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 2; +static const uint8_t SCL = 1; + +static const uint8_t SS = 8; +static const uint8_t MOSI = 10; +static const uint8_t MISO = 11; +static const uint8_t SCK = 9; + +static const uint8_t A0 = 1; +static const uint8_t A1 = 2; +static const uint8_t A2 = 3; +static const uint8_t A3 = 4; +static const uint8_t A4 = 5; +static const uint8_t A5 = 6; +static const uint8_t A6 = 7; +static const uint8_t A7 = 8; +static const uint8_t A8 = 9; +static const uint8_t A9 = 10; +static const uint8_t A10 = 11; +static const uint8_t A11 = 12; +static const uint8_t A12 = 13; +static const uint8_t A13 = 14; +static const uint8_t A14 = 15; +static const uint8_t A15 = 16; +static const uint8_t A16 = 17; +static const uint8_t A17 = 18; +static const uint8_t A18 = 19; +static const uint8_t A19 = 20; + +static const uint8_t T1 = 1; +static const uint8_t T2 = 2; +static const uint8_t T3 = 3; +static const uint8_t T4 = 4; +static const uint8_t T5 = 5; +static const uint8_t T6 = 6; +static const uint8_t T7 = 7; +static const uint8_t T8 = 8; +static const uint8_t T9 = 9; +static const uint8_t T10 = 10; +static const uint8_t T11 = 11; +static const uint8_t T12 = 12; +static const uint8_t T13 = 13; +static const uint8_t T14 = 14; + +static const uint8_t RST_LoRa = 12; +static const uint8_t BUSY_LoRa = 13; +static const uint8_t DIO1 = 14; + +#endif /* Pins_Arduino_h */ diff --git a/variants/heltec_vision_master_t190/platformio.ini b/variants/heltec_vision_master_t190/platformio.ini new file mode 100644 index 00000000..026e1e18 --- /dev/null +++ b/variants/heltec_vision_master_t190/platformio.ini @@ -0,0 +1,85 @@ +[Heltec_Vision_Master_T190_base] +extends = esp32_base +board = heltec_vision_master_t190 +build_flags = + ${esp32_base.build_flags} + -I variants/heltec_vision_master_t190 + -I src/helpers/ui + -D HELTEC_VISION_MASTER_T190 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D PIN_USER_BTN=0 + -D PIN_VEXT_EN=5 + -D PIN_VEXT_EN_ACTIVE=HIGH + -D PIN_VBAT_READ=6 + -D PIN_ADC_CTRL=46 + -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 PIN_BOARD_SDA=2 + -D PIN_BOARD_SCL=1 + -D PIN_TFT_SCL=38 + -D PIN_TFT_SDA=48 + -D PIN_TFT_RST=40 + -D PIN_TFT_VDD_CTL=7 + -D PIN_TFT_LEDA_CTL=17 + -D PIN_TFT_LEDA_CTL_ACTIVE=HIGH + -D PIN_TFT_CS=39 + -D PIN_TFT_DC=47 + -D ST7789 + -D DISPLAY_CLASS=ST7789Display +build_src_filter = ${esp32_base.build_src_filter} + +<../variants/heltec_vision_master_t190> + + + + + + + + +lib_deps = + ${esp32_base.lib_deps} + adafruit/Adafruit GFX Library @ ^1.12.1 + +[env:Heltec_Vision_Master_T190_radio_ble] +extends = Heltec_Vision_Master_T190_base +build_flags = + ${Heltec_Vision_Master_T190_base.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 ; dynamic, random PIN + -D BLE_DEBUG_LOGGING=1 + -D OFFLINE_QUEUE_SIZE=256 +build_src_filter = ${Heltec_Vision_Master_T190_base.build_src_filter} + + + +<../examples/companion_radio> +lib_deps = + ${Heltec_Vision_Master_T190_base.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Heltec_Vision_Master_T190_repeater] +extends = Heltec_Vision_Master_T190_base +build_flags = + ${Heltec_Vision_Master_T190_base.build_flags} + -D ADVERT_NAME='"Heltec T190 Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 +build_src_filter = ${Heltec_Vision_Master_T190_base.build_src_filter} + +<../examples/simple_repeater> +lib_deps = + ${Heltec_Vision_Master_T190_base.lib_deps} + ${esp32_ota.lib_deps} + +[env:Heltec_Vision_Master_T190_room_server] +extends = Heltec_Vision_Master_T190_base +build_flags = + ${Heltec_Vision_Master_T190_base.build_flags} + -D ADVERT_NAME='"Heltec T190 Room"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +build_src_filter = ${Heltec_Vision_Master_T190_base.build_src_filter} + +<../examples/simple_room_server> +lib_deps = + ${Heltec_Vision_Master_T190_base.lib_deps} + ${esp32_ota.lib_deps} diff --git a/variants/heltec_vision_master_t190/target.cpp b/variants/heltec_vision_master_t190/target.cpp new file mode 100644 index 00000000..9e13d36b --- /dev/null +++ b/variants/heltec_vision_master_t190/target.cpp @@ -0,0 +1,53 @@ +#include "target.h" +#include + +HeltecT190Board board; + +#if defined(P_LORA_SCLK) + static SPIClass spi(FSPI); + 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 + +WRAPPER_CLASS radio_driver(radio, board); + +ESP32RTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); + +SensorManager sensors; + +#ifdef DISPLAY_CLASS +DISPLAY_CLASS display; +#endif + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + +#if defined(P_LORA_SCLK) + return radio.std_init(&spi); +#else + return radio.std_init(); +#endif +} + +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 +} diff --git a/variants/heltec_vision_master_t190/target.h b/variants/heltec_vision_master_t190/target.h new file mode 100644 index 00000000..9dfab3d8 --- /dev/null +++ b/variants/heltec_vision_master_t190/target.h @@ -0,0 +1,27 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include +#ifdef DISPLAY_CLASS +#include +#endif + +extern HeltecT190Board board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; +extern SensorManager sensors; + +#ifdef DISPLAY_CLASS +extern DISPLAY_CLASS display; +#endif + +bool radio_init(); +uint32_t radio_get_rng_seed(); +void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); +void radio_set_tx_power(uint8_t dbm); +mesh::LocalIdentity radio_new_identity(); \ No newline at end of file From 2d5016bac3f2871cff8af730f3ff46998b1518a9 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Mon, 25 Aug 2025 23:45:50 +1200 Subject: [PATCH 02/21] add ability to remove neighbour via cli --- examples/simple_repeater/main.cpp | 11 +++++++++++ src/helpers/CommonCLI.cpp | 11 +++++++++++ src/helpers/CommonCLI.h | 1 + 3 files changed, 23 insertions(+) diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 622a0554..ea3f7de6 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -719,6 +719,17 @@ public: *dp = 0; // null terminator } + void removeNeighbor(const uint8_t* pubkey, int key_len) override { +#if MAX_NEIGHBOURS + for (int i = 0; i < MAX_NEIGHBOURS; i++) { + NeighbourInfo* neighbour = &neighbours[i]; + if(memcmp(neighbour->id.pub_key, pubkey, key_len) == 0){ + neighbours[i] = {}; // clear neighbour entry + } + } +#endif + } + mesh::LocalIdentity& getSelfId() override { return self_id; } void clearStats() override { diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 2abb4f7c..083fe2b7 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -165,6 +165,17 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch } } else if (memcmp(command, "neighbors", 9) == 0) { _callbacks->formatNeighborsReply(reply); + } else if (memcmp(command, "neighbor.remove ", 16) == 0) { + const char* hex = &command[16]; + uint8_t pubkey[PUB_KEY_SIZE]; + int hex_len = min(strlen(hex), PUB_KEY_SIZE*2); + int pubkey_len = hex_len / 2; + if (mesh::Utils::fromHex(pubkey, pubkey_len, hex)) { + _callbacks->removeNeighbor(pubkey, pubkey_len); + strcpy(reply, "OK"); + } else { + strcpy(reply, "ERR: bad pubkey"); + } } else if (memcmp(command, "tempradio ", 10) == 0) { strcpy(tmp, &command[10]); const char *parts[5]; diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 92deb718..3bf71b5a 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -43,6 +43,7 @@ public: virtual void dumpLogFile() = 0; virtual void setTxPower(uint8_t power_dbm) = 0; virtual void formatNeighborsReply(char *reply) = 0; + virtual void removeNeighbor(const uint8_t* pubkey, int key_len) = 0; virtual mesh::LocalIdentity& getSelfId() = 0; virtual void clearStats() = 0; virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0; From a16e011bd21cf3070f04b3513d562add0d090838 Mon Sep 17 00:00:00 2001 From: Laura J Date: Mon, 25 Aug 2025 22:10:18 -0700 Subject: [PATCH 03/21] modified T114 code to disable many unused peripherals, and set up the LOWPWR power mode. all changes should be quite safe, but testing for a couple days just in case. --- src/helpers/nrf52/T114Board.cpp | 39 +++++++++++++++++++++++++++++++++ src/helpers/nrf52/T114Board.h | 5 +++++ 2 files changed, 44 insertions(+) diff --git a/src/helpers/nrf52/T114Board.cpp b/src/helpers/nrf52/T114Board.cpp index 1f8c5854..78c21b33 100644 --- a/src/helpers/nrf52/T114Board.cpp +++ b/src/helpers/nrf52/T114Board.cpp @@ -26,6 +26,45 @@ void T114Board::begin() { pinMode(PIN_VBAT_READ, INPUT); + // Enable SoftDevice low-power mode + sd_power_mode_set(NRF_POWER_MODE_LOWPWR); + + // Enable DC/DC converter for better efficiency (REG1 stage) + NRF_POWER->DCDCEN = 1; + + // Power down unused communication peripherals + // UART1 - Not used on T114 + NRF_UARTE1->ENABLE = 0; + + // SPIM2/SPIS2 - Not used (SPI is on SPIM0) + NRF_SPIM2->ENABLE = 0; + NRF_SPIS2->ENABLE = 0; + + // TWI1 (I2C1) - Not used (I2C is on TWI0) + NRF_TWIM1->ENABLE = 0; + NRF_TWIS1->ENABLE = 0; + + // PWM modules - Not used for standard T114 functions + NRF_PWM1->ENABLE = 0; + NRF_PWM2->ENABLE = 0; + NRF_PWM3->ENABLE = 0; + + // PDM (Digital Microphone Interface) - Not used + NRF_PDM->ENABLE = 0; + + // I2S - Not used + NRF_I2S->ENABLE = 0; + + // QSPI - Not used (no external flash) + NRF_QSPI->ENABLE = 0; + + // Disable unused analog peripherals + // SAADC channels - only keep what's needed for battery monitoring + NRF_SAADC->ENABLE = 0; // Re-enable only when needed for measurements + + // COMP - Comparator not used + NRF_COMP->ENABLE = 0; + #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL) Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL); #endif diff --git a/src/helpers/nrf52/T114Board.h b/src/helpers/nrf52/T114Board.h index cd58134d..cf345937 100644 --- a/src/helpers/nrf52/T114Board.h +++ b/src/helpers/nrf52/T114Board.h @@ -40,6 +40,9 @@ public: uint16_t getBattMilliVolts() override { int adcvalue = 0; + + NRF_SAADC->ENABLE = 1; + analogReadResolution(12); analogReference(AR_INTERNAL_3_0); pinMode(PIN_BAT_CTL, OUTPUT); // battery adc can be read only ctrl pin 6 set to high @@ -49,6 +52,8 @@ public: adcvalue = analogRead(PIN_VBAT_READ); digitalWrite(6, 0); + NRF_SAADC->ENABLE = 0; + return (uint16_t)((float)adcvalue * MV_LSB * 4.9); } From 6536e9931d82faaf129bfd716777c951a45b9a6e Mon Sep 17 00:00:00 2001 From: ave Date: Tue, 26 Aug 2025 21:30:56 +0200 Subject: [PATCH 04/21] add why2025 badge as a target --- variants/xiao_c6/platformio.ini | 62 +++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/variants/xiao_c6/platformio.ini b/variants/xiao_c6/platformio.ini index fdf0f337..602bd6ae 100644 --- a/variants/xiao_c6/platformio.ini +++ b/variants/xiao_c6/platformio.ini @@ -121,3 +121,65 @@ build_src_filter = ${Meshimi.build_src_filter} lib_deps = ${Meshimi.lib_deps} densaugeo/base64 @ ~1.4.0 + +; WHY2025 badge variant +; requires soldering 2 pins between the esp32-C6 and the lora chip as shown here: https://wiki.why2025.org/Project:Meshtastic_on_the_WHY2025_badge +; also requires wiping the esp32-P4 +[WHY2025_badge] +extends = Xiao_C6 +board_build.partitions = default_8MB.csv +board_upload.flash_size = 8MB +board_upload.maximum_size = 8388608 +build_flags = + ${Xiao_C6.build_flags} + -D P_LORA_SCLK=6 + -D P_LORA_MISO=2 + -D P_LORA_MOSI=7 + -D P_LORA_NSS=4 + -D P_LORA_DIO_1=5 + -D P_LORA_BUSY=11 + -D P_LORA_RESET=1 + -D SX126X_TXEN=3 + -UPIN_BOARD_SDA + -UPIN_BOARD_SCL + -UP_LORA_TX_LED + -USX126X_RXEN + -USX126X_DIO2_AS_RF_SWITCH + -USX126X_DIO3_TCXO_VOLTAGE + +[env:WHY2025_badge_Repeater] +extends = WHY2025_badge +build_src_filter = ${WHY2025_badge.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${WHY2025_badge.build_flags} + -D ADVERT_NAME='"WHY2025 Badge Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${WHY2025_badge.lib_deps} +; ${esp32_ota.lib_deps} + +[env:WHY2025_badge_companion_radio_ble] +extends = WHY2025_badge +build_flags = ${WHY2025_badge.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D BLE_PIN_CODE=123456 + -D BLE_DEBUG_LOGGING=1 + -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_PRIVATE_KEY_IMPORT=1 + -D ENABLE_PRIVATE_KEY_EXPORT=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${WHY2025_badge.build_src_filter} + + + - + +<../examples/companion_radio/*.cpp> +lib_deps = + ${WHY2025_badge.lib_deps} + densaugeo/base64 @ ~1.4.0 From c10b387e6338c0dfb9439b00c0d7d442a39e7542 Mon Sep 17 00:00:00 2001 From: 446564 Date: Wed, 27 Aug 2025 10:30:56 -0700 Subject: [PATCH 05/21] add remaining roles to t1000e usb companion, repeater and room server --- variants/t1000-e/platformio.ini | 63 ++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini index 2811e243..c555a735 100644 --- a/variants/t1000-e/platformio.ini +++ b/variants/t1000-e/platformio.ini @@ -34,6 +34,67 @@ build_src_filter = ${nrf52840_t1000e.build_src_filter} debug_tool = jlink upload_protocol = nrfutil +[env:t1000e_repeater] +extends = t1000-e +build_flags = ${t1000-e.build_flags} + -I examples/companion_radio/ui-orig + -D ADVERT_NAME='"t1000-e Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + -D RX_BOOSTED_GAIN=true + -D RF_SWITCH_TABLE + -D DISPLAY_CLASS=NullDisplayDriver +build_src_filter = ${t1000-e.build_src_filter} + +<../examples/simple_repeater> +lib_deps = ${t1000-e.lib_deps} + stevemarple/MicroNMEA @ ^2.0.6 + +[env:t1000e_room_server] +extends = t1000-e +build_flags = ${t1000-e.build_flags} + -I examples/companion_radio/ui-orig + -D ADVERT_NAME='"t1000-e Room"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + -D RX_BOOSTED_GAIN=true + -D RF_SWITCH_TABLE + -D DISPLAY_CLASS=NullDisplayDriver +build_src_filter = ${t1000-e.build_src_filter} + +<../examples/simple_room_server> +lib_deps = ${t1000-e.lib_deps} + stevemarple/MicroNMEA @ ^2.0.6 + +[env:t1000e_companion_radio_usb] +extends = t1000-e +build_flags = ${t1000-e.build_flags} + -I examples/companion_radio/ui-orig + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 + -D OFFLINE_QUEUE_SIZE=256 + -D RX_BOOSTED_GAIN=true + -D RF_SWITCH_TABLE + -D DISPLAY_CLASS=NullDisplayDriver + -D PIN_BUZZER=25 + -D PIN_BUZZER_EN=37 ; P1/5 - required for T1000-E +build_src_filter = ${t1000-e.build_src_filter} + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-orig/*.cpp> +lib_deps = ${t1000-e.lib_deps} + densaugeo/base64 @ ~1.4.0 + stevemarple/MicroNMEA @ ^2.0.6 + end2endzone/NonBlockingRTTTL@^1.3.0 + [env:t1000e_companion_radio_ble] extends = t1000-e build_flags = ${t1000-e.build_flags} @@ -58,4 +119,4 @@ build_src_filter = ${t1000-e.build_src_filter} lib_deps = ${t1000-e.lib_deps} densaugeo/base64 @ ~1.4.0 stevemarple/MicroNMEA @ ^2.0.6 - end2endzone/NonBlockingRTTTL@^1.3.0 \ No newline at end of file + end2endzone/NonBlockingRTTTL@^1.3.0 From 136f733df52c8e3e801fec5534261fa42357f17d Mon Sep 17 00:00:00 2001 From: Florent Date: Wed, 27 Aug 2025 21:19:12 +0200 Subject: [PATCH 06/21] SensorMesh: add the possibility to receive msgs from admin --- examples/simple_sensor/SensorMesh.cpp | 99 +++++++++++++++++++-------- examples/simple_sensor/SensorMesh.h | 3 +- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/examples/simple_sensor/SensorMesh.cpp b/examples/simple_sensor/SensorMesh.cpp index ce36e0c2..ad295501 100644 --- a/examples/simple_sensor/SensorMesh.cpp +++ b/examples/simple_sensor/SensorMesh.cpp @@ -613,6 +613,23 @@ void SensorMesh::getPeerSharedSecret(uint8_t* dest_secret, int peer_idx) { } } +void SensorMesh::sendAckTo(const ContactInfo& dest, uint32_t ack_hash) { + if (dest.out_path_len < 0) { + mesh::Packet* ack = createAck(ack_hash); + if (ack) sendFlood(ack, TXT_ACK_DELAY); + } else { + uint32_t d = TXT_ACK_DELAY; + if (getExtraAckTransmitCount() > 0) { + mesh::Packet* a1 = createMultiAck(ack_hash, 1); + if (a1) sendDirect(a1, dest.out_path, dest.out_path_len, d); + d += 300; + } + + mesh::Packet* a2 = createAck(ack_hash); + if (a2) sendDirect(a2, dest.out_path, dest.out_path_len, d); + } +} + void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) { int i = matching_peer_indexes[sender_idx]; if (i < 0 || i >= num_contacts) { @@ -656,38 +673,55 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i memcpy(&sender_timestamp, data, 4); // timestamp (by sender's RTC clock - which could be wrong) uint flags = (data[4] >> 2); // message attempt number, and other flags - if (!(flags == TXT_TYPE_CLI_DATA)) { - MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags); - } else if (sender_timestamp > from.last_timestamp) { // prevent replay attacks - from.last_timestamp = sender_timestamp; - from.last_activity = getRTCClock()->getCurrentTime(); + if (sender_timestamp > from.last_timestamp) { // prevent replay attacks + if (flags == TXT_TYPE_PLAIN) { + bool handled = handleIncomingMsg(from, sender_timestamp, &data[5], flags, len - 5); + if (handled) { // if msg was handled then send an ack + uint32_t ack_hash; // calc truncated hash of the message timestamp + text + sender pub_key, to prove to sender that we got it + mesh::Utils::sha256((uint8_t *) &ack_hash, 4, data, 5 + strlen((char *)&data[5]), from.id.pub_key, PUB_KEY_SIZE); - // len can be > original length, but 'text' will be padded with zeroes - data[len] = 0; // need to make a C string again, with null terminator - - uint8_t temp[166]; - char *command = (char *) &data[5]; - char *reply = (char *) &temp[5]; - handleCommand(sender_timestamp, command, reply); - - int text_len = strlen(reply); - if (text_len > 0) { - uint32_t timestamp = getRTCClock()->getCurrentTimeUnique(); - if (timestamp == sender_timestamp) { - // WORKAROUND: the two timestamps need to be different, in the CLI view - timestamp++; - } - memcpy(temp, ×tamp, 4); // mostly an extra blob to help make packet_hash unique - temp[4] = (TXT_TYPE_CLI_DATA << 2); - - auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from.id, secret, temp, 5 + text_len); - if (reply) { - if (from.out_path_len < 0) { - sendFlood(reply, CLI_REPLY_DELAY_MILLIS); + if (packet->isRouteFlood()) { + // let this sender know path TO here, so they can use sendDirect(), and ALSO encode the ACK + mesh::Packet* path = createPathReturn(from.id, secret, packet->path, packet->path_len, + PAYLOAD_TYPE_ACK, (uint8_t *) &ack_hash, 4); + if (path) sendFlood(path, TXT_ACK_DELAY); } else { - sendDirect(reply, from.out_path, from.out_path_len, CLI_REPLY_DELAY_MILLIS); + sendAckTo(from, ack_hash); + } + } + } else if (flags == TXT_TYPE_CLI_DATA) { + from.last_timestamp = sender_timestamp; + from.last_activity = getRTCClock()->getCurrentTime(); + + // len can be > original length, but 'text' will be padded with zeroes + data[len] = 0; // need to make a C string again, with null terminator + + uint8_t temp[166]; + char *command = (char *) &data[5]; + char *reply = (char *) &temp[5]; + handleCommand(sender_timestamp, command, reply); + + int text_len = strlen(reply); + if (text_len > 0) { + uint32_t timestamp = getRTCClock()->getCurrentTimeUnique(); + if (timestamp == sender_timestamp) { + // WORKAROUND: the two timestamps need to be different, in the CLI view + timestamp++; + } + memcpy(temp, ×tamp, 4); // mostly an extra blob to help make packet_hash unique + temp[4] = (TXT_TYPE_CLI_DATA << 2); + + auto reply = createDatagram(PAYLOAD_TYPE_TXT_MSG, from.id, secret, temp, 5 + text_len); + if (reply) { + if (from.out_path_len < 0) { + sendFlood(reply, CLI_REPLY_DELAY_MILLIS); + } else { + sendDirect(reply, from.out_path, from.out_path_len, CLI_REPLY_DELAY_MILLIS); + } } } + } else { + MESH_DEBUG_PRINTLN("onPeerDataRecv: unsupported text type received: flags=%02x", (uint32_t)flags); } } else { MESH_DEBUG_PRINTLN("onPeerDataRecv: possible replay attack detected"); @@ -695,6 +729,15 @@ void SensorMesh::onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_i } } +bool SensorMesh::handleIncomingMsg(ContactInfo& from, uint32_t timestamp, uint8_t* data, uint flags, size_t len) { + MESH_DEBUG_PRINT("handleIncomingMsg: unhandled msg from "); + #ifdef MESH_DEBUG + mesh::Utils::printHex(Serial, from.id.pub_key, PUB_KEY_SIZE); + Serial.printf(": %s\n", data); + #endif + return false; +} + bool SensorMesh::onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) { int i = matching_peer_indexes[sender_idx]; if (i < 0 || i >= num_contacts) { diff --git a/examples/simple_sensor/SensorMesh.h b/examples/simple_sensor/SensorMesh.h index 0d87617b..62c1867e 100644 --- a/examples/simple_sensor/SensorMesh.h +++ b/examples/simple_sensor/SensorMesh.h @@ -140,7 +140,8 @@ protected: void onPeerDataRecv(mesh::Packet* packet, uint8_t type, int sender_idx, const uint8_t* secret, uint8_t* data, size_t len) override; bool onPeerPathRecv(mesh::Packet* packet, int sender_idx, const uint8_t* secret, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) override; void onAckRecv(mesh::Packet* packet, uint32_t ack_crc) override; - + virtual bool handleIncomingMsg(ContactInfo& from, uint32_t timestamp, uint8_t* data, uint flags, size_t len); + void sendAckTo(const ContactInfo& dest, uint32_t ack_hash); private: FILESYSTEM* _fs; unsigned long next_local_advert, next_flood_advert; From 666b036d3dd83c715d1bf5d76fb73d72d740c922 Mon Sep 17 00:00:00 2001 From: Quency-D Date: Thu, 28 Aug 2025 14:03:20 +0800 Subject: [PATCH 07/21] Adapt the new UI for heltec paper. --- variants/heltec_wireless_paper/platformio.ini | 5 ++++- variants/heltec_wireless_paper/target.cpp | 1 + variants/heltec_wireless_paper/target.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index b0c9ed1d..bc3168e9 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -29,6 +29,7 @@ build_flags = -D WIRELESS_PAPER build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_wireless_paper> + + lib_deps = ${esp32_base.lib_deps} https://github.com/todd-herbert/heltec-eink-modules/archive/9207eb6ab2b96f66298e0488740218c17b006af7.zip @@ -37,6 +38,7 @@ lib_deps = extends = Heltec_Wireless_Paper_base build_flags = ${Heltec_Wireless_Paper_base.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=E213Display @@ -46,7 +48,8 @@ build_flags = build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} + + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_Wireless_Paper_base.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/heltec_wireless_paper/target.cpp b/variants/heltec_wireless_paper/target.cpp index d434b241..dd2d51c0 100644 --- a/variants/heltec_wireless_paper/target.cpp +++ b/variants/heltec_wireless_paper/target.cpp @@ -19,6 +19,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; +MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/heltec_wireless_paper/target.h b/variants/heltec_wireless_paper/target.h index cb95905c..65b972d0 100644 --- a/variants/heltec_wireless_paper/target.h +++ b/variants/heltec_wireless_paper/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include +#include #endif extern HeltecV3Board board; @@ -18,6 +19,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; +extern MomentaryButton user_btn; #endif bool radio_init(); From 141579214104ab7123dfd4f405917a7bb1f4f336 Mon Sep 17 00:00:00 2001 From: Quency-D Date: Thu, 28 Aug 2025 14:29:56 +0800 Subject: [PATCH 08/21] Adapt the new UI for heltec e213. --- variants/heltec_vision_master_e213/platformio.ini | 8 ++++++-- variants/heltec_vision_master_e213/target.cpp | 1 + variants/heltec_vision_master_e213/target.h | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/variants/heltec_vision_master_e213/platformio.ini b/variants/heltec_vision_master_e213/platformio.ini index 29611dfa..6eb7e69a 100644 --- a/variants/heltec_vision_master_e213/platformio.ini +++ b/variants/heltec_vision_master_e213/platformio.ini @@ -28,7 +28,8 @@ build_flags = -D DISP_MOSI=6 -D Vision_Master_E213 build_src_filter = ${esp32_base.build_src_filter} - +<../variants/heltec_vision_master_e213> + +<../variants/heltec_vision_master_e213> + + lib_deps = ${esp32_base.lib_deps} https://github.com/Quency-D/heltec-eink-modules/archive/563dd41fd850a1bc3039b8723da4f3a20fe1c800.zip @@ -37,6 +38,7 @@ lib_deps = extends = Heltec_Vision_Master_E213_base build_flags = ${Heltec_Vision_Master_E213_base.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=E213Display @@ -46,7 +48,9 @@ build_flags = build_src_filter = ${Heltec_Vision_Master_E213_base.build_src_filter} + + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_Vision_Master_E213_base.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/heltec_vision_master_e213/target.cpp b/variants/heltec_vision_master_e213/target.cpp index dfba0103..23561850 100644 --- a/variants/heltec_vision_master_e213/target.cpp +++ b/variants/heltec_vision_master_e213/target.cpp @@ -19,6 +19,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; +MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/heltec_vision_master_e213/target.h b/variants/heltec_vision_master_e213/target.h index ec113879..9ecdc212 100644 --- a/variants/heltec_vision_master_e213/target.h +++ b/variants/heltec_vision_master_e213/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include +#include #endif extern HeltecE213Board board; @@ -18,6 +19,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; +extern MomentaryButton user_btn; #endif bool radio_init(); From d5bec3d6a5cc7c10ae65d0ad5b72fceebe5b64de Mon Sep 17 00:00:00 2001 From: Quency-D Date: Thu, 28 Aug 2025 14:36:56 +0800 Subject: [PATCH 09/21] Remove duplicate rows. --- variants/heltec_vision_master_e213/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/variants/heltec_vision_master_e213/platformio.ini b/variants/heltec_vision_master_e213/platformio.ini index 6eb7e69a..de5f2417 100644 --- a/variants/heltec_vision_master_e213/platformio.ini +++ b/variants/heltec_vision_master_e213/platformio.ini @@ -49,7 +49,6 @@ build_src_filter = ${Heltec_Vision_Master_E213_base.build_src_filter} + + +<../examples/companion_radio/*.cpp> - +<../examples/companion_radio/*.cpp> +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_Vision_Master_E213_base.lib_deps} From 2e49eef3375da12725746efb3f3e60f0767468a5 Mon Sep 17 00:00:00 2001 From: Quency-D Date: Thu, 28 Aug 2025 15:00:27 +0800 Subject: [PATCH 10/21] Adapt the new UI for heltec e290. --- variants/heltec_vision_master_e290/platformio.ini | 5 ++++- variants/heltec_vision_master_e290/target.cpp | 1 + variants/heltec_vision_master_e290/target.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/variants/heltec_vision_master_e290/platformio.ini b/variants/heltec_vision_master_e290/platformio.ini index b3ba33be..83d479e1 100644 --- a/variants/heltec_vision_master_e290/platformio.ini +++ b/variants/heltec_vision_master_e290/platformio.ini @@ -23,6 +23,7 @@ build_flags = -D Vision_Master_E290 build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_vision_master_e290> + + lib_deps = ${esp32_base.lib_deps} https://github.com/Quency-D/heltec-eink-modules/archive/563dd41fd850a1bc3039b8723da4f3a20fe1c800.zip @@ -31,6 +32,7 @@ lib_deps = extends = Heltec_Vision_Master_E290_base build_flags = ${Heltec_Vision_Master_E290_base.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=E290Display @@ -40,7 +42,8 @@ build_flags = build_src_filter = ${Heltec_Vision_Master_E290_base.build_src_filter} + + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_Vision_Master_E290_base.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/heltec_vision_master_e290/target.cpp b/variants/heltec_vision_master_e290/target.cpp index 2e897e49..92b02092 100644 --- a/variants/heltec_vision_master_e290/target.cpp +++ b/variants/heltec_vision_master_e290/target.cpp @@ -19,6 +19,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; +MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/heltec_vision_master_e290/target.h b/variants/heltec_vision_master_e290/target.h index 00b27e54..60770112 100644 --- a/variants/heltec_vision_master_e290/target.h +++ b/variants/heltec_vision_master_e290/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include +#include #endif extern HeltecE290Board board; @@ -18,6 +19,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; +extern MomentaryButton user_btn; #endif bool radio_init(); From ec6d1199003fa471854763d70b0f88159e290b12 Mon Sep 17 00:00:00 2001 From: Quency-D Date: Thu, 28 Aug 2025 17:07:33 +0800 Subject: [PATCH 11/21] Adapt the new UI for heltec t190. --- variants/heltec_vision_master_t190/platformio.ini | 4 +++- variants/heltec_vision_master_t190/target.cpp | 1 + variants/heltec_vision_master_t190/target.h | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/variants/heltec_vision_master_t190/platformio.ini b/variants/heltec_vision_master_t190/platformio.ini index 026e1e18..ecf71409 100644 --- a/variants/heltec_vision_master_t190/platformio.ini +++ b/variants/heltec_vision_master_t190/platformio.ini @@ -44,6 +44,7 @@ lib_deps = extends = Heltec_Vision_Master_T190_base build_flags = ${Heltec_Vision_Master_T190_base.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D BLE_PIN_CODE=123456 ; dynamic, random PIN @@ -51,7 +52,8 @@ build_flags = -D OFFLINE_QUEUE_SIZE=256 build_src_filter = ${Heltec_Vision_Master_T190_base.build_src_filter} + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_Vision_Master_T190_base.lib_deps} densaugeo/base64 @ ~1.4.0 diff --git a/variants/heltec_vision_master_t190/target.cpp b/variants/heltec_vision_master_t190/target.cpp index 9e13d36b..b9357594 100644 --- a/variants/heltec_vision_master_t190/target.cpp +++ b/variants/heltec_vision_master_t190/target.cpp @@ -19,6 +19,7 @@ SensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; +MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif bool radio_init() { diff --git a/variants/heltec_vision_master_t190/target.h b/variants/heltec_vision_master_t190/target.h index 9dfab3d8..8a5fc716 100644 --- a/variants/heltec_vision_master_t190/target.h +++ b/variants/heltec_vision_master_t190/target.h @@ -9,6 +9,7 @@ #include #ifdef DISPLAY_CLASS #include +#include #endif extern HeltecT190Board board; @@ -18,6 +19,7 @@ extern SensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; +extern MomentaryButton user_btn; #endif bool radio_init(); From 3fe2d48a6182c3acc3d55e160bacc10014fdfffa Mon Sep 17 00:00:00 2001 From: Quency-D Date: Thu, 28 Aug 2025 19:20:11 +0800 Subject: [PATCH 12/21] Remove duplicate rows. --- variants/heltec_vision_master_e290/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/variants/heltec_vision_master_e290/platformio.ini b/variants/heltec_vision_master_e290/platformio.ini index 83d479e1..d52dcc0d 100644 --- a/variants/heltec_vision_master_e290/platformio.ini +++ b/variants/heltec_vision_master_e290/platformio.ini @@ -23,7 +23,6 @@ build_flags = -D Vision_Master_E290 build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_vision_master_e290> - + lib_deps = ${esp32_base.lib_deps} https://github.com/Quency-D/heltec-eink-modules/archive/563dd41fd850a1bc3039b8723da4f3a20fe1c800.zip From 789629f5f8a80f4599ab37a52664589179fc3a8b Mon Sep 17 00:00:00 2001 From: 446564 Date: Thu, 28 Aug 2025 08:13:33 -0700 Subject: [PATCH 13/21] remove display class from repeater and room --- variants/t1000-e/platformio.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini index c555a735..b1826139 100644 --- a/variants/t1000-e/platformio.ini +++ b/variants/t1000-e/platformio.ini @@ -47,7 +47,6 @@ build_flags = ${t1000-e.build_flags} ; -D MESH_DEBUG=1 -D RX_BOOSTED_GAIN=true -D RF_SWITCH_TABLE - -D DISPLAY_CLASS=NullDisplayDriver build_src_filter = ${t1000-e.build_src_filter} +<../examples/simple_repeater> lib_deps = ${t1000-e.lib_deps} @@ -66,7 +65,6 @@ build_flags = ${t1000-e.build_flags} ; -D MESH_DEBUG=1 -D RX_BOOSTED_GAIN=true -D RF_SWITCH_TABLE - -D DISPLAY_CLASS=NullDisplayDriver build_src_filter = ${t1000-e.build_src_filter} +<../examples/simple_room_server> lib_deps = ${t1000-e.lib_deps} From 13cd849fcd5fa30982fa7459fce52a09cc599105 Mon Sep 17 00:00:00 2001 From: 446564 Date: Thu, 28 Aug 2025 08:37:25 -0700 Subject: [PATCH 14/21] add power off to nano g2 --- variants/nano_g2_ultra/nano-g2.h | 66 +++++++++++++++++--------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/variants/nano_g2_ultra/nano-g2.h b/variants/nano_g2_ultra/nano-g2.h index 884ed7f8..69df0c65 100644 --- a/variants/nano_g2_ultra/nano-g2.h +++ b/variants/nano_g2_ultra/nano-g2.h @@ -1,39 +1,40 @@ #pragma once -#include +#include "variant.h" + #include +#include // LoRa radio module pins -#define P_LORA_DIO_1 (32 + 10) -#define P_LORA_NSS (32 + 13) -#define P_LORA_RESET (32 + 15) -#define P_LORA_BUSY (32 + 11) -#define P_LORA_SCLK (0 + 12) -#define P_LORA_MISO (32 + 9) -#define P_LORA_MOSI (0 + 11) +#define P_LORA_DIO_1 (32 + 10) +#define P_LORA_NSS (32 + 13) +#define P_LORA_RESET (32 + 15) +#define P_LORA_BUSY (32 + 11) +#define P_LORA_SCLK (0 + 12) +#define P_LORA_MISO (32 + 9) +#define P_LORA_MOSI (0 + 11) #define SX126X_DIO2_AS_RF_SWITCH true #define SX126X_DIO3_TCXO_VOLTAGE 1.8 -#define SX126X_POWER_EN 37 +#define SX126X_POWER_EN 37 // buttons -#define PIN_BUTTON1 (32 + 6) -#define BUTTON_PIN PIN_BUTTON1 -#define PIN_USER_BTN BUTTON_PIN +#define PIN_BUTTON1 (32 + 6) +#define BUTTON_PIN PIN_BUTTON1 +#define PIN_USER_BTN BUTTON_PIN // GPS -#define GPS_EN PIN_GPS_STANDBY +#define GPS_EN PIN_GPS_STANDBY // built-ins -#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 +#define VBAT_MV_PER_LSB (0.73242188F) // 3.0V ADC range and 12-bit ADC resolution = 3000mV/4096 -#define VBAT_DIVIDER (0.5F) // 150K + 150K voltage divider on VBAT, actually 100K + 100K -#define VBAT_DIVIDER_COMP (2.0F) // Compensation factor for the VBAT divider +#define VBAT_DIVIDER (0.5F) // 150K + 150K voltage divider on VBAT, actually 100K + 100K +#define VBAT_DIVIDER_COMP (2.0F) // Compensation factor for the VBAT divider -#define PIN_VBAT_READ (0 + 2) -#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB) +#define PIN_VBAT_READ (0 + 2) +#define REAL_VBAT_MV_PER_LSB (VBAT_DIVIDER_COMP * VBAT_MV_PER_LSB) -class NanoG2Ultra : public mesh::MainBoard -{ +class NanoG2Ultra : public mesh::MainBoard { protected: uint8_t startup_reason; @@ -42,18 +43,21 @@ public: uint16_t getBattMilliVolts() override; bool startOTAUpdate(const char *id, char reply[]) override; - uint8_t getStartupReason() const override - { - return startup_reason; - } + uint8_t getStartupReason() const override { return startup_reason; } - const char *getManufacturerName() const override - { - return "Nano G2 Ultra"; - } + const char *getManufacturerName() const override { return "Nano G2 Ultra"; } - void reboot() override - { - NVIC_SystemReset(); + void reboot() override { NVIC_SystemReset(); } + + void powerOff() override { + // put GPS chip to sleep + digitalWrite(PIN_GPS_STANDBY, LOW); +// unset buzzer to prevent notification circuit activating on hibernate +#undef PIN_BUZZER + + nrf_gpio_cfg_sense_input(digitalPinToInterrupt(PIN_USER_BTN), NRF_GPIO_PIN_NOPULL, + NRF_GPIO_PIN_SENSE_LOW); + + sd_power_system_off(); } }; From c49ecc121e4228e35636fedac73c28d791d58084 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Fri, 29 Aug 2025 18:08:06 +1200 Subject: [PATCH 15/21] use new instance of neighbour info object when removing neighbour --- examples/simple_repeater/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index ea3f7de6..81c4d455 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -724,7 +724,7 @@ public: for (int i = 0; i < MAX_NEIGHBOURS; i++) { NeighbourInfo* neighbour = &neighbours[i]; if(memcmp(neighbour->id.pub_key, pubkey, key_len) == 0){ - neighbours[i] = {}; // clear neighbour entry + neighbours[i] = NeighbourInfo(); // clear neighbour entry } } #endif From 9ee01520845599a3820f0a1f0eb6ee1e0afe4f7c Mon Sep 17 00:00:00 2001 From: liamcottle Date: Fri, 29 Aug 2025 18:17:01 +1200 Subject: [PATCH 16/21] add default no op implementation for remove neighbor function --- src/helpers/CommonCLI.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 3bf71b5a..d1e49873 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -43,7 +43,9 @@ public: virtual void dumpLogFile() = 0; virtual void setTxPower(uint8_t power_dbm) = 0; virtual void formatNeighborsReply(char *reply) = 0; - virtual void removeNeighbor(const uint8_t* pubkey, int key_len) = 0; + virtual void removeNeighbor(const uint8_t* pubkey, int key_len) { + // no op by default + }; virtual mesh::LocalIdentity& getSelfId() = 0; virtual void clearStats() = 0; virtual void applyTempRadioParams(float freq, float bw, uint8_t sf, uint8_t cr, int timeout_mins) = 0; From 09e45f25b7767f5fef653d09fa46e6f285f5afc9 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Fri, 29 Aug 2025 18:58:54 +1200 Subject: [PATCH 17/21] add new ui to heltec v3 wifi companion --- variants/heltec_v3/platformio.ini | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index 24bc0bf0..32673b1f 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -129,6 +129,7 @@ lib_deps = extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} + -I examples/companion_radio/ui-new -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SSD1306Display @@ -141,7 +142,8 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + - +<../examples/companion_radio> + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> lib_deps = ${Heltec_lora32_v3.lib_deps} densaugeo/base64 @ ~1.4.0 From 6984d9f496765339d9abf995bd9be032dd0946b4 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Fri, 29 Aug 2025 17:01:39 +1000 Subject: [PATCH 18/21] * minor compilation fix --- src/helpers/CommonCLI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 083fe2b7..443fcc30 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -168,7 +168,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch } else if (memcmp(command, "neighbor.remove ", 16) == 0) { const char* hex = &command[16]; uint8_t pubkey[PUB_KEY_SIZE]; - int hex_len = min(strlen(hex), PUB_KEY_SIZE*2); + int hex_len = min((int)strlen(hex), PUB_KEY_SIZE*2); int pubkey_len = hex_len / 2; if (mesh::Utils::fromHex(pubkey, pubkey_len, hex)) { _callbacks->removeNeighbor(pubkey, pubkey_len); From 796b4c705c345aed9a15e550c34d653a47fb6f01 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Fri, 29 Aug 2025 19:47:24 +1200 Subject: [PATCH 19/21] disconnect existing wifi client when new connection established --- src/helpers/esp32/SerialWifiInterface.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/helpers/esp32/SerialWifiInterface.cpp b/src/helpers/esp32/SerialWifiInterface.cpp index e7dc055e..2df9980a 100644 --- a/src/helpers/esp32/SerialWifiInterface.cpp +++ b/src/helpers/esp32/SerialWifiInterface.cpp @@ -44,7 +44,18 @@ bool SerialWifiInterface::isWriteBusy() const { } size_t SerialWifiInterface::checkRecvFrame(uint8_t dest[]) { - if (!client) client = server.available(); + // check if new client connected + auto newClient = server.available(); + if (newClient) { + + // disconnect existing client + deviceConnected = false; + client.stop(); + + // switch active connection to new client + client = newClient; + + } if (client.connected()) { if (!deviceConnected) { From 4eaaeebfcace926f039f3025c2fc665df6aa1d3f Mon Sep 17 00:00:00 2001 From: Quency-D Date: Fri, 29 Aug 2025 17:12:35 +0800 Subject: [PATCH 20/21] Remove duplicate rows. --- variants/heltec_vision_master_e213/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/variants/heltec_vision_master_e213/platformio.ini b/variants/heltec_vision_master_e213/platformio.ini index de5f2417..9ca9b5ad 100644 --- a/variants/heltec_vision_master_e213/platformio.ini +++ b/variants/heltec_vision_master_e213/platformio.ini @@ -29,7 +29,6 @@ build_flags = -D Vision_Master_E213 build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_vision_master_e213> - + lib_deps = ${esp32_base.lib_deps} https://github.com/Quency-D/heltec-eink-modules/archive/563dd41fd850a1bc3039b8723da4f3a20fe1c800.zip From fee79756684305d3dda3ae61340e62ee473ba8cf Mon Sep 17 00:00:00 2001 From: Quency-D Date: Fri, 29 Aug 2025 17:31:28 +0800 Subject: [PATCH 21/21] Remove duplicate rows. --- variants/heltec_wireless_paper/platformio.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index bc3168e9..adb24676 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -29,7 +29,6 @@ build_flags = -D WIRELESS_PAPER build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_wireless_paper> - + lib_deps = ${esp32_base.lib_deps} https://github.com/todd-herbert/heltec-eink-modules/archive/9207eb6ab2b96f66298e0488740218c17b006af7.zip