From 7f7c5cbd629e5188939926fd7c0a64280405df6f Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 1 Feb 2024 15:24:39 -0600 Subject: [PATCH] Triple GPS state (#3157) * Triple state GPS refactoring * Skip probe * Move GPS toggle into the GPSThread * Consolidate * make all happy (including me) * corrected screen texts * NOT_PRESENT guard in main.cpp --------- Co-authored-by: mverch67 --- src/ButtonThread.h | 10 +------- src/gps/GPS.cpp | 30 +++++++++++++++++------ src/gps/GPS.h | 5 +++- src/graphics/Screen.cpp | 28 +++++++++++---------- src/main.cpp | 3 ++- src/mesh/NodeDB.cpp | 16 +++++++++++- src/mesh/generated/meshtastic/config.pb.h | 2 +- 7 files changed, 61 insertions(+), 33 deletions(-) diff --git a/src/ButtonThread.h b/src/ButtonThread.h index 3301df0973..66efd60046 100644 --- a/src/ButtonThread.h +++ b/src/ButtonThread.h @@ -193,15 +193,7 @@ class ButtonThread : public concurrency::OSThread static void userButtonMultiPressed() { if (!config.device.disable_triple_click && (gps != nullptr)) { - config.position.gps_enabled = !(config.position.gps_enabled); - if (config.position.gps_enabled) { - LOG_DEBUG("Flag set to true to restore power\n"); - gps->enable(); - - } else { - LOG_DEBUG("Flag set to false for gps power\n"); - gps->disable(); - } + gps->toggleGpsMode(); } } diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index bc186c1819..ed286228d1 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -604,7 +604,7 @@ uint32_t GPS::getSleepTime() const uint32_t t = config.position.gps_update_interval; // We'll not need the GPS thread to wake up again after first acq. with fixed position. - if (!config.position.gps_enabled || config.position.fixed_position) + if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED || config.position.fixed_position) t = UINT32_MAX; // Sleep forever now if (t == UINT32_MAX) @@ -625,21 +625,24 @@ void GPS::publishUpdate() // Notify any status instances that are observing us const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p); newStatus.notifyObservers(&status); - if (config.position.gps_enabled) + if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) { positionModule->handleNewPosition(); + } } } int32_t GPS::runOnce() { if (!GPSInitFinished) { - if (!_serial_gps) + if (!_serial_gps || config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) { + LOG_INFO("GPS set to not-present. Skipping probe.\n"); return disable(); + } if (!setup()) return 2000; // Setup failed, re-run in two seconds // We have now loaded our saved preferences from flash - if (config.position.gps_enabled == false) { + if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) { return disable(); } // ONCE we will factory reset the GPS for bug #327 @@ -662,7 +665,7 @@ int32_t GPS::runOnce() // if we have received valid NMEA claim we are connected setConnected(); } else { - if ((config.position.gps_enabled == 1) && (gnssModel == GNSS_MODEL_UBLOX)) { + if ((config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) && (gnssModel == GNSS_MODEL_UBLOX)) { // reset the GPS on next bootup if (devicestate.did_gps_reset && (millis() - lastWakeStartMsec > 60000) && !hasFlow()) { LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n"); @@ -902,7 +905,7 @@ GPS *GPS::createGps() int8_t _rx_gpio = config.position.rx_gpio; int8_t _tx_gpio = config.position.tx_gpio; int8_t _en_gpio = config.position.gps_en_gpio; -#if defined(HAS_GPS) && !defined(ARCH_ESP32) +#if HAS_GPS && !defined(ARCH_ESP32) _rx_gpio = 1; // We only specify GPS serial ports on ESP32. Otherwise, these are just flags. _tx_gpio = 1; #endif @@ -1098,7 +1101,7 @@ bool GPS::lookForLocation() #ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS fixType = atoi(gsafixtype.value()); // will set to zero if no data - // LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType); + // LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType); #endif // check if GPS has an acceptable lock @@ -1280,4 +1283,17 @@ int32_t GPS::disable() setAwake(false); return INT32_MAX; +} + +void GPS::toggleGpsMode() +{ + if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) { + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED; + LOG_DEBUG("Flag set to false for gps power. GpsMode: DISABLED\n"); + disable(); + } else if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_DISABLED) { + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED; + LOG_DEBUG("Flag set to true to restore power. GpsMode: ENABLED\n"); + enable(); + } } \ No newline at end of file diff --git a/src/gps/GPS.h b/src/gps/GPS.h index 80894dd517..1b56c2ee47 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -133,6 +133,9 @@ class GPS : private concurrency::OSThread // Disable the thread int32_t disable() override; + // toggle between enabled/disabled + void toggleGpsMode(); + void setGPSPower(bool on, bool standbyOnly, uint32_t sleepTime); /// Returns true if we have acquired GPS lock. @@ -144,7 +147,7 @@ class GPS : private concurrency::OSThread /// Return true if we are connected to a GPS bool isConnected() const { return hasGPS; } - bool isPowerSaving() const { return !config.position.gps_enabled; } + bool isPowerSaving() const { return config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED; } // Empty the input buffer as quickly as possible void clearBuffer(); diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index fb27e3c016..82b511e6c7 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -558,15 +558,20 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus } } -// Draw status when gps is disabled by PMU +// Draw status when GPS is disabled or not present static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps) { - String displayLine = "GPS disabled"; - int16_t xPos = display->getStringWidth(displayLine); - - if (!config.position.gps_enabled) { - display->drawString(x + xPos, y, displayLine); + String displayLine; + int pos; + if (y < FONT_HEIGHT_SMALL) { // Line 1: use short string + displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "No GPS" : "GPS off"; + pos = SCREEN_WIDTH - display->getStringWidth(displayLine); + } else { + displayLine = config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT ? "GPS not present" + : "GPS is disabled"; + pos = (SCREEN_WIDTH - display->getStringWidth(displayLine)) / 2; } + display->drawString(x + pos, y, displayLine); } static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps) @@ -594,7 +599,7 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const String displayLine = ""; if (!gps->getIsConnected() && !config.position.fixed_position) { - displayLine = "No GPS Module"; + displayLine = "No GPS present"; display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine); } else if (!gps->getHasLock() && !config.position.fixed_position) { displayLine = "No GPS Lock"; @@ -1549,7 +1554,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus); } // Display GPS status - if (!config.position.gps_enabled) { + if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) { drawGPSpowerstat(display, x, y + 2, gpsStatus); } else { if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) { @@ -1777,7 +1782,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat char chUtil[13]; snprintf(chUtil, sizeof(chUtil), "ChUtil %2.0f%%", airTime->channelUtilizationPercent()); display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil); - if (config.position.gps_enabled) { + if (config.position.gps_mode == meshtastic_Config_PositionConfig_GpsMode_ENABLED) { // Line 3 if (config.display.gps_format != meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude @@ -1786,10 +1791,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat // Line 4 drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus); } else { - drawGPSpowerstat(display, x - (SCREEN_WIDTH / 4), y + FONT_HEIGHT_SMALL * 2, gpsStatus); -#ifdef GPS_POWER_TOGGLE - display->drawString(x + 30, (y + FONT_HEIGHT_SMALL * 3), " by button"); -#endif + drawGPSpowerstat(display, x, y + FONT_HEIGHT_SMALL * 2, gpsStatus); } /* Display a heartbeat pixel that blinks every time the frame is redrawn */ #ifdef SHOW_REDRAWS diff --git a/src/main.cpp b/src/main.cpp index f853dc0ec3..f89ece9dce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -685,7 +685,8 @@ void setup() readFromRTC(); // read the main CPU RTC at first (in case we can't get GPS time) // If we're taking on the repeater role, ignore GPS - if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) { + if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER && + config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) { gps = GPS::createGps(); } if (gps) { diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 2eebd64ed6..891b7a61f9 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -182,7 +182,16 @@ void NodeDB::installDefaultConfig() #else config.device.disable_triple_click = true; #endif - config.position.gps_enabled = true; +#if !HAS_GPS || defined(T_DECK) + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT; +#elif !defined(GPS_RX_PIN) + if (config.position.rx_gpio == 0) + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT; + else + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED; +#else + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED; +#endif config.position.position_broadcast_smart_enabled = true; config.position.broadcast_smart_minimum_distance = 100; config.position.broadcast_smart_minimum_interval_secs = 30; @@ -454,6 +463,11 @@ void NodeDB::init() memcpy(devicestate.node_remote_hardware_pins, empty, sizeof(empty)); } + if (config.position.gps_enabled) { + config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED; + config.position.gps_enabled = 0; + } + saveToDisk(saveWhat); } diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index b06e9a7072..1f1ff6a749 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -836,4 +836,4 @@ extern const pb_msgdesc_t meshtastic_Config_BluetoothConfig_msg; } /* extern "C" */ #endif -#endif +#endif \ No newline at end of file