first compiled version

Dependencies:   mbed-rtos mbed C12832_lcd LM75B

Committer:
nleoni
Date:
Tue Mar 11 06:39:37 2014 +0000
Revision:
9:f40c7c08d1c2
Parent:
8:4fcba095bdf0
Added 6 test cases covering regular and extreme uses of the program

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nleoni 7:4992146d9872 1 //LAB 6: RTOS AND IPC
nleoni 7:4992146d9872 2 //WRITTEN BY: ROBERT HARRELL AND NAPOLEON LEONI
nleoni 7:4992146d9872 3
nleoni 9:f40c7c08d1c2 4 //IPC: INTER PROGRAMMER COMMUNICATION....
nleoni 9:f40c7c08d1c2 5 //This program tests IPC for the mbed RTOS
nleoni 9:f40c7c08d1c2 6 //It features an LCD thread that updates the Pot value,
nleoni 9:f40c7c08d1c2 7 //Temperature and the fortune cookie using IPC methods with timeout
nleoni 9:f40c7c08d1c2 8 //The POT thread reads the POT value in a polling loop every 10 seconds
nleoni 9:f40c7c08d1c2 9 //and uses the IPC queue to send the data to the LCD thread
nleoni 9:f40c7c08d1c2 10 //The TEMP thread reads the temp value in a polling loop every 60 seconds
nleoni 9:f40c7c08d1c2 11 //and uses the IPC queue to send the data to the LCD thread
nleoni 9:f40c7c08d1c2 12 //The fortune cookie thread reads a fortune from a user using getc on a polling loop
nleoni 9:f40c7c08d1c2 13 //every 100 ms and sends the fortune cookie via an IPC memory pool to the LCD thread
nleoni 9:f40c7c08d1c2 14 //The TOD thread updates the time of date once a minute, it uses a mutex to share the LCD
nleoni 9:f40c7c08d1c2 15 //with the LCD thread.
nleoni 7:4992146d9872 16
nleoni 3:0945093f48ec 17
nleoni 9:f40c7c08d1c2 18 //***************************** TESTING ********************************************************//
nleoni 9:f40c7c08d1c2 19 // TEST TEST DESCRIPTION STATUS //
nleoni 9:f40c7c08d1c2 20 // 1 POT thread updates to a in less than 10 s when pot PASS //
nleoni 9:f40c7c08d1c2 21 // value is changed //
nleoni 9:f40c7c08d1c2 22 // 2 Temp thread updates to a in less than 60 s when sensor PASS //
nleoni 9:f40c7c08d1c2 23 // sensor temperature changes //
nleoni 9:f40c7c08d1c2 24 // 3 Strings entered with the terminal are faithfully displayed PASS //
nleoni 9:f40c7c08d1c2 25 // in the LCD, no missing characters regardless of typing //
nleoni 9:f40c7c08d1c2 26 // speed //
nleoni 9:f40c7c08d1c2 27 // 4 Enetering a fortune cookie in the terminal does not block PASS //
nleoni 9:f40c7c08d1c2 28 // normsl executions o the other threads //
nleoni 9:f40c7c08d1c2 29 // 5 There is no risk of overunning the fortune cookie buffer PASS //
nleoni 9:f40c7c08d1c2 30 // if the user continues to type beyond the allowable cookie //
nleoni 9:f40c7c08d1c2 31 // length the program trims the fortune cookie and reads the //
nleoni 9:f40c7c08d1c2 32 // reamining characters for the next cookie, no missing characters //
nleoni 9:f40c7c08d1c2 33 // 6 Pressing center joystick button at reset allows entering date PASS //
nleoni 9:f40c7c08d1c2 34 // from the terminal.
nleoni 9:f40c7c08d1c2 35 //**********************************************************************************************//
nleoni 5:d40a563e2c3b 36
robertwharrell 1:83bc9f91d154 37
nleoni 0:7ae4f23f84a3 38 #include "mbed.h"
nleoni 0:7ae4f23f84a3 39 #include "rtos.h"
nleoni 3:0945093f48ec 40 #include "C12832_lcd.h"
robertwharrell 6:45c3ad45a252 41 #include "LM75B.h"
nleoni 3:0945093f48ec 42 #include <string>
nleoni 3:0945093f48ec 43
nleoni 8:4fcba095bdf0 44 //#define _DEBUGMODE //Uncomment to enter debug mode which prints some diagnostic strings to the terminal
nleoni 3:0945093f48ec 45 #define BUFFER 17
nleoni 3:0945093f48ec 46 #define COOKIEQUEUE 30
nleoni 9:f40c7c08d1c2 47 #define TIMEOUT 200
nleoni 3:0945093f48ec 48
nleoni 3:0945093f48ec 49 C12832_LCD lcd;
nleoni 5:d40a563e2c3b 50 Serial pc(USBTX, USBRX); //To differentiate from LCD functions
robertwharrell 2:43cd60e0e32f 51
robertwharrell 6:45c3ad45a252 52 Mutex lcdMutex;
robertwharrell 6:45c3ad45a252 53
nleoni 0:7ae4f23f84a3 54 AnalogIn pot1(p19);
nleoni 3:0945093f48ec 55 MemoryPool<float, 10> potReadingBuffer;
nleoni 0:7ae4f23f84a3 56 Queue<float,10> potReadingQueue;
nleoni 0:7ae4f23f84a3 57
robertwharrell 6:45c3ad45a252 58 //Temperature Sensor
robertwharrell 6:45c3ad45a252 59 LM75B tmp(p28,p27);
robertwharrell 6:45c3ad45a252 60 Queue<float,10> tempReadingQueue;
nleoni 5:d40a563e2c3b 61
nleoni 3:0945093f48ec 62 MemoryPool<char[BUFFER], COOKIEQUEUE> cookieReadingBuffer;
nleoni 3:0945093f48ec 63 Queue<char[BUFFER],COOKIEQUEUE> cookieReadingQueue;
robertwharrell 2:43cd60e0e32f 64
robertwharrell 6:45c3ad45a252 65 DigitalIn center(p14); //Initiate RTC clock setup
robertwharrell 6:45c3ad45a252 66
robertwharrell 2:43cd60e0e32f 67 /******************************************************************
robertwharrell 2:43cd60e0e32f 68 *
robertwharrell 2:43cd60e0e32f 69 *An LCD thread that updates the LCD based on information
robertwharrell 2:43cd60e0e32f 70 *received from other threads via IPC
robertwharrell 2:43cd60e0e32f 71 *
robertwharrell 2:43cd60e0e32f 72 *Uses the top 3 lines of the LCD to reflect the pot, the
robertwharrell 2:43cd60e0e32f 73 *temperature, and the cookie. This task must use IPC (with
robertwharrell 2:43cd60e0e32f 74 *timeout) methods to get data from each of the previous threads
robertwharrell 2:43cd60e0e32f 75 *
robertwharrell 2:43cd60e0e32f 76 *******************************************************************/
nleoni 0:7ae4f23f84a3 77 void lcdUpdate(void const*){
nleoni 0:7ae4f23f84a3 78 while(1){
nleoni 9:f40c7c08d1c2 79 osStatus lcdStatus = lcdMutex.lock(TIMEOUT);
robertwharrell 6:45c3ad45a252 80 if(lcdStatus == osOK){
nleoni 9:f40c7c08d1c2 81 osEvent evtPot = potReadingQueue.get(TIMEOUT);
robertwharrell 6:45c3ad45a252 82 if (evtPot.status == osEventMessage) {
robertwharrell 6:45c3ad45a252 83 float *queuePot = (float*)evtPot.value.p;
robertwharrell 6:45c3ad45a252 84 lcd.locate(0,0);
nleoni 9:f40c7c08d1c2 85 lcd.printf("Volt: %.2f V", *queuePot);
robertwharrell 6:45c3ad45a252 86 potReadingBuffer.free(queuePot);
robertwharrell 6:45c3ad45a252 87 }
nleoni 9:f40c7c08d1c2 88 osEvent evtTemp = tempReadingQueue.get(TIMEOUT);
robertwharrell 6:45c3ad45a252 89 if (evtPot.status == osEventMessage) {
robertwharrell 6:45c3ad45a252 90 float *queueTemp = (float*)evtTemp.value.p;
robertwharrell 6:45c3ad45a252 91 lcd.locate(0,8);
robertwharrell 6:45c3ad45a252 92 lcd.printf("Temp: %.2f F", *queueTemp);
robertwharrell 6:45c3ad45a252 93 }
nleoni 9:f40c7c08d1c2 94 osEvent evtCookie = cookieReadingQueue.get(TIMEOUT);
robertwharrell 6:45c3ad45a252 95 if (evtCookie.status == osEventMessage) {
robertwharrell 6:45c3ad45a252 96 char (*queueCookie)[BUFFER] = (char (*)[BUFFER])evtCookie.value.p;
robertwharrell 6:45c3ad45a252 97 lcd.locate(0,16);
robertwharrell 6:45c3ad45a252 98 string str(*queueCookie);
robertwharrell 6:45c3ad45a252 99 lcd.printf("F.Cookie: %s", str);
robertwharrell 6:45c3ad45a252 100 cookieReadingBuffer.free(queueCookie);
robertwharrell 6:45c3ad45a252 101 }
nleoni 0:7ae4f23f84a3 102 }
robertwharrell 6:45c3ad45a252 103 lcdMutex.unlock();
nleoni 3:0945093f48ec 104 Thread::wait(1000);
nleoni 0:7ae4f23f84a3 105 }
nleoni 0:7ae4f23f84a3 106 }
nleoni 0:7ae4f23f84a3 107
robertwharrell 2:43cd60e0e32f 108 /******************************************************************
robertwharrell 2:43cd60e0e32f 109 *
robertwharrell 2:43cd60e0e32f 110 *A POT thread that reads the pot value in a polling loop
robertwharrell 2:43cd60e0e32f 111 *every 10 seconds and sends value to LCD thread via IPC Queue
robertwharrell 2:43cd60e0e32f 112 *
robertwharrell 2:43cd60e0e32f 113 *******************************************************************/
nleoni 0:7ae4f23f84a3 114 void readPOT(void const*){
nleoni 0:7ae4f23f84a3 115 while(1){
nleoni 3:0945093f48ec 116 float *queue = potReadingBuffer.alloc();
nleoni 0:7ae4f23f84a3 117 *queue = pot1;
nleoni 9:f40c7c08d1c2 118 potReadingQueue.put(queue,TIMEOUT);
nleoni 8:4fcba095bdf0 119 #ifdef _DEBUGMODE
robertwharrell 2:43cd60e0e32f 120 pc.printf("POT read");
nleoni 8:4fcba095bdf0 121 #endif
robertwharrell 2:43cd60e0e32f 122 Thread::wait(10000);
robertwharrell 2:43cd60e0e32f 123 }
robertwharrell 2:43cd60e0e32f 124
robertwharrell 2:43cd60e0e32f 125 }
robertwharrell 2:43cd60e0e32f 126
robertwharrell 2:43cd60e0e32f 127 /******************************************************************
robertwharrell 2:43cd60e0e32f 128 *
robertwharrell 2:43cd60e0e32f 129 *A TEMP thread that read the temperature every 60 seconds
robertwharrell 2:43cd60e0e32f 130 *and sends the value to the LCD task via IPC Queue
robertwharrell 2:43cd60e0e32f 131 *
robertwharrell 2:43cd60e0e32f 132 *******************************************************************/
nleoni 5:d40a563e2c3b 133
robertwharrell 2:43cd60e0e32f 134 void readTemp(void const*){
robertwharrell 6:45c3ad45a252 135 float temp = 0.0;
robertwharrell 6:45c3ad45a252 136 float *temp_ptr;
robertwharrell 6:45c3ad45a252 137
robertwharrell 2:43cd60e0e32f 138 while(1){
nleoni 5:d40a563e2c3b 139 //pc.printf("TEMP read");
robertwharrell 6:45c3ad45a252 140 temp = tmp.read()*9/5+32;
robertwharrell 6:45c3ad45a252 141 temp_ptr = &temp;
robertwharrell 6:45c3ad45a252 142 tempReadingQueue.put(temp_ptr);
robertwharrell 6:45c3ad45a252 143 Thread::wait(5000);
nleoni 0:7ae4f23f84a3 144 }
nleoni 0:7ae4f23f84a3 145
nleoni 0:7ae4f23f84a3 146 }
nleoni 0:7ae4f23f84a3 147
robertwharrell 2:43cd60e0e32f 148 /******************************************************************
robertwharrell 2:43cd60e0e32f 149 *
robertwharrell 2:43cd60e0e32f 150 *A SCANF thread that reads in a fortune cookie from user
robertwharrell 2:43cd60e0e32f 151 *and sends it to the LCD task via IPC Memory Pool
robertwharrell 2:43cd60e0e32f 152 *
robertwharrell 2:43cd60e0e32f 153 *******************************************************************/
nleoni 5:d40a563e2c3b 154 void readCookie(void const*){
nleoni 5:d40a563e2c3b 155 pc.printf(">Enter your fortune cookie\n>");
nleoni 5:d40a563e2c3b 156 char (*ptrBuffer)[BUFFER] = cookieReadingBuffer.alloc();
nleoni 5:d40a563e2c3b 157 char *ptrChar;
nleoni 5:d40a563e2c3b 158 ptrChar=*ptrBuffer;
robertwharrell 2:43cd60e0e32f 159 while(1){
nleoni 9:f40c7c08d1c2 160 //Note the choice of using getc instead of scanf to read the fortune cookie,
nleoni 9:f40c7c08d1c2 161 //this is a non-blocking call and allows the rest of our threads to continue operating
nleoni 9:f40c7c08d1c2 162 //only when a new character is typed this thread executes its body otherwise
nleoni 9:f40c7c08d1c2 163 //it immediately yields to other threads.
nleoni 3:0945093f48ec 164 if(pc.readable()){
nleoni 3:0945093f48ec 165 *ptrChar=pc.getc();
nleoni 3:0945093f48ec 166 pc.putc(*ptrChar);
nleoni 3:0945093f48ec 167 if((*ptrChar=='\n') || ((ptrChar-*ptrBuffer)>=(BUFFER-1)) ){
nleoni 3:0945093f48ec 168 if((ptrChar-*ptrBuffer)>=(BUFFER-1)) *++ptrChar='\n';
nleoni 3:0945093f48ec 169 while((ptrChar-*ptrBuffer)<=(BUFFER-1)){
nleoni 3:0945093f48ec 170 *ptrChar++=' ';
nleoni 3:0945093f48ec 171 }
nleoni 3:0945093f48ec 172 *ptrChar='\0';
nleoni 9:f40c7c08d1c2 173 cookieReadingQueue.put(ptrBuffer,TIMEOUT);
nleoni 3:0945093f48ec 174 pc.printf(">Enter your fortune cookie\n>");
nleoni 3:0945093f48ec 175 ptrChar=*ptrBuffer;
nleoni 3:0945093f48ec 176 } else {
nleoni 3:0945093f48ec 177 ptrChar++;
nleoni 3:0945093f48ec 178 }
nleoni 3:0945093f48ec 179 }
nleoni 9:f40c7c08d1c2 180 //A 100 ms wait seems like reasonable delay which allows operation of the remaining threads.
nleoni 9:f40c7c08d1c2 181 Thread::wait(100);
robertwharrell 2:43cd60e0e32f 182 }
nleoni 0:7ae4f23f84a3 183 }
nleoni 0:7ae4f23f84a3 184
robertwharrell 2:43cd60e0e32f 185
robertwharrell 2:43cd60e0e32f 186 /******************************************************************
robertwharrell 2:43cd60e0e32f 187 *
robertwharrell 2:43cd60e0e32f 188 *A TOD thread that updates the 4th line of the LCD with time
robertwharrell 2:43cd60e0e32f 189 *of day once a minute. It shares the LCD with the LCD thread
robertwharrell 2:43cd60e0e32f 190 *using mutual exclusion
robertwharrell 2:43cd60e0e32f 191 *
robertwharrell 2:43cd60e0e32f 192 *******************************************************************/
robertwharrell 6:45c3ad45a252 193 void readTOD(void const*){
robertwharrell 6:45c3ad45a252 194 struct tm dt, *dtp;
robertwharrell 6:45c3ad45a252 195 time_t t;
robertwharrell 6:45c3ad45a252 196 char s[ 30 ];
robertwharrell 6:45c3ad45a252 197 dtp = &dt;
robertwharrell 6:45c3ad45a252 198
robertwharrell 6:45c3ad45a252 199 while(1){
nleoni 9:f40c7c08d1c2 200 osStatus lcdStatus = lcdMutex.lock(TIMEOUT);
robertwharrell 6:45c3ad45a252 201 if(lcdStatus == osOK){
robertwharrell 6:45c3ad45a252 202 //pc.printf("TOD updated");
robertwharrell 6:45c3ad45a252 203 t = time( NULL );
robertwharrell 6:45c3ad45a252 204 dtp = localtime( &t );
robertwharrell 6:45c3ad45a252 205
robertwharrell 6:45c3ad45a252 206 strftime( s, 20, "%b %d, %Y", dtp );
robertwharrell 6:45c3ad45a252 207 lcd.locate( 70, 0 );
robertwharrell 6:45c3ad45a252 208 lcd.printf( "%s", s );
robertwharrell 6:45c3ad45a252 209
robertwharrell 6:45c3ad45a252 210 strftime( s, 10, "%H:%M", dtp );
robertwharrell 6:45c3ad45a252 211 lcd.locate( 70, 8 );
robertwharrell 6:45c3ad45a252 212 lcd.printf( "%s", s );
robertwharrell 6:45c3ad45a252 213 }
robertwharrell 6:45c3ad45a252 214 lcdMutex.unlock();
robertwharrell 6:45c3ad45a252 215 Thread::wait(60000);
robertwharrell 2:43cd60e0e32f 216 }
nleoni 0:7ae4f23f84a3 217 }
nleoni 0:7ae4f23f84a3 218
robertwharrell 6:45c3ad45a252 219 //Using a terminal, set the RTC to current date and time
robertwharrell 6:45c3ad45a252 220 void rtc_setup(void)
robertwharrell 6:45c3ad45a252 221 {
robertwharrell 6:45c3ad45a252 222 // get the current time from the terminal
robertwharrell 6:45c3ad45a252 223 struct tm t;
robertwharrell 6:45c3ad45a252 224
robertwharrell 6:45c3ad45a252 225 lcd.locate( 0, 0 );
robertwharrell 6:45c3ad45a252 226 lcd.printf( "Please set time from serial terminal\n\r" );
robertwharrell 6:45c3ad45a252 227
robertwharrell 6:45c3ad45a252 228 pc.printf("Enter current date and time:\n\r");
robertwharrell 6:45c3ad45a252 229 pc.printf("YYYY MM DD HH MM[enter]\n\r");
robertwharrell 6:45c3ad45a252 230 pc.scanf("%d %d %d %d %d", &t.tm_year, &t.tm_mon, &t.tm_mday
robertwharrell 6:45c3ad45a252 231 , &t.tm_hour, &t.tm_min);
robertwharrell 6:45c3ad45a252 232
robertwharrell 6:45c3ad45a252 233 // adjust for tm structure required values
robertwharrell 6:45c3ad45a252 234 t.tm_year = t.tm_year - 1900;
robertwharrell 6:45c3ad45a252 235 t.tm_mon = t.tm_mon - 1;
robertwharrell 6:45c3ad45a252 236
robertwharrell 6:45c3ad45a252 237 // set the time
robertwharrell 6:45c3ad45a252 238 set_time(mktime(&t));
robertwharrell 6:45c3ad45a252 239 }
robertwharrell 6:45c3ad45a252 240
nleoni 0:7ae4f23f84a3 241 DigitalOut myled(LED1);
nleoni 0:7ae4f23f84a3 242
nleoni 0:7ae4f23f84a3 243 int main() {
robertwharrell 6:45c3ad45a252 244 //RTC setup if Center Button is held down
robertwharrell 6:45c3ad45a252 245 if (center) { rtc_setup(); }
robertwharrell 6:45c3ad45a252 246 lcd.cls();
nleoni 3:0945093f48ec 247
robertwharrell 6:45c3ad45a252 248 Thread threadLCD(lcdUpdate);
robertwharrell 6:45c3ad45a252 249 Thread threadPOT(readPOT);
robertwharrell 6:45c3ad45a252 250 Thread threadTemp(readTemp);
robertwharrell 6:45c3ad45a252 251 Thread threadCookie(readCookie);
robertwharrell 6:45c3ad45a252 252 Thread threadTOD(readTOD);
nleoni 0:7ae4f23f84a3 253
nleoni 0:7ae4f23f84a3 254 while(1) {
nleoni 3:0945093f48ec 255 Thread::wait(250);
nleoni 3:0945093f48ec 256
nleoni 0:7ae4f23f84a3 257 }
nleoni 0:7ae4f23f84a3 258 }