FRDM-KL46Z clock based on Paul Staron's FRDM-KL46Z-LCD-rtc-demo. Uses the on-board touch slider to set hours, minutes and seconds.

Dependencies:   SLCD TSI mbed-src

Fork of FRDM-KL46Z LCD rtc Demo by Paul Staron

After the instructions have finished scrolling across the LCD, press SW3 to cycle between, SET_HOURS, SET_MINUTES, SET_SECONDS and SHOW_TIME modes.

In (e.g.) SET_HOURS mode, press the capacitive touch slider (TSI), releasing when the LCD shows the correct hour (24H clock).

Files at this revision

API Documentation at this revision

Comitter:
tmorgan
Date:
Mon Feb 24 20:48:50 2014 +0000
Parent:
1:34f0bfc62803
Commit message:
Initial release.

Changed in this revision

TSI.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TSI.lib	Mon Feb 24 20:48:50 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/vsluiter/code/TSI/#4dc2f5a3a731
--- a/main.cpp	Mon Jan 27 21:58:45 2014 +0000
+++ b/main.cpp	Mon Feb 24 20:48:50 2014 +0000
@@ -1,136 +1,234 @@
+/*
+ * LCD code based on FRDM-KL46Z-LCD-rtc-Demo by Paul Staron.
+ * Touch slider code based on serialSENS by Aaron Huang.
+ */
 #include "mbed.h"
 #include "SLCD.h"
+#include "TSISensor.h"
 
-time_t seconds = time(NULL); // needed to start rtc on reset to maintain reasonable time if hard reset
+// Peripherals
+SLCD        sLCD;
+Serial      pc(USBTX, USBRX);
+TSISensor   tsi;
+DigitalOut  greenLED(LED1);
+DigitalOut  redLED(LED2);
+InterruptIn setModeSwitch (SW3);
+
+// FUNCTION-MODES
+// In SET_HOURS mode, wait for slider touch to set hours, or SW3 press to enter SET_MINUTES mode.
+// In SET_MINUTES mode, wait for slider touch to set minutes, or SW3 press to enter SET_SECONDS mode.
+// In SET_SECONDS mode, wait for slider touch to set seconds, or SW3 press to enter SHOW_TIME mode.
+// In SHOW_TIME mode, advance display state every seconds, or, on SW3 press, enter SET_HOURS mode.
+#define SET_HOURS   0
+#define SET_MINUTES 1
+#define SET_SECONDS 2
+#define SHOW_TIME   3
+int function_mode;
+
+// TIME-DISPLAY STATES
+// Show HH:MM from state SHOW_HHMM to state SHOW_SS,
+// Show   :SS from state SHOW_SS to state SHOW_LOOP
+#define SHOW_HHMM   0
+#define SHOW_SS     5
+#define SHOW_LOOP   10
+int display_state;
+
+char LCDbuffer[32];
+
+// Scroll instructions across the LCD
+void scroll_message(void)
+{
+    char message[60] = "    Press SW3 and touch slider to set time    ";
+    
+    for (int start = 0; start < strlen(message) - 4; start++)
+    {
+        for (int digit = 0; digit < 4; digit++)
+            sLCD.putc(message[start + digit]);
+        wait(0.25);
+    }
+}
 
-SLCD slcd;
-Timer scroll;
-DigitalOut  led1(LED1);
-DigitalOut  led2(LED2);
-InterruptIn setmin (SW1);
-InterruptIn sethour (SW3);
+// Set Real-time Clock HH:MM:SS
+void set_HHMMSS(int hours, int minutes, int seconds)
+{
+    struct tm t;
+    
+    if(hours > 23) hours = 0;
+    if(minutes > 59) minutes = 0;
+    t.tm_sec = seconds;
+    t.tm_min = minutes;
+    t.tm_hour = hours;
+    t.tm_mday = 23;
+    t.tm_mon = 2;
+    t.tm_year = 114;
+    set_time (mktime(&t));
+}
+
+// Read Real-time Clock HH:MM:SS
+void get_HHMMSS(int *hours, int *minutes, int *seconds)
+{
+    time_t rtcTime = time(NULL);
+    struct tm *t = localtime(&rtcTime);
+    *hours = t->tm_hour;
+    *minutes = t->tm_min;
+    *seconds = t->tm_sec;
+}
+
+// On SW3 press, cycle between function-modes
+void setMode(void)
+{
+    if (function_mode == SET_HOURS)
+        function_mode = SET_MINUTES;
+    else if (function_mode == SET_MINUTES)
+        function_mode = SET_SECONDS;
+    else if (function_mode == SET_SECONDS)
+        function_mode = SHOW_TIME;
+    else if (function_mode == SHOW_TIME)
+        function_mode = SET_HOURS;
+}
+
+// Wait for slider to be pressed (or mode change)
+void waitForTouch(int mode)
+{
+    redLED = 0;
+    while(tsi.readDistance() == 0 && function_mode == mode)
+    {
+        wait(0.2);
+        redLED = !redLED;
+    }
+    redLED = 1;
+}
 
-struct tm t;
+// Wait for slider to be released and return slider value between 0 and <scale>
+int waitForRelease(char *label, int scale)
+{
+    float pct;
+    int return_value = 0;
+    
+    greenLED = 0;
+    while((pct = tsi.readPercentage()) != 0)
+    {
+        // In practice, readPercentage returns a number in the range 0.06..0.99
+        // Stretch it to 0.00..0.99 before applying scale.
+        pct = (pct - 0.09)/ 0.90;
+        if (pct < 0.0) pct = 0.0;
+        return_value = scale * pct;
+        sLCD.printf("%2s%2i", label, return_value);
+        wait(0.2);
+        greenLED = !greenLED;
+    }
+    greenLED = 1;
+    return return_value;
+}
+
+// If slider is touched, update hours
+void setHours(void)
+{
+    int hours, minutes, seconds;
+
+    get_HHMMSS(&hours, &minutes, &seconds);
+    sLCD.printf("HH%2i", hours);
+    waitForTouch(SET_HOURS);
+    if (function_mode == SET_HOURS)
+    {
+        hours = waitForRelease("HH",24);
+        pc.printf("Setting hours to %i\r\n", hours);
+        set_HHMMSS(hours, minutes, seconds);
+        function_mode = SHOW_TIME;
+        display_state = SHOW_HHMM;
+    }
+}
 
-int i,j,k,lastscroll,display_timer,minute,hour,colon,dp;
-char message[60];
-void scroll_message();
-char buffer[32];
+// If slider is touched, update minutes
+void setMinutes(void)
+{
+    int hours, minutes, seconds;
+    
+    get_HHMMSS(&hours, &minutes, &seconds);
+    sLCD.printf("MM%2i", minutes);
+    waitForTouch(SET_MINUTES);
+    if (function_mode == SET_MINUTES)
+    {
+        minutes = waitForRelease("MM",60);
+        pc.printf("Setting minutes to %i\r\n", minutes);
+        set_HHMMSS(hours, minutes, seconds);
+        function_mode = SHOW_TIME;
+        display_state = SHOW_HHMM;
+    }
+}
 
-void setminIRQ();
-void sethourIRQ();
+// If slider is touched, update seconds
+void setSeconds(void)
+{
+    int hours, minutes, seconds;
+    
+    get_HHMMSS(&hours, &minutes, &seconds);
+    sLCD.printf("SS%2i", seconds);
+    waitForTouch(SET_SECONDS);
+    if (function_mode == SET_SECONDS)
+    {
+        seconds = waitForRelease("SS",60);
+        pc.printf("Setting seconds to %i\r\n", seconds);
+        set_HHMMSS(hours, minutes, seconds);
+        function_mode = SHOW_TIME;
+        display_state = SHOW_SS;
+    }
+}
 
+// Cycle between time-display states
+// In states SHOW_HHMM to SHOW_SS - 1, display HH:MM & flash green LED.
+// In states SHOW_SS to SHOW_LOOP, display :SS & flash red LED.
+void showTime(void)
+{
+    DigitalOut *flashLED;
+    time_t rtcTime = time(NULL);
+    
+    if(display_state < SHOW_SS)
+    {
+        strftime(LCDbuffer, 4, "%H%M", localtime(&rtcTime));// display HH:MM 
+        flashLED = &greenLED;                               // while flashing green LED
+    }
+    else
+    {
+        strftime(LCDbuffer, 4, "  %S", localtime(&rtcTime));// display :SS           
+        flashLED = &redLED;                                 // while flashing red LED
+    }
+    sLCD.printf(LCDbuffer);     // Send to LCD
+    redLED = 1; greenLED = 1;   // Both LEDs off
+    wait(0.5);
+    *flashLED = 0;              // Red or Green on.
+    wait(0.5);
+    redLED = 1; greenLED = 1;   // Both LEDs off.
+    if (function_mode == SHOW_TIME) display_state++;        // Increment display counter if no switch pressed
+    if (display_state > SHOW_LOOP) display_state = SHOW_HHMM;
+}
 
 main()
 {
-    slcd.All_Segments(1);
-    wait(2);
-    slcd.All_Segments(0);
-    wait(1);    
+    pc.printf("\r\n\nFRDM-KL46Z Clock\r\n");
     
-    led1 = 1;led2 = 1;
-    
-    sprintf(message, "    rtc clock    s3 sets the hours    s1 sets the minutes");
+    sLCD.All_Segments(1); wait(1);  // Flash LCD segments
+    sLCD.All_Segments(0); wait(1);    
     
-// scrolling message    
-    scroll.start();
-    while (i<58) {
-
-        while (i<58) {
-            scroll_message();
-         }
-    }
-    wait(1);
+    greenLED = 1; redLED = 1;       // Both LEDs off
+    
+    scroll_message();               // Display instructions
+    
+    setModeSwitch.rise(setMode);    // Enable setMode interrupt handler
     
-    setmin.rise(setminIRQ);     // start set Minutes IRQ
-    sethour.rise(sethourIRQ);   // start set Hours IRQ
-    
-// rtc clock function    
-    while(1) {
-
-        time_t seconds = time(NULL);
-
-        if(display_timer>6) {
-            strftime(buffer, 4, "%H%M", localtime(&seconds));// display Hours,Minutes for 2 seconds
-            slcd.Colon(1);led2=0;
-            slcd.DP2(0);led1=1;
-        } else {
-            strftime(buffer, 4, "%M%S", localtime(&seconds));// display Minutes,Seconds for 8 seconds            
-            slcd.Colon(0);led2=1;
-            slcd.DP2(1);led1=0;
-        }
-        slcd.printf(buffer);
-        wait(.5);
-        slcd.DP2(0);led1=1;
-        display_timer++;
-        if (display_timer>9)display_timer=0;
-        wait(.5);
+    sLCD.Colon(1); sLCD.DP2(0);
+    function_mode = SHOW_TIME;
+    while(1)
+    {
+        if (function_mode == SET_HOURS)
+            setHours();
+        else if (function_mode == SET_MINUTES)
+            setMinutes();
+        else if (function_mode == SET_SECONDS)
+            setSeconds();
+        else if (function_mode == SHOW_TIME)
+            showTime();
     }
 }
 
-void scroll_message()
-{
-    if (scroll.read_ms() > lastscroll + 350) {
-        scroll.reset();
-        if (i > 58) {
-            i=0;
-        }
-        int j, k = i;
-        for (j = 0; j < 4; j++) {
-            if (message[k+j]) {
-                slcd.putc(message[k+j]);
-            } else {
-                slcd.putc(' ');
-                k--;
-            }
-        }
-        i++;
-        lastscroll=scroll.read_ms();
-    }
-}
 
-void setminIRQ(void) // set Minutes ISR
-{
-    display_timer=7;
-    time_t seconds = time(NULL);
-    char buffer[2];
-    strftime(buffer, 2,"%H", localtime(&seconds));
-    hour = atoi(buffer);    // get Hour integer
-    strftime(buffer, 2,"%M", localtime(&seconds));
-    minute = atoi(buffer);  // get Minutes integer
-    minute++;
-    if(minute>59) minute=0;
-    t.tm_sec = 0;   // Seconds reset to zero
-    t.tm_min = minute;
-    t.tm_hour = hour;
-    t.tm_mday = 1;
-    t.tm_mon = 2;
-    t.tm_year = 114;
-    set_time (mktime(&t));
-
-}
-
-void sethourIRQ(void) // set Hours ISR
-{
-    display_timer=7;
-    time_t seconds = time(NULL);
-    char buffer[2];
-    strftime(buffer, 2,"%H", localtime(&seconds));
-    hour = atoi(buffer);    // get Hour integer
-    strftime(buffer, 2,"%M", localtime(&seconds));
-    minute = atoi(buffer);  // get Minutes integer
-    hour++;
-    if(hour>23) hour=0;
-    t.tm_sec = 0;   // Seconds reset to zero
-    t.tm_min = minute;
-    t.tm_hour = hour;
-    t.tm_mday = 1;
-    t.tm_mon = 2;
-    t.tm_year = 114;
-    set_time (mktime(&t));
-
-}
-
-
-
-