IF482 precision improvement

This commit is contained in:
Klaus K Wilting 2019-02-11 23:37:45 +01:00
parent 87378738d2
commit 035b7abe26
4 changed files with 49 additions and 31 deletions

View File

@ -23,6 +23,6 @@ float get_rtctemp(void);
void IRAM_ATTR CLOCKIRQ();
int timepulse_init(uint32_t pps_freq);
void timepulse_start();
uint8_t sync_clock(time_t t);
time_t sync_clock(time_t t);
#endif // _RTCTIME_H

View File

@ -88,10 +88,11 @@ time_t tmConvert_t(uint16_t YYYY, uint8_t MM, uint8_t DD, uint8_t hh,
// function to fetch current time from gps
time_t get_gpstime(void) {
// never call now() in this function, this would cause a recursion!
// never call now() in this function, this would break this function
// to use as SyncProvider due to recursive call to now()
time_t t = 0;
if ((gps.time.age() < 1500) && (gps.time.isValid())) {
t = tmConvert_t(gps.date.year(), gps.date.month(), gps.date.day(),
t = 1 + tmConvert_t(gps.date.year(), gps.date.month(), gps.date.day(),
gps.time.hour(), gps.time.minute(), gps.time.second());
ESP_LOGD(TAG, "GPS time: %4d/%02d/%02d %02d:%02d:%02d", year(t), month(t),
day(t), hour(t), minute(t), second(t));

View File

@ -115,19 +115,19 @@ int if482_init(void) {
"if482loop", // name of task
2048, // stack size of task
(void *)1, // parameter of the task
3, // priority of the task
4, // priority of the task
&ClockTask, // task handle
0); // CPU core
assert(ClockTask); // has clock task started?
timepulse_start(); // start pulse
// timepulse_start(); // start pulse
return 1; // success
} // if482_init
String IF482_Out(time_t tt) {
time_t t = myTZ.toLocal(tt);
time_t t = 1 + myTZ.toLocal(tt);
char mon, buf[14], out[IF482_FRAME_SIZE];
switch (timeStatus()) { // indicates if time has been set and recently synced
@ -159,18 +159,32 @@ void if482_loop(void *pvParameters) {
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
time_t tOut;
TickType_t wakeTime;
const TickType_t timeOffset =
tx_time(HAS_IF482); // duration of telegram transmit
const TickType_t startTime = xTaskGetTickCount(); // now
const TickType_t tTx = tx_time(HAS_IF482); // duration of telegram transmit
BitsPending = true; // start blink in display
sync_clock(now()); // wait until begin of a new second
BitsPending = true; // start blink in display
// phase 1: sync task on top of second
// take timestamp at moment of start of new second
const TickType_t shotTime = xTaskGetTickCount() - startTime - timeOffset;
sync_clock(now());
// task remains in blocked state until it is notified by isr
const TickType_t t0 = xTaskGetTickCount(); // moment of start top of second
timepulse_start(); // start timepulse
xTaskNotifyWait(
0x00, // don't clear any bits on entry
ULONG_MAX, // clear all bits on exit
&wakeTime, // receives moment of call from isr
portMAX_DELAY); // wait forever (missing error handling here...)
const TickType_t tOffset = wakeTime - t0;
const TickType_t tShot =
(tOffset < tTx) ? (1000 - tOffset - tTx) : (tOffset - tTx);
ESP_LOGI(TAG, "IF482 signal synced with precision %dms", 1000 - tOffset);
// phase 2: sync task on time pulse interrupt
for (;;) {
xTaskNotifyWait(
0x00, // don't clear any bits on entry
@ -178,22 +192,25 @@ void if482_loop(void *pvParameters) {
&wakeTime, // receives moment of call from isr
portMAX_DELAY); // wait forever (missing error handling here...)
tOut = now() + 1; // next second after waketime
// select clock scale
#if (PPS == IF482_PULSE_DURATION) // we don't need clock rescaling
// wait until it's time to start transmit telegram for next second
vTaskDelayUntil(&wakeTime, shotTime); // sets waketime to moment of shot
IF482.print(IF482_Out(now() + 1));
vTaskDelayUntil(&wakeTime, tShot); // sets waketime to moment of tShot
IF482.print(IF482_Out(tOut));
#elif (PPS > IF482_PULSE_DURATION) // we need upclocking
for (uint8_t i = 1; i <= PPS / IF482_PULSE_DURATION; i++) {
vTaskDelayUntil(&wakeTime, shotTime); // sets waketime to moment of shot
IF482.print(IF482_Out(now() + 1));
vTaskDelayUntil(&wakeTime, tShot); // sets waketime to moment of shot
IF482.print(IF482_Out(tOut));
}
#elif (PPS < IF482_PULSE_DURATION) // we need downclocking, not yet implemented
#error Timepulse is too low for IF482!
#endif
}
} // forever
} // if482_loop()
// helper function to calculate IF482 telegram serial tx time from serial

View File

@ -1,5 +1,7 @@
#include "rtctime.h"
#define I2C_DELAY (12) // 12ms is i2c delay when saving time to RTC chip
// Local logging tag
static const char TAG[] = "main";
@ -60,11 +62,13 @@ error:
} // rtc_init()
int set_rtctime(time_t t) { // t is epoch time starting 1.1.1970
int set_rtctime(time_t t) { // t is seconds epoch time starting 1.1.1970
if (I2C_MUTEX_LOCK()) {
Rtc.SetDateTime(RtcDateTime(t));
time_t tt = sync_clock(t); // wait for top of second
Rtc.SetDateTime(RtcDateTime(tt));
I2C_MUTEX_UNLOCK(); // release i2c bus access
return 1; // success
ESP_LOGI(TAG, "RTC calibrated");
return 1; // success
}
return 0; // failure
} // set_rtctime()
@ -176,15 +180,11 @@ void timepulse_start() {
#endif
}
// helper function to sync phase of DCF output signal to start of second t
uint8_t sync_clock(time_t t) {
time_t tt = t;
// delay until start of next second
do {
tt = now();
} while (t == tt);
ESP_LOGI(TAG, "Sync on Sec %d", second(tt));
return second(tt);
// helper function to sync time_t of top of next second
time_t sync_clock(time_t t) {
while (millis() % 1000)
; // wait for milli seconds to be zero before setting new time
return (now());
}
// interrupt service routine triggered by either rtc pps or esp32 hardware