A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2011 by Amaury Pouly
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "time.h"
24#include "system.h"
25#include "rtc.h"
26#include "timefuncs.h"
27#include "rtc-imx233.h"
28
29#define YEAR1980 315532800 /* 1980/1/1 00:00:00 in UTC */
30
31#if defined(SANSA_FUZEPLUS) || defined(SONY_NWZE360) || defined(SONY_NWZE370) || \
32 defined(CREATIVE_ZENXFI2) || defined(CREATIVE_ZENXFI3)
33#define USE_PERSISTENT
34#endif
35
36void rtc_init(void)
37{
38 /* rtc-imx233 is initialized by the system */
39}
40
41static void seconds_to_datetime(uint32_t seconds, struct tm *tm)
42{
43#ifdef USE_PERSISTENT
44 /* The OF uses PERSISTENT2 register to keep the adjustment and only changes
45 * SECONDS if necessary. */
46 seconds += imx233_rtc_read_persistent(2);
47#else
48 /* The Freescale recommended way of keeping time is the number of seconds
49 * since 00:00 1/1/1980 */
50 seconds += YEAR1980;
51#endif
52
53 gmtime_r(&seconds, tm);
54}
55
56int rtc_read_datetime(struct tm *tm)
57{
58 seconds_to_datetime(imx233_rtc_read_seconds(), tm);
59 return 0;
60}
61
62int rtc_write_datetime(const struct tm *tm)
63{
64 uint32_t seconds;
65
66 seconds = mktime((struct tm *)tm);
67
68#ifdef USE_PERSISTENT
69 /* The OF uses PERSISTENT2 register to keep the adjustment and only changes
70 * SECONDS if necessary.
71 * NOTE: the OF uses this mechanism to prevent roll back in time. Although
72 * Rockbox will handle a negative PERSISTENT2 value, the OF will detect
73 * it and won't return in time before SECONDS */
74 imx233_rtc_write_persistent(2, seconds - imx233_rtc_read_seconds());
75#else
76 /* The Freescale recommended way of keeping time is the number of seconds
77 * since 00:00 1/1/1980 */
78 imx233_rtc_write_seconds(seconds - YEAR1980);
79#endif
80
81 return 0;
82}
83
84void rtc_set_alarm(int h, int m)
85{
86 /* transform alarm time to absolute time */
87 struct tm tm;
88 seconds_to_datetime(imx233_rtc_read_seconds(), &tm);
89 /* if same date and hour/min is in the past, advance one day */
90 if(h < tm.tm_hour || (h == tm.tm_hour && m <= tm.tm_min))
91 seconds_to_datetime(imx233_rtc_read_seconds() + 3600 * 60, &tm);
92 tm.tm_hour = h;
93 tm.tm_min = m;
94 tm.tm_sec = 0;
95
96 uint32_t seconds = mktime(&tm);
97#ifdef USE_PERSISTENT
98 imx233_rtc_write_alarm(seconds - imx233_rtc_read_persistent(2));
99#else
100 imx233_rtc_write_alarm(seconds - YEAR1980);
101#endif
102}
103
104void rtc_get_alarm(int *h, int *m)
105{
106 struct tm tm;
107 seconds_to_datetime(imx233_rtc_read_alarm(), &tm);
108 *m = tm.tm_min;
109 *h = tm.tm_hour;
110}
111
112void rtc_enable_alarm(bool enable)
113{
114 BF_CLR(RTC_CTRL, ALARM_IRQ_EN);
115 BF_CLR(RTC_CTRL, ALARM_IRQ);
116 uint32_t val = imx233_rtc_read_persistent(0);
117 BF_WRX(val, RTC_PERSISTENT0, ALARM_EN(enable));
118 BF_WRX(val, RTC_PERSISTENT0, ALARM_WAKE_EN(enable));
119 BF_WRX(val, RTC_PERSISTENT0, ALARM_WAKE(0));
120 imx233_rtc_write_persistent(0, val);
121}
122
123/**
124 * Check if alarm caused unit to start.
125 */
126bool rtc_check_alarm_started(bool release_alarm)
127{
128 bool res = BF_RDX(imx233_rtc_read_persistent(0), RTC_PERSISTENT0, ALARM_WAKE);
129 if(release_alarm)
130 rtc_enable_alarm(false);
131 return res;
132}
133
134/**
135 * Checks if an alarm interrupt has triggered since last we checked.
136 */
137bool rtc_check_alarm_flag(void)
138{
139 return BF_RD(RTC_CTRL, ALARM_IRQ);
140}