getting time from GPS reworked
This commit is contained in:
		
							parent
							
								
									817f7793c4
								
							
						
					
					
						commit
						a71a7e08a4
					
				@ -5,17 +5,10 @@
 | 
			
		||||
#include <RtcDateTime.h>
 | 
			
		||||
#include "timekeeper.h"
 | 
			
		||||
 | 
			
		||||
#ifdef GPS_I2C // Needed for reading from I2C Bus
 | 
			
		||||
#include <Wire.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef GPS_BAUDRATE
 | 
			
		||||
#define GPS_BAUDRATE 115200
 | 
			
		||||
#define GPS_BAUDRATE 115200UL
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define NMEA_FRAME_SIZE 82           // NEMA has a maxium of 82 bytes per record
 | 
			
		||||
#define NMEA_COMPENSATION_FACTOR 480 // empiric for Ublox Neo 6M
 | 
			
		||||
 | 
			
		||||
extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe
 | 
			
		||||
extern TaskHandle_t GpsTask;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -21,13 +21,13 @@ extern Ticker timesyncer;
 | 
			
		||||
extern timesource_t timeSource;
 | 
			
		||||
extern TaskHandle_t ClockTask;
 | 
			
		||||
extern DRAM_ATTR bool TimePulseTick; // 1sec pps flag set by GPS or RTC
 | 
			
		||||
extern DRAM_ATTR unsigned long lastPPS;
 | 
			
		||||
extern hw_timer_t *ppsIRQ;
 | 
			
		||||
extern portMUX_TYPE mux;
 | 
			
		||||
 | 
			
		||||
void IRAM_ATTR CLOCKIRQ(void);
 | 
			
		||||
void IRAM_ATTR GPSIRQ(void);
 | 
			
		||||
void clock_init(void);
 | 
			
		||||
void clock_loop(void *pvParameters);
 | 
			
		||||
void timepulse_start(void);
 | 
			
		||||
void setTimeSyncIRQ(void);
 | 
			
		||||
uint8_t timepulse_init(void);
 | 
			
		||||
bool timeIsValid(time_t const t);
 | 
			
		||||
@ -38,5 +38,4 @@ time_t compileTime(void);
 | 
			
		||||
time_t mkgmtime(const struct tm *ptm);
 | 
			
		||||
TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
 | 
			
		||||
                    int8_t rxPin, int8_t txPins);
 | 
			
		||||
 | 
			
		||||
#endif // _timekeeper_H
 | 
			
		||||
@ -317,9 +317,6 @@ void dp_drawPage(bool nextpage) {
 | 
			
		||||
 | 
			
		||||
#if (TIME_SYNC_INTERVAL)
 | 
			
		||||
    timeState = TimePulseTick ? ' ' : timeSetSymbols[timeSource];
 | 
			
		||||
    portENTER_CRITICAL(&mux);
 | 
			
		||||
    TimePulseTick = false; // flip global variable pulse ticker
 | 
			
		||||
    portEXIT_CRITICAL(&mux);
 | 
			
		||||
    time(&now);
 | 
			
		||||
    localtime_r(&now, &timeinfo);
 | 
			
		||||
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										200
									
								
								src/gpsread.cpp
									
									
									
									
									
								
							
							
						
						
									
										200
									
								
								src/gpsread.cpp
									
									
									
									
									
								
							@ -6,38 +6,12 @@
 | 
			
		||||
// Local logging tag
 | 
			
		||||
static const char TAG[] = __FILE__;
 | 
			
		||||
 | 
			
		||||
// we use NMEA ZDA sentence field 1 for time synchronization
 | 
			
		||||
// ZDA gives time for preceding pps pulse
 | 
			
		||||
// downsight is that it does not have a constant offset
 | 
			
		||||
// thus precision is only +/- 1 second
 | 
			
		||||
 | 
			
		||||
TinyGPSPlus gps;
 | 
			
		||||
TinyGPSCustom gpstime(gps, "GPZDA", 1);  // field 1 = UTC time (hhmmss.ss)
 | 
			
		||||
TinyGPSCustom gpsday(gps, "GPZDA", 2);   // field 2 = day (01..31)
 | 
			
		||||
TinyGPSCustom gpsmonth(gps, "GPZDA", 3); // field 3 = month (01..12)
 | 
			
		||||
TinyGPSCustom gpsyear(gps, "GPZDA", 4);  // field 4 = year (4-digit)
 | 
			
		||||
static const String ZDA_Request = "$EIGPQ,ZDA*39\r\n";
 | 
			
		||||
TaskHandle_t GpsTask;
 | 
			
		||||
 | 
			
		||||
HardwareSerial GPS_Serial(1); // use UART #1
 | 
			
		||||
static uint16_t nmea_txDelay_ms =
 | 
			
		||||
    (tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL) / portTICK_PERIOD_MS);
 | 
			
		||||
 | 
			
		||||
// helper functions to send UBX commands to ublox gps chip
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
// Print the UBX packet for debugging
 | 
			
		||||
void printPacket(byte *packet, byte len) {
 | 
			
		||||
  char temp[3];
 | 
			
		||||
 | 
			
		||||
  for (byte i = 0; i < len; i++) {
 | 
			
		||||
    sprintf(temp, "%.2X", packet[i]);
 | 
			
		||||
    ESP_LOGD(TAG, "%s", temp);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
// Send the packet specified to the receiver.
 | 
			
		||||
void sendPacket(byte *packet, byte len) {
 | 
			
		||||
 | 
			
		||||
  uint8_t CK_A = 0;
 | 
			
		||||
@ -55,55 +29,85 @@ void sendPacket(byte *packet, byte len) {
 | 
			
		||||
  GPS_Serial.write(CK_B);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Send a packet to the receiver to restore default configuration.
 | 
			
		||||
void restoreDefaults() {
 | 
			
		||||
  // CFG-CFG packet.
 | 
			
		||||
  // UBX CFG-CFG packet
 | 
			
		||||
  byte packet[] = {
 | 
			
		||||
      0xB5,       // sync char 1
 | 
			
		||||
      0x62,       // sync char 2
 | 
			
		||||
      0x06,       // class
 | 
			
		||||
      0x09,       // id
 | 
			
		||||
      0x0D,       // length
 | 
			
		||||
      0x00,       // length
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0b00011111, // clearmask
 | 
			
		||||
      0b00000110, // clearmask
 | 
			
		||||
      0x00,       // clearmask
 | 
			
		||||
      0x00,       // clearmask
 | 
			
		||||
      0x00,       // savemask
 | 
			
		||||
      0x00,       // savemask
 | 
			
		||||
      0x00,       // savemask
 | 
			
		||||
      0b00000110, // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // savemask
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0b00011111, // loadmask
 | 
			
		||||
      0b00000110, // loadmask
 | 
			
		||||
      0x00,       // loadmask
 | 
			
		||||
      0x00,       // loadmask
 | 
			
		||||
      0b00000110, // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0b00010001  // devicemask
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  sendPacket(packet, sizeof(packet));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Send a set of packets to the receiver to disable NMEA messages.
 | 
			
		||||
void setTimePulse() {
 | 
			
		||||
  // UBX TIM-TP packet
 | 
			
		||||
  byte packet[] = {
 | 
			
		||||
      0xB5,       // sync char 1
 | 
			
		||||
      0x62,       // sync char 2
 | 
			
		||||
      0x06,       // class
 | 
			
		||||
      0x07,       // id
 | 
			
		||||
      0x14,       // length
 | 
			
		||||
      0x40,       // time interval for time pulse [us]
 | 
			
		||||
      0x42,       // -> 1 sec = 1000000us
 | 
			
		||||
      0x0F,       // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0xE8,       // length of time pulse [us]
 | 
			
		||||
      0x03,       // -> 1000us
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x01,       // status -> positive edge
 | 
			
		||||
      0x00,       // timeRef -> UTC
 | 
			
		||||
      0b00000001, // syncMode asynchronized
 | 
			
		||||
      0x00,       // reserved
 | 
			
		||||
      0x00,       // antenna cable delay [ns]
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // receiver rf group delay [ns]
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // user time function delay [ns]
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00,       // .
 | 
			
		||||
      0x00        // .
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  sendPacket(packet, sizeof(packet));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void disableNmea() {
 | 
			
		||||
 | 
			
		||||
  // for tinygps++ we need only $GPGGA and $GPRMC
 | 
			
		||||
  // for getting time we use $GPZDA
 | 
			
		||||
  // we disable all other NMEA messages
 | 
			
		||||
  // thus, we disable all other NMEA messages
 | 
			
		||||
 | 
			
		||||
  // Array of two bytes for CFG-MSG packets payload.
 | 
			
		||||
  byte messages[][2] = {{0xF0, 0x01}, {0xF0, 0x02}, {0xF0, 0x03}, {0xF0, 0x05},
 | 
			
		||||
                        {0xF0, 0x06}, {0xF0, 0x07}, {0xF0, 0x09}, {0xF0, 0x0A},
 | 
			
		||||
                        {0xF0, 0x0E}, {0xF1, 0x00}, {0xF1, 0x03}, {0xF1, 0x04},
 | 
			
		||||
                        {0xF1, 0x05}, {0xF1, 0x06}};
 | 
			
		||||
                        {0xF0, 0x06}, {0xF0, 0x07}, {0xF0, 0x08}, {0xF0, 0x09},
 | 
			
		||||
                        {0xF0, 0x0A}, {0xF0, 0x0E}, {0xF1, 0x00}, {0xF1, 0x03},
 | 
			
		||||
                        {0xF1, 0x04}, {0xF1, 0x05}, {0xF1, 0x06}};
 | 
			
		||||
 | 
			
		||||
  // CFG-MSG packet buffer.
 | 
			
		||||
  // UBX CFG-MSG packet
 | 
			
		||||
  byte packet[] = {
 | 
			
		||||
      0xB5, // sync char 1
 | 
			
		||||
      0x62, // sync char 2
 | 
			
		||||
      0x06, // class
 | 
			
		||||
      0x01, // id
 | 
			
		||||
      0x03, // length
 | 
			
		||||
      0x00, // length
 | 
			
		||||
      0x00, // .
 | 
			
		||||
      0x00, // payload (first byte from messages array element)
 | 
			
		||||
      0x00, // payload (second byte from messages array element)
 | 
			
		||||
      0x00  // payload (zero to disable message)
 | 
			
		||||
@ -124,25 +128,24 @@ void disableNmea() {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Send a packet to the receiver to change baudrate to 115200.
 | 
			
		||||
void changeBaudrate(uint32_t baudRate) {
 | 
			
		||||
  // CFG-PRT packet.
 | 
			
		||||
  // UBX CFG-PRT packet
 | 
			
		||||
  byte packet[] = {
 | 
			
		||||
      0xB5,                   // sync char 1
 | 
			
		||||
      0x62,                   // sync char 2
 | 
			
		||||
      0x06,                   // class
 | 
			
		||||
      0x00,                   // id
 | 
			
		||||
      0x14,                   // length
 | 
			
		||||
      0x00,                   // length
 | 
			
		||||
      0x00,                   // .
 | 
			
		||||
      0x01,                   // portID (UART 1)
 | 
			
		||||
      0x00,                   // reserved
 | 
			
		||||
      0x00,                   // txReady
 | 
			
		||||
      0x00,                   // .
 | 
			
		||||
      0b11010000,             // UART mode: 8bit
 | 
			
		||||
      0b00001000,             // UART mode: No Parity, 1 Stopbit
 | 
			
		||||
      0b11010000,             // UART mode: 8N1
 | 
			
		||||
      0b00001000,             // .
 | 
			
		||||
      0x00,                   // .
 | 
			
		||||
      0x00,                   // .
 | 
			
		||||
      (byte)baudRate,         // baudrate (4 bytes)
 | 
			
		||||
      (byte)baudRate,         // baudrate
 | 
			
		||||
      (byte)(baudRate >> 8),  // .
 | 
			
		||||
      (byte)(baudRate >> 16), // .
 | 
			
		||||
      (byte)(baudRate >> 24), // .
 | 
			
		||||
@ -151,30 +154,9 @@ void changeBaudrate(uint32_t baudRate) {
 | 
			
		||||
      0b00000010,             // output protocols: NMEA
 | 
			
		||||
      0x00000000,             // .
 | 
			
		||||
      0x00,                   // reserved
 | 
			
		||||
      0x00,                   // reserved
 | 
			
		||||
      0x00,                   // reserved
 | 
			
		||||
      0x00                    // reserved
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  sendPacket(packet, sizeof(packet));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Send a packet to the receiver to change frequency to 100 ms.
 | 
			
		||||
void changeFrequency() {
 | 
			
		||||
  // CFG-RATE packet.
 | 
			
		||||
  byte packet[] = {
 | 
			
		||||
      0xB5, // sync char 1
 | 
			
		||||
      0x62, // sync char 2
 | 
			
		||||
      0x06, // class
 | 
			
		||||
      0x08, // id
 | 
			
		||||
      0x06, // length
 | 
			
		||||
      0x00, // length
 | 
			
		||||
      0x64, // Measurement rate 100ms
 | 
			
		||||
      0x00, // Measurement rate
 | 
			
		||||
      0x01, // Measurement cycles
 | 
			
		||||
      0x00, // Measurement cycles
 | 
			
		||||
      0x00, // Alignment to reference time: UTC time
 | 
			
		||||
      0x00  // payload
 | 
			
		||||
      0x00,                   // .
 | 
			
		||||
      0x00,                   // .
 | 
			
		||||
      0x00                    // .
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  sendPacket(packet, sizeof(packet));
 | 
			
		||||
@ -184,8 +166,11 @@ void changeFrequency() {
 | 
			
		||||
int gps_init(void) {
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Opening serial GPS");
 | 
			
		||||
 | 
			
		||||
  GPS_Serial.begin(GPS_SERIAL);
 | 
			
		||||
 | 
			
		||||
  restoreDefaults();
 | 
			
		||||
  delay(100);
 | 
			
		||||
 | 
			
		||||
  changeBaudrate(GPS_BAUDRATE);
 | 
			
		||||
  delay(100);
 | 
			
		||||
@ -193,8 +178,7 @@ int gps_init(void) {
 | 
			
		||||
  GPS_Serial.updateBaudRate(GPS_BAUDRATE);
 | 
			
		||||
 | 
			
		||||
  disableNmea();
 | 
			
		||||
  changeFrequency();
 | 
			
		||||
  // enableNavTimeUTC();
 | 
			
		||||
  setTimePulse();
 | 
			
		||||
 | 
			
		||||
  return 1;
 | 
			
		||||
 | 
			
		||||
@ -224,40 +208,38 @@ bool gps_hasfix() {
 | 
			
		||||
// function to poll UTC time from GPS NMEA data; note: this is costly
 | 
			
		||||
time_t get_gpstime(uint16_t *msec) {
 | 
			
		||||
 | 
			
		||||
  // poll NMEA ZDA sentence
 | 
			
		||||
  GPS_Serial.print(ZDA_Request);
 | 
			
		||||
  // wait for gps NMEA answer
 | 
			
		||||
  // vTaskDelay(tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL));
 | 
			
		||||
  *msec = 0;
 | 
			
		||||
 | 
			
		||||
  // did we get a current date & time?
 | 
			
		||||
  if (gpstime.isValid()) {
 | 
			
		||||
  if (gps.time.isValid() && gps.date.isValid() && gps.time.age() < 1000) {
 | 
			
		||||
 | 
			
		||||
    uint32_t delay_ms =
 | 
			
		||||
        gpstime.age() + nmea_txDelay_ms + NMEA_COMPENSATION_FACTOR;
 | 
			
		||||
    uint32_t zdatime = atof(gpstime.value());
 | 
			
		||||
 | 
			
		||||
    // convert UTC time from gps NMEA ZDA sentence to tm format
 | 
			
		||||
    // convert tinygps time format to struct tm format
 | 
			
		||||
    struct tm gps_tm = {0};
 | 
			
		||||
    gps_tm.tm_sec = zdatime % 100;                 // second (UTC)
 | 
			
		||||
    gps_tm.tm_min = (zdatime / 100) % 100;         // minute (UTC)
 | 
			
		||||
    gps_tm.tm_hour = zdatime / 10000;              // hour (UTC)
 | 
			
		||||
    gps_tm.tm_mday = atoi(gpsday.value());         // day, 01 to 31
 | 
			
		||||
    gps_tm.tm_mon = atoi(gpsmonth.value()) - 1;    // month, 01 to 12
 | 
			
		||||
    gps_tm.tm_year = atoi(gpsyear.value()) - 1900; // year, YYYY
 | 
			
		||||
    gps_tm.tm_sec = gps.time.second();
 | 
			
		||||
    gps_tm.tm_min = gps.time.minute();
 | 
			
		||||
    gps_tm.tm_hour = gps.time.hour();
 | 
			
		||||
    gps_tm.tm_mday = gps.date.day();
 | 
			
		||||
    gps_tm.tm_mon = gps.date.month() - 1;    // 1-12 -> 0-11
 | 
			
		||||
    gps_tm.tm_year = gps.date.year() - 1900; // 2000+ -> years since 1900
 | 
			
		||||
 | 
			
		||||
    // convert UTC tm to time_t epoch
 | 
			
		||||
    gps_tm.tm_isdst = 0; // UTC has no DST
 | 
			
		||||
    time_t t = mkgmtime(&gps_tm);
 | 
			
		||||
 | 
			
		||||
    // add protocol delay with millisecond precision
 | 
			
		||||
    t += (time_t)(delay_ms / 1000);
 | 
			
		||||
    *msec = delay_ms % 1000; // fractional seconds
 | 
			
		||||
#ifdef GPS_INT
 | 
			
		||||
    // if we have a recent GPS PPS pulse, sync on top of next second
 | 
			
		||||
    if (millis() - lastPPS < 1000)
 | 
			
		||||
      *msec = (uint16_t)(millis() - lastPPS);
 | 
			
		||||
    else {
 | 
			
		||||
      ESP_LOGD(TAG, "no PPS from GPS");
 | 
			
		||||
      return 0;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    return t;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ESP_LOGD(TAG, "no valid GPS time");
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
 | 
			
		||||
} // get_gpstime()
 | 
			
		||||
@ -271,20 +253,24 @@ void gps_loop(void *pvParameters) {
 | 
			
		||||
 | 
			
		||||
    while (cfg.payloadmask & GPS_DATA) {
 | 
			
		||||
      // feed GPS decoder with serial NMEA data from GPS device
 | 
			
		||||
      while (GPS_Serial.available())
 | 
			
		||||
        if (gps.encode(GPS_Serial.read()))
 | 
			
		||||
          break; // leave encode loop after each NMEA complete sentence
 | 
			
		||||
      while (GPS_Serial.available()) {
 | 
			
		||||
        if (gps.encode(GPS_Serial.read())) {
 | 
			
		||||
 | 
			
		||||
      // show NMEA data, very noisy,  useful only for debugging GPS
 | 
			
		||||
      // ESP_LOGV(TAG, "GPS NMEA data: passed %u / failed: %u / with fix:
 | 
			
		||||
      //                  %u", gps.passedChecksum(), gps.failedChecksum(), gps
 | 
			
		||||
      //                       .sentencesWithFix());
 | 
			
		||||
          // show NMEA data, very noisy, for debugging GPS
 | 
			
		||||
          // ESP_LOGV(
 | 
			
		||||
          //    TAG,
 | 
			
		||||
          //    "GPS NMEA data: chars %u / passed %u / failed: %u / with fix:
 | 
			
		||||
          //    %u", gps.charsProcessed(), gps.passedChecksum(),
 | 
			
		||||
          //    gps.failedChecksum(), gps.sentencesWithFix());
 | 
			
		||||
 | 
			
		||||
          delay(5); // yield after each sentence to crack NMEA burst
 | 
			
		||||
        }
 | 
			
		||||
      } // read from serial buffer loop
 | 
			
		||||
      delay(5);
 | 
			
		||||
    } // inner while loop
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    delay(1000);
 | 
			
		||||
  } // outer while loop
 | 
			
		||||
  } // infinite while loop
 | 
			
		||||
 | 
			
		||||
} // gps_loop()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -62,7 +62,7 @@ triggers pps 1 sec impulse
 | 
			
		||||
 | 
			
		||||
ISRs fired by CPU or GPIO:
 | 
			
		||||
DisplayIRQ      <- esp32 timer 0
 | 
			
		||||
CLOCKIRQ        <- esp32 timer 1 or GPIO (RTC_INT or GPS_INT)
 | 
			
		||||
CLOCKIRQ        <- esp32 timer 1 or GPIO (RTC_INT)
 | 
			
		||||
MatrixDisplayIRQ<- esp32 timer 3
 | 
			
		||||
ButtonIRQ       <- GPIO <- Button
 | 
			
		||||
PMUIRQ          <- GPIO <- PMU chip
 | 
			
		||||
@ -492,8 +492,7 @@ void setup() {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  ESP_LOGI(TAG, "Starting Timekeeper...");
 | 
			
		||||
  _ASSERT(timepulse_init()); // setup pps timepulse
 | 
			
		||||
  timepulse_start();         // starts pps and cyclic time sync
 | 
			
		||||
  _ASSERT(timepulse_init()); // starts pps and cyclic time sync
 | 
			
		||||
  strcat_P(features, " TIME");
 | 
			
		||||
 | 
			
		||||
#endif // timesync
 | 
			
		||||
 | 
			
		||||
@ -19,9 +19,8 @@ static const char TAG[] = __FILE__;
 | 
			
		||||
// G = GPS / R = RTC / L = LORA / * = no sync / ? = never synced
 | 
			
		||||
const char timeSetSymbols[] = {'G', 'R', 'L', '*', '?'};
 | 
			
		||||
 | 
			
		||||
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
 | 
			
		||||
 | 
			
		||||
DRAM_ATTR bool TimePulseTick = false;
 | 
			
		||||
DRAM_ATTR unsigned long lastPPS = millis();
 | 
			
		||||
timesource_t timeSource = _unsynced;
 | 
			
		||||
TaskHandle_t ClockTask = NULL;
 | 
			
		||||
hw_timer_t *ppsIRQ = NULL;
 | 
			
		||||
@ -144,26 +143,23 @@ uint8_t timepulse_init() {
 | 
			
		||||
  // sntp_init();
 | 
			
		||||
  sntp_set_sync_mode(SNTP_SYNC_MODE_IMMED);
 | 
			
		||||
 | 
			
		||||
// use time pulse from GPS as time base with fixed 1Hz frequency
 | 
			
		||||
// if we have, use PPS time pulse from GPS for syncing time on top of second
 | 
			
		||||
#ifdef GPS_INT
 | 
			
		||||
 | 
			
		||||
  // setup external interupt pin for rising edge GPS INT
 | 
			
		||||
  // setup external interupt pin for rising edge of GPS PPS
 | 
			
		||||
  pinMode(GPS_INT, INPUT_PULLDOWN);
 | 
			
		||||
  // setup external rtc 1Hz clock as pulse per second clock
 | 
			
		||||
  ESP_LOGI(TAG, "Timepulse: external (GPS)");
 | 
			
		||||
  return 1; // success
 | 
			
		||||
  attachInterrupt(digitalPinToInterrupt(GPS_INT), GPSIRQ, RISING);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// use pulse from on board RTC chip as time base with fixed frequency
 | 
			
		||||
#elif defined RTC_INT
 | 
			
		||||
// if we have, use pulse from on board RTC chip as time base for calendar time
 | 
			
		||||
#if defined RTC_INT
 | 
			
		||||
 | 
			
		||||
  // setup external interupt pin for falling edge RTC INT
 | 
			
		||||
  pinMode(RTC_INT, INPUT_PULLUP);
 | 
			
		||||
 | 
			
		||||
  // setup external rtc 1Hz clock as pulse per second clock
 | 
			
		||||
  // setup external rtc 1Hz clock pulse
 | 
			
		||||
  if (I2C_MUTEX_LOCK()) {
 | 
			
		||||
    Rtc.SetSquareWavePinClockFrequency(DS3231SquareWaveClock_1Hz);
 | 
			
		||||
    Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock);
 | 
			
		||||
    I2C_MUTEX_UNLOCK();
 | 
			
		||||
    pinMode(RTC_INT, INPUT_PULLUP);
 | 
			
		||||
    attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
 | 
			
		||||
    ESP_LOGI(TAG, "Timepulse: external (RTC)");
 | 
			
		||||
    return 1; // success
 | 
			
		||||
  } else {
 | 
			
		||||
@ -173,33 +169,39 @@ uint8_t timepulse_init() {
 | 
			
		||||
  return 1; // success
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
  // use ESP32 hardware timer as time base with adjustable frequency
 | 
			
		||||
  // use ESP32 hardware timer as time base for calendar time
 | 
			
		||||
  ppsIRQ = timerBegin(1, 8000, true);   // set 80 MHz prescaler to 1/10000 sec
 | 
			
		||||
  timerAlarmWrite(ppsIRQ, 10000, true); // 1000ms
 | 
			
		||||
  timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, true);
 | 
			
		||||
  timerAlarmEnable(ppsIRQ);
 | 
			
		||||
  ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
 | 
			
		||||
  return 1; // success
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
} // timepulse_init
 | 
			
		||||
 | 
			
		||||
void timepulse_start(void) {
 | 
			
		||||
#ifdef GPS_INT // start external clock gps pps line
 | 
			
		||||
  attachInterrupt(digitalPinToInterrupt(GPS_INT), CLOCKIRQ, RISING);
 | 
			
		||||
#elif defined RTC_INT // start external clock rtc
 | 
			
		||||
  attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
 | 
			
		||||
#else                 // start internal clock esp32 hardware timer
 | 
			
		||||
  timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, true);
 | 
			
		||||
  timerAlarmEnable(ppsIRQ);
 | 
			
		||||
#endif
 | 
			
		||||
  // start cyclic time sync
 | 
			
		||||
  timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
 | 
			
		||||
 | 
			
		||||
  // get time if we don't have one
 | 
			
		||||
  if (timeSource != _set)
 | 
			
		||||
    setTimeSyncIRQ(); // init systime by RTC or GPS or LORA
 | 
			
		||||
  // start cyclic time sync
 | 
			
		||||
  timesyncer.attach(TIME_SYNC_INTERVAL * 60, setTimeSyncIRQ);
 | 
			
		||||
 | 
			
		||||
} // timepulse_init
 | 
			
		||||
 | 
			
		||||
// interrupt service routine triggered by GPS PPS
 | 
			
		||||
void IRAM_ATTR GPSIRQ(void) {
 | 
			
		||||
 | 
			
		||||
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 | 
			
		||||
 | 
			
		||||
  // take timestamp
 | 
			
		||||
  lastPPS = millis(); // last time of pps
 | 
			
		||||
 | 
			
		||||
  // yield only if we should
 | 
			
		||||
  if (xHigherPriorityTaskWoken)
 | 
			
		||||
    portYIELD_FROM_ISR();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// interrupt service routine triggered by either pps or esp32 hardware timer
 | 
			
		||||
// interrupt service routine triggered by esp32 hardware timer
 | 
			
		||||
void IRAM_ATTR CLOCKIRQ(void) {
 | 
			
		||||
 | 
			
		||||
  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
 | 
			
		||||
@ -212,11 +214,7 @@ void IRAM_ATTR CLOCKIRQ(void) {
 | 
			
		||||
 | 
			
		||||
// flip time pulse ticker, if needed
 | 
			
		||||
#ifdef HAS_DISPLAY
 | 
			
		||||
#if (defined GPS_INT || defined RTC_INT)
 | 
			
		||||
  portENTER_CRITICAL(&mux);
 | 
			
		||||
  TimePulseTick = !TimePulseTick; // flip global variable pulse ticker
 | 
			
		||||
  portEXIT_CRITICAL(&mux);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  // yield only if we should
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user