rtc example with tm1637 driver
[cortex-from-scratch] / rtc.c
1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
2  * 
3  * $LOG$
4  * 2019/8/14 - ROBIN KRENS      
5  * Initial version 
6  * 
7  * $DESCRIPTION$
8  * Real Time Clock configuration. A Real Time Clock is configured to use
9  * the more accurate external chrystal (LSE) and ticks at exactly
10  * one second. (Can be further calibrated using a tamper pin)
11  * Each clock tick triggers an interrupt and invokes the real time clock
12  * service routine.
13  *
14  * Note: this is not the Cortex M3/M4 SysTick!
15  * 
16  * */
17
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21
22 #include <sys/robsys.h>
23 #include <sys/mmap.h>
24
25 #include <lib/regfunc.h>
26 #include <lib/tinyprintf.h>
27
28 #include <drivers/led.h>
29 #include <drivers/tm1637.h>
30
31
32 /* This handler is invoked each clock tick. I've included two examples 
33  * one is writing the clock count to a 4 grid led display. Another is a simple LED blink */
34 void * rtc_handler() {
35
36         // Real time clock output on a LED display 
37         int cntvalue = *RTC_CNTL;
38         if (cntvalue < 9999) {
39
40         unsigned char dn[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
41                 
42         int grid0, grid1, grid2, grid3;
43
44         grid0 = cntvalue % 10;
45         grid1 = ((cntvalue % 100) - grid0) / 10;
46         grid2 = ((cntvalue % 1000) - grid0 - grid1) / 100;
47         grid3 = ((cntvalue % 10000) - grid0 - grid1 - grid2) / 1000;
48
49         printf("%d, %d, %d, %d\n", grid0, grid1, grid2, grid3);
50         
51         
52         char current[4] = { dn[grid3], dn[grid2], dn[grid1], dn[grid0] }; 
53
54         //char current[4] = { dn[1], dn[1], dn[1], dn[1] };
55         for (int i = 0; i < 4; i++) {
56                 set_grid(i, current[i], false);
57         }
58
59         set_display(true, 0); 
60         
61         }
62
63         // Simple LED blink 
64         //uint32_t curr = *RTC_CNTL;
65         //int even = *RTC_CNTL % 2;
66         //(!even) ? led_off() : led_on();
67
68         rclrbit(RTC_CRL, 0); /* clear interrupt flag */
69 }
70
71 /* Enable a periodic interrupt. At each clock count a interrupt is triggered
72  * and consequently the handler is invoked. */
73 static void periodic_intr() {
74
75         while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
76         rsetbit(RTC_CRL, 4); // start configure
77         rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt
78         
79         while(!rchkbit(RTC_CRL, 5)); 
80         rwrite(RTC_PRLL, 0x7FFF); // 0x7FFF equals 1 second clock configuration 
81         rclrbit(RTC_CRL, 4); // stop configure
82         while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
83         rsetbit(NVIC_ISER0, 3); // enable in register vector
84 }
85
86 /* Setup the Real time clock to work with the Low speed external 
87  * chrystal (32.768 kHz) */
88 static void setup_rtc() {
89
90         /* Enable PWREN and BKPEN */
91         rsetbit(RCC_APB1ENR, 28);
92         rsetbit(RCC_APB1ENR, 27);
93
94         /* Enable access to backup registers and RTC */
95         rsetbit(PWR_CR, 8);
96
97         rsetbit(RCC_BDCR, 0); /* LSE enable */
98         while(!rchkbit(RCC_BDCR, 1)); /* wait for LSE to come up */
99         
100         rsetbitsfrom(RCC_BDCR, 8, 0x1); /* use LSE as RTC source */
101         rsetbit(RCC_BDCR, 15); /* enable RTC */
102         
103         ivt_set_gate(19, rtc_handler, 0); /* setup interrupt handler */
104
105         //calibrate_rtc(); // uncomment if need, needs TAMPER PIN
106         
107         periodic_intr();// setup periodic interrupt
108
109 }
110
111 /* Function to calibrate the RTC even more accurate. 
112  * Output to a so-called tamper pin. Uncomment if needed */
113 static void calibrate_rtc() {
114                 /* rsetbit(BKP_RTCCR, 7); // enable CC0, 
115         while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
116         rsetbit(RTC_CRL, 4);
117         // Set up and check tamper pin
118         rclrbit(RTC_CRL, 4);
119         while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated */
120 }
121
122 void rtc_init() {
123
124 #ifdef ENABLE_RTC
125         setup_rtc();
126 #endif
127
128 }