diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 23223622..879200b7 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -613,10 +613,10 @@ void MyMesh::begin(bool has_display) { _prefs.cr = constrain(_prefs.cr, 5, 8); _prefs.tx_power_dbm = constrain(_prefs.tx_power_dbm, 1, MAX_LORA_TX_POWER); -#ifdef BLE_PIN_CODE +#ifdef BLE_PIN_CODE // 123456 by default if (_prefs.ble_pin == 0) { #ifdef DISPLAY_CLASS - if (has_display) { + if (has_display && BLE_PIN_CODE == 123456) { StdRNG rng; _active_ble_pin = rng.nextInt(100000, 999999); // random pin each session } else { diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index 891a390e..247a9b3d 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -10,11 +10,11 @@ #define FIRMWARE_VER_CODE 6 #ifndef FIRMWARE_BUILD_DATE -#define FIRMWARE_BUILD_DATE "29 Jun 2025" +#define FIRMWARE_BUILD_DATE "2 Jul 2025" #endif #ifndef FIRMWARE_VERSION -#define FIRMWARE_VERSION "v1.7.1" +#define FIRMWARE_VERSION "v1.7.2" #endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 8b797991..71c9f24a 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -22,11 +22,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "29 Jun 2025" + #define FIRMWARE_BUILD_DATE "2 Jul 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.7.1" + #define FIRMWARE_VERSION "v1.7.2" #endif #ifndef LORA_FREQ diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index 3d6cf80b..c394f3e5 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -22,11 +22,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "29 Jun 2025" + #define FIRMWARE_BUILD_DATE "2 Jul 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.7.1" + #define FIRMWARE_VERSION "v1.7.2" #endif #ifndef LORA_FREQ diff --git a/src/Mesh.cpp b/src/Mesh.cpp index a6b06c07..87f99878 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -135,7 +135,7 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { int k = 0; uint8_t path_len = data[k++]; uint8_t* path = &data[k]; k += path_len; - uint8_t extra_type = data[k++]; + uint8_t extra_type = data[k++] & 0x0F; // upper 4 bits reserved for future use uint8_t* extra = &data[k]; uint8_t extra_len = len - k; // remainder of packet (may be padded with zeroes!) if (onPeerPathRecv(pkt, j, secret, path, path_len, extra_type, extra, extra_len)) { diff --git a/src/helpers/CustomLR1110Wrapper.h b/src/helpers/CustomLR1110Wrapper.h index 7e2ffa2d..947bb51d 100644 --- a/src/helpers/CustomLR1110Wrapper.h +++ b/src/helpers/CustomLR1110Wrapper.h @@ -17,7 +17,7 @@ public: void onSendFinished() override { RadioLibWrapper::onSendFinished(); - _radio->setPreambleLength(8); // overcomes weird issues with small and big pkts + _radio->setPreambleLength(16); // overcomes weird issues with small and big pkts } float getLastRSSI() const override { return ((CustomLR1110 *)_radio)->getRSSI(); } diff --git a/src/helpers/HeltecV3Board.h b/src/helpers/HeltecV3Board.h index 57015a04..b71514cc 100644 --- a/src/helpers/HeltecV3Board.h +++ b/src/helpers/HeltecV3Board.h @@ -4,7 +4,7 @@ #include // LoRa radio module pins for Heltec V3 -// Also for Heltec Wireless Tracker +// Also for Heltec Wireless Tracker/Paper #define P_LORA_DIO_1 14 #define P_LORA_NSS 8 #define P_LORA_RESET RADIOLIB_NC @@ -14,7 +14,9 @@ #define P_LORA_MOSI 10 // built-ins -#define PIN_VBAT_READ 1 +#ifndef PIN_VBAT_READ // set in platformio.ini for boards like Heltec Wireless Paper (20) + #define PIN_VBAT_READ 1 +#endif #ifndef PIN_ADC_CTRL // set in platformio.ini for Heltec Wireless Tracker (2) #define PIN_ADC_CTRL 37 #endif diff --git a/src/helpers/ui/E213Display.cpp b/src/helpers/ui/E213Display.cpp new file mode 100644 index 00000000..92bf37fb --- /dev/null +++ b/src/helpers/ui/E213Display.cpp @@ -0,0 +1,116 @@ +#include "E213Display.h" + +#include "../../MeshCore.h" + +bool E213Display::begin() { + if (_init) return true; + + powerOn(); + display.begin(); + + // Set to landscape mode rotated 180 degrees + display.setRotation(3); + + _init = true; + _isOn = true; + + clear(); + display.fastmodeOn(); // Enable fast mode for quicker (partial) updates + + return true; +} + +void E213Display::powerOn() { +#ifdef PIN_VEXT_EN + pinMode(PIN_VEXT_EN, OUTPUT); + digitalWrite(PIN_VEXT_EN, LOW); // Active low + delay(50); // Allow power to stabilize +#endif +} + +void E213Display::powerOff() { +#ifdef PIN_VEXT_EN + digitalWrite(PIN_VEXT_EN, HIGH); // Turn off power +#endif +} + +void E213Display::turnOn() { + if (!_init) begin(); + powerOn(); + _isOn = true; +} + +void E213Display::turnOff() { + powerOff(); + _isOn = false; +} + +void E213Display::clear() { + display.clear(); +} + +void E213Display::startFrame(Color bkg) { + // Fill screen with white first to ensure clean background + display.fillRect(0, 0, width(), height(), WHITE); + if (bkg == LIGHT) { + // Fill with black if light background requested (inverted for e-ink) + display.fillRect(0, 0, width(), height(), BLACK); + } +} + +void E213Display::setTextSize(int sz) { + // The library handles text size internally + display.setTextSize(sz); +} + +void E213Display::setColor(Color c) { + // implemented in individual display methods +} + +void E213Display::setCursor(int x, int y) { + display.setCursor(x, y); +} + +void E213Display::print(const char *str) { + display.print(str); +} + +void E213Display::fillRect(int x, int y, int w, int h) { + display.fillRect(x, y, w, h, BLACK); +} + +void E213Display::drawRect(int x, int y, int w, int h) { + display.drawRect(x, y, w, h, BLACK); +} + +void E213Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h) { + // Width in bytes for bitmap processing + uint16_t widthInBytes = (w + 7) / 8; + + // Process the bitmap row by row + for (int by = 0; by < h; by++) { + // Scan across the row bit by bit + for (int bx = 0; bx < w; bx++) { + // Get the current bit using MSB ordering (like GxEPDDisplay) + uint16_t byteOffset = (by * widthInBytes) + (bx / 8); + uint8_t bitMask = 0x80 >> (bx & 7); + bool bitSet = bits[byteOffset] & bitMask; + + // If the bit is set, draw the pixel + if (bitSet) { + display.drawPixel(x + bx, y + by, BLACK); + } + } + } +} + +uint16_t E213Display::getTextWidth(const char *str) { + int16_t x1, y1; + uint16_t w, h; + display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h); + return w; +} + +void E213Display::endFrame() { + display.update(); +} diff --git a/src/helpers/ui/E213Display.h b/src/helpers/ui/E213Display.h new file mode 100644 index 00000000..330a2b6d --- /dev/null +++ b/src/helpers/ui/E213Display.h @@ -0,0 +1,37 @@ +#pragma once + +#include "DisplayDriver.h" + +#include +#include +#include + +// Display driver for E213 e-ink display +class E213Display : public DisplayDriver { + EInkDisplay_VisionMasterE213 display; + bool _init = false; + bool _isOn = false; + +public: + E213Display() : DisplayDriver(250, 122) {} + + bool begin(); + bool isOn() override { return _isOn; } + void turnOn() override; + void turnOff() override; + void clear() override; + void startFrame(Color bkg = DARK) override; + void setTextSize(int sz) override; + void setColor(Color c) override; + void setCursor(int x, int y) override; + void print(const char *str) override; + void fillRect(int x, int y, int w, int h) override; + void drawRect(int x, int y, int w, int h) override; + void drawXbm(int x, int y, const uint8_t *bits, int w, int h) override; + uint16_t getTextWidth(const char *str) override; + void endFrame() override; + +private: + void powerOn(); + void powerOff(); +}; \ No newline at end of file diff --git a/variants/heltec_tracker/target.cpp b/variants/heltec_tracker/target.cpp index 042c7c0d..f41702c5 100644 --- a/variants/heltec_tracker/target.cpp +++ b/variants/heltec_tracker/target.cpp @@ -23,43 +23,16 @@ HWTSensorManager sensors = HWTSensorManager(nmea); DISPLAY_CLASS display(&board.periph_power); // peripheral power pin is shared #endif -#ifndef LORA_CR - #define LORA_CR 5 -#endif - bool radio_init() { fallback_clock.begin(); rtc_clock.begin(Wire); -#ifdef SX126X_DIO3_TCXO_VOLTAGE - float tcxo = SX126X_DIO3_TCXO_VOLTAGE; -#else - float tcxo = 1.6f; -#endif - #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, 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); + return radio.std_init(&spi); +#else + return radio.std_init(); #endif - return true; // success } uint32_t radio_get_rng_seed() { diff --git a/variants/heltec_v2/platformio.ini b/variants/heltec_v2/platformio.ini index 562b309d..43bc43ad 100644 --- a/variants/heltec_v2/platformio.ini +++ b/variants/heltec_v2/platformio.ini @@ -96,7 +96,7 @@ build_flags = -D DISPLAY_CLASS=SSD1306Display -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=0 + -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 ; -D MESH_PACKET_LOGGING=1 diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index 17a0899a..c39e9c76 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -114,7 +114,7 @@ build_flags = -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 -D DISPLAY_CLASS=SSD1306Display - -D BLE_PIN_CODE=0 ; dynamic, random PIN + -D BLE_PIN_CODE=123456 ; dynamic, random PIN -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 ; -D MESH_PACKET_LOGGING=1 diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini new file mode 100644 index 00000000..0b9ac38e --- /dev/null +++ b/variants/heltec_wireless_paper/platformio.ini @@ -0,0 +1,84 @@ +[Heltec_Wireless_Paper_base] +extends = esp32_base +board = esp32-s3-devkitc-1 +build_flags = + ${esp32_base.build_flags} + -I variants/heltec_wireless_paper + -D HELTEC_WIRELESS_PAPER + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D P_LORA_TX_LED=18 + ; -D PIN_BOARD_SDA=17 + ; -D PIN_BOARD_SCL=18 + -D PIN_USER_BTN=0 + -D PIN_VEXT_EN=45 + -D PIN_VBAT_READ=20 + -D PIN_ADC_CTRL=19 + -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 DISP_CS=4 + -D DISP_BUSY=7 + -D DISP_DC=5 + -D DISP_RST=6 + -D DISP_SCLK=3 + -D DISP_MOSI=2 + -D ARDUINO_heltec_wifi_lora_32_V3 + -D WIRELESS_PAPER +build_src_filter = ${esp32_base.build_src_filter} + +<../variants/heltec_wireless_paper> +lib_deps = + ${esp32_base.lib_deps} + todd-herbert/heltec-eink-modules @ 4.5.0 + +[env:Heltec_Wireless_Paper_companion_radio_ble] +extends = Heltec_Wireless_Paper_base +build_flags = + ${Heltec_Wireless_Paper_base.build_flags} + -D MAX_CONTACTS=100 + -D MAX_GROUP_CHANNELS=8 + -D DISPLAY_CLASS=E213Display + -D BLE_PIN_CODE=0 ; dynamic, random PIN + -D BLE_DEBUG_LOGGING=1 + -D OFFLINE_QUEUE_SIZE=256 +build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} + + + + + +<../examples/companion_radio> +lib_deps = + ${Heltec_Wireless_Paper_base.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Heltec_Wireless_Paper_repeater] +extends = Heltec_Wireless_Paper_base +build_flags = + ${Heltec_Wireless_Paper_base.build_flags} + -D DISPLAY_CLASS=E213Display + -D ADVERT_NAME='"Heltec WP Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 +build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${Heltec_Wireless_Paper_base.lib_deps} + ${esp32_ota.lib_deps} + +[env:Heltec_Wireless_Paper_room_server] +extends = Heltec_Wireless_Paper_base +build_flags = + ${Heltec_Wireless_Paper_base.build_flags} + -D DISPLAY_CLASS=E213Display + -D ADVERT_NAME='"Heltec WP Room"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} + + + +<../examples/simple_room_server> +lib_deps = + ${Heltec_Wireless_Paper_base.lib_deps} + ${esp32_ota.lib_deps} \ No newline at end of file diff --git a/variants/heltec_wireless_paper/target.cpp b/variants/heltec_wireless_paper/target.cpp new file mode 100644 index 00000000..65eaab04 --- /dev/null +++ b/variants/heltec_wireless_paper/target.cpp @@ -0,0 +1,45 @@ +#include "target.h" + +#include + +HeltecV3Board board; + +static SPIClass spi; +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); + +SensorManager sensors; + +#ifdef DISPLAY_CLASS +DISPLAY_CLASS display; +#endif + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + return radio.std_init(&spi); +} + +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 +} \ No newline at end of file diff --git a/variants/heltec_wireless_paper/target.h b/variants/heltec_wireless_paper/target.h new file mode 100644 index 00000000..f06eead3 --- /dev/null +++ b/variants/heltec_wireless_paper/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 HeltecV3Board 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 diff --git a/variants/lilygo_t3s3/target.cpp b/variants/lilygo_t3s3/target.cpp index 7fa45e54..b7c4542c 100644 --- a/variants/lilygo_t3s3/target.cpp +++ b/variants/lilygo_t3s3/target.cpp @@ -3,13 +3,8 @@ ESP32Board board; -#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 - +static SPIClass spi; +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; @@ -28,35 +23,7 @@ bool radio_init() { fallback_clock.begin(); rtc_clock.begin(Wire); -#ifdef SX126X_DIO3_TCXO_VOLTAGE - float tcxo = SX126X_DIO3_TCXO_VOLTAGE; -#else - float tcxo = 1.6f; -#endif - -#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, 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() { diff --git a/variants/nano_g2_ultra/platformio.ini b/variants/nano_g2_ultra/platformio.ini index 20928bdf..c2bb1f23 100644 --- a/variants/nano_g2_ultra/platformio.ini +++ b/variants/nano_g2_ultra/platformio.ini @@ -36,7 +36,7 @@ build_flags = -I src/helpers/ui -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 - -D BLE_PIN_CODE=0 + -D BLE_PIN_CODE=123456 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 -D DISPLAY_CLASS=SH1106Display diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 49ae26eb..f6fb1f04 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -54,7 +54,7 @@ bool radio_init() { 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_LR11X0_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); if (status != RADIOLIB_ERR_NONE) { Serial.print("ERROR: radio init failed: "); Serial.println(status);