diff --git a/bin/version.sh b/bin/version.sh index bf6adf67a..5a11b5c23 100644 --- a/bin/version.sh +++ b/bin/version.sh @@ -1,3 +1,3 @@ -export VERSION=0.9.1 \ No newline at end of file +export VERSION=0.9.2 \ No newline at end of file diff --git a/proto b/proto index c715e506d..3caee2e5b 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit c715e506df9ab1a76293d1c20dd5c904b009e1ea +Subproject commit 3caee2e5b92d4429c6cf47a4c88d4615001f300b diff --git a/release/.gitignore b/release/.gitignore index cb3628489..82d2caa70 100644 --- a/release/.gitignore +++ b/release/.gitignore @@ -1,4 +1,5 @@ *.elf *.bin *.map -*.zip \ No newline at end of file +*.zip +*.uf2 diff --git a/src/configuration.h b/src/configuration.h index d23a42f84..4b1addbb3 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -158,12 +158,26 @@ along with this program. If not, see . #define BUTTON_PIN 38 // The middle button GPIO on the T-Beam #define BUTTON_PIN_ALT 13 // Alternate GPIO for an external button if needed -#ifndef USE_JTAG -#define RF95_RESET 14 +// TTGO uses a common pinout for their SX1262 vs RF95 modules - both can be enabled and we will probe at runtime for RF95 and if +// not found then probe for SX1262 +#define USE_RF95 +#define USE_SX1262 + +#define LORA_DIO0 26 // a No connect on the SX1262 module +#define LORA_RESET 23 +#define LORA_DIO1 33 // SX1262 IRQ +#define LORA_DIO2 32 // SX1262 BUSY +#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled + +#ifdef USE_SX1262 +#define SX1262_CS RF95_NSS // FIXME - we really should define LORA_CS instead +#define SX1262_DIO1 LORA_DIO1 +#define SX1262_BUSY LORA_DIO2 +#define SX1262_RESET LORA_RESET +#define SX1262_E22 // Not really an E22 but TTGO seems to be trying to clone that +// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface +// code) #endif -#define RF95_IRQ 26 -#define RF95_DIO1 33 // Note: not really used on this board -#define RF95_DIO2 32 // Note: not really used on this board // Leave undefined to disable our PMU IRQ handler #define PMU_IRQ 35 @@ -181,12 +195,13 @@ along with this program. If not, see . #define BUTTON_PIN 39 #define BATTERY_PIN 35 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage -#ifndef USE_JTAG -#define RF95_RESET 23 -#endif -#define RF95_IRQ 26 -#define RF95_DIO1 33 // Note: not really used on this board -#define RF95_DIO2 32 // Note: not really used on this board +#define USE_RF95 + +#define USE_RF95 +#define LORA_DIO0 26 // a No connect on the SX1262 module +#define LORA_RESET 23 +#define LORA_DIO1 33 // Not really used +#define LORA_DIO2 32 // Not really used // This board has different GPS pins than all other boards #undef GPS_RX_PIN @@ -216,12 +231,14 @@ along with this program. If not, see . #define LED_PIN 25 // If defined we will blink this LED #define BUTTON_PIN 0 // If defined, this will be used for user button presses +#define USE_RF95 +#define LORA_DIO0 26 // a No connect on the SX1262 module #ifndef USE_JTAG -#define RF95_RESET 14 // If defined, this pin will be used to reset the LORA radio +#define LORA_RESET 14 #endif -#define RF95_IRQ 26 -#define RF95_DIO1 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number -#define RF95_DIO2 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number +#define LORA_DIO1 35 // Not really used +#define LORA_DIO2 34 // Not really used + #elif defined(TLORA_V1) // This string must exactly match the case used in release file names or the android updater won't work #define HW_VENDOR "tlora-v1" @@ -239,10 +256,11 @@ along with this program. If not, see . #define LED_PIN 2 // If defined we will blink this LED #define BUTTON_PIN 0 // If defined, this will be used for user button presses -#define RF95_RESET 14 // If defined, this pin will be used to reset the LORA radio -#define RF95_IRQ 26 // IRQ line for the LORA radio -#define RF95_DIO1 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number -#define RF95_DIO2 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number +#define USE_RF95 +#define LORA_DIO0 26 // a No connect on the SX1262 module +#define LORA_RESET 14 +#define LORA_DIO1 35 // Not really used +#define LORA_DIO2 34 // Not really used #elif defined(TLORA_V2) // This string must exactly match the case used in release file names or the android updater won't work @@ -264,10 +282,11 @@ along with this program. If not, see . 0 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one // between this pin and ground -#define RESET_GPIO 14 // If defined, this pin will be used to reset the LORA radio -#define RF95_IRQ_GPIO 26 // IRQ line for the LORA radio -#define DIO1_GPIO 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number -#define DIO2_GPIO 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number +#define USE_RF95 +#define LORA_DIO0 26 // a No connect on the SX1262 module +#define LORA_RESET 14 +#define LORA_DIO1 35 // Not really used +#define LORA_DIO2 34 // Not really used #elif defined(TLORA_V2_1_16) // This string must exactly match the case used in release file names or the android updater won't work @@ -291,10 +310,12 @@ along with this program. If not, see . 12 // If defined, this will be used for user button presses, if your board doesn't have a physical switch, you can wire one // between this pin and ground -#define RF95_RESET 14 // If defined, this pin will be used to reset the LORA radio -#define RF95_IRQ 26 // IRQ line for the LORA radio -#define RF95_DIO1 35 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number -#define RF95_DIO2 34 // DIO1 & DIO2 are not currently used, but they must be assigned to a pin number +#define USE_RF95 +#define LORA_DIO0 26 // a No connect on the SX1262 module +#define LORA_RESET 14 +#define LORA_DIO1 35 // Not really used +#define LORA_DIO2 34 // Not really used + #endif #ifdef ARDUINO_NRF52840_PCA10056 @@ -316,6 +337,13 @@ along with this program. If not, see . #endif +#ifdef USE_RF95 +#define RF95_RESET LORA_RESET +#define RF95_IRQ LORA_DIO0 // on SX1262 version this is a no connect DIO0 +#define RF95_DIO1 LORA_DIO1 // Note: not really used for RF95 +#define RF95_DIO2 LORA_DIO2 // Note: not really used for RF95 +#endif + // ----------------------------------------------------------------------------- // DEBUG // ----------------------------------------------------------------------------- diff --git a/src/gps/UBloxGPS.cpp b/src/gps/UBloxGPS.cpp index c7a8501c1..cab1ada4c 100644 --- a/src/gps/UBloxGPS.cpp +++ b/src/gps/UBloxGPS.cpp @@ -52,39 +52,7 @@ bool UBloxGPS::setup() if (isConnected) { DEBUG_MSG("Connected to UBLOX GPS successfully\n"); - bool factoryReset = false; - bool ok; - if (factoryReset) { - // It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have - // GPS_TX connected) - ublox.factoryReset(); - delay(3000); - tryConnect(); - DEBUG_MSG("Factory reset success=%d\n", isConnected); - ok = ublox.saveConfiguration(3000); - assert(ok); - return false; - } else { - if (_serial_gps) { - ok = ublox.setUART1Output(COM_TYPE_UBX, 500); // Use native API - assert(ok); - } - if (i2cAddress) { - ok = ublox.setI2COutput(COM_TYPE_UBX, 500); - assert(ok); - } - - ok = ublox.setNavigationFrequency(1, 500); // Produce 4x/sec to keep the amount of time we stall in getPVT low - assert(ok); - // ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M - // assert(ok); - // ok = ublox.setDynamicModel(DYN_MODEL_BIKE); // probably PEDESTRIAN but just in case assume bike speeds - // assert(ok); - ok = ublox.powerSaveMode(true, 2000); // use power save mode, the default timeout (1100ms seems a bit too tight) - assert(ok); - } - ok = ublox.saveConfiguration(3000); - if (!ok) + if (!setUBXMode()) recordCriticalError(UBloxInitFailed); // Don't halt the boot if saving the config fails, but do report the bug concurrency::PeriodicTask::setup(); // We don't start our periodic task unless we actually found the device @@ -95,6 +63,54 @@ bool UBloxGPS::setup() } } +bool UBloxGPS::setUBXMode() +{ + if (_serial_gps) { + if (!ublox.setUART1Output(COM_TYPE_UBX, 1000)) // Use native API + return false; + } + if (i2cAddress) { + if (!ublox.setI2COutput(COM_TYPE_UBX, 1000)) + return false; + } + + if (!ublox.setNavigationFrequency(1, 1000)) // Produce 4x/sec to keep the amount of time we stall in getPVT low + return false; + + // ok = ublox.setAutoPVT(false); // Not implemented on NEO-6M + // assert(ok); + // ok = ublox.setDynamicModel(DYN_MODEL_BIKE); // probably PEDESTRIAN but just in case assume bike speeds + // assert(ok); + if (!ublox.powerSaveMode(true, 2000)) // use power save mode, the default timeout (1100ms seems a bit too tight) + return false; + + if (!ublox.saveConfiguration(3000)) + return false; + + return true; +} + +/** + * Reset our GPS back to factory settings + * + * @return true for success + */ +bool UBloxGPS::factoryReset() +{ + bool ok = false; + + // It is useful to force back into factory defaults (9600baud, NEMA to test the behavior of boards that don't have + // GPS_TX connected) + ublox.factoryReset(); + delay(3000); + tryConnect(); // sets isConnected + DEBUG_MSG("GPS Factory reset success=%d\n", isConnected); + if (isConnected) + ok = setUBXMode(); + + return ok; +} + /// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs int UBloxGPS::prepareSleep(void *unused) { diff --git a/src/gps/UBloxGPS.h b/src/gps/UBloxGPS.h index e0e3d636b..7a2d3cdba 100644 --- a/src/gps/UBloxGPS.h +++ b/src/gps/UBloxGPS.h @@ -1,8 +1,8 @@ #pragma once +#include "../concurrency/PeriodicTask.h" #include "GPS.h" #include "Observer.h" -#include "../concurrency/PeriodicTask.h" #include "SparkFun_Ublox_Arduino_Library.h" /** @@ -33,12 +33,22 @@ class UBloxGPS : public GPS, public concurrency::PeriodicTask * called after the CPU wakes from light-sleep state */ virtual void startLock(); - private: + /** + * Reset our GPS back to factory settings + * + * @return true for success + */ + bool factoryReset(); + private: /// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs /// always returns 0 to indicate okay to sleep int prepareSleep(void *unused); /// Attempt to connect to our GPS, returns false if no gps is present bool tryConnect(); + + /// Switch to our desired operating mode and save the settings to flash + /// returns true for success + bool setUBXMode(); }; diff --git a/src/main.cpp b/src/main.cpp index 3cc4097d6..ce9e3d46b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -231,15 +231,18 @@ void setup() // If we know we have a L80 GPS, don't try UBLOX #ifndef L80_RESET // Init GPS - first try ublox - gps = new UBloxGPS(); + auto ublox = new UBloxGPS(); + gps = ublox; if (!gps->setup()) { DEBUG_MSG("ERROR: No UBLOX GPS found\n"); + delete ublox; + gps = ublox = NULL; + if (GPS::_serial_gps) { // Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just // assume NEMA at 9600 baud. DEBUG_MSG("Hoping that NEMA might work\n"); - delete gps; // dumb NEMA access only work for serial GPSes) gps = new NEMAGPS(); @@ -255,6 +258,16 @@ void setup() service.init(); + // We have now loaded our saved preferences from flash + + // ONCE we will factory reset the GPS for bug #327 + if (ublox && !devicestate.did_gps_reset) { + if (ublox->factoryReset()) { // If we don't succeed try again next time + devicestate.did_gps_reset = true; + nodeDB.saveToDisk(); + } + } + #ifdef SX1262_ANT_SW // make analog PA vs not PA switch on SX1262 eval board work properly pinMode(SX1262_ANT_SW, OUTPUT); @@ -271,17 +284,42 @@ void setup() #endif // MUST BE AFTER service.init, so we have our radio config settings (from nodedb init) - RadioInterface *rIf = + RadioInterface *rIf = NULL; + #if defined(RF95_IRQ) - // new CustomRF95(); old Radiohead based driver - new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, SPI); -#elif defined(SX1262_CS) - new SX1262Interface(SX1262_CS, SX1262_DIO1, SX1262_RESET, SX1262_BUSY, SPI); -#else - new SimRadio(); + if (!rIf) { + rIf = new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, SPI); + if (!rIf->init()) { + DEBUG_MSG("Warning: Failed to find RF95 radio\n"); + delete rIf; + rIf = NULL; + } + } #endif - if (!rIf || !rIf->init()) +#if defined(SX1262_CS) + if (!rIf) { + rIf = new SX1262Interface(SX1262_CS, SX1262_DIO1, SX1262_RESET, SX1262_BUSY, SPI); + if (!rIf->init()) { + DEBUG_MSG("Warning: Failed to find SX1262 radio\n"); + delete rIf; + rIf = NULL; + } + } +#endif + +#ifdef USE_SIM_RADIO + if (!rIf) { + rIf = new SimRadio; + if (!rIf->init()) { + DEBUG_MSG("Warning: Failed to find simulated radio\n"); + delete rIf; + rIf = NULL; + } + } +#endif + + if (!rIf) recordCriticalError(ErrNoRadio); else router.addInterface(rIf); diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index bfaefb1f2..ae94231d2 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -13,7 +13,6 @@ RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq SPIClass &spi, PhysicalLayer *_iface) : concurrency::PeriodicTask(0), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface) { - assert(!instance); // We assume only one for now instance = this; } diff --git a/src/mesh/mesh.pb.h b/src/mesh/mesh.pb.h index 23ed6b5db..27ff63f9b 100644 --- a/src/mesh/mesh.pb.h +++ b/src/mesh/mesh.pb.h @@ -193,6 +193,7 @@ typedef struct _DeviceState { MeshPacket rx_text_message; uint32_t version; bool no_save; + bool did_gps_reset; } DeviceState; typedef struct _FromRadio { @@ -250,7 +251,7 @@ typedef struct _ToRadio { #define RadioConfig_UserPreferences_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, {0, 0, 0}} #define NodeInfo_init_default {0, false, User_init_default, false, Position_init_default, 0, 0} #define MyNodeInfo_init_default {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} -#define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0} +#define DeviceState_init_default {false, RadioConfig_init_default, false, MyNodeInfo_init_default, false, User_init_default, 0, {NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default, NodeInfo_init_default}, 0, {MeshPacket_init_default}, false, MeshPacket_init_default, 0, 0, 0} #define DebugString_init_default {""} #define FromRadio_init_default {0, 0, {MeshPacket_init_default}} #define ToRadio_init_default {0, {MeshPacket_init_default}} @@ -266,7 +267,7 @@ typedef struct _ToRadio { #define RadioConfig_UserPreferences_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "", "", 0, 0, {0, 0, 0}} #define NodeInfo_init_zero {0, false, User_init_zero, false, Position_init_zero, 0, 0} #define MyNodeInfo_init_zero {0, 0, 0, "", "", "", 0, 0, 0, 0, 0, 0, 0, 0} -#define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0} +#define DeviceState_init_zero {false, RadioConfig_init_zero, false, MyNodeInfo_init_zero, false, User_init_zero, 0, {NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero, NodeInfo_init_zero}, 0, {MeshPacket_init_zero}, false, MeshPacket_init_zero, 0, 0, 0} #define DebugString_init_zero {""} #define FromRadio_init_zero {0, 0, {MeshPacket_init_zero}} #define ToRadio_init_zero {0, {MeshPacket_init_zero}} @@ -363,6 +364,7 @@ typedef struct _ToRadio { #define DeviceState_version_tag 8 #define DeviceState_rx_text_message_tag 7 #define DeviceState_no_save_tag 9 +#define DeviceState_did_gps_reset_tag 10 #define FromRadio_packet_tag 2 #define FromRadio_my_info_tag 3 #define FromRadio_node_info_tag 4 @@ -516,7 +518,8 @@ X(a, STATIC, REPEATED, MESSAGE, node_db, 4) \ X(a, STATIC, REPEATED, MESSAGE, receive_queue, 5) \ X(a, STATIC, OPTIONAL, MESSAGE, rx_text_message, 7) \ X(a, STATIC, SINGULAR, UINT32, version, 8) \ -X(a, STATIC, SINGULAR, BOOL, no_save, 9) +X(a, STATIC, SINGULAR, BOOL, no_save, 9) \ +X(a, STATIC, SINGULAR, BOOL, did_gps_reset, 10) #define DeviceState_CALLBACK NULL #define DeviceState_DEFAULT NULL #define DeviceState_radio_MSGTYPE RadioConfig @@ -614,7 +617,7 @@ extern const pb_msgdesc_t ManufacturingData_msg; #define RadioConfig_UserPreferences_size 188 #define NodeInfo_size 132 #define MyNodeInfo_size 110 -#define DeviceState_size 5427 +#define DeviceState_size 5429 #define DebugString_size 258 #define FromRadio_size 322 #define ToRadio_size 316