rtc example with tm1637 driver
[cortex-from-scratch] / rtc.c
diff --git a/rtc.c b/rtc.c
index 4877d92..1f1136a 100644 (file)
--- a/rtc.c
+++ b/rtc.c
@@ -1,10 +1,17 @@
 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
  * 
  * $LOG$
- * 2019/7/30 - ROBIN KRENS     
+ * 2019/8/14 - ROBIN KRENS     
  * Initial version 
  * 
  * $DESCRIPTION$
+ * Real Time Clock configuration. A Real Time Clock is configured to use
+ * the more accurate external chrystal (LSE) and ticks at exactly
+ * one second. (Can be further calibrated using a tamper pin)
+ * Each clock tick triggers an interrupt and invokes the real time clock
+ * service routine.
+ *
+ * Note: this is not the Cortex M3/M4 SysTick!
  * 
  * */
 
 #include <sys/mmap.h>
 
 #include <lib/regfunc.h>
-#include <lib/stdio.h>
+#include <lib/tinyprintf.h>
 
 #include <drivers/led.h>
+#include <drivers/tm1637.h>
 
 
-static void periodic_intr() {
+/* This handler is invoked each clock tick. I've included two examples 
+ * one is writing the clock count to a 4 grid led display. Another is a simple LED blink */
+void * rtc_handler() {
 
-       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
-       rsetbit(RTC_CRL, 4); // start configure
-       
-       rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt
-       
-       while(!rchkbit(RTC_CRL, 5)); 
+       // Real time clock output on a LED display 
+       int cntvalue = *RTC_CNTL;
+       if (cntvalue < 9999) {
 
-       rwrite(RTC_PRLL, 0x7FFF); // 1 second
-       rclrbit(RTC_CRL, 4); // stop configure
-       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
-       rsetbit(NVIC_ISER0, 3); // enable in register vector
-}
+       unsigned char dn[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
+               
+       int grid0, grid1, grid2, grid3;
 
-static void calibrate_rtc() {
+       grid0 = cntvalue % 10;
+       grid1 = ((cntvalue % 100) - grid0) / 10;
+       grid2 = ((cntvalue % 1000) - grid0 - grid1) / 100;
+        grid3 = ((cntvalue % 10000) - grid0 - grid1 - grid2) / 1000;
 
+       printf("%d, %d, %d, %d\n", grid0, grid1, grid2, grid3);
+       
+       
+       char current[4] = { dn[grid3], dn[grid2], dn[grid1], dn[grid0] }; 
 
-//     rsetbit(BKP_RTCCR, 7); // enable CC0, 
-//     while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
-//     rsetbit(RTC_CRL, 4);
+       //char current[4] = { dn[1], dn[1], dn[1], dn[1] };
+       for (int i = 0; i < 4; i++) {
+               set_grid(i, current[i], false);
+       }
 
-       // Set up and check tamper pin
+       set_display(true, 0); 
        
-//     rclrbit(RTC_CRL, 4);
-//     while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
-}
-
-void * rtc_handler() {
+       }
 
-       //cputs("TICKING IN REAL TIME\n");
+       // Simple LED blink 
        //uint32_t curr = *RTC_CNTL;
-       int even = *RTC_CNTL % 2;
-       (!even) ? led_off() : led_on();
+       //int even = *RTC_CNTL % 2;
+       //(!even) ? led_off() : led_on();
 
-       rclrbit(RTC_CRL, 0);
+       rclrbit(RTC_CRL, 0); /* clear interrupt flag */
 }
 
+/* Enable a periodic interrupt. At each clock count a interrupt is triggered
+ * and consequently the handler is invoked. */
+static void periodic_intr() {
+
+       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+       rsetbit(RTC_CRL, 4); // start configure
+       rsetbit(RTC_CRH, 0); // enable periodic (second) interrupt
+       
+       while(!rchkbit(RTC_CRL, 5)); 
+       rwrite(RTC_PRLL, 0x7FFF); // 0x7FFF equals 1 second clock configuration 
+       rclrbit(RTC_CRL, 4); // stop configure
+       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+       rsetbit(NVIC_ISER0, 3); // enable in register vector
+}
+
+/* Setup the Real time clock to work with the Low speed external 
+ * chrystal (32.768 kHz) */
 static void setup_rtc() {
 
-// TODO: long time to get stable?
        /* Enable PWREN and BKPEN */
        rsetbit(RCC_APB1ENR, 28);
        rsetbit(RCC_APB1ENR, 27);
@@ -77,12 +102,23 @@ static void setup_rtc() {
        
        ivt_set_gate(19, rtc_handler, 0); /* setup interrupt handler */
 
-//     calibrate_rtc(); TODO: TAMPER PIN?
+       //calibrate_rtc(); // uncomment if need, needs TAMPER PIN
        
        periodic_intr();// setup periodic interrupt
 
 }
 
+/* Function to calibrate the RTC even more accurate. 
+ * Output to a so-called tamper pin. Uncomment if needed */
+static void calibrate_rtc() {
+               /* rsetbit(BKP_RTCCR, 7); // enable CC0, 
+       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated
+       rsetbit(RTC_CRL, 4);
+       // Set up and check tamper pin
+       rclrbit(RTC_CRL, 4);
+       while(!rchkbit(RTC_CRL, 5)); // Check last write is terminated */
+}
+
 void rtc_init() {
 
 #ifdef ENABLE_RTC