Gerrod Ubben / Mbed 2 deprecated ECE4180_Final_Project

Dependencies:   mbed mbed-rtos 4DGL-uLCD-SE RPCInterface

Revision:
14:5b3f49d7bf19
Parent:
13:f1649dc31b04
Child:
15:5120c88a7a87
--- a/main.cpp	Tue Nov 12 19:27:35 2019 +0000
+++ b/main.cpp	Wed Dec 04 01:55:03 2019 +0000
@@ -3,50 +3,142 @@
 
 #include "mbed_rpc.h"
 #include "uLCD_4DGL.h"
+#include <time.h>
+#include <math.h>
 
 /* Example RPC commands that have currently been implemented
 
 /writeLCD/run Hello_world
-/setTime/run 1256729737
+/setTime/run <unix time> <UTC offset (-5 for Atlanta)>
+/setTime/run 1256729737 -5
 
 */
 
+volatile bool display_notification = false;
+volatile bool display_time = true;
+
+volatile int utc_offset; //keeps track of the current timezone of the watch
+
 uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin;
-Serial bluetooth(p13,p14);
+//Serial bluetooth(p13,p14);
 Serial pc(USBTX, USBRX);
 
+InterruptIn view_button(p12);
+
 Mutex stdio_mutex; //mutex used when accessing stdio functions
-Mutex lcd_mutex; //mutex used when accessing the bluetooth serial object
+Mutex lcd_mutex; //mutex used when accessing the lcd object
 
 Thread bluetooth_thread; //thread responsible for receiving rpc commands over bluetooth
 Thread time_thread; //thread responsible for updating the lcd with the current time
 
 //rpc function prototypes
-void writeLCD(Arguments *in, Reply *out);
+void displayNotification(Arguments *in, Reply *out);
 void setTime (Arguments *in, Reply *out);
-RPCFunction rpcWriteLCD(&writeLCD, "writeLCD");
+RPCFunction rpcWriteLCD(&displayNotification, "notify");
 RPCFunction rpcSetTime(&setTime, "setTime");
 
+//interrupt routine for when the input button is pressed
+void view_button_pressed(void){
+    display_notification = false;
+    display_time = true;
+}
+
+//flip the y coordinate around so that standard cartesian coordinates can be used
+int flipy(int y_coord){
+ return (128-y_coord);
+}
+
+#define C_X 64
+#define C_Y 64
+#define M_PI 3.141592
+//create the tick marks for an analog clock on the lcd display
+void setup_analog_clock(uint32_t color){
+     
+     lcd_mutex.lock();
+     uLCD.filled_circle(64, 64, 5, color); //centercircle
+     double angle;
+     //start from 3 oclock and draw all the clock tick marks counter-clockwise
+     for(angle = 0; angle < (2*M_PI)-(M_PI/12); angle += M_PI/6){
+         uLCD.line(54*cos(angle)+C_X,flipy(54*sin(angle)+C_Y), 64*cos(angle)+C_X,flipy(64*sin(angle)+C_Y), color); //3 oclock tick mark
+     }
+    lcd_mutex.unlock();
+    
+}
+
+#define RAD_PER_SEC (2*M_PI)/60
+#define RAD_PER_MIN (2*M_PI)/60
+#define RAD_PER_HOUR (2*M_PI)/12
+//create the second, minute, and hour hands for an analog clock on the lcd display
+void show_time_analog(int sec, int minute, int hour, int day, int month, int year, uint32_t sec_color, uint32_t min_color, uint32_t hour_color, uint32_t back_color) {
+    static double angle;
+    static int prev_sec;
+    static int prev_minute;
+    static int prev_hour;
+    
+    lcd_mutex.lock();
+    
+    //tear down the previous hands that were drawn
+    angle = -(RAD_PER_SEC*prev_sec) + M_PI/2;
+    uLCD.line(C_X,C_Y,64*cos(angle)+C_X, flipy(64*sin(angle)+C_Y),back_color);
+    
+    angle = -(RAD_PER_MIN*prev_minute) + M_PI/2;
+    uLCD.line(C_X,C_Y,52*cos(angle)+C_X, flipy(52*sin(angle)+C_Y),back_color);
+    
+    angle = -(RAD_PER_HOUR*prev_hour) + M_PI/2;
+    uLCD.line(C_X,C_Y,40*cos(angle)+C_X, flipy(40*sin(angle)+C_Y),back_color);
+    
+    //draw the new hands
+    angle = -(RAD_PER_SEC*sec) + M_PI/2;
+    uLCD.line(C_X,C_Y,64*cos(angle)+C_X, flipy(64*sin(angle)+C_Y),sec_color);
+    
+    angle = -(RAD_PER_MIN*minute) + M_PI/2;
+    uLCD.line(C_X,C_Y,52*cos(angle)+C_X, flipy(52*sin(angle)+C_Y),min_color);
+    
+    angle = -(RAD_PER_HOUR*hour) + M_PI/2;
+    uLCD.line(C_X,C_Y,40*cos(angle)+C_X, flipy(40*sin(angle)+C_Y),hour_color);
+    
+    stdio_mutex.lock();
+    
+    //print the current date in a month/day/year format
+    //uLCD.locate(4,10);
+    //uLCD.printf("        ");
+    uLCD.locate(4,10);
+    uLCD.printf("%2d/%2d/%4d",month, day, year);
+    uLCD.locate(8,11);
+    if (hour < 12) {uLCD.printf("AM");}
+    else {uLCD.printf("PM");}
+    
+    stdio_mutex.unlock();
+    lcd_mutex.unlock();
+    
+    //store the location of the current hands
+    prev_sec = sec;
+    prev_minute = minute;
+    prev_hour = hour;
+  
+}
 
 void time_thread_func() {
- 
+    struct tm * t; //time struct defined in time.h
+    static time_t unix_time;
+    static bool prev_display_time;
+    
     while (true) {
-        time_t seconds = time(NULL);
-        
-        stdio_mutex.lock();
-        lcd_mutex.lock();
-        
-        uLCD.locate(0,0);
-        uLCD.printf("%s", ctime(&seconds)); //Time as a basic string
-        
-        stdio_mutex.unlock();
-        lcd_mutex.unlock();
-        
-        //printf("Time as seconds since January 1, 1970 = %d\n", seconds);
- 
-        //char buffer[32];
-        //strftime(buffer, 32, "%I:%M %p\n", localtime(&seconds));
-        //printf("Time as a custom formatted string = %s", buffer);
+        if (display_time == true) {
+            if (prev_display_time == false){ //clear whatever was previously on the screen
+                lcd_mutex.lock();
+                uLCD.cls();
+                lcd_mutex.unlock(); 
+            }
+            unix_time = time(NULL);
+            t = localtime(&unix_time);
+
+            setup_analog_clock(WHITE);
+            int hour = (t->tm_hour + utc_offset);
+            if (hour < 0){ hour += 24;}
+            show_time_analog(t->tm_sec,t->tm_min,hour,t->tm_mday,t->tm_mon+1,t->tm_year+1900,RED+BLUE,WHITE,BLUE,BLACK);
+        }
+        prev_display_time = display_time;
         
         Thread::wait(1000); //only update every second
     }
@@ -96,20 +188,26 @@
 
 int main() {
     
+    uLCD.baudrate(3000000); //jack up baud rate to max for fast display
+    view_button.mode(PullUp);
+    view_button.fall(&view_button_pressed);
+    
+    
     bluetooth_thread.start(bluetooth_thread_func);
     time_thread.start(time_thread_func);
 
 }
 
-
 // Make sure the method takes in Arguments and Reply objects.
 void setTime (Arguments *in, Reply *out)   {
     static const char * unix_time_str;
     uint32_t unix_time;
-    
+    int offset;
     //set_time(1256729737);  // Set RTC time to Wed, 28 Oct 2009 11:35:37
     unix_time_str = in->getArg<const char*>(); //get a pointer to the location where the argument string is stored
+    offset = in->getArg<int>();
     unix_time = atoll(unix_time_str);
+    utc_offset = offset;
     
     set_time(unix_time);  // Set RTC time to Wed, 28 Oct 2009 11:35:37
     
@@ -117,16 +215,36 @@
 
 
 // Make sure the method takes in Arguments and Reply objects.
-void writeLCD (Arguments *in, Reply *out)   {
+void displayNotification (Arguments *in, Reply *out)   {
+    static char display_str[18];
     static const char * msg_str;
+    int i,j;
+    bool break_out = false;
+    
+    display_notification = true;
+    display_time = false;
     
     msg_str = in->getArg<const char*>(); //get a pointer to the location where the argument string is stored
     
     stdio_mutex.lock();
     lcd_mutex.lock();
     
-    uLCD.locate(0,2);
-    uLCD.printf("%s\r\n",msg_str);
+    uLCD.cls();
+    uLCD.locate(0,0);
+    i = 0;
+    while(true){
+        for(j=0; j<18; j++){
+            if (msg_str[i+j] == '_'){
+                display_str[j] = ' ';
+            } else {
+                display_str[j] = msg_str[i+j];
+            }
+            if (msg_str[i+j] == '\0') {break_out = true; break;}
+        }
+        i+= 18;
+        uLCD.printf("%s\r\n",display_str);
+        if (break_out){break;}
+    }
     
     stdio_mutex.unlock();
     lcd_mutex.unlock();