diff options
-rw-r--r-- | firmware/common/timefuncs.c | 45 | ||||
-rw-r--r-- | firmware/drivers/rtc/rtc_mc13783.c | 13 | ||||
-rw-r--r-- | firmware/export/config.h | 10 | ||||
-rw-r--r-- | firmware/target/arm/as3525/ascodec-as3525.c | 35 | ||||
-rw-r--r-- | firmware/target/arm/as3525/rtc-target.h | 27 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/mc13783-target.h | 4 | ||||
-rw-r--r-- | firmware/target/arm/imx31/rtc-target.h | 27 |
7 files changed, 140 insertions, 21 deletions
diff --git a/firmware/common/timefuncs.c b/firmware/common/timefuncs.c index c8819ea76e..50addad27a 100644 --- a/firmware/common/timefuncs.c +++ b/firmware/common/timefuncs.c | |||
@@ -24,13 +24,21 @@ | |||
24 | 24 | ||
25 | #include "kernel.h" | 25 | #include "kernel.h" |
26 | #include "rtc.h" | 26 | #include "rtc.h" |
27 | #ifdef HAVE_RTC_IRQ | ||
28 | #include "rtc-target.h" | ||
29 | #endif | ||
27 | #include "timefuncs.h" | 30 | #include "timefuncs.h" |
28 | #include "debug.h" | 31 | #include "debug.h" |
29 | 32 | ||
30 | static struct tm tm; | 33 | static struct tm tm; |
31 | 34 | ||
32 | #if !CONFIG_RTC | 35 | #if !CONFIG_RTC |
33 | static void fill_default_tm(struct tm *tm) | 36 | static inline bool rtc_dirty(void) |
37 | { | ||
38 | return true; | ||
39 | } | ||
40 | |||
41 | static inline int rtc_read_datetime(struct tm *tm) | ||
34 | { | 42 | { |
35 | tm->tm_sec = 0; | 43 | tm->tm_sec = 0; |
36 | tm->tm_min = 0; | 44 | tm->tm_min = 0; |
@@ -38,9 +46,9 @@ static void fill_default_tm(struct tm *tm) | |||
38 | tm->tm_mday = 1; | 46 | tm->tm_mday = 1; |
39 | tm->tm_mon = 0; | 47 | tm->tm_mon = 0; |
40 | tm->tm_year = 70; | 48 | tm->tm_year = 70; |
41 | tm->tm_wday = 1; | 49 | tm->tm_wday = 4; |
42 | tm->tm_yday = 0; /* Not implemented for now */ | 50 | tm->tm_yday = 0; |
43 | tm->tm_isdst = -1; /* Not implemented for now */ | 51 | return 1; |
44 | } | 52 | } |
45 | #endif /* !CONFIG_RTC */ | 53 | #endif /* !CONFIG_RTC */ |
46 | 54 | ||
@@ -58,24 +66,37 @@ bool valid_time(const struct tm *tm) | |||
58 | else | 66 | else |
59 | return true; | 67 | return true; |
60 | } | 68 | } |
61 | #endif /* CONFIG_RTC */ | ||
62 | 69 | ||
63 | struct tm *get_time(void) | 70 | /* Don't read the RTC more than once per second |
71 | * returns true if the rtc needs to be read | ||
72 | * targets may override with their own implementation | ||
73 | */ | ||
74 | #ifndef HAVE_RTC_IRQ | ||
75 | static inline bool rtc_dirty(void) | ||
64 | { | 76 | { |
65 | #if CONFIG_RTC | ||
66 | static long timeout = 0; | 77 | static long timeout = 0; |
67 | 78 | ||
68 | /* Don't read the RTC more than once per second */ | 79 | /* Don't read the RTC more than once per second */ |
69 | if (TIME_AFTER(current_tick, timeout)) | 80 | if (TIME_AFTER(current_tick, timeout)) |
70 | { | 81 | { |
71 | /* Once per second, 1/10th of a second off */ | 82 | /* Once per second, 1/5th of a second off */ |
72 | timeout = HZ * (current_tick / HZ + 1) + HZ / 5; | 83 | timeout = current_tick / HZ * HZ + 6*HZ / 5; |
84 | return true; | ||
85 | } | ||
86 | |||
87 | return false; | ||
88 | } | ||
89 | #endif /* HAVE_RTC_IRQ */ | ||
90 | #endif /* CONFIG_RTC */ | ||
91 | |||
92 | struct tm *get_time(void) | ||
93 | { | ||
94 | if (rtc_dirty()) | ||
95 | { | ||
73 | rtc_read_datetime(&tm); | 96 | rtc_read_datetime(&tm); |
74 | tm.tm_isdst = -1; /* Not implemented for now */ | 97 | tm.tm_isdst = -1; /* Not implemented for now */ |
75 | } | 98 | } |
76 | #else /* No RTC */ | 99 | |
77 | fill_default_tm(&tm); | ||
78 | #endif /* RTC */ | ||
79 | return &tm; | 100 | return &tm; |
80 | } | 101 | } |
81 | 102 | ||
diff --git a/firmware/drivers/rtc/rtc_mc13783.c b/firmware/drivers/rtc/rtc_mc13783.c index a1f78f738d..aedf5f6fa5 100644 --- a/firmware/drivers/rtc/rtc_mc13783.c +++ b/firmware/drivers/rtc/rtc_mc13783.c | |||
@@ -69,6 +69,7 @@ static const unsigned char rtc_registers[RTC_NUM_REGS_RD] = | |||
69 | 69 | ||
70 | /* was it an alarm that triggered power on ? */ | 70 | /* was it an alarm that triggered power on ? */ |
71 | static bool alarm_start = false; | 71 | static bool alarm_start = false; |
72 | static unsigned long rtc_is_dirty = 1; /* force a read right away */ | ||
72 | 73 | ||
73 | static const unsigned short month_table[13] = | 74 | static const unsigned short month_table[13] = |
74 | { | 75 | { |
@@ -96,6 +97,16 @@ static bool read_time_and_day(uint32_t regs[RTC_NUM_REGS_RD]) | |||
96 | return true; | 97 | return true; |
97 | } | 98 | } |
98 | 99 | ||
100 | void MC13783_EVENT_CB_1HZ(void) | ||
101 | { | ||
102 | rtc_is_dirty = 1; | ||
103 | } | ||
104 | |||
105 | bool rtc_mc13783_dirty(void) | ||
106 | { | ||
107 | return bitclr32(&rtc_is_dirty, 1); | ||
108 | } | ||
109 | |||
99 | /** Public APIs **/ | 110 | /** Public APIs **/ |
100 | void rtc_init(void) | 111 | void rtc_init(void) |
101 | { | 112 | { |
@@ -105,6 +116,8 @@ void rtc_init(void) | |||
105 | alarm_start = true; | 116 | alarm_start = true; |
106 | mc13783_write(MC13783_INTERRUPT_STATUS1, MC13783_TODAI); | 117 | mc13783_write(MC13783_INTERRUPT_STATUS1, MC13783_TODAI); |
107 | } | 118 | } |
119 | |||
120 | mc13783_enable_event(MC13783_INT_ID_1HZ, true); | ||
108 | } | 121 | } |
109 | 122 | ||
110 | int rtc_read_datetime(struct tm *tm) | 123 | int rtc_read_datetime(struct tm *tm) |
diff --git a/firmware/export/config.h b/firmware/export/config.h index 475bd573d4..a4f0ea94fd 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h | |||
@@ -742,6 +742,16 @@ Lyre prototype 1 */ | |||
742 | #endif /* CONFIG_RDS */ | 742 | #endif /* CONFIG_RDS */ |
743 | #endif /* HAVE_RDS_CAP */ | 743 | #endif /* HAVE_RDS_CAP */ |
744 | 744 | ||
745 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
746 | #if CONFIG_RTC == RTC_AS3514 | ||
747 | #if CONFIG_CPU == AS3525 || CONFIG_CPU == AS3525v2 | ||
748 | #define HAVE_RTC_IRQ | ||
749 | #endif | ||
750 | #elif CONFIG_RTC == RTC_MC13783 | ||
751 | #define HAVE_RTC_IRQ | ||
752 | #endif | ||
753 | #endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) */ | ||
754 | |||
745 | #ifndef CONFIG_ORIENTATION | 755 | #ifndef CONFIG_ORIENTATION |
746 | #if LCD_HEIGHT > LCD_WIDTH | 756 | #if LCD_HEIGHT > LCD_WIDTH |
747 | #define CONFIG_ORIENTATION SCREEN_PORTRAIT | 757 | #define CONFIG_ORIENTATION SCREEN_PORTRAIT |
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c index 1bd07c57b1..a8ad9706f8 100644 --- a/firmware/target/arm/as3525/ascodec-as3525.c +++ b/firmware/target/arm/as3525/ascodec-as3525.c | |||
@@ -131,6 +131,16 @@ static unsigned long ascodec_enrd0_shadow = 0; | |||
131 | 131 | ||
132 | static void ascodec_wait_cb(struct ascodec_request *req); | 132 | static void ascodec_wait_cb(struct ascodec_request *req); |
133 | 133 | ||
134 | /* RTC interrupt and status | ||
135 | * Caution: To avoid an extra variable, IRQ_RTC is used as a flag for | ||
136 | * ascodec_enrd0_shadow, which conflicts with RVDD_WASLOW, but we're not using | ||
137 | * that right now */ | ||
138 | #if CONFIG_RTC | ||
139 | #define IFRTC_IRQ_RTC IRQ_RTC | ||
140 | #else /* !CONFIG_RTC */ | ||
141 | #define IFRTC_IRQ_RTC 0 | ||
142 | #endif /* CONFIG_RTC */ | ||
143 | |||
134 | /** --debugging help-- **/ | 144 | /** --debugging help-- **/ |
135 | 145 | ||
136 | #ifdef DEBUG | 146 | #ifdef DEBUG |
@@ -149,7 +159,6 @@ static struct int_audio_counters { | |||
149 | 159 | ||
150 | #define COUNT_INT(x) IFDEBUG((int_audio_counters.int_##x)++) | 160 | #define COUNT_INT(x) IFDEBUG((int_audio_counters.int_##x)++) |
151 | 161 | ||
152 | |||
153 | /** --stock request and callback functionality -- **/ | 162 | /** --stock request and callback functionality -- **/ |
154 | 163 | ||
155 | /* init for common request data (call before submitting) */ | 164 | /* init for common request data (call before submitting) */ |
@@ -510,13 +519,12 @@ static void ascodec_int_audio_cb(struct ascodec_request *req) | |||
510 | } | 519 | } |
511 | } | 520 | } |
512 | 521 | ||
522 | #if CONFIG_RTC | ||
513 | if (data[2] & IRQ_RTC) { /* rtc irq */ | 523 | if (data[2] & IRQ_RTC) { /* rtc irq */ |
514 | /* | 524 | ascodec_enrd0_shadow |= IRQ_RTC; |
515 | * Can be configured for once per second or once per minute, | ||
516 | * default is once per second | ||
517 | */ | ||
518 | COUNT_INT(rtc); | 525 | COUNT_INT(rtc); |
519 | } | 526 | } |
527 | #endif /* CONFIG_RTC */ | ||
520 | 528 | ||
521 | if (data[2] & IRQ_ADC) { /* adc finished */ | 529 | if (data[2] & IRQ_ADC) { /* adc finished */ |
522 | COUNT_INT(adc); | 530 | COUNT_INT(adc); |
@@ -580,6 +588,14 @@ int ascodec_read_charger(void) | |||
580 | } | 588 | } |
581 | #endif /* CONFIG_CHARGING */ | 589 | #endif /* CONFIG_CHARGING */ |
582 | 590 | ||
591 | #if CONFIG_RTC | ||
592 | /* read sticky rtc dirty status */ | ||
593 | bool ascodec_rtc_dirty(void) | ||
594 | { | ||
595 | return bitclr32(&ascodec_enrd0_shadow, IRQ_RTC) & IRQ_RTC; | ||
596 | } | ||
597 | #endif /* CONFIG_RTC */ | ||
598 | |||
583 | /* | 599 | /* |
584 | * NOTE: | 600 | * NOTE: |
585 | * After the conversion to interrupts, ascodec_(lock|unlock) are only used by | 601 | * After the conversion to interrupts, ascodec_(lock|unlock) are only used by |
@@ -635,8 +651,9 @@ void ascodec_init(void) | |||
635 | VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO; | 651 | VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO; |
636 | VIC_INT_ENABLE = INTERRUPT_AUDIO; | 652 | VIC_INT_ENABLE = INTERRUPT_AUDIO; |
637 | 653 | ||
638 | /* detect if USB was connected at startup since there is no transition */ | 654 | /* detect if USB was connected at startup since there is no transition; |
639 | ascodec_enrd0_shadow = ascodec_read(AS3514_IRQ_ENRD0); | 655 | force an initial read of the clock (if CONFIG_RTC) */ |
656 | ascodec_enrd0_shadow = ascodec_read(AS3514_IRQ_ENRD0) | IFRTC_IRQ_RTC; | ||
640 | if(ascodec_enrd0_shadow & USB_STATUS) | 657 | if(ascodec_enrd0_shadow & USB_STATUS) |
641 | usb_insert_int(); | 658 | usb_insert_int(); |
642 | 659 | ||
@@ -651,10 +668,10 @@ void ascodec_init(void) | |||
651 | /* XIRQ = IRQ, active low reset signal, 6mA push-pull output */ | 668 | /* XIRQ = IRQ, active low reset signal, 6mA push-pull output */ |
652 | ascodec_write_pmu(0x1a, 3, (1<<2)|3); /* 1A-3 = Out_Cntr3 register */ | 669 | ascodec_write_pmu(0x1a, 3, (1<<2)|3); /* 1A-3 = Out_Cntr3 register */ |
653 | /* Generate irq on (rtc,) adc change */ | 670 | /* Generate irq on (rtc,) adc change */ |
654 | ascodec_write(AS3514_IRQ_ENRD2, /*IRQ_RTC |*/ IRQ_ADC); | 671 | ascodec_write(AS3514_IRQ_ENRD2, IFRTC_IRQ_RTC | IRQ_ADC); |
655 | #else | 672 | #else |
656 | /* Generate irq for push-pull, active high, irq on rtc+adc change */ | 673 | /* Generate irq for push-pull, active high, irq on rtc+adc change */ |
657 | ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE | | 674 | ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE | |
658 | /*IRQ_RTC |*/ IRQ_ADC); | 675 | IFRTC_IRQ_RTC | IRQ_ADC); |
659 | #endif | 676 | #endif |
660 | } | 677 | } |
diff --git a/firmware/target/arm/as3525/rtc-target.h b/firmware/target/arm/as3525/rtc-target.h new file mode 100644 index 0000000000..900aa357d0 --- /dev/null +++ b/firmware/target/arm/as3525/rtc-target.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2017 by Michael Sevakis | ||
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 | #ifndef RTC_TARGET_H | ||
22 | #define RTC_TARGET_H | ||
23 | |||
24 | bool ascodec_rtc_dirty(void); | ||
25 | #define rtc_dirty ascodec_rtc_dirty | ||
26 | |||
27 | #endif /* RTC_TARGET_H */ | ||
diff --git a/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h b/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h index 179c65cad6..4bb148e36c 100644 --- a/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/mc13783-target.h | |||
@@ -46,6 +46,10 @@ static struct spi_node mc13783_spi = | |||
46 | MC13783_EVENT_VECTOR_TBL_START() | 46 | MC13783_EVENT_VECTOR_TBL_START() |
47 | /* ADC conversion complete */ | 47 | /* ADC conversion complete */ |
48 | MC13783_EVENT_VECTOR(ADCDONE, 0) | 48 | MC13783_EVENT_VECTOR(ADCDONE, 0) |
49 | #if CONFIG_RTC | ||
50 | /* RTC tick */ | ||
51 | MC13783_EVENT_VECTOR(1HZ, 0) | ||
52 | #endif /* CONFIG_RTC */ | ||
49 | /* Power button */ | 53 | /* Power button */ |
50 | MC13783_EVENT_VECTOR(ONOFD1, MC13783_ONOFD1S) | 54 | MC13783_EVENT_VECTOR(ONOFD1, MC13783_ONOFD1S) |
51 | /* Main charger detection */ | 55 | /* Main charger detection */ |
diff --git a/firmware/target/arm/imx31/rtc-target.h b/firmware/target/arm/imx31/rtc-target.h new file mode 100644 index 0000000000..b6dc46204d --- /dev/null +++ b/firmware/target/arm/imx31/rtc-target.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2017 by Michael Sevakis | ||
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 | #ifndef RTC_TARGET_H | ||
22 | #define RTC_TARGET_H | ||
23 | |||
24 | bool rtc_mc13783_dirty(void); | ||
25 | #define rtc_dirty rtc_mc13783_dirty | ||
26 | |||
27 | #endif /* RTC_TARGET_H */ | ||