diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 034f0206..d996d752 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -1474,7 +1474,6 @@ void MyMesh::loop() { #ifdef DISPLAY_CLASS ui_task.setHasConnection(_serial->isConnected()); - ui_task.loop(); #endif } diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 098baf99..34c30498 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -193,4 +193,7 @@ void setup() { void loop() { the_mesh.loop(); sensors.loop(); +#ifdef DISPLAY_CLASS + ui_task.loop(); +#endif } diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 63e2740c..323f3633 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -144,7 +144,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch uint32_t curr = getRTCClock()->getCurrentTime(); if (sender_timestamp > curr) { getRTCClock()->setCurrentTime(sender_timestamp + 1); - strcpy(reply, "OK - clock set"); + uint32_t now = getRTCClock()->getCurrentTime(); + DateTime dt = DateTime(now); + sprintf(reply, "OK - clock set: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year()); } else { strcpy(reply, "ERR: clock cannot go backwards"); } @@ -161,7 +163,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch uint32_t curr = getRTCClock()->getCurrentTime(); if (secs > curr) { getRTCClock()->setCurrentTime(secs); - strcpy(reply, "(OK - clock set!)"); + uint32_t now = getRTCClock()->getCurrentTime(); + DateTime dt = DateTime(now); + sprintf(reply, "OK - clock set: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year()); } else { strcpy(reply, "(ERR: clock cannot go backwards)"); } @@ -245,10 +249,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch strcpy(reply, "OK"); } else if (memcmp(config, "flood.advert.interval ", 22) == 0) { int hours = _atoi(&config[22]); - if (hours > 0 && hours < 3) { - sprintf(reply, "Error: min is 3 hours"); - } else if (hours > 48) { - strcpy(reply, "Error: max is 48 hours"); + if ((hours > 0 && hours < 3) || (hours > 48)) { + strcpy(reply, "Error: interval range is 3-48 hours"); } else { _prefs->flood_advert_interval = (uint8_t)(hours); _callbacks->updateFloodAdvertTimer(); @@ -257,10 +259,8 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch } } else if (memcmp(config, "advert.interval ", 16) == 0) { int mins = _atoi(&config[16]); - if (mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) { - sprintf(reply, "Error: min is %d mins", MIN_LOCAL_ADVERT_INTERVAL); - } else if (mins > 240) { - strcpy(reply, "Error: max is 240 mins"); + if ((mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) || (mins > 240)) { + sprintf(reply, "Error: interval range is %d-240 minutes", MIN_LOCAL_ADVERT_INTERVAL); } else { _prefs->advert_interval = (uint8_t)(mins / 2); _callbacks->updateAdvertTimer(); diff --git a/src/helpers/CustomLLCC68.h b/src/helpers/CustomLLCC68.h index db037639..52b37a0e 100644 --- a/src/helpers/CustomLLCC68.h +++ b/src/helpers/CustomLLCC68.h @@ -9,6 +9,76 @@ class CustomLLCC68 : public LLCC68 { public: CustomLLCC68(Module *mod) : LLCC68(mod) { } + #ifdef RP2040_PLATFORM + bool std_init(SPIClassRP2040* spi = NULL) + #else + bool std_init(SPIClass* spi = NULL) + #endif + { + #ifdef SX126X_DIO3_TCXO_VOLTAGE + float tcxo = SX126X_DIO3_TCXO_VOLTAGE; + #else + float tcxo = 1.6f; + #endif + + #ifdef LORA_CR + uint8_t cr = LORA_CR; + #else + uint8_t cr = 5; + #endif + + #if defined(P_LORA_SCLK) + #ifdef NRF52_PLATFORM + if (spi) { spi->setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI); spi->begin(); } + #elif defined(RP2040_PLATFORM) + if (spi) { + spi->setMISO(P_LORA_MISO); + //spi->setCS(P_LORA_NSS); // Setting CS results in freeze + spi->setSCK(P_LORA_SCLK); + spi->setMOSI(P_LORA_MOSI); + spi->begin(); + } + #else + if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + #endif + #endif + int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f + if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { + #define SX126X_DIO3_TCXO_VOLTAGE (0.0f); + tcxo = SX126X_DIO3_TCXO_VOLTAGE; + status = begin(LORA_FREQ, LORA_BW, LORA_SF, 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 + } + + setCRC(1); + + #ifdef SX126X_CURRENT_LIMIT + setCurrentLimit(SX126X_CURRENT_LIMIT); + #endif + #ifdef SX126X_DIO2_AS_RF_SWITCH + setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); + #endif + #ifdef SX126X_RX_BOOSTED_GAIN + setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); + #endif + #if defined(SX126X_RXEN) || defined(SX126X_TXEN) + #ifndef SX1262X_RXEN + #define SX1262X_RXEN RADIOLIB_NC + #endif + #ifndef SX1262X_TXEN + #define SX1262X_TXEN RADIOLIB_NC + #endif + setRfSwitchPins(SX126X_RXEN, SX126X_TXEN); + #endif + + return true; // success + } + bool isReceiving() { uint16_t irq = getIrqFlags(); bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED); diff --git a/src/helpers/CustomSX1268.h b/src/helpers/CustomSX1268.h index a8180fc4..eb2d4f12 100644 --- a/src/helpers/CustomSX1268.h +++ b/src/helpers/CustomSX1268.h @@ -9,6 +9,76 @@ class CustomSX1268 : public SX1268 { public: CustomSX1268(Module *mod) : SX1268(mod) { } + #ifdef RP2040_PLATFORM + bool std_init(SPIClassRP2040* spi = NULL) + #else + bool std_init(SPIClass* spi = NULL) + #endif + { + #ifdef SX126X_DIO3_TCXO_VOLTAGE + float tcxo = SX126X_DIO3_TCXO_VOLTAGE; + #else + float tcxo = 1.6f; + #endif + + #ifdef LORA_CR + uint8_t cr = LORA_CR; + #else + uint8_t cr = 5; + #endif + + #if defined(P_LORA_SCLK) + #ifdef NRF52_PLATFORM + if (spi) { spi->setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI); spi->begin(); } + #elif defined(RP2040_PLATFORM) + if (spi) { + spi->setMISO(P_LORA_MISO); + //spi->setCS(P_LORA_NSS); // Setting CS results in freeze + spi->setSCK(P_LORA_SCLK); + spi->setMOSI(P_LORA_MOSI); + spi->begin(); + } + #else + if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + #endif + #endif + int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f + if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { + #define SX126X_DIO3_TCXO_VOLTAGE (0.0f); + tcxo = SX126X_DIO3_TCXO_VOLTAGE; + status = begin(LORA_FREQ, LORA_BW, LORA_SF, 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 + } + + setCRC(1); + + #ifdef SX126X_CURRENT_LIMIT + setCurrentLimit(SX126X_CURRENT_LIMIT); + #endif + #ifdef SX126X_DIO2_AS_RF_SWITCH + setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); + #endif + #ifdef SX126X_RX_BOOSTED_GAIN + setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); + #endif + #if defined(SX126X_RXEN) || defined(SX126X_TXEN) + #ifndef SX1262X_RXEN + #define SX1262X_RXEN RADIOLIB_NC + #endif + #ifndef SX1262X_TXEN + #define SX1262X_TXEN RADIOLIB_NC + #endif + setRfSwitchPins(SX126X_RXEN, SX126X_TXEN); + #endif + + return true; // success + } + bool isReceiving() { uint16_t irq = getIrqFlags(); bool detected = (irq & SX126X_IRQ_HEADER_VALID) || (irq & SX126X_IRQ_PREAMBLE_DETECTED); diff --git a/src/helpers/HeltecV2Board.h b/src/helpers/HeltecV2Board.h index 32545b61..5bf78778 100644 --- a/src/helpers/HeltecV2Board.h +++ b/src/helpers/HeltecV2Board.h @@ -68,7 +68,7 @@ public: } raw = raw / 8; - return (1.883 * (2 / 1024.0) * raw) * 1000; + return (1.98 * (2 / 1024.0) * raw) * 1000; } const char* getManufacturerName() const override { diff --git a/src/helpers/HeltecV3Board.h b/src/helpers/HeltecV3Board.h index 988e66d9..57015a04 100644 --- a/src/helpers/HeltecV3Board.h +++ b/src/helpers/HeltecV3Board.h @@ -99,7 +99,7 @@ public: digitalWrite(PIN_ADC_CTRL, !adc_active_state); - return (5.2 * (3.3 / 1024.0) * raw) * 1000; + return (5.42 * (3.3 / 1024.0) * raw) * 1000; } const char* getManufacturerName() const override { diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index dda1fd55..ed20b8a4 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -220,7 +220,7 @@ void EnvironmentSensorManager::loop() { _location->loop(); if (millis() > next_gps_update) { - if (_location->isValid()) { + if (gps_active && _location->isValid()) { node_lat = ((double)_location->getLatitude())/1000000.; node_lon = ((double)_location->getLongitude())/1000000.; MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index e8818fdd..8f9b1a27 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -21,6 +21,10 @@ build_flags = -D ENV_INCLUDE_BME280=1 -D ENV_INCLUDE_INA3221=1 -D ENV_INCLUDE_INA219=1 + -D ENV_INCLUDE_GPS=1 + -D PIN_GPS_RX=45 + -D PIN_GPS_TX=46 + -D PIN_GPS_EN=-1 build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_v3> + @@ -30,7 +34,8 @@ lib_deps = adafruit/Adafruit INA3221 Library @ ^1.0.1 adafruit/Adafruit INA219 @ ^1.2.3 adafruit/Adafruit AHTX0 @ ^2.0.5 - adafruit/Adafruit BME280 Library @ ^2.3.0 + adafruit/Adafruit BME280 Library @ ^2.3.0 + stevemarple/MicroNMEA @ ^2.0.6 [env:Heltec_v3_repeater] extends = Heltec_lora32_v3 diff --git a/variants/heltec_v3/target.cpp b/variants/heltec_v3/target.cpp index de8e0f92..4ae06be3 100644 --- a/variants/heltec_v3/target.cpp +++ b/variants/heltec_v3/target.cpp @@ -14,7 +14,14 @@ WRAPPER_CLASS radio_driver(radio, board); ESP32RTCClock fallback_clock; AutoDiscoverRTCClock rtc_clock(fallback_clock); -EnvironmentSensorManager sensors; + +#if ENV_INCLUDE_GPS + #include + MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1); + EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea); +#else + EnvironmentSensorManager sensors; +#endif #ifdef DISPLAY_CLASS DISPLAY_CLASS display; diff --git a/variants/rak4631/target.cpp b/variants/rak4631/target.cpp index daadd044..ede755e2 100644 --- a/variants/rak4631/target.cpp +++ b/variants/rak4631/target.cpp @@ -23,10 +23,6 @@ RAK4631SensorManager sensors; DISPLAY_CLASS display; #endif -#ifndef LORA_CR - #define LORA_CR 5 -#endif - #ifdef MESH_DEBUG uint32_t deviceOnline = 0x00; void scanDevices(TwoWire *w) @@ -75,35 +71,7 @@ void scanDevices(TwoWire *w) bool radio_init() { rtc_clock.begin(Wire); - -#ifdef SX126X_DIO3_TCXO_VOLTAGE - float tcxo = SX126X_DIO3_TCXO_VOLTAGE; -#else - float tcxo = 1.6f; -#endif - - 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_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/xiao_c6/platformio.ini b/variants/xiao_c6/platformio.ini new file mode 100644 index 00000000..bc1c789b --- /dev/null +++ b/variants/xiao_c6/platformio.ini @@ -0,0 +1,67 @@ +[Xiao_C6] +extends = esp32c6_base +board = esp32-c6-devkitm-1 +board_build.partitions = min_spiffs.csv ; get around 4mb flash limit +build_flags = + ${esp32c6_base.build_flags} + -I variants/xiao_c6 + -D ARDUINO_USB_CDC_ON_BOOT=1 + -D ARDUINO_USB_MODE=1 + -D P_LORA_TX_LED=15 + -D P_LORA_SCLK=19 + -D P_LORA_MISO=20 + -D P_LORA_MOSI=18 + -D P_LORA_NSS=22 + -D P_LORA_DIO_1=1 + -D P_LORA_BUSY=21 + -D P_LORA_RESET=2 + -D PIN_BOARD_SDA=16 + -D PIN_BOARD_SCL=17 + -D SX126X_RXEN=23 + -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 RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D LORA_TX_POWER=22 + -D DISABLE_WIFI_OTA=1 +build_src_filter = ${esp32c6_base.build_src_filter} + +<../variants/xiao_c6> + +[env:Xiao_C6_Repeater] +extends = Xiao_C6 +build_src_filter = ${Xiao_C6.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Xiao_C6.build_flags} + -D ADVERT_NAME='"Xiao C6 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 = + ${Xiao_C6.lib_deps} +; ${esp32_ota.lib_deps} + +[env:Xiao_C6_companion_radio_ble] +extends = Xiao_C6 +build_flags = ${Xiao_C6.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 = ${Xiao_C6.build_src_filter} + + + - + +<../examples/companion_radio> +lib_deps = + ${Xiao_C6.lib_deps} + densaugeo/base64 @ ~1.4.0 diff --git a/variants/xiao_c6/target.cpp b/variants/xiao_c6/target.cpp new file mode 100644 index 00000000..caca57bc --- /dev/null +++ b/variants/xiao_c6/target.cpp @@ -0,0 +1,49 @@ +#include +#include "target.h" + +ESP32Board board; + +#if defined(P_LORA_SCLK) + static SPIClass spi(0); + 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; + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + +#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/xiao_c6/target.h b/variants/xiao_c6/target.h new file mode 100644 index 00000000..eef923ab --- /dev/null +++ b/variants/xiao_c6/target.h @@ -0,0 +1,20 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include + +extern ESP32Board board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; +extern SensorManager sensors; + +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();