first compiled version
Dependencies: mbed-rtos mbed C12832_lcd LM75B
main.cpp@9:f40c7c08d1c2, 2014-03-11 (annotated)
- 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?
User | Revision | Line number | New 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 | } |