mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
On the T114, GPS_RESET (pin 38) is the same pin as PIN_3V3_EN. MicroNMEALocationProvider::begin() sets pin 38 HIGH (powering the 3V3 rail) but stop() never set it back LOW, leaving the GPS module powered even when disabled. Assert reset pin in stop() to mirror begin(), and guard _location->loop() behind gps_active check. Fixes meshcore-dev/MeshCore#1628
143 lines
4 KiB
C++
143 lines
4 KiB
C++
#pragma once
|
|
|
|
#include "LocationProvider.h"
|
|
#include <MicroNMEA.h>
|
|
#include <RTClib.h>
|
|
#include <helpers/RefCountedDigitalPin.h>
|
|
|
|
#ifndef GPS_EN
|
|
#ifdef PIN_GPS_EN
|
|
#define GPS_EN PIN_GPS_EN
|
|
#else
|
|
#define GPS_EN (-1)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef PIN_GPS_EN_ACTIVE
|
|
#define PIN_GPS_EN_ACTIVE HIGH
|
|
#endif
|
|
|
|
#ifndef GPS_RESET
|
|
#ifdef PIN_GPS_RESET
|
|
#define GPS_RESET PIN_GPS_RESET
|
|
#else
|
|
#define GPS_RESET (-1)
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef GPS_RESET_FORCE
|
|
#ifdef PIN_GPS_RESET_ACTIVE
|
|
#define GPS_RESET_FORCE PIN_GPS_RESET_ACTIVE
|
|
#else
|
|
#define GPS_RESET_FORCE LOW
|
|
#endif
|
|
#endif
|
|
|
|
class MicroNMEALocationProvider : public LocationProvider {
|
|
char _nmeaBuffer[100];
|
|
MicroNMEA nmea;
|
|
mesh::RTCClock* _clock;
|
|
Stream* _gps_serial;
|
|
RefCountedDigitalPin* _peripher_power;
|
|
int _pin_reset;
|
|
int _pin_en;
|
|
long next_check = 0;
|
|
long time_valid = 0;
|
|
|
|
public :
|
|
MicroNMEALocationProvider(Stream& ser, mesh::RTCClock* clock = NULL, int pin_reset = GPS_RESET, int pin_en = GPS_EN,RefCountedDigitalPin* peripher_power=NULL) :
|
|
_gps_serial(&ser), nmea(_nmeaBuffer, sizeof(_nmeaBuffer)), _pin_reset(pin_reset), _pin_en(pin_en), _clock(clock), _peripher_power(peripher_power) {
|
|
if (_pin_reset != -1) {
|
|
pinMode(_pin_reset, OUTPUT);
|
|
digitalWrite(_pin_reset, GPS_RESET_FORCE);
|
|
}
|
|
if (_pin_en != -1) {
|
|
pinMode(_pin_en, OUTPUT);
|
|
digitalWrite(_pin_en, LOW);
|
|
}
|
|
}
|
|
|
|
void begin() override {
|
|
if (_peripher_power) _peripher_power->claim();
|
|
if (_pin_en != -1) {
|
|
digitalWrite(_pin_en, PIN_GPS_EN_ACTIVE);
|
|
}
|
|
if (_pin_reset != -1) {
|
|
digitalWrite(_pin_reset, !GPS_RESET_FORCE);
|
|
}
|
|
}
|
|
|
|
void reset() override {
|
|
if (_pin_reset != -1) {
|
|
digitalWrite(_pin_reset, GPS_RESET_FORCE);
|
|
delay(10);
|
|
digitalWrite(_pin_reset, !GPS_RESET_FORCE);
|
|
}
|
|
}
|
|
|
|
void stop() override {
|
|
if (_pin_en != -1) {
|
|
digitalWrite(_pin_en, !PIN_GPS_EN_ACTIVE);
|
|
}
|
|
if (_pin_reset != -1) {
|
|
digitalWrite(_pin_reset, GPS_RESET_FORCE);
|
|
}
|
|
if (_peripher_power) _peripher_power->release();
|
|
}
|
|
|
|
bool isEnabled() override {
|
|
// directly read the enable pin if present as gps can be
|
|
// activated/deactivated outside of here ...
|
|
if (_pin_en != -1) {
|
|
return digitalRead(_pin_en) == PIN_GPS_EN_ACTIVE;
|
|
} else {
|
|
return true; // no enable so must be active
|
|
}
|
|
}
|
|
|
|
void syncTime() override { nmea.clear(); LocationProvider::syncTime(); }
|
|
long getLatitude() override { return nmea.getLatitude(); }
|
|
long getLongitude() override { return nmea.getLongitude(); }
|
|
long getAltitude() override {
|
|
long alt = 0;
|
|
nmea.getAltitude(alt);
|
|
return alt;
|
|
}
|
|
long satellitesCount() override { return nmea.getNumSatellites(); }
|
|
bool isValid() override { return nmea.isValid(); }
|
|
|
|
long getTimestamp() override {
|
|
DateTime dt(nmea.getYear(), nmea.getMonth(),nmea.getDay(),nmea.getHour(),nmea.getMinute(),nmea.getSecond());
|
|
return dt.unixtime();
|
|
}
|
|
|
|
void sendSentence(const char *sentence) override {
|
|
nmea.sendSentence(*_gps_serial, sentence);
|
|
}
|
|
|
|
void loop() override {
|
|
|
|
while (_gps_serial->available()) {
|
|
char c = _gps_serial->read();
|
|
#ifdef GPS_NMEA_DEBUG
|
|
Serial.print(c);
|
|
#endif
|
|
nmea.process(c);
|
|
}
|
|
|
|
if (!isValid()) time_valid = 0;
|
|
|
|
if (millis() > next_check) {
|
|
next_check = millis() + 1000;
|
|
if (_time_sync_needed && time_valid > 2) {
|
|
if (_clock != NULL) {
|
|
_clock->setCurrentTime(getTimestamp());
|
|
_time_sync_needed = false;
|
|
}
|
|
}
|
|
if (isValid()) {
|
|
time_valid ++;
|
|
}
|
|
}
|
|
}
|
|
};
|