IF482 precision improvement
This commit is contained in:
parent
87378738d2
commit
035b7abe26
@ -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
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user