timekeeper fixes (experimental)
This commit is contained in:
parent
b2a563c84e
commit
c489123e06
@ -22,6 +22,8 @@ void DCF77_Pulse(time_t t, uint8_t const *DCFpulse) {
|
|||||||
TickType_t startTime = xTaskGetTickCount();
|
TickType_t startTime = xTaskGetTickCount();
|
||||||
uint8_t sec = second(t);
|
uint8_t sec = second(t);
|
||||||
|
|
||||||
|
ESP_LOGD (TAG, "DCF second %d", sec);
|
||||||
|
|
||||||
// induce 10 pulses
|
// induce 10 pulses
|
||||||
for (uint8_t pulse = 0; pulse <= 9; pulse++) {
|
for (uint8_t pulse = 0; pulse <= 9; pulse++) {
|
||||||
|
|
||||||
|
@ -92,14 +92,14 @@ time_t get_gpstime(void) {
|
|||||||
|
|
||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
|
|
||||||
if ((gps.time.age() < gpsDelay_ms) && (gps.time.isValid())) {
|
if ((gps.time.age() < gpsDelay_ms) && (gps.time.isValid()) && (gps.date.isValid())) {
|
||||||
|
|
||||||
ESP_LOGD(TAG, "GPS time age: %dms, is valid: %s", gps.time.age(),
|
ESP_LOGD(TAG, "GPS time age: %dms, second: %d, is valid: %s", gps.time.age(), gps.time.second(),
|
||||||
gps.time.isValid() ? "yes" : "no");
|
gps.time.isValid() ? "yes" : "no");
|
||||||
|
|
||||||
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());
|
||||||
}
|
}
|
||||||
return TimeIsValid(t);
|
return TimeIsValid(t);
|
||||||
} // get_gpstime()
|
} // get_gpstime()
|
||||||
|
|
||||||
|
@ -27,11 +27,11 @@ Uused tasks and timers:
|
|||||||
|
|
||||||
Task Core Prio Purpose
|
Task Core Prio Purpose
|
||||||
====================================================================================
|
====================================================================================
|
||||||
clockloop 0 4 generates realtime telegrams for external clock
|
|
||||||
ledloop 0 3 blinks LEDs
|
ledloop 0 3 blinks LEDs
|
||||||
spiloop 0 2 reads/writes data on spi interface
|
spiloop 0 2 reads/writes data on spi interface
|
||||||
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
||||||
|
|
||||||
|
clockloop 1 4 generates realtime telegrams for external clock
|
||||||
looptask 1 1 arduino core -> runs the LMIC LoRa stack
|
looptask 1 1 arduino core -> runs the LMIC LoRa stack
|
||||||
irqhandler 1 1 executes tasks triggered by hw irq, see table below
|
irqhandler 1 1 executes tasks triggered by hw irq, see table below
|
||||||
gpsloop 1 2 reads data from GPS via serial or i2c
|
gpsloop 1 2 reads data from GPS via serial or i2c
|
||||||
@ -362,7 +362,6 @@ void setup() {
|
|||||||
ESP_LOGI(TAG, "Starting Timekeeper...");
|
ESP_LOGI(TAG, "Starting Timekeeper...");
|
||||||
assert(timepulse_init()); // setup timepulse
|
assert(timepulse_init()); // setup timepulse
|
||||||
timepulse_start();
|
timepulse_start();
|
||||||
timeSync();
|
|
||||||
|
|
||||||
// start wifi in monitor mode and start channel rotation timer
|
// start wifi in monitor mode and start channel rotation timer
|
||||||
ESP_LOGI(TAG, "Starting Wifi...");
|
ESP_LOGI(TAG, "Starting Wifi...");
|
||||||
@ -417,6 +416,7 @@ void setup() {
|
|||||||
|
|
||||||
#if defined HAS_IF482 || defined HAS_DCF77
|
#if defined HAS_IF482 || defined HAS_DCF77
|
||||||
ESP_LOGI(TAG, "Starting Clock Controller...");
|
ESP_LOGI(TAG, "Starting Clock Controller...");
|
||||||
|
timeSync();
|
||||||
clock_init();
|
clock_init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@ const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
|
|||||||
|
|
||||||
getExternalTime TimeSourcePtr; // pointer to time source function
|
getExternalTime TimeSourcePtr; // pointer to time source function
|
||||||
|
|
||||||
|
|
||||||
// syncs systime from external time source and sets/reads RTC, called by
|
// syncs systime from external time source and sets/reads RTC, called by
|
||||||
// cyclic.cpp
|
// cyclic.cpp
|
||||||
void timeSync(void) {
|
void timeSync(void) {
|
||||||
@ -16,47 +15,36 @@ void timeSync(void) {
|
|||||||
time_t t = 0;
|
time_t t = 0;
|
||||||
|
|
||||||
#ifdef HAS_GPS
|
#ifdef HAS_GPS
|
||||||
// do we have a valid GPS time?
|
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1100)); // wait for pps
|
||||||
if (get_gpstime()) { // then let's sync GPS time on top of second
|
t = get_gpstime(); // fetch recent time from last NEMA record
|
||||||
|
if (t) {
|
||||||
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // wait for pps
|
/ t++; // last NMEA record concerns past second, so we add one
|
||||||
vTaskDelay(gpsDelay_ticks);
|
ESP_LOGD(TAG, "millis: %d, second: %d", millis(), second(t));
|
||||||
t = get_gpstime(); // fetch time from recent NEMA record
|
setTime(t);
|
||||||
if (t) {
|
|
||||||
t++; // gps time concerns past second, so we add one
|
|
||||||
xSemaphoreTake(TimePulse, pdMS_TO_TICKS(1000)); // wait for pps
|
|
||||||
setTime(t);
|
|
||||||
#ifdef HAS_RTC
|
#ifdef HAS_RTC
|
||||||
set_rtctime(t); // calibrate RTC
|
set_rtctime(t); // calibrate RTC
|
||||||
#endif
|
#endif
|
||||||
timeSource = _gps;
|
timeSource = _gps;
|
||||||
goto exit;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#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 = get_rtctime();
|
t = get_rtctime();
|
||||||
if (t) {
|
if (t) {
|
||||||
setTime(t);
|
setTime(t);
|
||||||
timeSource = _rtc;
|
timeSource = _rtc;
|
||||||
} else
|
}
|
||||||
ESP_LOGW(TAG, "no confident RTC time");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// try lora sync if we have
|
// try lora sync if we have
|
||||||
#if defined HAS_LORA && defined TIME_SYNC_LORA
|
#if defined HAS_LORA && defined TIME_SYNC_LORA
|
||||||
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
|
LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
exit:
|
if (!t)
|
||||||
|
timeSource = _unsynced;
|
||||||
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;
|
|
||||||
|
|
||||||
} // timeSync()
|
} // timeSync()
|
||||||
|
|
||||||
@ -66,7 +54,7 @@ uint8_t timepulse_init() {
|
|||||||
// use time pulse from GPS as time base with fixed 1Hz frequency
|
// use time pulse from GPS as time base with fixed 1Hz frequency
|
||||||
#ifdef GPS_INT
|
#ifdef GPS_INT
|
||||||
|
|
||||||
// setup external interupt pin for GPS INT output
|
// 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
|
// setup external rtc 1Hz clock as pulse per second clock
|
||||||
ESP_LOGI(TAG, "Timepulse: external (GPS)");
|
ESP_LOGI(TAG, "Timepulse: external (GPS)");
|
||||||
@ -75,7 +63,7 @@ uint8_t timepulse_init() {
|
|||||||
// use pulse from on board RTC chip as time base with fixed frequency
|
// use pulse from on board RTC chip as time base with fixed frequency
|
||||||
#elif defined RTC_INT
|
#elif defined RTC_INT
|
||||||
|
|
||||||
// setup external interupt pin for active low RTC INT output
|
// setup external interupt pin for falling edge RTC INT
|
||||||
pinMode(RTC_INT, INPUT_PULLUP);
|
pinMode(RTC_INT, INPUT_PULLUP);
|
||||||
|
|
||||||
// setup external rtc 1Hz clock as pulse per second clock
|
// setup external rtc 1Hz clock as pulse per second clock
|
||||||
@ -114,12 +102,15 @@ void timepulse_start(void) {
|
|||||||
|
|
||||||
// interrupt service routine triggered by either pps or esp32 hardware timer
|
// interrupt service routine triggered by either pps or esp32 hardware timer
|
||||||
void IRAM_ATTR CLOCKIRQ(void) {
|
void IRAM_ATTR CLOCKIRQ(void) {
|
||||||
|
|
||||||
if (ClockTask != NULL)
|
if (ClockTask != NULL)
|
||||||
xTaskNotifyFromISR(ClockTask, xTaskGetTickCountFromISR(), eSetBits, NULL);
|
xTaskNotifyFromISR(ClockTask, uint32_t(now()), eSetBits, NULL);
|
||||||
|
|
||||||
#if defined GPS_INT || defined RTC_INT
|
#if defined GPS_INT || defined RTC_INT
|
||||||
xSemaphoreGiveFromISR(TimePulse, NULL);
|
xSemaphoreGiveFromISR(TimePulse, &xHigherPriorityTaskWoken);
|
||||||
TimePulseTick = !TimePulseTick; // flip ticker
|
TimePulseTick = !TimePulseTick; // flip ticker
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +172,7 @@ void clock_init(void) {
|
|||||||
(void *)1, // task parameter
|
(void *)1, // task parameter
|
||||||
4, // priority of the task
|
4, // priority of the task
|
||||||
&ClockTask, // task handle
|
&ClockTask, // task handle
|
||||||
0); // CPU core
|
1); // CPU core
|
||||||
|
|
||||||
assert(ClockTask); // has clock task started?
|
assert(ClockTask); // has clock task started?
|
||||||
} // clock_init
|
} // clock_init
|
||||||
@ -191,10 +182,11 @@ void clock_loop(void *pvParameters) { // ClockTask
|
|||||||
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
||||||
|
|
||||||
TickType_t wakeTime;
|
TickType_t wakeTime;
|
||||||
|
uint32_t ppstime;
|
||||||
time_t t;
|
time_t t;
|
||||||
|
|
||||||
#define t1(t) (t + DCF77_FRAME_SIZE + 1) // future time for next DCF77 frame
|
#define t1(t) (t + DCF77_FRAME_SIZE + 1) // future minute for next DCF77 frame
|
||||||
#define t2(t) (t + 1) // future time for sync with 1pps trigger
|
#define t2(t) (t + 1) // future second after sync with 1pps trigger
|
||||||
|
|
||||||
// preload first DCF frame before start
|
// preload first DCF frame before start
|
||||||
#ifdef HAS_DCF77
|
#ifdef HAS_DCF77
|
||||||
@ -204,14 +196,14 @@ void clock_loop(void *pvParameters) { // ClockTask
|
|||||||
|
|
||||||
// output time telegram for second following sec beginning with timepulse
|
// output time telegram for second following sec beginning with timepulse
|
||||||
for (;;) {
|
for (;;) {
|
||||||
xTaskNotifyWait(0x00, ULONG_MAX, &wakeTime,
|
xTaskNotifyWait(0x00, ULONG_MAX, &ppstime,
|
||||||
portMAX_DELAY); // wait for timepulse
|
portMAX_DELAY); // wait for timepulse
|
||||||
|
|
||||||
// no confident time -> suppress clock output
|
// no confident time -> suppress clock output
|
||||||
if (timeStatus() == timeNotSet)
|
if (timeStatus() == timeNotSet)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
t = now(); // payload to send to clock
|
t = time_t(ppstime);
|
||||||
|
|
||||||
#if defined HAS_IF482
|
#if defined HAS_IF482
|
||||||
|
|
||||||
@ -222,8 +214,10 @@ void clock_loop(void *pvParameters) { // ClockTask
|
|||||||
if (second(t) == DCF77_FRAME_SIZE - 1) // is it time to load new frame?
|
if (second(t) == DCF77_FRAME_SIZE - 1) // is it time to load new frame?
|
||||||
DCFpulse = DCF77_Frame(t1(t)); // generate next frame
|
DCFpulse = DCF77_Frame(t1(t)); // generate next frame
|
||||||
|
|
||||||
if (DCFpulse[DCF77_FRAME_SIZE] ==
|
if (DCFpulse[DCF77_FRAME_SIZE] !=
|
||||||
minute(t1(t))) // have recent frame? (pulses could be missed!)
|
minute(t1(t))) // have recent frame? (timepulses could be missed!)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
DCF77_Pulse(t2(t), DCFpulse); // then output next second of this frame
|
DCF77_Pulse(t2(t), DCFpulse); // then output next second of this frame
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user