/*---------------------------------------------------------------------------- * Copyright (c) TJD Technologies Co., Ltd. 2024. All rights reserved. * * Description: rtc_api.c * * Author: luziquan@ss-tjd.com * * Create: 2024-07-12 *--------------------------------------------------------------------------*/ #include "rtc_api.h" #include "rtc_port.h" #include "sys/time.h" #include "sys_config.h" #include "time.h" #include #define ENABLE_PRINT_INFO 1 #if ENABLE_PRINT_INFO #define static_print_info(...) sys_rtc_log_i(__VA_ARGS__) // 一般信息打印宏控制 #define static_print_warn(...) sys_rtc_log_w(__VA_ARGS__) // 警告信息打印一般常开 #define static_print_error(...) sys_rtc_log_e(__VA_ARGS__) // 错误信息打印一般常开 #else #define static_print_info(...) #define static_print_warn(...) #define static_print_error(...) #endif static const uint64_t g_rtc_default_time = 965347200; // 2000-08-04 08:00:00 #ifndef RTC_BASE_YEAR #define RTC_BASE_YEAR (1900) #endif #ifndef SECONDS_PER_MINUTE #define SECONDS_PER_MINUTE 60 #endif static const uint8_t rtc_days_in_month[2][12] = {{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; static inline bool is_leap_year(uint32_t year) { return (uint32_t)(((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)); } static int rtc_month_days(uint32_t month, uint32_t year) { return rtc_days_in_month[is_leap_year(year)][month]; } static void statdard_time_to_rtc_time(const struct tm *time_standard, struct rtc_time *time) { time->tm_year = time_standard->tm_year + RTC_BASE_YEAR; time->tm_mon = time_standard->tm_mon + 1; time->tm_mday = time_standard->tm_mday; time->tm_hour = time_standard->tm_hour; time->tm_min = time_standard->tm_min; time->tm_sec = time_standard->tm_sec; time->tm_wday = time_standard->tm_wday; time->tm_yday = time_standard->tm_yday; time->tm_isdst = time_standard->tm_isdst; } static void rtc_time_to_standard_time(const struct rtc_time *time, struct tm *time_standard) { time_standard->tm_year = time->tm_year - RTC_BASE_YEAR; time_standard->tm_mon = time->tm_mon - 1; time_standard->tm_mday = time->tm_mday; time_standard->tm_hour = time->tm_hour; time_standard->tm_min = time->tm_min; time_standard->tm_sec = time->tm_sec; time_standard->tm_wday = time->tm_wday; time_standard->tm_yday = time->tm_yday; time_standard->tm_isdst = time->tm_isdst; } static uint32_t rtc_standard_time_valid(const struct tm *time) { if (time->tm_year < (100) || time->tm_year > (199)) { return RTC_INVALID_PARAM_YEAR; } if (time->tm_mon < 0 || time->tm_mon > 11) { return RTC_INVALID_PARAM_MONTH; } if (time->tm_mday < 1 || time->tm_mday > rtc_month_days(time->tm_mon, time->tm_year)) { return RTC_INVALID_PARAM_DAY; } if (time->tm_hour < 0 || time->tm_hour > 23) { return RTC_INVALID_PARAM_HOUR; } if (time->tm_min < 0 || time->tm_min > 59) { return RTC_INVALID_PARAM_MIN; } if (time->tm_sec < 0 || time->tm_sec > 59) { return RTC_INVALID_PARAM_SEC; } return RTC_SUCC; } static uint32_t rtc_dev_open(void) { uint64_t timestamp = 0; uint32_t ret = rtc_host_peripheral_init(×tamp); if (ret != RTC_SUCC) { static_print_error("rtc_host_peripheral_init failed, ret = %x", ret); } if (timestamp == 0) { static_print_info("calendar is not set, use default time"); } static_print_info("rtc_host_peripheral_init success timestamp: %llu", timestamp); rtc_set_timestamp(timestamp <= 0 ? g_rtc_default_time : timestamp); #if ALARM_ENABLE ret = rtc_alarm_init(); if (ret != RTC_SUCC) { return RTC_FAIL; } #endif return RTC_SUCC; } static void rtc_dev_close(void) { uint32_t ret = rtc_host_peripheral_deinit(); if (ret != RTC_SUCC) { return; } #if ALARM_ENABLE ret = rtc_alarm_deinit(); if (ret != RTC_SUCC) { return; } #endif } static uint32_t rtc_set_time(const struct rtc_time *time) { struct tm time_standard = {0}; // rtc时间转换为标准时间 rtc_time_to_standard_time(time, &time_standard); uint32_t ret = rtc_standard_time_valid(&time_standard); if (ret != RTC_SUCC) { static_print_error("invalid time %x", ret); return ret; } return rtc_set_timestamp(mktime(&time_standard)); } static uint32_t rtc_set_standard_time(const struct tm *time) { uint32_t ret = rtc_standard_time_valid(time); if (ret != RTC_SUCC) { static_print_error("invalid time %x", ret); return ret; } return rtc_set_timestamp(mktime((struct tm *)time)); } static uint32_t rtc_get_time(struct rtc_time *time) { struct tm time_standard = {0}; /* UTC时间戳转换为本地时间 */ uint64_t timestamp = 0; uint32_t ret = rtc_get_timestamp(×tamp); if (ret != RTC_SUCC) { static_print_error("rtc_get_timestamp failed, ret = %x", ret); return ret; } localtime_r((time_t *)×tamp, &time_standard); // rtc时间转换为标准时间 statdard_time_to_rtc_time(&time_standard, time); return ret; } static uint32_t rtc_get_utc_time(struct rtc_time *time) { struct tm time_standard = {0}; /* UTC时间戳转换为本地时间 */ uint64_t timestamp = 0; uint32_t ret = rtc_get_timestamp(×tamp); if (ret != RTC_SUCC) { static_print_error("rtc_get_timestamp failed, ret = %x", ret); return ret; } gmtime_r((time_t *)×tamp, &time_standard); // rtc时间转换为标准时间 statdard_time_to_rtc_time(&time_standard, time); return ret; } static uint32_t rtc_get_standard_time(struct tm *time) { /* UTC时间戳转换为本地时间 */ uint64_t timestamp = 0; uint32_t ret = rtc_get_timestamp(×tamp); if (ret != RTC_SUCC) { static_print_error("rtc_get_timestamp failed, ret = %x", ret); return ret; } localtime_r((time_t *)×tamp, time); return ret; } #if ALARM_ENABLE static uint32_t rtc_get_alarm(struct tm *alarm) { return 0; } static uint32_t rtc_set_alarm(const struct tm *alarm) { return ret_alarm_start(); } static uint32_t register_callback(alarm_callback callback) { return register_rtc_alarm_callback(callback); } #endif static uint32_t rtc_save_time(void) { uint64_t timestamp = 0; uint32_t ret = rtc_get_timestamp(×tamp); if (ret != RTC_SUCC) { return ret; } static_print_info("timestamp: %lld", timestamp); return rtc_save_time_of_sql(timestamp); } static struct rtc_class_ops g_rtc_ops = { .open = rtc_dev_open, .close = rtc_dev_close, .set_rtc_time = rtc_set_time, .set_standard_time = rtc_set_standard_time, .get_rtc_time = rtc_get_time, .get_rtc_utc_time = rtc_get_utc_time, .get_standard_time = rtc_get_standard_time, .set_timestamp = rtc_set_timestamp, .set_ms_timestamp = rtc_set_ms_timestamp, .get_timestamp = rtc_get_timestamp, .get_ms_timestamp = rtc_get_ms_timestamp, .set_diff = rtc_set_diff_time_of_sec, .get_diff = rtc_get_diff, #if ALARM_ENABLE .get_alarm = rtc_get_alarm, .set_alarm = rtc_set_alarm, .register_alarm_callback = register_callback, #endif }; uint32_t tjd_driver_rtc_parse_str(const char *str, struct rtc_time *time) { uint32_t ret = RTC_SUCC; ret = sscanf(str, "%d-%d-%d %d:%d:%d", &time->tm_year, &time->tm_mon, &time->tm_mday, &time->tm_hour, &time->tm_min, &time->tm_sec); if (ret != 6) { static_print_error("sscanf failed, ret = %x", ret); return ret; } return RTC_SUCC; } uint32_t tjd_driver_rtc_parse_time(const struct rtc_time *time, char *str) { if (time == NULL || str == NULL) { return RTC_INVALID_PARAM; } sprintf(str, "%d-%d-%d %d:%d:%d", time->tm_year, time->tm_mon, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); return RTC_SUCC; } uint32_t tjd_driver_rtc_save_time(void) { return rtc_save_time(); } uint32_t tjd_driver_rtc_sync_bt_time(uint8_t *data, uint32_t len) { uint8_t str[11]; // 11:49:36.429 I/Ble_Order: [writeBytes 设置设备时间 >>>>>> ab0b040118060f0b3124b1] // ab 0b 04 01 18 06 0f 0b 31 24 b1 // 包头 长度 类型 发标志 16进制时间 校验和 if (len < 11) { return RTC_FAIL; } int year = data[4] + 2000; int month = data[5]; int day = data[6]; int hour = data[7]; int minute = data[8]; int second = data[9]; struct rtc_time time_swap = { .tm_year = year, .tm_mon = month, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second, }; #if ENABLE_PRINT_INFO == 1 char str_time[20]; tjd_driver_rtc_parse_time(&time_swap, str_time); static_print_info("%s", str_time); #endif return rtc_set_time(&time_swap); } struct rtc_class_ops *tjd_driver_rtc_get_ops(void) { return &g_rtc_ops; }