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