rtc example with tm1637 driver
authorRobin Krens <robin@robinkrens.nl>
Wed, 14 Aug 2019 14:21:21 +0000 (22:21 +0800)
committerRobin Krens <robin@robinkrens.nl>
Wed, 14 Aug 2019 14:21:21 +0000 (22:21 +0800)
drivers/tm1637.c
include/drivers/tm1637.h
main.c
rtc.c

index b6453ae..1d78f7a 100644 (file)
@@ -84,7 +84,6 @@ void tm1637_reset() {
  * grid. Grid 1 an 2 have an additional dot that can be set */
 int set_grid(uint8_t offset, char value, bool dot) {
 
-       //int (*ack)() = ack_recv; /* Scary function pointer :D */
 
        if (offset > 3) {
                printf("Offset incorrect");
@@ -118,13 +117,21 @@ int set_grid(uint8_t offset, char value, bool dot) {
 
        tm1637_reset();
 
+
+       int (*ack)() = &ack_recv;
+        if ((((value >> 4) & 0xF) == 0xF ) && !(value & 0x08)) {
+               ack = &ack10_recv;
+       }
+       
        /* Write value to segments */
        start_condition();
        rwrite(I2C_DR, value);
-       if(!ack_recv())
-               return -1;
-       stop_condition(); 
+       if(!ack()) {
+       //      return -1;
+       }
 
+       stop_condition(); 
+       delay(); // wait for the chip to finish writing
        tm1637_reset();
 
        return 0;
@@ -145,27 +152,20 @@ int set_display(bool on, uint8_t degree) {
                return -1;
        }
        stop_condition();
-
        tm1637_reset();
 
        return 0;
-
 }
 
-
 void tm1637_example() {
 
-unsigned char display_number[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
-
-
+       unsigned char dn[10] = {0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE0, 0xFE, 0xF6};
        char love[4]  = { 0x1C, 0xFC, 0x7C, 0x9E };
-       
+               
        for (int i = 0; i < 4; i++) {
                set_grid(i, love[i], NODOT);
        }
 
-       set_display(true, 0);
-
 }
 
 /* HELPER ROUTINES */
@@ -207,6 +207,14 @@ int ack10_recv() {
 
 }
 
+/* Write delay chip */
+static void delay() {
+        int a = 0;
+        for (int i = 0; i < 500; i++)
+                a++;
+}
+
+
 /* Check if lines are idle (i.e. stop condition finished)*/
 int idle() {
        int cnt = 0;
index e537cdf..64e1f78 100644 (file)
@@ -7,10 +7,12 @@ static void stop_condition();
 static int ack_recv();
 static int ack10_recv();
 static int idle();
+static void delay();
 
 extern void tm1637_init();
 extern int set_grid(uint8_t offset, char value, bool dot);
 extern int set_display(bool on, uint8_t degree);
+
 extern void tm1637_example();
 
 #endif
diff --git a/main.c b/main.c
index 68eaa03..da28711 100644 (file)
--- a/main.c
+++ b/main.c
@@ -69,10 +69,10 @@ void main()
        led_init();
 //     eeprom_at24c_init();
 //     eeprom_test();
+       tm1637_init();
+
        rtc_init();
 
-       tm1637_init();
-       tm1637_example();
 
        //uint32_t test = hextoreg("12345678");
                
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