From be76ef041b7f96284f93549f456a4110cc4f8172 Mon Sep 17 00:00:00 2001 From: FoxExe Date: Mon, 20 Jul 2026 15:46:42 +0500 Subject: [PATCH] ESP32-S3 Supermini + Waveshare Core1121 (LR1121-HF) + WeActStuido 2.9" epaper display --- variants/ESP32_S3_Supermini/SuperminiBoard.h | 63 ++++++ variants/ESP32_S3_Supermini/platformio.ini | 219 +++++++++++++++++++ variants/ESP32_S3_Supermini/target.cpp | 47 ++++ variants/ESP32_S3_Supermini/target.h | 53 +++++ 4 files changed, 382 insertions(+) create mode 100644 variants/ESP32_S3_Supermini/SuperminiBoard.h create mode 100644 variants/ESP32_S3_Supermini/platformio.ini create mode 100644 variants/ESP32_S3_Supermini/target.cpp create mode 100644 variants/ESP32_S3_Supermini/target.h diff --git a/variants/ESP32_S3_Supermini/SuperminiBoard.h b/variants/ESP32_S3_Supermini/SuperminiBoard.h new file mode 100644 index 000000000..fe5e675f9 --- /dev/null +++ b/variants/ESP32_S3_Supermini/SuperminiBoard.h @@ -0,0 +1,63 @@ +#pragma once + +#include +#include "target.h" +#include +#include +#include + + +class SuperminiBoard : public ESP32Board { +private: + float adc_mult = ADC_MULTIPLIER; +public: + SuperminiBoard() {} + + void begin() { + ESP32Board::begin(); + + pinMode(PIN_VBAT_READ, INPUT); + pinMode(BUTTON_PIN, 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); + + 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); + } + + esp_deep_sleep_start(); + } + + void powerOff() override { + enterDeepSleep(0); + } + + const char* getManufacturerName() const override { + return "ESP32 Supermini"; + } +}; \ No newline at end of file diff --git a/variants/ESP32_S3_Supermini/platformio.ini b/variants/ESP32_S3_Supermini/platformio.ini new file mode 100644 index 000000000..9e9ef67cf --- /dev/null +++ b/variants/ESP32_S3_Supermini/platformio.ini @@ -0,0 +1,219 @@ +[ESP32_S3_Supermini] +extends=esp32_base +board=esp32-s3-zero +board_build.partitions = huge_app.csv ; FW weight: ~1.7MB, but default partition is only ~1.3MB. Remove OTA and raise APP partition upto 3MB +;build_type = debug +;debug_tool = esp-builtin +monitor_echo = yes +;monitor_filters = esp32_exception_decoder + +build_flags = + ${esp32_base.build_flags} + ${sensor_base.build_flags} + -I variants/ESP32_S3_Supermini + -D ESP32_CPU_FREQ=80 + -D BOARD_HAS_PSRAM + + ; SPI-0 / LoRa (LR1121-HF) + -D PIN_SPI_MISO=11 + -D PIN_SPI_MOSI=10 + -D PIN_SPI_SCK=9 + -D PIN_SPI_NSS=8 + + -D P_LORA_MISO=PIN_SPI_MISO + -D P_LORA_MOSI=PIN_SPI_MOSI + -D P_LORA_SCLK=PIN_SPI_SCK + -D P_LORA_NSS=PIN_SPI_NSS + -D P_LORA_DIO_1=1 ; IRQ + -D P_LORA_RESET=12 + -D P_LORA_BUSY=13 + + -D LORA_TX_POWER=22 ; Max 14 for 2.4GHz or 22 for <900MHz + -D LR11X0_DIO3_TCXO_VOLTAGE=3.0 + -D LR11X0_DIO_AS_RF_SWITCH=1 + -D RX_BOOSTED_GAIN=1 + + ; Wire/i2c + -D PIN_BOARD_SDA=4 + -D PIN_BOARD_SCL=5 + ; 2nd wire for sensors + ;-D ENV_PIN_SDA=4 + ;-D ENV_PIN_SCL=5 + + ; Serial / UART (For GPS) + -D ENV_INCLUDE_GPS=0 ; Disable GPS support + ;-D PIN_GPS_TX=6 + ;-D PIN_GPS_RX=7 + ;-D PIN_GPS_EN=-1 + ;-D GPS_BAUD_RATE=9600 + ;-D ENV_SKIP_GPS_DETECT + ;-D FORCE_GPS_ALIVE + + ; Builtin LEDs + -D LED_PIN=48 + -D LED_STATE_ON=0 + -D PIN_LED=LED_PIN + -D LED_RED=LED_PIN + -D LED_BLUE=-1 + + ; Button + -D PIN_BUTTON1=0 + -D BUTTON_PIN=PIN_BUTTON1 + -D PIN_USER_BTN=PIN_BUTTON1 + + ; Battery ADC + -D PIN_VBAT_READ=16 + -D ADC_MULTIPLIER=2.085 ; BAT- -> 1M -> ADC -> 1M -> BAT+ + + ; SPI-1 / Display + -D PIN_SPI1_SCK=45 + -D PIN_SPI1_MISO=47 ; NC + -D PIN_SPI1_MOSI=46 + + -D UI_RECENT_LIST_SIZE=4 + ;-D UI_SENSORS_PAGE=1 + -D AUTO_OFF_MILLIS=0 ; Disable display off (eink wont need it) + -D BOOT_SCREEN_MILLIS=1000 ; Reduce boot time + + -D DISPLAY_CLASS=GxEPDDisplay + -D EINK_DISPLAY_MODEL=GxEPD2_290_BS + -D EINK_LOGICAL_W=128 + -D EINK_LOGICAL_H=296 + -D EINK_SCALE_X=1.0f + -D EINK_SCALE_Y=1.0f + -D EINK_X_OFFSET=0 + -D EINK_Y_OFFSET=0 + + -D PIN_DISPLAY_SCLK=PIN_SPI1_SCK + -D PIN_DISPLAY_MISO=PIN_SPI1_MISO + -D PIN_DISPLAY_MOSI=PIN_SPI1_MOSI + -D PIN_DISPLAY_CS=42 + -D PIN_DISPLAY_DC=41 + -D PIN_DISPLAY_RST=40 + -D PIN_DISPLAY_BUSY=39 + + ; Logging + -D DISABLE_DIAGNOSTIC_OUTPUT ; GxEPD2 debug off + ;-D BLE_DEBUG_LOGGING=1 + ;-D MESH_PACKET_LOGGING=1 + ;-D MESH_DEBUG=1 + ;-D RADIOLIB_DEBUG_BASIC=1 + ;-D RADIOLIB_DEBUG_PROTOCOL=1 + ;-D RADIOLIB_DEBUG_SPI=0 + ;-D RADIOLIB_VERBOSE_ASSERT=1 + ;-D CORE_DEBUG_LEVEL=3 + ;-D ARDUINO_USB_CDC_ON_BOOT=1 + ;-D ARDUINO_USB_MODE=1 + +build_src_filter=${esp32_base.build_src_filter} + +<../variants/ESP32_S3_Supermini> + + + ; Display + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = + ${esp32_base.lib_deps} + ${sensor_base.lib_deps} + bakercp/CRC32 + ;densaugeo/base64 + ;end2endzone/NonBlockingRTTTL + ;zinggjm/GxEPD2 ; ePaper displays drivers + GxEPD2 + +[env:ESP32_S3_Supermini_repeater] +extends=ESP32_S3_Supermini +build_flags = + ${ESP32_S3_Supermini.build_flags} + -D ADVERT_NAME='"Meshcore Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=50 +build_src_filter=${ESP32_S3_Supermini.build_src_filter} + +<../examples/simple_repeater> +lib_deps = + ${ESP32_S3_Supermini.lib_deps} + ${esp32_ota.lib_deps} + bakercp/CRC32 @ ^2.0.0 + +[env:ESP32_S3_Supermini_bridge_rs232] +extends=ESP32_S3_Supermini +build_flags = + ${ESP32_S3_Supermini.build_flags} + -D ADVERT_NAME='"RS232 Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=50 + + -D WITH_RS232_BRIDGE=Serial2 ; TODO + -D WITH_RS232_BRIDGE_RX=5 + -D WITH_RS232_BRIDGE_TX=6 + +build_src_filter=${ESP32_S3_Supermini.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${ESP32_S3_Supermini.lib_deps} + ${esp32_ota.lib_deps} + +[env:ESP32_S3_Supermini_room_server] +extends=ESP32_S3_Supermini +build_flags = + ${ESP32_S3_Supermini.build_flags} + -D ADVERT_NAME='"Room server"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +build_src_filter=${ESP32_S3_Supermini.build_src_filter} + +<../examples/simple_room_server> +lib_deps = + ${ESP32_S3_Supermini.lib_deps} + ${esp32_ota.lib_deps} + +[env:ESP32_S3_Supermini_terminal_chat] +extends=ESP32_S3_Supermini +build_flags = + ${ESP32_S3_Supermini.build_flags} + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=1 +build_src_filter=${ESP32_S3_Supermini.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${ESP32_S3_Supermini.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:ESP32_S3_Supermini_sensor] +extends=ESP32_S3_Supermini +build_flags = + ${ESP32_S3_Supermini.build_flags} + -D ADVERT_NAME='"Meshcore Sensor"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' +build_src_filter=${ESP32_S3_Supermini.build_src_filter} + +<../examples/simple_sensor> +lib_deps = + ${ESP32_S3_Supermini.lib_deps} + ${esp32_ota.lib_deps} + +[env:ESP32_S3_Supermini_companion_radio_uni] +extends=ESP32_S3_Supermini +build_flags = + ${ESP32_S3_Supermini.build_flags} + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D OFFLINE_QUEUE_SIZE=256 + -D WITH_COMPANION_CLI + -D WITH_WIFI_SWITCHING +build_src_filter=${ESP32_S3_Supermini.build_src_filter} + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = + ${ESP32_S3_Supermini.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/ESP32_S3_Supermini/target.cpp b/variants/ESP32_S3_Supermini/target.cpp new file mode 100644 index 000000000..5d6958a94 --- /dev/null +++ b/variants/ESP32_S3_Supermini/target.cpp @@ -0,0 +1,47 @@ +#pragma once + +#include "target.h" + + +static SPIClass spi(HSPI); // FSPI = SPI-1 (Display), HSPI = SPI-2 (LoRa) + +CustomLR1121 radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); + +CustomLR1121Wrapper radio_driver(radio, board); + +ESP32RTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); + +GxEPDDisplay display; +// (pin, long_press_mills, reverse, pulldownup, multiclick) +MomentaryButton user_btn(PIN_USER_BTN, 1000, true, true, true); + +#if ENV_INCLUDE_GPS +#include +MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); +EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else +EnvironmentSensorManager sensors; +#endif + +SuperminiBoard board; + + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + + bool result = radio.std_init(&spi); + + if (result) { +#ifdef RX_BOOSTED_GAIN + radio.setRxBoostedGainMode(RX_BOOSTED_GAIN); +#endif + } + return result; +}; + +mesh::LocalIdentity radio_new_identity() { + RadioNoiseListener rng(radio); + return mesh::LocalIdentity(&rng); // create new random identity +}; diff --git a/variants/ESP32_S3_Supermini/target.h b/variants/ESP32_S3_Supermini/target.h new file mode 100644 index 000000000..c1b843a1c --- /dev/null +++ b/variants/ESP32_S3_Supermini/target.h @@ -0,0 +1,53 @@ +#pragma once + +/* ESP32-S3 Supermini + Waveshare Core1121 (LR1121-HF) + WeAct ePaper 2.9" + * + * _____[:::::]_____ + * IN/OUT - 5v - | [] [] | - ?? - UART-0 Tx + * GND - | B+ B- | - ?? - UART-0 Rx + * OUT - 3.3v - | --- | - 01 - LORA_IRQ + * LORA_BUSY - 13 - | BOOST | - 02 - + * LORA_RESET - 12 - | | - 03 - + * LORA_MISO - 11 - | | - 04 - I2C_SDA + * LORA_MOSI - 10 - | | - 05 - I2C_SCL + * LORA_SCK - 09 - | | - 06 - GPS_Rx / Serial1_Tx + * LORA_CS - 08 - | | - 07 - GPS_Tx / Serial1_Rx + * ***************** + * + * Additional pins on board: + * + * 34 38 LED - 48 NOTE: Regular LED and WS2818 RGB led IN at same pin! + * 33 37 EINK_MISO - 47 + * 21 36 EINK_MOSI - 46 + * 18 35 EINK_SCK - 45 + * 17 EINK_CS - 42 + * BAT_ADC - 16 EINK_DC - 41 + * 15 EINK_RST - 40 + * 14 EINK_BUSY - 39 + * +*/ + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include "SuperminiBoard.h" + +// Display +#include +#include + +extern GxEPDDisplay display; +extern MomentaryButton user_btn; + +// Board +extern SuperminiBoard board; +extern AutoDiscoverRTCClock rtc_clock; +extern EnvironmentSensorManager sensors; + +// Radio / LoRa module +extern CustomLR1121Wrapper radio_driver; +bool radio_init(); +mesh::LocalIdentity radio_new_identity();