Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed mbed-rtos 4DGL-uLCD-SE RPCInterface
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 }
Generated on Thu Jul 28 2022 05:53:35 by
1.7.2