ESP32-PaxCounter/src/rtctime.cpp

191 lines
5.2 KiB
C++
Raw Normal View History

2019-01-20 22:38:53 +01:00
#include "rtctime.h"
// Local logging tag
static const char TAG[] = "main";
2019-02-07 23:05:26 +01:00
TaskHandle_t ClockTask;
hw_timer_t *clockCycle = NULL;
bool volatile TimePulseTick = false;
2019-02-15 14:08:27 +01:00
// helper function to setup a pulse per second for time synchronisation
int timepulse_init() {
// use time pulse from GPS as time base with fixed 1Hz frequency
2019-02-15 14:08:27 +01:00
#ifdef GPS_INT
// setup external interupt for active low RTC INT pin
pinMode(GPS_INT, INPUT_PULLDOWN);
// setup external rtc 1Hz clock as pulse per second clock
2019-02-16 15:02:07 +01:00
ESP_LOGI(TAG, "Time base: external (GPS)");
return 1; // success
// use pulse from on board RTC chip as time base with fixed frequency
2019-02-15 14:08:27 +01:00
#elif defined RTC_INT
// setup external interupt for active low RTC INT pin
pinMode(RTC_INT, INPUT_PULLUP);
2019-02-15 14:08:27 +01:00
// setup external rtc 1Hz clock as pulse per second clock
if (I2C_MUTEX_LOCK()) {
2019-02-15 14:08:27 +01:00
Rtc.SetSquareWavePinClockFrequency(DS3231SquareWaveClock_1Hz);
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeClock);
I2C_MUTEX_UNLOCK();
2019-02-16 15:02:07 +01:00
ESP_LOGI(TAG, "Time base: external (RTC)");
2019-02-15 14:08:27 +01:00
return 1; // success
} else {
ESP_LOGE(TAG, "I2c bus busy - RTC initialization error");
return 0; // failure
}
return 1; // success
#else
// use ESP32 hardware timer as time base with adjustable frequency
2019-02-15 14:08:27 +01:00
clockCycle = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
2019-02-16 15:02:07 +01:00
//timerAttachInterrupt(clockCycle, &CLOCKIRQ, true);
2019-02-15 14:08:27 +01:00
timerAlarmWrite(clockCycle, 10000, true); // 1000ms
2019-02-16 15:02:07 +01:00
ESP_LOGI(TAG, "Time base: internal (ESP32 hardware timer)");
return 1; // success
#endif
2019-02-15 14:08:27 +01:00
} // timepulse_init
void timepulse_start(void) {
#ifdef GPS_INT // start external clock gps pps line
attachInterrupt(digitalPinToInterrupt(GPS_INT), CLOCKIRQ, RISING);
#elif defined RTC_INT // start external clock rtc
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
#else // start internal clock esp32 hardware timer
2019-02-16 15:02:07 +01:00
timerAttachInterrupt(clockCycle, &CLOCKIRQ, true);
timerAlarmEnable(clockCycle);
#endif
}
2019-02-16 15:02:07 +01:00
// helper function to sync systime on start of next second
int sync_SysTime(time_t t) {
if (sync_TimePulse()) {
setTime(t + 1);
ESP_LOGD(TAG, "Systime synced on timepulse");
return 1; // success
} else
return 0; // failure
}
// helper function to sync moment on timepulse
int sync_TimePulse(void) {
// sync on top of next second by timepulse
2019-02-16 15:02:07 +01:00
if (xSemaphoreTake(TimePulse, pdMS_TO_TICKS(PPS)) == pdTRUE) {
return 1;
} // success
2019-02-15 14:08:27 +01:00
else
2019-02-16 15:02:07 +01:00
ESP_LOGW(TAG, "Missing timepulse, time not synced");
return 0; // failure
}
// interrupt service routine triggered by either rtc pps or esp32 hardware
// timer
void IRAM_ATTR CLOCKIRQ() {
xTaskNotifyFromISR(ClockTask, xTaskGetTickCountFromISR(), eSetBits, NULL);
2019-02-15 14:08:27 +01:00
#if defined GPS_INT || defined RTC_INT
xSemaphoreGiveFromISR(TimePulse, NULL);
TimePulseTick = !TimePulseTick; // flip ticker
#endif
portYIELD_FROM_ISR();
}
2019-02-07 23:05:26 +01:00
#ifdef HAS_RTC // we have hardware RTC
RtcDS3231<TwoWire> Rtc(Wire); // RTC hardware i2c interface
// initialize RTC
2019-01-21 16:16:39 +01:00
int rtc_init(void) {
// return = 0 -> error / return = 1 -> success
// block i2c bus access
2019-01-26 12:32:17 +01:00
if (I2C_MUTEX_LOCK()) {
Wire.begin(HAS_RTC);
Rtc.Begin();
RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
if (!Rtc.IsDateTimeValid()) {
2019-01-20 22:38:53 +01:00
ESP_LOGW(TAG,
"RTC has no valid RTC date/time, setting to compilation date");
Rtc.SetDateTime(compiled);
}
if (!Rtc.GetIsRunning()) {
ESP_LOGI(TAG, "RTC not running, starting now");
Rtc.SetIsRunning(true);
}
RtcDateTime now = Rtc.GetDateTime();
if (now < compiled) {
2019-01-28 00:38:31 +01:00
ESP_LOGI(TAG, "RTC date/time is older than compilation date, updating");
Rtc.SetDateTime(compiled);
}
// configure RTC chip
Rtc.Enable32kHzPin(false);
Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
} else {
ESP_LOGE(TAG, "I2c bus busy - RTC initialization error");
goto error;
}
2019-01-26 12:32:17 +01:00
I2C_MUTEX_UNLOCK(); // release i2c bus access
ESP_LOGI(TAG, "RTC initialized");
return 1;
error:
2019-01-26 12:32:17 +01:00
I2C_MUTEX_UNLOCK(); // release i2c bus access
return 0;
} // rtc_init()
2019-02-11 23:37:45 +01:00
int set_rtctime(time_t t) { // t is seconds epoch time starting 1.1.1970
2019-01-26 12:32:17 +01:00
if (I2C_MUTEX_LOCK()) {
Rtc.SetDateTime(RtcDateTime(t));
2019-01-26 12:32:17 +01:00
I2C_MUTEX_UNLOCK(); // release i2c bus access
2019-02-11 23:37:45 +01:00
ESP_LOGI(TAG, "RTC calibrated");
return 1; // success
2019-01-20 22:38:53 +01:00
}
2019-01-29 22:54:16 +01:00
return 0; // failure
2019-01-20 22:38:53 +01:00
} // set_rtctime()
2019-02-02 09:15:31 +01:00
int set_rtctime(uint32_t t) { // t is epoch seconds starting 1.1.1970
return set_rtctime(static_cast<time_t>(t));
// set_rtctime()
}
2019-01-29 22:54:16 +01:00
2019-01-21 16:16:39 +01:00
time_t get_rtctime(void) {
2019-02-16 15:02:07 +01:00
// !! never call now() or delay in this function, this would break this
// function to be used as SyncProvider for Time.h
2019-01-28 23:59:52 +01:00
time_t t = 0;
// block i2c bus access
2019-01-26 12:32:17 +01:00
if (I2C_MUTEX_LOCK()) {
2019-01-28 23:59:52 +01:00
if (Rtc.IsDateTimeValid()) {
RtcDateTime tt = Rtc.GetDateTime();
t = tt.Epoch32Time();
2019-01-21 16:16:39 +01:00
} else {
2019-01-28 23:59:52 +01:00
ESP_LOGW(TAG, "RTC has no confident time");
2019-01-21 16:16:39 +01:00
}
2019-01-26 12:32:17 +01:00
I2C_MUTEX_UNLOCK(); // release i2c bus access
2019-01-20 22:38:53 +01:00
}
2019-01-28 23:59:52 +01:00
return t;
2019-01-21 16:16:39 +01:00
} // get_rtctime()
2019-01-21 16:16:39 +01:00
float get_rtctemp(void) {
// block i2c bus access
2019-01-26 12:32:17 +01:00
if (I2C_MUTEX_LOCK()) {
RtcTemperature temp = Rtc.GetTemperature();
2019-01-26 12:32:17 +01:00
I2C_MUTEX_UNLOCK(); // release i2c bus access
return temp.AsFloatDegC();
} // while
return 0;
2019-01-28 23:59:52 +01:00
} // get_rtctemp()
#endif // HAS_RTC