225 lines
5.8 KiB
C
225 lines
5.8 KiB
C
/*
|
|
* rtc.c
|
|
*
|
|
* Created on: Jan 16, 2023
|
|
* Author: Sword
|
|
*/
|
|
#include "rtc.h"
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
|
|
|
|
|
|
/** Date and time set to: 1st of December 2014, 23 hour 59 min and 31 seconds */
|
|
#define SET_HOUR 13 /*< Set hour to the RTC */
|
|
#define SET_MINUTE 0 /*< Set minute to the RTC */
|
|
#define SET_SECOND 0 /*< Set second to the RTC */
|
|
#define SET_WEEKDAY 3 /*< Set weekday to the RTC */
|
|
#define SET_YEARDAY 16 /*< day in the year, range 0 to 365 */
|
|
#define SET_DAY 16 /*< Set day to the RTC */
|
|
#define SET_MONTH 1 /*< Set month to the RTC */
|
|
#define SET_YEAR 2023 /*< Set year to the RTC */
|
|
|
|
#define RTC_SUBSECOND_COUNTER_LOAD_VALUE 32767
|
|
|
|
static const char* TAG = "RTC";
|
|
|
|
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
|
|
#include "esp_log.h"
|
|
|
|
static bool rtc_set = false;
|
|
|
|
int app_rtc_init(void)
|
|
{
|
|
int retval = RTC_STATUS_OK;
|
|
|
|
//RTC_InitType RTC_Init_struct;
|
|
//RTC_StructInit(&RTC_Init_struct);
|
|
|
|
//SysCtrl_PeripheralClockCmd(CLOCK_PERIPH_RTC, ENABLE);
|
|
/* Try to enable the down-counter to use as a millisecond counter, but
|
|
* does not seem to work without this __NOP delay.
|
|
*/
|
|
//RTC_Init_struct.RTC_TLR1 = RTC_SUBSECOND_COUNTER_LOAD_VALUE;
|
|
//RTC_Init(&RTC_Init_struct);
|
|
|
|
/** Delay between two write in RTC->TCR register has to be
|
|
* at least 3 x 32k cycle + 2 CPU cycle. For that reason it
|
|
* is neccessary to add the delay.
|
|
*/
|
|
// for (volatile uint32_t i = 0; i < 600; i++) {
|
|
// __asm("NOP");
|
|
// }
|
|
|
|
//RTC_DateTimeType RTC_DateTime;
|
|
|
|
struct tm rtc_time;
|
|
|
|
/* Set the present time and date */
|
|
/*RTC_DateTime.Second = SET_SECOND;
|
|
RTC_DateTime.Minute = SET_MINUTE;
|
|
RTC_DateTime.Hour = SET_HOUR;
|
|
RTC_DateTime.WeekDay = SET_WEEKDAY;
|
|
RTC_DateTime.MonthDay = SET_DAY;
|
|
RTC_DateTime.Month = SET_MONTH;
|
|
RTC_DateTime.Year = SET_YEAR;
|
|
RTC_SetTimeDate(&RTC_DateTime);*/
|
|
|
|
rtc_time.tm_sec = SET_SECOND;
|
|
rtc_time.tm_min = SET_MINUTE;
|
|
rtc_time.tm_hour = SET_HOUR;
|
|
rtc_time.tm_wday = SET_WEEKDAY;
|
|
rtc_time.tm_mday = SET_DAY;
|
|
rtc_time.tm_mon = SET_MONTH;
|
|
rtc_time.tm_year = SET_YEAR;
|
|
rtc_time.tm_yday = SET_YEARDAY;
|
|
|
|
time_t t = mktime(&rtc_time);
|
|
struct timeval now = { .tv_sec = t };
|
|
|
|
settimeofday(&now, NULL);
|
|
|
|
/* Enable RTC */
|
|
// RTC_Cmd(ENABLE);
|
|
/* Enable RTC clockwatch */
|
|
// RTC_ClockwatchCmd(ENABLE);
|
|
|
|
rtc_set = false;
|
|
|
|
return retval;
|
|
}
|
|
|
|
void rtc_get_timestamp(rtc_timestamp_t* ts)
|
|
{
|
|
if (ts) {
|
|
//RTC_DateTimeType RTC_DateTime;
|
|
//RTC_GetTimeDate(&RTC_DateTime);
|
|
/* RTC subsecond counter is a count-down counter */
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
|
|
struct tm *info = localtime( &tv.tv_sec );
|
|
|
|
ts->Millisecond = 7+1000*(info->tm_sec); //((RTC_SUBSECOND_COUNTER_LOAD_VALUE - RTC_GetTimerValue()) * 1000 + RTC_SUBSECOND_COUNTER_LOAD_VALUE) /
|
|
ts->Second = info->tm_sec;
|
|
ts->Minute = info->tm_min;
|
|
ts->Hour = info->tm_hour;
|
|
ts->WeekDay = info->tm_wday;
|
|
ts->MonthDay = info->tm_mday;
|
|
ts->Month = info->tm_mon;
|
|
ts->Year = info->tm_year;
|
|
}
|
|
}
|
|
|
|
void rtc_set_timestamp(rtc_timestamp_t* ts)
|
|
{
|
|
if (ts) {
|
|
|
|
rtc_set_timestamp_tz(ts, 0);
|
|
}
|
|
}
|
|
|
|
/* Set timestamp including a timezone offset in seconds.
|
|
* The timezone offset may be positive or negative. It is applied
|
|
* by subtraction, so a -ve offset (e.g. UTC-5) results in the
|
|
* timezone offset being added to the local timestamp
|
|
*/
|
|
void rtc_set_timestamp_tz(rtc_timestamp_t* ts, int32_t tz_offset_sec)
|
|
{
|
|
if (ts) {
|
|
|
|
struct tm buf;
|
|
buf.tm_year = ts->Year - 1900;
|
|
buf.tm_mon = ts->Month - 1;
|
|
buf.tm_mday = ts->MonthDay;
|
|
buf.tm_hour = ts->Hour;
|
|
buf.tm_min = ts->Minute;
|
|
buf.tm_sec = ts->Second;
|
|
time_t t = mktime(&buf);
|
|
|
|
/* Apply offset */
|
|
t -= tz_offset_sec;
|
|
/*
|
|
if (!rtc_is_set()) {
|
|
rtc_set_epoch((uint32_t)t);
|
|
}
|
|
*/
|
|
rtc_set_epoch((uint32_t)t);
|
|
}
|
|
}
|
|
|
|
void rtc_set_epoch(uint32_t epoch)
|
|
{
|
|
/*
|
|
* struct tm
|
|
Member Type Meaning Range
|
|
tm_sec int seconds after the minute 0 - 60 *
|
|
tm_min int minutes after the hour 0 - 59
|
|
tm_hour int hours since midnight 0 - 23
|
|
tm_mday int day of the month 1 - 31
|
|
tm_mon int months since January 0 - 11
|
|
tm_year int years since 1900
|
|
tm_wday int days since Sunday 0 - 6
|
|
tm_yday int days since January 1 0 - 365
|
|
tm_isdst int Daylight Saving Time flag
|
|
*/
|
|
|
|
struct tm* buf;
|
|
time_t t = epoch;
|
|
|
|
buf = localtime(&t);
|
|
|
|
ESP_LOGD(TAG,"rtc_set_epoch: %s\n", asctime(buf));
|
|
|
|
//RTC_DateTimeType RTC_DateTime;
|
|
//
|
|
///* Set the present time and date */
|
|
//RTC_DateTime.Second = buf->tm_sec;
|
|
//RTC_DateTime.Minute = buf->tm_min;
|
|
//RTC_DateTime.Hour = buf->tm_hour;
|
|
//RTC_DateTime.WeekDay = buf->tm_wday;
|
|
//RTC_DateTime.MonthDay = buf->tm_mday;
|
|
//RTC_DateTime.Month = buf->tm_mon + 1;
|
|
//RTC_DateTime.Year = buf->tm_year + 1900;
|
|
//RTC_SetTimeDate(&RTC_DateTime);
|
|
|
|
time_t tmi = mktime(buf);
|
|
struct timeval now = { .tv_sec = tmi };
|
|
|
|
settimeofday(&now, NULL);
|
|
|
|
rtc_set = true;
|
|
}
|
|
|
|
uint32_t rtc_get_epoch(void)
|
|
{
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
|
|
struct tm *info = localtime( &tv.tv_sec );
|
|
|
|
struct tm buf;
|
|
buf.tm_year = info->tm_year - 1900;
|
|
buf.tm_mon = info->tm_mon - 1;
|
|
buf.tm_mday = info->tm_mday;
|
|
buf.tm_hour = info->tm_hour;
|
|
buf.tm_min = info->tm_min;
|
|
buf.tm_sec = info->tm_sec;
|
|
buf.tm_isdst = 0;
|
|
|
|
time_t t = mktime(&buf);
|
|
|
|
ESP_LOGD(TAG,"rtc_get_epoch: %s\n", ctime(&t));
|
|
|
|
return (uint32_t)t;
|
|
}
|
|
|
|
bool rtc_is_set(void)
|
|
{
|
|
return rtc_set;
|
|
}
|
|
|
|
|
|
|
|
|