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,13 +41,13 @@
#define SCREEN_MODE (0x80)
// I2C bus access control
#define I2C_MUTEX_LOCK() \
xSemaphoreTake(I2Caccess, (3 * DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == \
pdTRUE
#define I2C_MUTEX_LOCK()
xSemaphoreTake(I2Caccess,
(3 * DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == pdTRUE
#define I2C_MUTEX_UNLOCK() xSemaphoreGive(I2Caccess)
// Struct holding devices's runtime configuration
typedef struct {
// Struct holding devices's runtime configuration
typedef struct {
uint8_t lorasf; // 7-12, lora spreadfactor
uint8_t txpower; // 2-15, lora tx power
uint8_t adrmode; // 0=disabled, 1=enabled
@ -107,8 +107,9 @@ extern configData_t cfg; // current device configuration
extern char display_line6[], display_line7[]; // screen buffers
extern uint8_t volatile channel; // wifi channel rotation counter
extern uint16_t volatile macs_total, macs_wifi, macs_ble,
batt_voltage; // display values
extern bool volatile TimePulseTick; // one-pulse-per-second flags set by GPS or RTC
batt_voltage; // display values
extern bool volatile TimePulseTick; // one-pulse-per-second flags set by GPS or
// RTC
extern hw_timer_t *sendCycle, *displaytimer, *clockCycle;
extern SemaphoreHandle_t I2Caccess, TimePulse;
extern TaskHandle_t irqHandlerTask, ClockTask;

View File

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

View File

@ -2,6 +2,7 @@
#define _IF482_H
#include "globals.h"
#include "timekeeper.h"
#define IF482_FRAME_SIZE (17)
#define IF482_PULSE_LENGTH (1000)
@ -10,7 +11,5 @@ extern HardwareSerial IF482;
void IF482_Pulse(time_t t);
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

View File

@ -20,12 +20,13 @@ void clock_init(void);
void clock_loop(void *pvParameters);
time_t time_sync(void);
void timepulse_start(void);
time_t syncTime(getExternalTime getTimeFunction, timesource_t const caller);
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 compiledUTC(void);
time_t tmConvert(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh, uint8_t mm,
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

View File

@ -75,22 +75,29 @@ void gps_read() {
// function to fetch current time from gps
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;
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(),
gps.time.isValid() ? "yes" : "no");
// use recent gps time
t = tmConvert(gps.date.year(), gps.date.month(), gps.date.day(),
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()
// 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) {
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();
@ -124,17 +124,4 @@ String IRAM_ATTR IF482_Frame(time_t startTime) {
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

View File

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

View File

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

View File

@ -13,18 +13,26 @@ time_t time_sync() {
time_t t = 0;
#ifdef TIME_SYNC_INTERVAL
#ifdef HAS_GPS
t = syncTime(get_gpstime, _gps);
if (t)
return t; // attempt sync with GPS time
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // wait for pps
ESP_LOGD(TAG, "micros = %d", micros());
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
// no GPS -> fallback to RTC time while trying lora sync
#ifdef HAS_RTC
t = syncTime(get_rtctime, _rtc); // sync with RTC time
if (!t)
t = get_rtctime();
if (t)
timeSource = _rtc;
else
ESP_LOGW(TAG, "no confident RTC time");
#endif
@ -33,45 +41,18 @@ time_t time_sync() {
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
#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;
} // 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
uint8_t timepulse_init() {
@ -136,11 +117,11 @@ void IRAM_ATTR CLOCKIRQ(void) {
}
// 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
ESP_LOGD(TAG, "t=%d, tt=%d, valid: %s", t, compiledUTC(),
(t >= compiledUTC()) ? "yes" : "no");
return (t >= compiledUTC());
return (t >= compiledUTC() ? t : 0);
}
// 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);
}
// 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_DCF77 && defined HAS_IF482