timekeeper once again reworked and shortened
This commit is contained in:
parent
5fb4c7bec2
commit
5c191a269f
@ -41,13 +41,13 @@
|
|||||||
#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
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t lorasf; // 7-12, lora spreadfactor
|
uint8_t lorasf; // 7-12, lora spreadfactor
|
||||||
uint8_t txpower; // 2-15, lora tx power
|
uint8_t txpower; // 2-15, lora tx power
|
||||||
uint8_t adrmode; // 0=disabled, 1=enabled
|
uint8_t adrmode; // 0=disabled, 1=enabled
|
||||||
@ -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;
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
@ -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
|
@ -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
|
||||||
|
@ -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
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user