timekeeper once again reworked and shortened

This commit is contained in:
Klaus K Wilting 2019-02-25 20:22:03 +01:00
parent 5fb4c7bec2
commit 5c191a269f
9 changed files with 68 additions and 78 deletions

View File

@ -41,9 +41,9 @@
#define SCREEN_MODE (0x80) #define SCREEN_MODE (0x80)
// I2C bus access control // I2C bus access control
#define I2C_MUTEX_LOCK() \ #define I2C_MUTEX_LOCK()
xSemaphoreTake(I2Caccess, (3 * DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == \ xSemaphoreTake(I2Caccess,
pdTRUE (3 * DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == pdTRUE
#define I2C_MUTEX_UNLOCK() xSemaphoreGive(I2Caccess) #define I2C_MUTEX_UNLOCK() xSemaphoreGive(I2Caccess)
// Struct holding devices's runtime configuration // Struct holding devices's runtime configuration
@ -108,7 +108,8 @@ extern char display_line6[], display_line7[]; // screen buffers
extern uint8_t volatile channel; // wifi channel rotation counter extern uint8_t volatile channel; // wifi channel rotation counter
extern uint16_t volatile macs_total, macs_wifi, macs_ble, extern uint16_t volatile macs_total, macs_wifi, macs_ble,
batt_voltage; // display values batt_voltage; // display values
extern bool volatile TimePulseTick; // one-pulse-per-second flags set by GPS or RTC extern bool volatile TimePulseTick; // one-pulse-per-second flags set by GPS or
// RTC
extern hw_timer_t *sendCycle, *displaytimer, *clockCycle; extern hw_timer_t *sendCycle, *displaytimer, *clockCycle;
extern SemaphoreHandle_t I2Caccess, TimePulse; extern SemaphoreHandle_t I2Caccess, TimePulse;
extern TaskHandle_t irqHandlerTask, ClockTask; extern TaskHandle_t irqHandlerTask, ClockTask;

View File

@ -3,6 +3,7 @@
#include <TinyGPS++.h> // library for parsing NMEA data #include <TinyGPS++.h> // library for parsing NMEA data
#include <RtcDateTime.h> #include <RtcDateTime.h>
#include "timekeeper.h"
#ifdef GPS_I2C // Needed for reading from I2C Bus #ifdef GPS_I2C // Needed for reading from I2C Bus
#include <Wire.h> #include <Wire.h>

View File

@ -2,6 +2,7 @@
#define _IF482_H #define _IF482_H
#include "globals.h" #include "globals.h"
#include "timekeeper.h"
#define IF482_FRAME_SIZE (17) #define IF482_FRAME_SIZE (17)
#define IF482_PULSE_LENGTH (1000) #define IF482_PULSE_LENGTH (1000)
@ -10,7 +11,5 @@ extern HardwareSerial IF482;
void IF482_Pulse(time_t t); void IF482_Pulse(time_t t);
String IRAM_ATTR IF482_Frame(time_t tt); String IRAM_ATTR IF482_Frame(time_t tt);
TickType_t tx_Ticks(unsigned long baud, uint32_t config, int8_t rxPin,
int8_t txPins);
#endif #endif

View File

@ -20,12 +20,13 @@ void clock_init(void);
void clock_loop(void *pvParameters); void clock_loop(void *pvParameters);
time_t time_sync(void); time_t time_sync(void);
void timepulse_start(void); void timepulse_start(void);
time_t syncTime(getExternalTime getTimeFunction, timesource_t const caller);
uint8_t timepulse_init(void); uint8_t timepulse_init(void);
uint8_t TimeIsValid(time_t const t); time_t TimeIsValid(time_t const t);
time_t syncProvider_CB(void); time_t syncProvider_CB(void);
time_t compiledUTC(void); time_t compiledUTC(void);
time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm, time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm,
uint8_t ss); uint8_t ss);
TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
int8_t rxPin, int8_t txPins);
#endif // _timekeeper_H #endif // _timekeeper_H

View File

@ -75,22 +75,29 @@ void gps_read() {
// function to fetch current time from gps // function to fetch current time from gps
time_t get_gpstime(void) { time_t get_gpstime(void) {
#define NMEA_FRAME_SIZE 80 // NEMA has a maxium of 80 bytes per record
#define NMEA_BUFFER 50 // 50ms safety time regardless
time_t t = 0; time_t t = 0;
if ((gps.time.age() < 950) && (gps.time.isValid())) { // set timeout for reading recent time from GPS
#ifdef GPS_SERIAL // serial GPS
static const TickType_t txDelay =
pdMS_TO_TICKS(1000 - NMEA_BUFFER - tx_Ticks(NMEA_FRAME_SIZE, GPS_SERIAL));
#else // I2C GPS
static const TickType_t txDelay = 1000 - NMEA_BUFFER;
#endif
if ((gps.time.age() < txDelay) && (gps.time.isValid())) {
ESP_LOGD(TAG, "GPS time age: %dms, is valid: %s", gps.time.age(), ESP_LOGD(TAG, "GPS time age: %dms, is valid: %s", gps.time.age(),
gps.time.isValid() ? "yes" : "no"); gps.time.isValid() ? "yes" : "no");
// use recent gps time
t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(), t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(),
gps.time.hour(), gps.time.minute(), gps.time.second()); gps.time.hour(), gps.time.minute(), gps.time.second());
// ESP_LOGD(TAG, "GPS time: %02d.%02d.%04d %02d:%02d:%02d", gps.date.day(),
// gps.date.month(), gps.date.year(), gps.time.hour(),
// gps.time.minute(), gps.time.second());
} }
return t; return TimeIsValid(t);
} // get_gpstime() } // get_gpstime()
// GPS serial feed FreeRTos Task // GPS serial feed FreeRTos Task

View File

@ -90,7 +90,7 @@ HardwareSerial IF482(2); // use UART #2 (note: #1 may be in use for serial GPS)
void IF482_Pulse(time_t t) { void IF482_Pulse(time_t t) {
static const TickType_t txDelay = static const TickType_t txDelay =
pdMS_TO_TICKS(IF482_PULSE_LENGTH) - tx_Ticks(HAS_IF482); pdMS_TO_TICKS(IF482_PULSE_LENGTH - tx_Ticks(IF482_FRAME_SIZE, HAS_IF482));
TickType_t startTime = xTaskGetTickCount(); TickType_t startTime = xTaskGetTickCount();
@ -124,17 +124,4 @@ String IRAM_ATTR IF482_Frame(time_t startTime) {
return out; return out;
} }
// calculate serial tx time from IF482 serial settings
TickType_t tx_Ticks(unsigned long baud, uint32_t config, int8_t rxPin,
int8_t txPins) {
uint32_t databits = ((config & 0x0c) >> 2) + 5;
uint32_t stopbits = ((config & 0x20) >> 5) + 1;
uint32_t txTime =
(databits + stopbits + 2) * IF482_FRAME_SIZE * 1000.0 / baud;
// +2 ms margin for the startbit and the clock's processing time
return pdMS_TO_TICKS(round(txTime));
}
#endif // HAS_IF482 #endif // HAS_IF482

View File

@ -474,6 +474,7 @@ void user_request_network_time_callback(void *pVoidUserUTCTime,
// Update system time with time read from the network // Update system time with time read from the network
if (TimeIsValid(*pUserUTCTime)) { if (TimeIsValid(*pUserUTCTime)) {
setTime(*pUserUTCTime); setTime(*pUserUTCTime);
timeSource = _lora;
ESP_LOGI(TAG, "Received recent time from LoRa"); ESP_LOGI(TAG, "Received recent time from LoRa");
} }
else else

View File

@ -67,7 +67,7 @@ time_t get_rtctime(void) {
} }
I2C_MUTEX_UNLOCK(); I2C_MUTEX_UNLOCK();
} }
return t; return TimeIsValid(t);
} // get_rtctime() } // get_rtctime()
float get_rtctemp(void) { float get_rtctemp(void) {

View File

@ -13,18 +13,26 @@ time_t time_sync() {
time_t t = 0; time_t t = 0;
#ifdef TIME_SYNC_INTERVAL
#ifdef HAS_GPS #ifdef HAS_GPS
t = syncTime(get_gpstime, _gps); xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // wait for pps
if (t) ESP_LOGD(TAG, "micros = %d", micros());
return t; // attempt sync with GPS time t = get_gpstime();
if (t) {
t++; // gps time concerns past second, so we add one second
#ifdef HAS_RTC
set_rtctime(t); // calibrate RTC
#endif
timeSource = _gps;
goto exit;
}
#endif #endif
// no GPS -> fallback to RTC time while trying lora sync // no GPS -> fallback to RTC time while trying lora sync
#ifdef HAS_RTC #ifdef HAS_RTC
t = syncTime(get_rtctime, _rtc); // sync with RTC time t = get_rtctime();
if (!t) if (t)
timeSource = _rtc;
else
ESP_LOGW(TAG, "no confident RTC time"); ESP_LOGW(TAG, "no confident RTC time");
#endif #endif
@ -33,45 +41,18 @@ time_t time_sync() {
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime); LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
#endif #endif
#endif // TIME_SYNC_INTERVAL exit:
ESP_LOGD(TAG, "micros = %d", micros());
if (t)
ESP_LOGD(TAG, "Time was set by %c to %02d:%02d:%02d",
timeSetSymbols[timeSource], hour(t), minute(t), second(t));
else
timeSource = _unsynced;
return t; return t;
} // time_sync() } // time_sync()
// sync time on start of next second from GPS or RTC
time_t syncTime(getExternalTime getTimeFunction, timesource_t const caller) {
time_t t;
TimeSourcePtr = getTimeFunction;
if (!TimeSourcePtr)
goto error;
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // wait for pps
t = TimeSourcePtr(); // get time from given timesource
if (TimeIsValid(t)) {
if (caller == _gps) // gps time concerns past second
t++;
timeSource = caller;
ESP_LOGD(TAG, "Time source %c set time to %02d:%02d:%02d",
timeSetSymbols[timeSource], hour(t), minute(t), second(t));
#ifdef HAS_RTC
if (caller != _rtc)
set_rtctime(t);
#endif
return t; // success
}
error:
ESP_LOGD(TAG, "Time source %c sync attempt failed", timeSetSymbols[caller]);
timeSource = _unsynced;
return 0; // failure
} // syncTime()
// helper function to setup a pulse per second for time synchronisation // helper function to setup a pulse per second for time synchronisation
uint8_t timepulse_init() { uint8_t timepulse_init() {
@ -136,11 +117,11 @@ void IRAM_ATTR CLOCKIRQ(void) {
} }
// helper function to check plausibility of a time // helper function to check plausibility of a time
uint8_t TimeIsValid(time_t const t) { time_t TimeIsValid(time_t const t) {
// is it a time in the past? we use compile date to guess // is it a time in the past? we use compile date to guess
ESP_LOGD(TAG, "t=%d, tt=%d, valid: %s", t, compiledUTC(), ESP_LOGD(TAG, "t=%d, tt=%d, valid: %s", t, compiledUTC(),
(t >= compiledUTC()) ? "yes" : "no"); (t >= compiledUTC()) ? "yes" : "no");
return (t >= compiledUTC()); return (t >= compiledUTC() ? t : 0);
} }
// helper function to convert compile time to UTC time // helper function to convert compile time to UTC time
@ -162,6 +143,18 @@ time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm,
return makeTime(tm); return makeTime(tm);
} }
// helper function to calculate serial transmit time
TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
int8_t rxPin, int8_t txPins) {
uint32_t databits = ((config & 0x0c) >> 2) + 5;
uint32_t stopbits = ((config & 0x20) >> 5) + 1;
uint32_t txTime = (databits + stopbits + 2) * framesize * 1000.0 / baud;
// +1 ms margin for the startbit +1 ms for pending processing time
return round(txTime);
}
#if defined HAS_IF482 || defined HAS_DCF77 #if defined HAS_IF482 || defined HAS_DCF77
#if defined HAS_DCF77 && defined HAS_IF482 #if defined HAS_DCF77 && defined HAS_IF482