diff --git a/src/helpers/sensors/AirohaSleep.h b/src/helpers/sensors/AirohaSleep.h new file mode 100644 index 0000000000..6637d0fbfd --- /dev/null +++ b/src/helpers/sensors/AirohaSleep.h @@ -0,0 +1,19 @@ +#pragma once +#include + +// Board must keep the GPS RTC backup pin powered and can cut GPS power once we return. +// Returns true if the command was acked within 3 attempts, otherwise returns false. +static inline bool airohaEnterSleep(LocationProvider* nmea) { + for (uint8_t attempt = 0; attempt < 3; attempt++) { + nmea->drain(); + nmea->sendSentence("$PAIR650,0"); + if (nmea->waitFor("$PAIR001,650,0", 50)) { // wait for the command received signal + #ifdef GPS_NMEA_DEBUG + Serial.printf("Airoha RTC Backup sleep command accepted by GPS after %u attempts\r\n", attempt + 1); + #endif + nmea->waitFor("$PAIR650,0", 50); // give the GPS 50ms grace to signal it is ready for sleep + return true; + } + } + return false; +} \ No newline at end of file diff --git a/src/helpers/sensors/LocationProvider.h b/src/helpers/sensors/LocationProvider.h index 81d08652ed..e11b738b52 100644 --- a/src/helpers/sensors/LocationProvider.h +++ b/src/helpers/sensors/LocationProvider.h @@ -17,6 +17,8 @@ class LocationProvider { virtual bool isValid() = 0; virtual long getTimestamp() = 0; virtual void sendSentence(const char * sentence); + virtual bool waitFor(const char* prefix, uint32_t timeout_ms) { return false; } + virtual void drain() { } virtual void reset() = 0; virtual void begin() = 0; virtual void stop() = 0; diff --git a/src/helpers/sensors/MicroNMEALocationProvider.h b/src/helpers/sensors/MicroNMEALocationProvider.h index b66cb11458..e559ad018f 100644 --- a/src/helpers/sensors/MicroNMEALocationProvider.h +++ b/src/helpers/sensors/MicroNMEALocationProvider.h @@ -129,10 +129,31 @@ public : return dt.unixtime(); } + void drain() { while (_gps_serial->available()) _gps_serial->read(); } + + const char* getSentence() const { return nmea.getSentence(); } + void sendSentence(const char *sentence) override { nmea.sendSentence(*_gps_serial, sentence); } + bool waitFor(const char* prefix, uint32_t timeout_ms) { + size_t plen = strlen(prefix); + uint32_t timeout = millis() + timeout_ms; + while ((int32_t)(millis() - timeout) < 0) { + if (_gps_serial->available()) { + char c = _gps_serial->read(); + #ifdef GPS_NMEA_DEBUG + Serial.print(c); + #endif + if (nmea.process(c) && strncmp(nmea.getSentence(), prefix, plen) == 0) return true; + } else { + yield(); + } + } + return false; + } + void loop() override { while (_gps_serial->available()) { diff --git a/variants/meshtracker_x1/target.cpp b/variants/meshtracker_x1/target.cpp index d6d548b511..5b90d66093 100644 --- a/variants/meshtracker_x1/target.cpp +++ b/variants/meshtracker_x1/target.cpp @@ -1,6 +1,7 @@ #include #include "target.h" #include +#include MeshTrackerX1Board board; @@ -27,46 +28,27 @@ mesh::LocalIdentity radio_new_identity() { void MeshTrackerX1SensorManager::start_gps() { gps_active = true; - // this init sequence comes from seeed examples and deals with all gps pins - pinMode(GPS_EN, OUTPUT); digitalWrite(GPS_EN, HIGH); delay(10); - pinMode(GPS_VRTC_EN, OUTPUT); - digitalWrite(GPS_VRTC_EN, HIGH); - delay(10); - - pinMode(GPS_RESET, OUTPUT); - digitalWrite(GPS_RESET, HIGH); - delay(10); - digitalWrite(GPS_RESET, LOW); - - pinMode(GPS_SLEEP_INT, OUTPUT); - digitalWrite(GPS_SLEEP_INT, HIGH); - pinMode(GPS_RTC_INT, OUTPUT); - digitalWrite(GPS_RTC_INT, LOW); -} - -void MeshTrackerX1SensorManager::sleep_gps() { - gps_active = false; - digitalWrite(GPS_VRTC_EN, HIGH); // keep RTC alive for faster fix on wake - digitalWrite(GPS_EN, LOW); - digitalWrite(GPS_RESET, LOW); - digitalWrite(GPS_SLEEP_INT, HIGH); + digitalWrite(GPS_RTC_INT, HIGH); + delay(5); digitalWrite(GPS_RTC_INT, LOW); } void MeshTrackerX1SensorManager::stop_gps() { gps_active = false; - digitalWrite(GPS_VRTC_EN, LOW); + digitalWrite(GPS_VRTC_EN, HIGH); // keep GPS RTC alive for faster fix on wake + digitalWrite(GPS_RTC_INT, LOW); // make sure this is LOW so we can pulse it to wake + airohaEnterSleep(_nmea); digitalWrite(GPS_EN, LOW); - digitalWrite(GPS_RESET, LOW); - digitalWrite(GPS_SLEEP_INT, HIGH); - digitalWrite(GPS_RTC_INT, LOW); } bool MeshTrackerX1SensorManager::begin() { // init GPS Serial1.begin(GPS_BAUD_RATE); + digitalWrite(GPS_RESET, HIGH); + delay(10); + digitalWrite(GPS_RESET, LOW); // init SPA06-003 barometer baro_ok = spa06.begin(SPA06_003_DEFAULT_ADDR, &Wire) || spa06.begin(0x76, &Wire); @@ -122,7 +104,7 @@ const char* MeshTrackerX1SensorManager::getSettingValue(int i) const { bool MeshTrackerX1SensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { - sleep_gps(); // sleep for faster fix ! + stop_gps(); } else { start_gps(); } diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 4253282708..70a64359fd 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -2,6 +2,7 @@ #include "t1000e_sensors.h" #include "target.h" #include +#include T1000eBoard board; @@ -81,56 +82,28 @@ mesh::LocalIdentity radio_new_identity() { void T1000SensorManager::start_gps() { gps_active = true; - //_nmea->begin(); - // this init sequence should be better - // comes from seeed examples and deals with all gps pins - pinMode(GPS_EN, OUTPUT); digitalWrite(GPS_EN, HIGH); delay(10); - pinMode(GPS_VRTC_EN, OUTPUT); - digitalWrite(GPS_VRTC_EN, HIGH); - delay(10); - - pinMode(GPS_RESET, OUTPUT); - digitalWrite(GPS_RESET, HIGH); - delay(10); - digitalWrite(GPS_RESET, LOW); - - pinMode(GPS_SLEEP_INT, OUTPUT); - digitalWrite(GPS_SLEEP_INT, HIGH); - pinMode(GPS_RTC_INT, OUTPUT); + digitalWrite(GPS_RTC_INT, HIGH); + delay(5); digitalWrite(GPS_RTC_INT, LOW); - pinMode(GPS_RESETB, INPUT_PULLUP); -} - -void T1000SensorManager::sleep_gps() { - gps_active = false; - digitalWrite(GPS_VRTC_EN, HIGH); - digitalWrite(GPS_EN, LOW); - digitalWrite(GPS_RESET, HIGH); - digitalWrite(GPS_SLEEP_INT, HIGH); - digitalWrite(GPS_RTC_INT, LOW); - pinMode(GPS_RESETB, OUTPUT); - digitalWrite(GPS_RESETB, LOW); - //_nmea->stop(); } void T1000SensorManager::stop_gps() { gps_active = false; - digitalWrite(GPS_VRTC_EN, LOW); + digitalWrite(GPS_VRTC_EN, HIGH); // keep GPS RTC alive for faster fix on wake + digitalWrite(GPS_RTC_INT, LOW); // make sure this is LOW so we can pulse it to wake + airohaEnterSleep(_nmea); // send command to put the GPS into RTC backup sleep digitalWrite(GPS_EN, LOW); - digitalWrite(GPS_RESET, HIGH); - digitalWrite(GPS_SLEEP_INT, HIGH); - digitalWrite(GPS_RTC_INT, LOW); - pinMode(GPS_RESETB, OUTPUT); - digitalWrite(GPS_RESETB, LOW); - //_nmea->stop(); } bool T1000SensorManager::begin() { // init GPS Serial1.begin(115200); + digitalWrite(GPS_RESET, HIGH); + delay(10); + digitalWrite(GPS_RESET, LOW); return true; } @@ -156,7 +129,6 @@ void T1000SensorManager::loop() { node_lat = ((double)_nmea->getLatitude())/1000000.; node_lon = ((double)_nmea->getLongitude())/1000000.; node_altitude = ((double)_nmea->getAltitude()) / 1000.0; - //Serial.printf("lat %f lon %f\r\n", _lat, _lon); } next_gps_update = millis() + 1000; } @@ -176,7 +148,7 @@ const char* T1000SensorManager::getSettingValue(int i) const { bool T1000SensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { - sleep_gps(); // sleep for faster fix ! + stop_gps(); } else { start_gps(); } diff --git a/variants/t1000-e/variant.cpp b/variants/t1000-e/variant.cpp index ed21fd68cf..fc30a6197b 100644 --- a/variants/t1000-e/variant.cpp +++ b/variants/t1000-e/variant.cpp @@ -71,7 +71,7 @@ void initVariant() pinMode(LUX_SENSOR, INPUT); pinMode(EXT_CHRG_DETECT, INPUT); pinMode(EXT_PWR_DETECT, INPUT); - pinMode(GPS_RESETB, INPUT); + pinMode(GPS_RESETB, INPUT_PULLUP); pinMode(PIN_BUTTON1, INPUT); pinMode(PIN_3V3_EN, OUTPUT); @@ -89,10 +89,10 @@ void initVariant() digitalWrite(PIN_3V3_ACC_EN, LOW); digitalWrite(BUZZER_EN, LOW); digitalWrite(SENSOR_EN, LOW); - digitalWrite(GPS_EN, LOW); + digitalWrite(GPS_EN, HIGH); digitalWrite(GPS_RESET, LOW); - digitalWrite(GPS_VRTC_EN, LOW); - digitalWrite(GPS_SLEEP_INT, HIGH); + digitalWrite(GPS_VRTC_EN, HIGH); + digitalWrite(GPS_SLEEP_INT, LOW); digitalWrite(GPS_RTC_INT, LOW); digitalWrite(LED_PIN, LOW); }