mcu_hi3321_watch/tjd/driver/rtc/rtc_api.c
2025-05-26 20:15:20 +08:00

318 lines
9.2 KiB
C

/*----------------------------------------------------------------------------
* 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 <stdio.h>
#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(&timestamp);
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(&timestamp);
if (ret != RTC_SUCC) {
static_print_error("rtc_get_timestamp failed, ret = %x", ret);
return ret;
}
localtime_r((time_t *)&timestamp, &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(&timestamp);
if (ret != RTC_SUCC) {
static_print_error("rtc_get_timestamp failed, ret = %x", ret);
return ret;
}
gmtime_r((time_t *)&timestamp, &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(&timestamp);
if (ret != RTC_SUCC) {
static_print_error("rtc_get_timestamp failed, ret = %x", ret);
return ret;
}
localtime_r((time_t *)&timestamp, 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(&timestamp);
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; }