diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 16751d20..59a1b2de 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -260,13 +260,24 @@ public: #if ENV_INCLUDE_GPS == 1 } else if (_page == HomePage::GPS) { LocationProvider* nmea = sensors.getLocationProvider(); + char buf[50]; int y = 18; - display.drawTextLeftAlign(0, y, _task->getGPSState() ? "gps on" : "gps off"); + bool gps_state = _task->getGPSState(); +#ifdef PIN_GPS_SWITCH + bool hw_gps_state = digitalRead(PIN_GPS_SWITCH); + if (gps_state != hw_gps_state) { + strcpy(buf, gps_state ? "gps off(hw)" : "gps off(sw)"); + } else { + strcpy(buf, gps_state ? "gps on" : "gps off"); + } +#else + strcpy(buf, gps_state ? "gps on" : "gps off"); +#endif + display.drawTextLeftAlign(0, y, buf); if (nmea == NULL) { y = y + 12; display.drawTextLeftAlign(0, y, "Can't access GPS"); } else { - char buf[50]; strcpy(buf, nmea->isValid()?"fix":"no fix"); display.drawTextRightAlign(display.width()-1, y, buf); y = y + 12; @@ -716,10 +727,14 @@ void UITask::loop() { _analogue_pin_read_millis = millis(); } #endif -#if defined(DISP_BACKLIGHT) && defined(BACKLIGHT_BTN) +#if defined(BACKLIGHT_BTN) if (millis() > next_backlight_btn_check) { bool touch_state = digitalRead(PIN_BUTTON2); +#if defined(DISP_BACKLIGHT) digitalWrite(DISP_BACKLIGHT, !touch_state); +#elif defined(EXP_PIN_BACKLIGHT) + expander.digitalWrite(EXP_PIN_BACKLIGHT, !touch_state); +#endif next_backlight_btn_check = millis() + 300; } #endif diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 79dc87e5..bb675c27 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -548,7 +548,11 @@ void EnvironmentSensorManager::initBasicGPS() { delay(1000); // We'll consider GPS detected if we see any data on Serial1 +#ifdef ENV_SKIP_GPS_DETECT + gps_detected = true; +#else gps_detected = (Serial1.available() > 0); +#endif if (gps_detected) { MESH_DEBUG_PRINTLN("GPS detected"); diff --git a/src/helpers/ui/GxEPDDisplay.cpp b/src/helpers/ui/GxEPDDisplay.cpp index 34e31e30..ad47754b 100644 --- a/src/helpers/ui/GxEPDDisplay.cpp +++ b/src/helpers/ui/GxEPDDisplay.cpp @@ -1,13 +1,26 @@ #include "GxEPDDisplay.h" +#ifdef EXP_PIN_BACKLIGHT + #include + extern PCA9557 expander; +#endif + #ifndef DISPLAY_ROTATION #define DISPLAY_ROTATION 3 #endif +#ifdef ESP32 + SPIClass SPI1 = SPIClass(FSPI); +#endif + bool GxEPDDisplay::begin() { display.epd2.selectSPI(SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0)); +#ifdef ESP32 + SPI1.begin(PIN_DISPLAY_SCLK, PIN_DISPLAY_MISO, PIN_DISPLAY_MOSI, PIN_DISPLAY_CS); +#else SPI1.begin(); +#endif display.init(115200, true, 2, false); display.setRotation(DISPLAY_ROTATION); setTextSize(1); // Default to size 1 @@ -27,6 +40,8 @@ void GxEPDDisplay::turnOn() { if (!_init) begin(); #if defined(DISP_BACKLIGHT) && !defined(BACKLIGHT_BTN) digitalWrite(DISP_BACKLIGHT, HIGH); +#elif defined(EXP_PIN_BACKLIGHT) && !defined(BACKLIGHT_BTN) + expander.digitalWrite(EXP_PIN_BACKLIGHT, HIGH); #endif _isOn = true; } @@ -34,6 +49,8 @@ void GxEPDDisplay::turnOn() { void GxEPDDisplay::turnOff() { #if defined(DISP_BACKLIGHT) && !defined(BACKLIGHT_BTN) digitalWrite(DISP_BACKLIGHT, LOW); +#elif defined(EXP_PIN_BACKLIGHT) && !defined(BACKLIGHT_BTN) + expander.digitalWrite(EXP_PIN_BACKLIGHT, LOW); #endif _isOn = false; } diff --git a/variants/thinknode_m5/ThinknodeM5Board.cpp b/variants/thinknode_m5/ThinknodeM5Board.cpp new file mode 100644 index 00000000..5adc8c00 --- /dev/null +++ b/variants/thinknode_m5/ThinknodeM5Board.cpp @@ -0,0 +1,47 @@ +#include "ThinknodeM5Board.h" + +PCA9557 expander (0x18, &Wire1); + +void ThinknodeM5Board::begin() { + // Start expander and configure pins + Wire1.begin(48, 47); + expander.pinMode(EXP_PIN_POWER, OUTPUT); // eink + expander.pinMode(EXP_PIN_BACKLIGHT, OUTPUT); // peripherals + expander.pinMode(EXP_PIN_LED, OUTPUT); // peripherals + expander.digitalWrite(EXP_PIN_POWER, HIGH); + expander.digitalWrite(EXP_PIN_BACKLIGHT, LOW); + expander.digitalWrite(EXP_PIN_LED, LOW); + +#ifdef PIN_GPS_SWITCH + pinMode(PIN_GPS_SWITCH, INPUT); +#endif + + ESP32Board::begin(); + } + + void ThinknodeM5Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) { + esp_deep_sleep_start(); + } + + void ThinknodeM5Board::powerOff() { + enterDeepSleep(0); + } + + uint16_t ThinknodeM5Board::getBattMilliVolts() { + analogReadResolution(12); + analogSetPinAttenuation(PIN_VBAT_READ, ADC_11db); + + uint32_t mv = 0; + for (int i = 0; i < 8; ++i) { + mv += analogReadMilliVolts(PIN_VBAT_READ); + delayMicroseconds(200); + } + mv /= 8; + + analogReadResolution(10); + return static_cast(mv * ADC_MULTIPLIER ); +} + + const char* ThinknodeM5Board::getManufacturerName() const { + return "Elecrow ThinkNode M2"; + } diff --git a/variants/thinknode_m5/ThinknodeM5Board.h b/variants/thinknode_m5/ThinknodeM5Board.h new file mode 100644 index 00000000..3c120027 --- /dev/null +++ b/variants/thinknode_m5/ThinknodeM5Board.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include +#include + +extern PCA9557 expander; + +class ThinknodeM5Board : public ESP32Board { + +public: + + void begin(); + void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1); + void powerOff() override; + uint16_t getBattMilliVolts() override; + const char* getManufacturerName() const override ; + + void onBeforeTransmit() override { + expander.digitalWrite(EXP_PIN_LED, HIGH); // turn TX LED on + } + void onAfterTransmit() override { + expander.digitalWrite(EXP_PIN_LED, LOW); // turn TX LED off + } +}; \ No newline at end of file diff --git a/variants/thinknode_m5/pins_arduino.h b/variants/thinknode_m5/pins_arduino.h new file mode 100644 index 00000000..408ed236 --- /dev/null +++ b/variants/thinknode_m5/pins_arduino.h @@ -0,0 +1,28 @@ +// Need this file for ESP32-S3 +// No need to modify this file, changes to pins imported from variant.h +// Most is similar to https://github.com/espressif/arduino-esp32/blob/master/variants/esp32s3/pins_arduino.h + +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +// Serial +static const uint8_t TX = PIN_GPS_TX; +static const uint8_t RX = PIN_GPS_RX; + +// Default SPI will be mapped to Radio +static const uint8_t SS = P_LORA_NSS; +static const uint8_t SCK = P_LORA_SCLK; +static const uint8_t MOSI = P_LORA_MISO; +static const uint8_t MISO = P_LORA_MOSI; + +// The default Wire will be mapped to PMU and RTC +static const uint8_t SCL = PIN_BOARD_SCL; +static const uint8_t SDA = PIN_BOARD_SDA; + +#endif /* Pins_Arduino_h */ \ No newline at end of file diff --git a/variants/thinknode_m5/platformio.ini b/variants/thinknode_m5/platformio.ini new file mode 100644 index 00000000..23db506a --- /dev/null +++ b/variants/thinknode_m5/platformio.ini @@ -0,0 +1,224 @@ +[ThinkNode_M5] +extends = esp32_base +board = ESP32-S3-WROOM-1-N4 +build_flags = ${esp32_base.build_flags} + -I variants/thinknode_m5 + -I src/helpres/sensors + -D THINKNODE_M5 + -D PIN_BUZZER=9 + -D PIN_BOARD_SCL=1 + -D PIN_BOARD_SDA=2 + -D P_LORA_EN=46 + -D P_LORA_DIO_1=4 + -D P_LORA_NSS=17 + -D P_LORA_RESET=6 ; RADIOLIB_NC + -D P_LORA_BUSY=5 ; DIO2 = 38 + -D P_LORA_SCLK=16 + -D P_LORA_MISO=7 + -D P_LORA_MOSI=15 + -D PIN_USER_BTN=21 + -D PIN_BUTTON2=14 + -D EXP_PIN_LED=1 ; led is on bus expander + -D DISPLAY_ROTATION=4 + -D DISPLAY_CLASS=GxEPDDisplay + -D EINK_DISPLAY_MODEL=GxEPD2_154_D67 + -D EINK_SCALE_X=1.5625f + -D EINK_SCALE_Y=1.5625f + -D EINK_X_OFFSET=0 + -D EINK_Y_OFFSET=10 + -D BACKLIGHT_BTN=PIN_BUTTON2 + -D AUTO_OFF_MILLIS=0 + -D DISABLE_DIAGNOSTIC_OUTPUT + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=3.3 + -D SX126X_CURRENT_LIMIT=140 + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D SX126X_RX_BOOSTED_GAIN=1 + -D MESH_DEBUG=1 + -D ENV_INCLUDE_GPS=1 + -D PERSISTANT_GPS=1 + -D ENV_SKIP_GPS_DETECT=1 +build_src_filter = ${esp32_base.build_src_filter} + + + + + + + + + +<../variants/thinknode_m5> +lib_deps = ${esp32_base.lib_deps} + zinggjm/GxEPD2 @ 1.6.2 + bakercp/CRC32 @ ^2.0.0 + maxpromer/PCA9557-arduino + stevemarple/MicroNMEA @ ^2.0.6 + +[env:ThinkNode_M5_Repeater] +extends = ThinkNode_M5 +build_src_filter = ${ThinkNode_M5.build_src_filter} + +<../examples/simple_repeater/*.cpp> +build_flags = + ${ThinkNode_M5.build_flags} + -D ADVERT_NAME='"Thinknode M2 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 = + ${ThinkNode_M5.lib_deps} + ${esp32_ota.lib_deps} + +; [env:ThinkNode_M5_Repeater_bridge_rs232] +; extends = ThinkNode_M5 +; build_src_filter = ${ThinkNode_M5.build_src_filter} +; + +; +<../examples/simple_repeater/*.cpp> +; build_flags = +; ${ThinkNode_M5.build_flags} +; -D ADVERT_NAME='"RS232 Bridge"' +; -D ADVERT_LAT=0.0 +; -D ADVERT_LON=0.0 +; -D ADMIN_PASSWORD='"password"' +; -D MAX_NEIGHBOURS=8 +; -D WITH_RS232_BRIDGE=Serial2 +; -D WITH_RS232_BRIDGE_RX=5 +; -D WITH_RS232_BRIDGE_TX=6 +; ; -D MESH_PACKET_LOGGING=1 +; ; -D MESH_DEBUG=1 +; lib_deps = +; ${ThinkNode_M5.lib_deps} +; ${esp32_ota.lib_deps} + +[env:ThinkNode_M5_Repeater_bridge_espnow] +extends = ThinkNode_M5 +build_src_filter = ${ThinkNode_M5.build_src_filter} + + + +<../examples/simple_repeater/*.cpp> +build_flags = + ${ThinkNode_M5.build_flags} + -D ADVERT_NAME='"ESPNow Bridge"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D WITH_ESPNOW_BRIDGE=1 + -D WITH_ESPNOW_BRIDGE_SECRET='"shared-secret"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${ThinkNode_M5.lib_deps} + ${esp32_ota.lib_deps} + +[env:ThinkNode_M5_room_server] +extends = ThinkNonde_M5 +build_src_filter = ${ThinkNode_M5.build_src_filter} + +<../examples/simple_room_server> +build_flags = + ${ThinkNode_M5.build_flags} + -D ADVERT_NAME='"Thinknode M2 Room Server"' + -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 +lib_deps = + ${ThinkNode_M5.lib_deps} + ${esp32_ota.lib_deps} + +[env:ThinkNode_M5_terminal_chat] +extends = ThinkNode_M5 +build_flags = + ${ThinkNode_M5.build_flags} + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${ThinkNode_M5.build_src_filter} + +<../examples/simple_secure_chat/main.cpp> +lib_deps = + ${ThinkNode_M5.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:ThinkNode_M5_companion_radio_ble] +extends = ThinkNode_M5 +build_flags = + ${ThinkNode_M5.build_flags} + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D BLE_PIN_CODE=123456 + -D OFFLINE_QUEUE_SIZE=256 + -D UI_RECENT_LIST_SIZE=9 +; -D BLE_DEBUG_LOGGING=1 +; -D MESH_PACKET_LOGGING=1 +; -D GPS_NMEA_DEBUG +build_src_filter = ${ThinkNode_M5.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = + ${ThinkNode_M5.lib_deps} + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:ThinkNode_M5_companion_radio_usb] +extends = ThinkNode_M5 +build_flags = + ${ThinkNode_M5.build_flags} + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D OFFLINE_QUEUE_SIZE=256 +build_src_filter = ${ThinkNode_M5.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = + ${ThinkNode_M5.lib_deps} + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:ThinkNode_M5_companion_radio_wifi] +extends = ThinkNode_M5 +build_flags = + ${ThinkNode_M5.build_flags} + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D OFFLINE_QUEUE_SIZE=256 + -D WIFI_DEBUG_LOGGING=1 + -D WIFI_SSID='"Livebox-633C"' + -D WIFI_PWD='"vvQUHGSxsWd7fKMYSr"' +build_src_filter = ${ThinkNode_M5.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = + ${ThinkNode_M5.lib_deps} + densaugeo/base64 @ ~1.4.0 + end2endzone/NonBlockingRTTTL@^1.3.0 + +[env:ThinkNode_M5_companion_radio_serial] +extends = ThinkNode_M5 +build_flags = + ${ThinkNode_M5.build_flags} + -I examples/companion_radio/ui-new + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D SERIAL_TX=D6 + -D SERIAL_RX=D7 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${ThinkNode_M5.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> + +<../examples/companion_radio/ui-new/*.cpp> +lib_deps = + ${ThinkNode_M5.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/thinknode_m5/target.cpp b/variants/thinknode_m5/target.cpp new file mode 100644 index 00000000..8208d2c4 --- /dev/null +++ b/variants/thinknode_m5/target.cpp @@ -0,0 +1,64 @@ +#include +#include "target.h" +#include + +ThinknodeM5Board 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 + +WRAPPER_CLASS radio_driver(radio, board); + +ESP32RTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); + +#ifdef ENV_INCLUDE_GPS +MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock); +EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else +EnvironmentSensorManager sensors = EnvironmentSensorManager(); +#endif + +#ifdef DISPLAY_CLASS + DISPLAY_CLASS display; + MomentaryButton user_btn(PIN_USER_BTN, 1000, true); +#endif + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + pinMode(P_LORA_EN, OUTPUT); + digitalWrite(P_LORA_EN, HIGH); + #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(); +#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/thinknode_m5/target.h b/variants/thinknode_m5/target.h new file mode 100644 index 00000000..2af42095 --- /dev/null +++ b/variants/thinknode_m5/target.h @@ -0,0 +1,35 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#ifdef DISPLAY_CLASS + #include + #include +#endif + +extern ThinknodeM5Board board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; +extern EnvironmentSensorManager sensors; +extern PCA9557 expander; + +#ifdef DISPLAY_CLASS + extern DISPLAY_CLASS display; + extern MomentaryButton user_btn; +#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/thinknode_m5/variant.h b/variants/thinknode_m5/variant.h new file mode 100644 index 00000000..9b82416b --- /dev/null +++ b/variants/thinknode_m5/variant.h @@ -0,0 +1,28 @@ +#define I2C_SCL 1 +#define I2C_SDA 2 +#define PIN_VBAT_READ 8 +#define AREF_VOLTAGE (3.0) +#define ADC_MULTIPLIER (2.11F) +#define PIN_BUZZER 9 +#define PIN_VEXT_EN_ACTIVE HIGH +#define PIN_VEXT_EN 46 +#define PIN_USER_BTN 21 +//#define PIN_LED 3 +//#define PIN_STATUS_LED 1 +#define PIN_PWRBTN 14 + +#define PIN_DISPLAY_MISO (-1) +#define PIN_DISPLAY_MOSI (45) +#define PIN_DISPLAY_SCLK (38) +#define PIN_DISPLAY_CS (39) +#define PIN_DISPLAY_DC (40) +#define PIN_DISPLAY_RST (41) +#define PIN_DISPLAY_BUSY (42) +#define EXP_PIN_BACKLIGHT (5) +#define EXP_PIN_POWER (4) + +#define PIN_GPS_EN (11) +#define PIN_GPS_RESET (13) +#define PIN_GPS_RX (20) +#define PIN_GPS_TX (19) +#define PIN_GPS_SWITCH (10) \ No newline at end of file