Haines Todd / Mbed 2 deprecated ECE4180_Final_Project

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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 #include "mbed.h"
00002 #include "rtos.h"
00003 
00004 #include "mbed_rpc.h"
00005 #include "uLCD_4DGL.h"
00006 #include <time.h>
00007 #include <math.h>
00008 #include "chime.h"
00009 
00010 /* Example RPC commands that have currently been implemented
00011 
00012 /notify/run This_is_a_notification_message_that_should_be_displayed_on_the_lcd
00013 /setTime/run <unix time> <UTC offset (-5 for Atlanta)>
00014 /setTime/run 1256729737 -5
00015 
00016 */
00017 
00018 volatile bool display_notification = false;
00019 volatile bool display_time = true;
00020 
00021 volatile int utc_offset; //keeps track of the current timezone of the watch
00022 
00023 uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin;
00024 Serial bluetooth(p28,p27);
00025 Serial pc(USBTX, USBRX);
00026 
00027 InterruptIn view_button(p12);
00028 
00029 Mutex stdio_mutex; //mutex used when accessing stdio functions
00030 Mutex lcd_mutex; //mutex used when accessing the lcd object
00031 
00032 Thread bluetooth_thread; //thread responsible for receiving rpc commands over bluetooth
00033 Thread time_thread; //thread responsible for updating the lcd with the current time
00034 
00035 //rpc function prototypes
00036 void display_notification_rpc_func(Arguments *in, Reply *out);
00037 void set_time_rpc_func (Arguments *in, Reply *out);
00038 RPCFunction rpcWriteLCD(&display_notification_rpc_func, "notify");
00039 RPCFunction rpcset_time_rpc_func(&set_time_rpc_func, "setTime");
00040 
00041 #define sample_freq 16000.0
00042 AnalogOut speaker(p18);
00043 Ticker notification_chime_ticker;
00044 
00045 //interrupt routine to play next audio sample from array in flash
00046 void audio_sample () {
00047     static int i=0;
00048     speaker.write_u16(((uint16_t)data[i]<<7));
00049     i++;
00050     if (i>= sizeof(data)) {
00051         i = 0;
00052         notification_chime_ticker.detach();
00053     }
00054 }
00055 
00056 //interrupt routine for when the input button is pressed
00057 //when the view button is pressed, dismiss the currently shown notification and display the current time
00058 void view_button_pressed(void){
00059     display_notification = false;
00060     display_time = true;
00061 }
00062 
00063 //flip the y coordinate around so that standard cartesian coordinates can be used
00064 int flipy(int y_coord){
00065  return (128-y_coord);
00066 }
00067 
00068 #define C_X 64
00069 #define C_Y 64
00070 #define M_PI 3.141592
00071 //create the tick marks for an analog clock on the lcd display
00072 void setup_analog_clock(uint32_t color){
00073      
00074      lcd_mutex.lock();
00075      uLCD.filled_circle(64, 64, 5, color); //centercircle
00076      double angle;
00077      //start from 3 oclock and draw all the clock tick marks counter-clockwise
00078      for(angle = 0; angle < (2*M_PI)-(M_PI/12); angle += M_PI/6){
00079          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
00080      }
00081     lcd_mutex.unlock();
00082     
00083 }
00084 
00085 #define RAD_PER_SEC (2*M_PI)/60
00086 #define RAD_PER_MIN (2*M_PI)/60
00087 #define RAD_PER_HOUR (2*M_PI)/12
00088 //function to handle the display of the time on the lcd screen
00089 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) {
00090     static double angle;
00091     static int prev_sec;
00092     static int prev_minute;
00093     static int prev_hour;
00094     
00095     lcd_mutex.lock();
00096     
00097     //tear down the previous hands that were drawn
00098     angle = -(RAD_PER_SEC*prev_sec) + M_PI/2;
00099     uLCD.line(C_X,C_Y,64*cos(angle)+C_X, flipy(64*sin(angle)+C_Y),back_color);
00100     
00101     angle = -(RAD_PER_MIN*prev_minute) + M_PI/2;
00102     uLCD.line(C_X,C_Y,52*cos(angle)+C_X, flipy(52*sin(angle)+C_Y),back_color);
00103     
00104     angle = -(RAD_PER_HOUR*prev_hour) + M_PI/2;
00105     uLCD.line(C_X,C_Y,40*cos(angle)+C_X, flipy(40*sin(angle)+C_Y),back_color);
00106     
00107     //draw the new hands
00108     angle = -(RAD_PER_SEC*sec) + M_PI/2;
00109     uLCD.line(C_X,C_Y,64*cos(angle)+C_X, flipy(64*sin(angle)+C_Y),sec_color);
00110     
00111     angle = -(RAD_PER_MIN*minute) + M_PI/2;
00112     uLCD.line(C_X,C_Y,52*cos(angle)+C_X, flipy(52*sin(angle)+C_Y),min_color);
00113     
00114     angle = -(RAD_PER_HOUR*hour) + M_PI/2;
00115     uLCD.line(C_X,C_Y,40*cos(angle)+C_X, flipy(40*sin(angle)+C_Y),hour_color);
00116     
00117     stdio_mutex.lock();
00118     
00119     //print the current date in a month/day/year format
00120     uLCD.locate(4,10);
00121     uLCD.printf("%2d/%2d/%4d",month, day, year);
00122     uLCD.locate(8,11);
00123     if (hour < 12) {uLCD.printf("AM");}
00124     else {uLCD.printf("PM");}
00125     
00126     stdio_mutex.unlock();
00127     lcd_mutex.unlock();
00128     
00129     //store the location of the current hands
00130     prev_sec = sec;
00131     prev_minute = minute;
00132     prev_hour = hour;
00133 }
00134 
00135 //function to update the time displayed on the lcd approximately every second
00136 void time_thread_func() {
00137     struct tm * t; //time struct defined in time.h
00138     static time_t unix_time; //the time in unix time
00139     static bool prev_display_time; //indicates whether time was being displayed the last time the thread ran
00140     
00141     while (true) {
00142         if (display_time == true) {
00143             if (prev_display_time == false){ //clear whatever was previously on the screen
00144                 lcd_mutex.lock();
00145                 uLCD.cls();
00146                 lcd_mutex.unlock(); 
00147             }
00148             unix_time = time(NULL);
00149             t = localtime(&unix_time);
00150 
00151             setup_analog_clock(WHITE);
00152             show_time_analog(t->tm_sec,t->tm_min,t->tm_hour,t->tm_mday,t->tm_mon+1,t->tm_year+1900,RED+BLUE,WHITE,BLUE,BLACK);
00153         }
00154         prev_display_time = display_time;
00155         
00156         Thread::wait(1000); //only update every second
00157     }
00158     
00159 }
00160 
00161 //function to continuously take in characters over bluetooth serial and parse them as RPC commands
00162 void bluetooth_thread_func() {
00163     char buf[256], outbuf[256];
00164     uint16_t buf_pos = 0;
00165     
00166     while(true) {
00167         
00168         //if (pc.readable() == true) { //comment out when using bluetooth to receive rpc commands
00169         if (bluetooth.readable() == true) {
00170             
00171             stdio_mutex.lock();
00172             
00173             //buf[buf_pos] = pc.getc(); //comment out when using bluetooth to receive rpc commands
00174             buf[buf_pos] = bluetooth.getc();
00175             
00176             stdio_mutex.unlock();
00177             
00178             if (buf[buf_pos] == '\n') { //the end of the RPC command has been received
00179                 buf[buf_pos] = '\0'; //replace the newline character with a null character
00180                 buf_pos = 0;
00181                 RPC::call(buf, outbuf);  //make an RPC call  
00182                 
00183                 stdio_mutex.lock();
00184                 pc.printf("%s\n", outbuf); //send the response
00185                 stdio_mutex.unlock();
00186             }
00187             else {
00188                 buf_pos++;
00189             }
00190             
00191         } else { 
00192             Thread::yield();
00193         }
00194         
00195     }
00196 }
00197 
00198 //RPC function to receive the current time
00199 //the first argument is unix time and the second argument is the offset from UTC time
00200 void set_time_rpc_func (Arguments *in, Reply *out)   {
00201     static const char * unix_time_str;
00202     uint32_t unix_time;
00203     int offset;
00204     unix_time_str = in->getArg<const char*>(); //get a pointer to the location where the argument string is stored
00205     offset = in->getArg<int>(); //get the second argument which indicates the offeset (in hours) from UTC time
00206     unix_time = atoll(unix_time_str);
00207     utc_offset = offset;
00208     
00209     set_time(unix_time + utc_offset*(3600.0));
00210     
00211 }
00212 
00213 //RPC function to receive notification strings
00214 //note notification strings should not contain the character ' ', in lieu
00215 //they should contain '_' to indicate spaces
00216 void display_notification_rpc_func (Arguments *in, Reply *out)   {
00217     static char title_str[18];
00218     static char display_str[18];
00219     static const char * msg_str;
00220     static const char * title_str_ptr;
00221     int i,j;
00222     bool break_out = false;
00223     
00224     display_notification = true;
00225     display_time = false;
00226     
00227     title_str_ptr = in->getArg<const char *>(); //get a pointer to the location where the title argument string is stored
00228     msg_str = in->getArg<const char*>(); //get a pointer to the location where the argument string is stored
00229     
00230     stdio_mutex.lock();
00231     lcd_mutex.lock();
00232     
00233     uLCD.cls();
00234     uLCD.locate(0,0);
00235     for(j=0; j<18; j++){
00236         if (title_str_ptr[j] == '_'){title_str[j] = ' ';} 
00237         else {title_str[j] = title_str_ptr[j];}
00238         if (title_str_ptr[j] == '\0') {break;}
00239     }
00240     uLCD.printf("%s\r\n",title_str);
00241     uLCD.filled_rectangle(0,10,128,15,RED+BLUE);
00242     
00243     uLCD.locate(0,2);
00244     i = 0;
00245     while(true){
00246         for(j=0; j<18; j++){
00247             if (msg_str[i+j] == '_'){
00248                 display_str[j] = ' ';
00249             } else {
00250                 display_str[j] = msg_str[i+j];
00251             }
00252             if (msg_str[i+j] == '\0') {break_out = true; break;}
00253         }
00254         i+= 18;
00255         uLCD.printf("%s\r\n",display_str);
00256         if (break_out){break;}
00257     }
00258     
00259     stdio_mutex.unlock();
00260     lcd_mutex.unlock();
00261     
00262     notification_chime_ticker.attach(&audio_sample, 1.0/sample_freq);
00263     
00264 }
00265 
00266 int main() {
00267     
00268     uLCD.baudrate(3000000); //increase the lcd baud rate
00269     
00270     //configure the input button and attach an interrupt routine to it
00271     view_button.mode(PullUp);
00272     view_button.fall(&view_button_pressed);
00273     
00274     
00275     bluetooth_thread.start(bluetooth_thread_func); //start the thread that takes in characters to construct RPC commands
00276     time_thread.start(time_thread_func); //start the thread that updates the displayed time
00277 
00278 }