KT25-0812_82A-UART/apps/soundbox/task_manager/rtc/rtc_simulate.c
2025-08-12 18:09:23 +08:00

206 lines
5.4 KiB
C

#include "app_config.h"
#include "rtc/alarm.h"
#include "app_action.h"
#include "system/includes.h"
#include "clock_cfg.h"
#include "ioctl_cmds.h"
#include "system/sys_time.h"
#if (TCFG_APP_RTC_EN && TCFG_USE_FAKE_RTC)
/*************************************************************
此文件函数主要是虚拟rtc设备的实现
应用于不外挂晶振的场景,用户可以忽略实现,
最后的应用的接口与挂晶振的接口一致
**************************************************************/
#define WRITE_ALARM BIT(1)
#define READ_ALARM BIT(5)
#define WRITE_RTC BIT(0)
#define READ_RTC BIT(4)
#define MAX_YEAR 2099
#define MIN_YEAR 2000
typedef struct _RTC_SIMULATE_VAR {
struct device device;
struct sys_time sys_simulate_time;
struct sys_time sys_alarm_time;
/* OS_MUTEX mutex; */
} RTC_SIMULATE_VAR;
#define __this (&rtc_smulate_var)
static RTC_SIMULATE_VAR rtc_smulate_var = {0};
static u8 g_alarm_flag = 0;
__attribute__((weak))void alm_wakeup_isr(void);
__attribute__((weak)) void set_rtc_default_time(struct sys_time *t);
static u8 is_the_same_time(struct sys_time *time1, struct sys_time *time2)
{
return (time1->year == time2->year &&
time1->month == time2->month &&
time1->day == time2->day &&
time1->hour == time2->hour &&
time1->min == time2->min &&
time1->sec == time2->sec);
}
static int rtc_simulate_init(const struct dev_node *node, void *arg)
{
/* os_mutex_create(&__this->mutex); */
if (set_rtc_default_time) {
set_rtc_default_time(&__this->sys_simulate_time);
} else {
__this->sys_simulate_time.year = 2020;
__this->sys_simulate_time.month = 1;
__this->sys_simulate_time.day = 1;
__this->sys_simulate_time.hour = 0;
__this->sys_simulate_time.min = 0;
__this->sys_simulate_time.sec = 0;
}
printf("rtc_simulate_init: %d-%d-%d %d:%d:%d\n",
__this->sys_simulate_time.year,
__this->sys_simulate_time.month,
__this->sys_simulate_time.day,
__this->sys_simulate_time.hour,
__this->sys_simulate_time.min,
__this->sys_simulate_time.sec);
return 0;
}
static int rtc_simulate_open(const char *name, struct device **device, void *arg)
{
*device = &__this->device;
return 0;
}
static void write_alarm(struct sys_time *alarm_time)
{
local_irq_disable();
memcpy(&__this->sys_alarm_time, alarm_time, sizeof(struct sys_time));
local_irq_enable();
}
static void write_sys_time(struct sys_time *curr_time)
{
local_irq_disable();
memcpy(&__this->sys_simulate_time, curr_time, sizeof(struct sys_time));
local_irq_enable();
}
static void read_sys_time(struct sys_time *curr_time)
{
local_irq_disable();
memcpy(curr_time, &__this->sys_simulate_time, sizeof(struct sys_time));
local_irq_enable();
}
static void set_alarm_ctrl(u8 set_alarm)
{
g_alarm_flag = set_alarm;
}
static int rtc_simulate_ioctl(struct device *device, u32 cmd, u32 arg)
{
int err = 0;
switch (cmd) {
case IOCTL_SET_ALARM:
write_alarm((struct sys_time *)arg);
break;
case IOCTL_SET_ALARM_ENABLE:
if (arg) {
set_alarm_ctrl(1);
} else {
set_alarm_ctrl(0);
}
break;
case IOCTL_GET_SYS_TIME:
read_sys_time((struct sys_time *)arg);
break;
case IOCTL_SET_SYS_TIME:
write_sys_time((struct sys_time *)arg);
break;
}
return err;
}
void set_fake_rtc_tick(u64 actual_ms)
{
#if (defined(TCFG_USE_FAKE_RTC) && (TCFG_USE_FAKE_RTC))
struct sys_time temp_time;
u16 msec = (u16)actual_ms;
static u16 l_msec = 0;
static u8 cal_flag = 0;
l_msec += msec;
if (l_msec >= 1000) {
l_msec -= 1000;
cal_flag = 1;
}
if (cal_flag) {
cal_flag = 0;
read_sys_time(&temp_time);
if (++temp_time.sec >= 60) {
temp_time.sec = 0;
if (++temp_time.min >= 60) {
temp_time.min = 0;
if (++temp_time.hour >= 24) {
temp_time.hour = 0;
if (++temp_time.day > month_for_day(temp_time.month, temp_time.year)) {
temp_time.day = 1;
if (++temp_time.month > 12) {
temp_time.month = 1;
if (++temp_time.year > MAX_YEAR) {
temp_time.year = MIN_YEAR;
}
}
}
}
}
}
write_sys_time(&temp_time);
printf("rtc_sys_time: %d-%d-%d %d:%d:%d\n",
temp_time.year,
temp_time.month,
temp_time.day,
temp_time.hour,
temp_time.min,
temp_time.sec);
local_irq_disable();
if (g_alarm_flag && is_the_same_time(&__this->sys_alarm_time, &__this->sys_simulate_time)) {
local_irq_enable();
if (alm_wakeup_isr) {
alm_wakeup_isr();
}
} else {
local_irq_enable();
}
}
#endif
}
const struct device_operations rtc_simulate_ops = {
.init = rtc_simulate_init,
.open = rtc_simulate_open,
.ioctl = rtc_simulate_ioctl,
.read = NULL,
.write = NULL,
};
#endif