From f1ab110ae12a17a06e268306eea5937bb6c25533 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Sat, 18 Jan 2025 21:45:47 +1100 Subject: [PATCH] * new targets: Xiao_C3_repeater_sx1262, _sx1268 --- examples/simple_repeater/main.cpp | 18 +++-- platformio.ini | 55 ++++++++++++++ src/Mesh.h | 9 ++- src/helpers/RadioLibWrappers.h | 4 +- src/helpers/XiaoC3Board.h | 121 ++++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+), 9 deletions(-) create mode 100644 src/helpers/XiaoC3Board.h diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index e372145e..6bc1f1db 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -24,6 +24,9 @@ #ifndef LORA_CR #define LORA_CR 5 #endif +#ifndef LORA_TX_POWER + #defne LORA_TX_POWER 20 +#endif #define ANNOUNCE_NAME "repeater1" @@ -32,6 +35,11 @@ #if defined(HELTEC_LORA_V3) #include static HeltecV3Board board; +#elif defined(ARDUINO_XIAO_ESP32C3) + #include + #include + #include + static XiaoC3Board board; #else #error "need to provide a 'board' object" #endif @@ -306,13 +314,13 @@ public: #if defined(P_LORA_SCLK) SPIClass spi; -CustomSX1262 radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); #else -CustomSX1262 radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); #endif StdRNG fast_rng; SimpleMeshTables tables; -MyMesh the_mesh(*new CustomSX1262Wrapper(radio, board), *new ArduinoMillis(), fast_rng, *new VolatileRTCClock(), tables); +MyMesh the_mesh(*new WRAPPER_CLASS(radio, board), *new ArduinoMillis(), fast_rng, *new VolatileRTCClock(), tables); void halt() { while (1) ; @@ -334,9 +342,9 @@ void setup() { #if defined(P_LORA_SCLK) spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, 22, 8, tcxo); + int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); #else - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, 22, 8, tcxo); + int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); #endif if (status != RADIOLIB_ERR_NONE) { Serial.print("ERROR: radio init failed: "); diff --git a/platformio.ini b/platformio.ini index 7b85ebec..0f52e436 100644 --- a/platformio.ini +++ b/platformio.ini @@ -50,6 +50,13 @@ board = esp32-s3-devkitc-1 build_flags = ${esp32_base.build_flags} -D HELTEC_LORA_V3 +; -D LORA_FREQ=867.5 +; -D LORA_BW=125 +; -D LORA_SF=11 + -D LORA_TX_POWER=22 + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=1.8 + -D SX126X_CURRENT_LIMIT=130.0f ; for best TX power! build_src_filter = ${esp32_base.build_src_filter} [env:Heltec_v3_ping_server] @@ -64,7 +71,11 @@ build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<../examples/ping_clien extends = Heltec_lora32_v3 build_flags = ${Heltec_lora32_v3.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper ; -D NODE_ID=2 + -D MESH_PACKET_LOGGING=1 + -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<../examples/simple_repeater/main.cpp> [env:Heltec_v3_chat_alice] @@ -73,6 +84,7 @@ build_flags = ${Heltec_lora32_v3.build_flags} -D RUN_AS_ALICE=true ; -D NODE_ID=1 + -D MESH_PACKET_LOGGING=1 -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<../examples/simple_secure_chat/main.cpp> @@ -82,6 +94,7 @@ build_flags = ${Heltec_lora32_v3.build_flags} -D RUN_AS_ALICE=false ; -D NODE_ID=3 + -D MESH_PACKET_LOGGING=1 -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<../examples/simple_secure_chat/main.cpp> @@ -92,5 +105,47 @@ build_flags = ; -D NODE_ID=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} +<../examples/test_admin/main.cpp> +; ================ +[Xiao_esp32_C3] +extends = esp32_base +board = seeed_xiao_esp32c3 +build_flags = + ${esp32_base.build_flags} + -D LORA_TX_BOOST_PIN=D3 + -D P_LORA_TX_LED=D5 + -D PIN_VBAT_READ=D0 + -D P_LORA_DIO_1=D2 + -D P_LORA_NSS=D4 + -D P_LORA_RESET=RADIOLIB_NC + -D P_LORA_BUSY=D1 + +[env:Xiao_C3_Repeater_sx1262] +extends = Xiao_esp32_C3 +build_src_filter = ${Xiao_esp32_C3.build_src_filter} +<../examples/simple_repeater/main.cpp> +build_flags = + ${Xiao_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D LORA_FREQ=915.0 + -D LORA_BW=250 + -D LORA_SF=10 + ; -D MESH_PACKET_LOGGING=1 + ; -D MESH_DEBUG=1 + +[env:Xiao_C3_Repeater_sx1268] +extends = Xiao_esp32_C3 +build_src_filter = ${Xiao_esp32_C3.build_src_filter} +<../examples/simple_repeater/main.cpp> +build_flags = + ${Xiao_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D LORA_FREQ=433.0 + -D LORA_BW=250 + -D LORA_SF=10 + ; -D MESH_PACKET_LOGGING=1 + ; -D MESH_DEBUG=1 + ; ============= diff --git a/src/Mesh.h b/src/Mesh.h index bc51be73..c7d689c1 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -92,8 +92,6 @@ protected: */ virtual void onPeerPathRecv(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) { } - virtual int searchChannelsByHash(const uint8_t* hash, GroupChannel channels[], int max_matches); - /** * \brief A new incoming Advertisement has been received. * NOTE: these can be received multiple times (per id/timestamp), via different routes @@ -114,6 +112,13 @@ protected: */ virtual void onPathRecv(Packet* packet, Identity& sender, uint8_t* path, uint8_t path_len, uint8_t extra_type, uint8_t* extra, uint8_t extra_len) { } + /** + * \brief Perform search of local DB of matching GroupChannels. + * \param channels OUT - store matching channels in this array, up to max_matches + * \returns Number of channels with matching hash + */ + virtual int searchChannelsByHash(const uint8_t* hash, GroupChannel channels[], int max_matches); + /** * \brief An encrypted group data packet has been received. * NOTE: the same payload can be received multiple times, via different routes diff --git a/src/helpers/RadioLibWrappers.h b/src/helpers/RadioLibWrappers.h index a888a93d..13288464 100644 --- a/src/helpers/RadioLibWrappers.h +++ b/src/helpers/RadioLibWrappers.h @@ -21,8 +21,8 @@ public: uint32_t getPacketsRecv() const { return n_recv; } uint32_t getPacketsSent() const { return n_sent; } - float getLastRSSI() const override; - float getLastSNR() const override; + virtual float getLastRSSI() const override; + virtual float getLastSNR() const override; }; /** diff --git a/src/helpers/XiaoC3Board.h b/src/helpers/XiaoC3Board.h new file mode 100644 index 00000000..d9f9db28 --- /dev/null +++ b/src/helpers/XiaoC3Board.h @@ -0,0 +1,121 @@ +#pragma once + +#include +#include + +// LoRa radio module pins for custom Seeduino XiaoC3 build +// #define P_LORA_SCLK D8 +// #define P_LORA_MISO D9 +// #define P_LORA_MOSI D10 + +#include +#include + +class XiaoC3Board : public ESP32Board { + uint8_t startup_reason; +public: + void begin() { + startup_reason = BD_STARTUP_NORMAL; + ESP32Board::begin(); + + esp_reset_reason_t reason = esp_reset_reason(); + if (reason == ESP_RST_DEEPSLEEP) { + long wakeup_source = esp_sleep_get_gpio_wakeup_status(); // 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; + } + + #if defined(LORA_TX_BOOST_PIN) + gpio_hold_dis((gpio_num_t) LORA_TX_BOOST_PIN); + gpio_deep_sleep_hold_dis(); + #endif + } + + #ifdef PIN_VBAT_READ + // battery read support + pinMode(PIN_VBAT_READ, INPUT); + #endif + + #ifdef LORA_TX_BOOST_PIN + pinMode(LORA_TX_BOOST_PIN, OUTPUT); + digitalWrite(LORA_TX_BOOST_PIN, HIGH); + #endif + + #ifdef P_LORA_TX_LED + pinMode(P_LORA_TX_LED, OUTPUT); + digitalWrite(P_LORA_TX_LED, LOW); + #endif + } + + uint8_t getStartupReason() const { return startup_reason; } + + void enterDeepSleep(uint32_t secs, int8_t wake_pin = -1) { + gpio_set_direction(gpio_num_t(P_LORA_DIO_1), GPIO_MODE_INPUT); + if (wake_pin >= 0) { + gpio_set_direction((gpio_num_t)wake_pin, GPIO_MODE_INPUT); + } + + //hold disable, isolate and power domain config functions may be unnecessary + //gpio_deep_sleep_hold_dis(); + //esp_sleep_config_gpio_isolate(); + gpio_deep_sleep_hold_en(); + +#if defined(LORA_TX_BOOST_PIN) + gpio_hold_en((gpio_num_t) LORA_TX_BOOST_PIN); + gpio_deep_sleep_hold_en(); +#endif + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + + if (wake_pin >= 0) { + esp_deep_sleep_enable_gpio_wakeup((1 << P_LORA_DIO_1) | (1 << wake_pin), ESP_GPIO_WAKEUP_GPIO_HIGH); + } else { + esp_deep_sleep_enable_gpio_wakeup(1 << P_LORA_DIO_1, ESP_GPIO_WAKEUP_GPIO_HIGH); + } + + 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! + } + +#if defined(LORA_TX_BOOST_PIN) || defined(P_LORA_TX_LED) + void onBeforeTransmit() override { + #if defined(P_LORA_TX_LED) + digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on + #endif + #if defined(LORA_TX_BOOST_PIN) + digitalWrite(LORA_TX_BOOST_PIN, LOW); + delay(5); + #endif + } + void onAfterTransmit() override { + #if defined(LORA_TX_BOOST_PIN) + digitalWrite(LORA_TX_BOOST_PIN, HIGH); + #endif + #if defined(P_LORA_TX_LED) + digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off + #endif + } +#endif + + uint16_t getBattMilliVolts() override { + #ifdef PIN_VBAT_READ + analogReadResolution(10); + uint32_t raw = 0; + for (int i = 0; i < 8; i++) { + raw += analogRead(PIN_VBAT_READ); + } + raw = raw / 8; + + return ((5.78 * raw) / 1024.0) * 1000; + #else + return 0; + #endif + } + + const char* getManufacturerName() const override { + return "Xiao C3"; + } +};