A simple microwave demo
Dependencies: C12832_lcd LM75B mbed-rtos mbed
rtos_hwk7.cpp@4:cd87e2050344, 2014-04-04 (annotated)
- Committer:
- joeroop
- Date:
- Fri Apr 04 02:16:32 2014 +0000
- Revision:
- 4:cd87e2050344
- Parent:
- 3:4fb0721ce794
for first publish no changes
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
joeroop | 4:cd87e2050344 | 1 | /* |
joeroop | 4:cd87e2050344 | 2 | Assignment: Hwk 7_1 |
joeroop | 4:cd87e2050344 | 3 | Due: 3/18/14 |
joeroop | 4:cd87e2050344 | 4 | Objective: |
joeroop | 4:cd87e2050344 | 5 | Finish lab #7. The purpose of this program is to use the RTOS along with |
joeroop | 4:cd87e2050344 | 6 | Interprocess comunication (IPC). In this program the IPC method utilizes |
joeroop | 4:cd87e2050344 | 7 | a MemoryPool and a Queue for a messaging system. Anytime a new message comes |
joeroop | 4:cd87e2050344 | 8 | through the LCD is updated. A union is used to reduce the size of the message |
joeroop | 4:cd87e2050344 | 9 | data structure. The prgram simulates a microwave with a requirement of having |
joeroop | 4:cd87e2050344 | 10 | the system shutdown within 1ms. There are no globals that are written to by the |
joeroop | 4:cd87e2050344 | 11 | threads this reduces the need for mutexes. All communcation is done by signals |
joeroop | 4:cd87e2050344 | 12 | and IPC in order to reduce global variables. |
joeroop | 4:cd87e2050344 | 13 | |
joeroop | 4:cd87e2050344 | 14 | Additions are LED4 light for door open and display the STATE (WAIT, COOK) on the lcd. |
joeroop | 4:cd87e2050344 | 15 | |
joeroop | 4:cd87e2050344 | 16 | Test Condition Pass/Fail Criteria Result |
joeroop | 4:cd87e2050344 | 17 | --------------------- --------------------------------------- --------- |
joeroop | 4:cd87e2050344 | 18 | See attached sheet |
joeroop | 0:3a19dcea1a01 | 19 | |
joeroop | 4:cd87e2050344 | 20 | */ |
joeroop | 0:3a19dcea1a01 | 21 | |
joeroop | 0:3a19dcea1a01 | 22 | |
joeroop | 0:3a19dcea1a01 | 23 | #include "mbed.h" |
joeroop | 0:3a19dcea1a01 | 24 | #include "rtos.h" |
joeroop | 0:3a19dcea1a01 | 25 | #include "C12832_lcd.h" //LCD interface |
joeroop | 0:3a19dcea1a01 | 26 | #include "LM75B.h" //temperature interface |
joeroop | 0:3a19dcea1a01 | 27 | |
joeroop | 4:cd87e2050344 | 28 | #ifndef DEBUG |
joeroop | 4:cd87e2050344 | 29 | //#define DEBUG |
joeroop | 4:cd87e2050344 | 30 | #endif /* DEBUG */ |
joeroop | 4:cd87e2050344 | 31 | |
joeroop | 1:896789dcc911 | 32 | |
joeroop | 1:896789dcc911 | 33 | #define DEBOUNCE_TIME_MS 10 |
joeroop | 2:324dc8b89365 | 34 | #define MAX_COOK_TIME_S 20 //3min |
joeroop | 4:cd87e2050344 | 35 | #define MIN_COOK_TIME_S 1 |
joeroop | 1:896789dcc911 | 36 | #define INIT_COOK_TIME_S 5 |
joeroop | 2:324dc8b89365 | 37 | #define TEMP_INTERVAL_S 5 |
joeroop | 4:cd87e2050344 | 38 | #define TEMP_INCREASE_F 10 |
joeroop | 1:896789dcc911 | 39 | |
joeroop | 1:896789dcc911 | 40 | |
joeroop | 0:3a19dcea1a01 | 41 | //globals and types |
joeroop | 4:cd87e2050344 | 42 | #ifdef DEBUG |
joeroop | 4:cd87e2050344 | 43 | Timer test_timer; //used to instrument the code |
joeroop | 4:cd87e2050344 | 44 | #endif |
joeroop | 0:3a19dcea1a01 | 45 | DigitalOut led1(LED1); |
joeroop | 0:3a19dcea1a01 | 46 | DigitalOut led2(LED2); |
joeroop | 1:896789dcc911 | 47 | DigitalOut led3(LED3); |
joeroop | 1:896789dcc911 | 48 | DigitalOut led4(LED4); |
joeroop | 0:3a19dcea1a01 | 49 | C12832_LCD lcd; |
joeroop | 2:324dc8b89365 | 50 | PwmOut spkr(p26); |
joeroop | 2:324dc8b89365 | 51 | LM75B therm(p28,p27); |
joeroop | 4:cd87e2050344 | 52 | Mutex lcd_mutex; //don't really need this but just to be safe |
joeroop | 1:896789dcc911 | 53 | Timer debounceTimer; |
joeroop | 1:896789dcc911 | 54 | InterruptIn irptTimeDn(p16); //cook down |
joeroop | 1:896789dcc911 | 55 | InterruptIn irptTimeUp(p13); //cook up |
joeroop | 1:896789dcc911 | 56 | InterruptIn irptStart(p15); //start cooking |
joeroop | 1:896789dcc911 | 57 | InterruptIn irptStop(p12); //stop cooking |
joeroop | 1:896789dcc911 | 58 | InterruptIn irptDoor(p14); //door interrupt |
joeroop | 4:cd87e2050344 | 59 | Thread *proxy_lcd; //pointers to the threads used for signalling |
joeroop | 1:896789dcc911 | 60 | Thread *proxy_temp; |
joeroop | 1:896789dcc911 | 61 | Thread *proxy_sound; |
joeroop | 1:896789dcc911 | 62 | Thread *proxy_state; |
joeroop | 1:896789dcc911 | 63 | Thread *proxy_led; |
joeroop | 1:896789dcc911 | 64 | Thread *proxy_timer; |
joeroop | 1:896789dcc911 | 65 | |
joeroop | 1:896789dcc911 | 66 | typedef enum { //start at one as we are using this as signals |
joeroop | 1:896789dcc911 | 67 | //states |
joeroop | 4:cd87e2050344 | 68 | WAITING = 1, //everything is ready for cooking, you can change the request time etc |
joeroop | 4:cd87e2050344 | 69 | COOKING, |
joeroop | 4:cd87e2050344 | 70 | DONE, //signal for threads to buzz, trurn off lights etc |
joeroop | 1:896789dcc911 | 71 | //interrupts signals |
joeroop | 1:896789dcc911 | 72 | TIMEUP, |
joeroop | 1:896789dcc911 | 73 | TIMEDN, |
joeroop | 1:896789dcc911 | 74 | START, |
joeroop | 1:896789dcc911 | 75 | STOP, |
joeroop | 1:896789dcc911 | 76 | DOOR |
joeroop | 4:cd87e2050344 | 77 | } state_t; //this is for signaling of threads with proxies |
joeroop | 1:896789dcc911 | 78 | |
joeroop | 1:896789dcc911 | 79 | char *stateStr[] = {"NULL","WAIT","COOK","DONE"}; |
joeroop | 1:896789dcc911 | 80 | |
joeroop | 0:3a19dcea1a01 | 81 | |
joeroop | 4:cd87e2050344 | 82 | typedef enum {TEMP_VAL, TIME_ELPS, TIME_RQST} data_t; //message data types |
joeroop | 1:896789dcc911 | 83 | |
joeroop | 1:896789dcc911 | 84 | typedef struct { |
joeroop | 1:896789dcc911 | 85 | state_t state; |
joeroop | 4:cd87e2050344 | 86 | data_t type; |
joeroop | 1:896789dcc911 | 87 | union { |
joeroop | 4:cd87e2050344 | 88 | float temp; |
joeroop | 1:896789dcc911 | 89 | int time_elapsed; //seconds of cooking |
joeroop | 1:896789dcc911 | 90 | int time_request; //seconds |
joeroop | 2:324dc8b89365 | 91 | } data; |
joeroop | 4:cd87e2050344 | 92 | } message_t; //used to pass messages to the lcd thread |
joeroop | 1:896789dcc911 | 93 | |
joeroop | 2:324dc8b89365 | 94 | MemoryPool<message_t,10> mpool; //used to hold all messages |
joeroop | 4:cd87e2050344 | 95 | Queue<message_t,10> queue; |
joeroop | 0:3a19dcea1a01 | 96 | |
joeroop | 1:896789dcc911 | 97 | bool debounce(void); |
joeroop | 4:cd87e2050344 | 98 | void blink_led(void const *args); //helper function to led thread |
joeroop | 4:cd87e2050344 | 99 | void send_time(void const *args); //helper function to timer thread |
joeroop | 1:896789dcc911 | 100 | |
joeroop | 1:896789dcc911 | 101 | //Threads |
joeroop | 1:896789dcc911 | 102 | void thread_state(void const *args); |
joeroop | 1:896789dcc911 | 103 | void thread_lcd(void const *args); |
joeroop | 1:896789dcc911 | 104 | void thread_temp(void const *args); |
joeroop | 1:896789dcc911 | 105 | void thread_sound(void const *args); |
joeroop | 1:896789dcc911 | 106 | void thread_led(void const *args); |
joeroop | 1:896789dcc911 | 107 | void thread_timer(void const *args); |
joeroop | 1:896789dcc911 | 108 | |
joeroop | 1:896789dcc911 | 109 | //ISRs |
joeroop | 1:896789dcc911 | 110 | void isrTimeUp(void); |
joeroop | 1:896789dcc911 | 111 | void isrTimeDn(void); |
joeroop | 1:896789dcc911 | 112 | void isrStart(void); |
joeroop | 1:896789dcc911 | 113 | void isrStop(void); |
joeroop | 1:896789dcc911 | 114 | void isrDoor(void); |
joeroop | 1:896789dcc911 | 115 | |
joeroop | 0:3a19dcea1a01 | 116 | int main(void){ |
joeroop | 1:896789dcc911 | 117 | debounceTimer.start(); |
joeroop | 4:cd87e2050344 | 118 | //interrupts debounce everything except for the door |
joeroop | 1:896789dcc911 | 119 | irptTimeUp.rise(&isrTimeUp); |
joeroop | 1:896789dcc911 | 120 | irptTimeDn.rise(&isrTimeDn); |
joeroop | 1:896789dcc911 | 121 | irptStart.rise(&isrStart); |
joeroop | 1:896789dcc911 | 122 | irptStop.rise(&isrStop); |
joeroop | 4:cd87e2050344 | 123 | irptDoor.rise(&isrDoor); |
joeroop | 4:cd87e2050344 | 124 | |
joeroop | 4:cd87e2050344 | 125 | //init the threads |
joeroop | 1:896789dcc911 | 126 | Thread t1(thread_state); |
joeroop | 1:896789dcc911 | 127 | Thread t2(thread_temp); |
joeroop | 1:896789dcc911 | 128 | Thread t3(thread_sound); |
joeroop | 1:896789dcc911 | 129 | Thread t4(thread_lcd); |
joeroop | 1:896789dcc911 | 130 | Thread t5(thread_led); |
joeroop | 1:896789dcc911 | 131 | Thread t6(thread_timer); |
joeroop | 1:896789dcc911 | 132 | |
joeroop | 4:cd87e2050344 | 133 | proxy_state = &t1; |
joeroop | 4:cd87e2050344 | 134 | proxy_temp = &t2; |
joeroop | 4:cd87e2050344 | 135 | proxy_sound = &t3; |
joeroop | 4:cd87e2050344 | 136 | proxy_lcd = &t4; |
joeroop | 4:cd87e2050344 | 137 | proxy_led = &t5; |
joeroop | 4:cd87e2050344 | 138 | proxy_timer = &t6; |
joeroop | 0:3a19dcea1a01 | 139 | |
joeroop | 4:cd87e2050344 | 140 | t1.set_priority(osPriorityRealtime); //state machine most important thread |
joeroop | 2:324dc8b89365 | 141 | proxy_state->signal_set(WAITING); //initialize all the threads |
joeroop | 1:896789dcc911 | 142 | |
joeroop | 0:3a19dcea1a01 | 143 | while(1){ |
joeroop | 0:3a19dcea1a01 | 144 | Thread::wait(250); |
joeroop | 0:3a19dcea1a01 | 145 | } |
joeroop | 0:3a19dcea1a01 | 146 | } |
joeroop | 0:3a19dcea1a01 | 147 | |
joeroop | 1:896789dcc911 | 148 | //function for a global debounce on the isrstick |
joeroop | 1:896789dcc911 | 149 | bool debounce(void){ |
joeroop | 1:896789dcc911 | 150 | if(debounceTimer.read_ms() > DEBOUNCE_TIME_MS){ |
joeroop | 1:896789dcc911 | 151 | debounceTimer.reset(); |
joeroop | 1:896789dcc911 | 152 | return true; |
joeroop | 1:896789dcc911 | 153 | }else{ |
joeroop | 1:896789dcc911 | 154 | return false; |
joeroop | 1:896789dcc911 | 155 | } |
joeroop | 1:896789dcc911 | 156 | } |
joeroop | 1:896789dcc911 | 157 | //ISRs |
joeroop | 1:896789dcc911 | 158 | void isrTimeUp(void){ |
joeroop | 1:896789dcc911 | 159 | if(debounce()){ |
joeroop | 1:896789dcc911 | 160 | proxy_state->signal_set(TIMEUP); //left |
joeroop | 1:896789dcc911 | 161 | } |
joeroop | 1:896789dcc911 | 162 | } |
joeroop | 1:896789dcc911 | 163 | void isrTimeDn(void){ |
joeroop | 1:896789dcc911 | 164 | if(debounce()){ |
joeroop | 1:896789dcc911 | 165 | proxy_state->signal_set(TIMEDN); //right |
joeroop | 1:896789dcc911 | 166 | } |
joeroop | 1:896789dcc911 | 167 | } |
joeroop | 1:896789dcc911 | 168 | void isrStart(void){ |
joeroop | 1:896789dcc911 | 169 | if(debounce()){ |
joeroop | 1:896789dcc911 | 170 | proxy_state->signal_set(START); //up |
joeroop | 1:896789dcc911 | 171 | } |
joeroop | 1:896789dcc911 | 172 | } |
joeroop | 1:896789dcc911 | 173 | void isrStop(void){ |
joeroop | 1:896789dcc911 | 174 | if(debounce()){ |
joeroop | 1:896789dcc911 | 175 | proxy_state->signal_set(STOP); //down |
joeroop | 1:896789dcc911 | 176 | } |
joeroop | 1:896789dcc911 | 177 | } |
joeroop | 1:896789dcc911 | 178 | void isrDoor(void){ |
joeroop | 1:896789dcc911 | 179 | //no debounce this is most important function! |
joeroop | 4:cd87e2050344 | 180 | #ifdef DEBUG |
joeroop | 4:cd87e2050344 | 181 | test_timer.start(); |
joeroop | 4:cd87e2050344 | 182 | #endif |
joeroop | 1:896789dcc911 | 183 | proxy_state->signal_set(DOOR); |
joeroop | 1:896789dcc911 | 184 | } |
joeroop | 1:896789dcc911 | 185 | |
joeroop | 4:cd87e2050344 | 186 | /* |
joeroop | 4:cd87e2050344 | 187 | * State thread to do most of the main state machine logic this is where control happens |
joeroop | 4:cd87e2050344 | 188 | */ |
joeroop | 1:896789dcc911 | 189 | void thread_state(void const *args){ |
joeroop | 1:896789dcc911 | 190 | osEvent evt; |
joeroop | 1:896789dcc911 | 191 | int32_t mask; |
joeroop | 1:896789dcc911 | 192 | bool openDoor = false; //start with door closed |
joeroop | 1:896789dcc911 | 193 | state_t state = WAITING; //WAITING, COOKING, DONE |
joeroop | 1:896789dcc911 | 194 | while(1){ |
joeroop | 1:896789dcc911 | 195 | evt = Thread::signal_wait(0); |
joeroop | 1:896789dcc911 | 196 | mask = evt.value.signals; |
joeroop | 1:896789dcc911 | 197 | switch(mask){ |
joeroop | 4:cd87e2050344 | 198 | case WAITING: //come from DONE to here |
joeroop | 1:896789dcc911 | 199 | state = WAITING; |
joeroop | 2:324dc8b89365 | 200 | proxy_led->signal_set(state); |
joeroop | 2:324dc8b89365 | 201 | proxy_timer->signal_set(state); |
joeroop | 2:324dc8b89365 | 202 | proxy_temp->signal_set(state); |
joeroop | 1:896789dcc911 | 203 | break; |
joeroop | 1:896789dcc911 | 204 | case COOKING: |
joeroop | 4:cd87e2050344 | 205 | if(!openDoor && state == WAITING){ //can't cook if door is open |
joeroop | 2:324dc8b89365 | 206 | state = COOKING; |
joeroop | 2:324dc8b89365 | 207 | proxy_led->signal_set(state); |
joeroop | 2:324dc8b89365 | 208 | proxy_timer->signal_set(state); |
joeroop | 2:324dc8b89365 | 209 | proxy_temp->signal_set(state); |
joeroop | 2:324dc8b89365 | 210 | } |
joeroop | 1:896789dcc911 | 211 | break; |
joeroop | 1:896789dcc911 | 212 | case DONE: //timer can signal this |
joeroop | 2:324dc8b89365 | 213 | state = DONE; |
joeroop | 4:cd87e2050344 | 214 | //tell everyone we are done so they can buzz, dispaly and stop blinking |
joeroop | 2:324dc8b89365 | 215 | proxy_led->signal_set(state); |
joeroop | 2:324dc8b89365 | 216 | proxy_timer->signal_set(state); |
joeroop | 2:324dc8b89365 | 217 | proxy_temp->signal_set(state); |
joeroop | 4:cd87e2050344 | 218 | #ifdef DEBUG |
joeroop | 4:cd87e2050344 | 219 | //test_timer.stop(); // ~21 us to here from interrupt |
joeroop | 4:cd87e2050344 | 220 | #endif |
joeroop | 4:cd87e2050344 | 221 | proxy_state->signal_set(WAITING); //goto WAITING |
joeroop | 1:896789dcc911 | 222 | break; |
joeroop | 1:896789dcc911 | 223 | case TIMEUP: //change the timer up |
joeroop | 1:896789dcc911 | 224 | if(state == WAITING) proxy_timer->signal_set(TIMEUP); |
joeroop | 1:896789dcc911 | 225 | break; |
joeroop | 1:896789dcc911 | 226 | case TIMEDN: //change the timer down |
joeroop | 1:896789dcc911 | 227 | if(state == WAITING) proxy_timer->signal_set(TIMEDN); |
joeroop | 1:896789dcc911 | 228 | break; |
joeroop | 1:896789dcc911 | 229 | case START: |
joeroop | 4:cd87e2050344 | 230 | proxy_state->signal_set(COOKING); |
joeroop | 1:896789dcc911 | 231 | break; |
joeroop | 1:896789dcc911 | 232 | case STOP: |
joeroop | 4:cd87e2050344 | 233 | proxy_state->signal_set(DONE); |
joeroop | 1:896789dcc911 | 234 | break; |
joeroop | 1:896789dcc911 | 235 | case DOOR: //door changed state |
joeroop | 1:896789dcc911 | 236 | openDoor = !openDoor; |
joeroop | 1:896789dcc911 | 237 | state = (openDoor == true) ? DONE : WAITING; //open door then done else state back to waiting |
joeroop | 4:cd87e2050344 | 238 | led4 = openDoor; //visual for when door is open |
joeroop | 2:324dc8b89365 | 239 | proxy_state->signal_set(state); //signal back to state thread |
joeroop | 2:324dc8b89365 | 240 | break; |
joeroop | 2:324dc8b89365 | 241 | } |
joeroop | 2:324dc8b89365 | 242 | } |
joeroop | 2:324dc8b89365 | 243 | } |
joeroop | 4:cd87e2050344 | 244 | /* |
joeroop | 4:cd87e2050344 | 245 | * Helper function for the timer thread gets called at 1sec intervals |
joeroop | 4:cd87e2050344 | 246 | */ |
joeroop | 2:324dc8b89365 | 247 | void send_time(void const *args){ |
joeroop | 2:324dc8b89365 | 248 | int time = (*((int*)args))--; //have the time in seconds send to lcd now |
joeroop | 2:324dc8b89365 | 249 | state_t state = COOKING; |
joeroop | 4:cd87e2050344 | 250 | if(time == 0){ //time is up signal state machine to done |
joeroop | 2:324dc8b89365 | 251 | state = DONE; |
joeroop | 4:cd87e2050344 | 252 | proxy_state->signal_set(state); //tell threads cooking time up |
joeroop | 4:cd87e2050344 | 253 | proxy_sound->signal_set(state); |
joeroop | 2:324dc8b89365 | 254 | } |
joeroop | 2:324dc8b89365 | 255 | proxy_temp->signal_set(state); //use this timer to schedule temperature read |
joeroop | 2:324dc8b89365 | 256 | |
joeroop | 4:cd87e2050344 | 257 | message_t *msg = mpool.alloc(); //allocate a new message lcd is recipient |
joeroop | 2:324dc8b89365 | 258 | msg->state = state; |
joeroop | 2:324dc8b89365 | 259 | msg->type = TIME_ELPS; |
joeroop | 2:324dc8b89365 | 260 | msg->data.time_elapsed = time; |
joeroop | 2:324dc8b89365 | 261 | queue.put(msg); |
joeroop | 2:324dc8b89365 | 262 | } |
joeroop | 4:cd87e2050344 | 263 | /* |
joeroop | 4:cd87e2050344 | 264 | * Timer thread to keep track of all the time requirements for temp reading and elapsed time |
joeroop | 4:cd87e2050344 | 265 | */ |
joeroop | 2:324dc8b89365 | 266 | void thread_timer(void const *args){ |
joeroop | 2:324dc8b89365 | 267 | int time_set, time; |
joeroop | 2:324dc8b89365 | 268 | time_set = INIT_COOK_TIME_S; |
joeroop | 2:324dc8b89365 | 269 | int *ptime = &time; |
joeroop | 2:324dc8b89365 | 270 | RtosTimer timer(send_time, osTimerPeriodic,(void*)ptime); |
joeroop | 2:324dc8b89365 | 271 | osEvent evt; |
joeroop | 2:324dc8b89365 | 272 | int32_t sig; |
joeroop | 2:324dc8b89365 | 273 | state_t state; |
joeroop | 2:324dc8b89365 | 274 | while(1){ |
joeroop | 2:324dc8b89365 | 275 | evt = Thread::signal_wait(0); //will time out then loop not needed |
joeroop | 2:324dc8b89365 | 276 | sig = evt.value.signals; |
joeroop | 2:324dc8b89365 | 277 | switch(sig){ |
joeroop | 2:324dc8b89365 | 278 | case WAITING: |
joeroop | 2:324dc8b89365 | 279 | state = WAITING; |
joeroop | 2:324dc8b89365 | 280 | break; |
joeroop | 2:324dc8b89365 | 281 | case COOKING: |
joeroop | 4:cd87e2050344 | 282 | state = COOKING; |
joeroop | 4:cd87e2050344 | 283 | timer.stop(); //stop the timer |
joeroop | 4:cd87e2050344 | 284 | time = time_set; |
joeroop | 4:cd87e2050344 | 285 | send_time(ptime); //initialize the elpased time |
joeroop | 4:cd87e2050344 | 286 | timer.start(1000); //this is the increments of the timer 1s using RtosTimer |
joeroop | 2:324dc8b89365 | 287 | break; |
joeroop | 2:324dc8b89365 | 288 | case DONE: |
joeroop | 4:cd87e2050344 | 289 | state = DONE; |
joeroop | 4:cd87e2050344 | 290 | time = INIT_COOK_TIME_S; |
joeroop | 4:cd87e2050344 | 291 | //if(time > 0) time_set = time; |
joeroop | 4:cd87e2050344 | 292 | //else time = INIT_COOK_TIME_S; |
joeroop | 4:cd87e2050344 | 293 | timer.stop(); |
joeroop | 2:324dc8b89365 | 294 | break; |
joeroop | 2:324dc8b89365 | 295 | case TIMEUP: |
joeroop | 4:cd87e2050344 | 296 | time_set = (++time_set) > MAX_COOK_TIME_S ? MAX_COOK_TIME_S : time_set; //check limits |
joeroop | 2:324dc8b89365 | 297 | break; |
joeroop | 2:324dc8b89365 | 298 | case TIMEDN: |
joeroop | 4:cd87e2050344 | 299 | time_set = (--time_set) < MIN_COOK_TIME_S ? MIN_COOK_TIME_S : time_set; //check limits |
joeroop | 2:324dc8b89365 | 300 | break; |
joeroop | 2:324dc8b89365 | 301 | } |
joeroop | 2:324dc8b89365 | 302 | if(sig){ |
joeroop | 4:cd87e2050344 | 303 | message_t *msg = mpool.alloc(); //allocate a new message to the lcd |
joeroop | 4:cd87e2050344 | 304 | if(msg != NULL){ |
joeroop | 4:cd87e2050344 | 305 | msg->state = state; |
joeroop | 4:cd87e2050344 | 306 | msg->type = TIME_RQST; |
joeroop | 4:cd87e2050344 | 307 | msg->data.time_request = time_set; |
joeroop | 4:cd87e2050344 | 308 | queue.put(msg); |
joeroop | 4:cd87e2050344 | 309 | } |
joeroop | 2:324dc8b89365 | 310 | } |
joeroop | 2:324dc8b89365 | 311 | } |
joeroop | 2:324dc8b89365 | 312 | } |
joeroop | 4:cd87e2050344 | 313 | /* |
joeroop | 4:cd87e2050344 | 314 | * LCD thread used to receive data from several other threads in the form of a message queue |
joeroop | 4:cd87e2050344 | 315 | */ |
joeroop | 2:324dc8b89365 | 316 | void thread_lcd(void const *args){ |
joeroop | 2:324dc8b89365 | 317 | osEvent evt; |
joeroop | 4:cd87e2050344 | 318 | int time_set = 0; //used to calculate the elapsed time |
joeroop | 2:324dc8b89365 | 319 | lcd.cls(); |
joeroop | 2:324dc8b89365 | 320 | while(1){ |
joeroop | 4:cd87e2050344 | 321 | evt = queue.get(osWaitForever); //wait for data message to post |
joeroop | 2:324dc8b89365 | 322 | if(evt.status == osEventMessage){ |
joeroop | 4:cd87e2050344 | 323 | message_t *msg = (message_t*)evt.value.p; //get the message |
joeroop | 4:cd87e2050344 | 324 | lcd_mutex.lock(); //dont really need this as this is the only thread that uses the lcd |
joeroop | 4:cd87e2050344 | 325 | |
joeroop | 4:cd87e2050344 | 326 | if(msg->state){ |
joeroop | 4:cd87e2050344 | 327 | #ifdef DEBUG |
joeroop | 4:cd87e2050344 | 328 | if(msg->state == DONE){ |
joeroop | 4:cd87e2050344 | 329 | test_timer.stop(); //~75 us, if move print ahead it is 3145 us! printing takes a while |
joeroop | 4:cd87e2050344 | 330 | lcd.locate(70,20); |
joeroop | 4:cd87e2050344 | 331 | lcd.printf("%dus",test_timer.read_us()); |
joeroop | 4:cd87e2050344 | 332 | test_timer.reset(); |
joeroop | 4:cd87e2050344 | 333 | } |
joeroop | 4:cd87e2050344 | 334 | #endif |
joeroop | 4:cd87e2050344 | 335 | lcd.locate(70,0); |
joeroop | 2:324dc8b89365 | 336 | lcd.printf("State: %s ",stateStr[msg->state]); |
joeroop | 4:cd87e2050344 | 337 | } |
joeroop | 2:324dc8b89365 | 338 | switch(msg->type){ |
joeroop | 2:324dc8b89365 | 339 | case TIME_RQST: |
joeroop | 2:324dc8b89365 | 340 | time_set = msg->data.time_request; |
joeroop | 2:324dc8b89365 | 341 | lcd.locate(0,0); |
joeroop | 4:cd87e2050344 | 342 | lcd.printf("Request: %3ds ",time_set); //requested time |
joeroop | 2:324dc8b89365 | 343 | break; |
joeroop | 2:324dc8b89365 | 344 | case TIME_ELPS: |
joeroop | 2:324dc8b89365 | 345 | lcd.locate(0,10); |
joeroop | 4:cd87e2050344 | 346 | lcd.printf("Elapsed: %3ds ",time_set - msg->data.time_elapsed); //elapesed time |
joeroop | 2:324dc8b89365 | 347 | break; |
joeroop | 2:324dc8b89365 | 348 | case TEMP_VAL: |
joeroop | 2:324dc8b89365 | 349 | lcd.locate(0,20); |
joeroop | 4:cd87e2050344 | 350 | lcd.printf("Temp: %-3.2fF ",msg->data.temp); //current cooking temp updated at different intervals |
joeroop | 2:324dc8b89365 | 351 | break; |
joeroop | 2:324dc8b89365 | 352 | } |
joeroop | 4:cd87e2050344 | 353 | lcd_mutex.unlock(); //free the mutex |
joeroop | 4:cd87e2050344 | 354 | mpool.free(msg); //free the message |
joeroop | 2:324dc8b89365 | 355 | } |
joeroop | 2:324dc8b89365 | 356 | } |
joeroop | 2:324dc8b89365 | 357 | } |
joeroop | 4:cd87e2050344 | 358 | /* |
joeroop | 4:cd87e2050344 | 359 | * Thread function to send the lcd the temp recieves timing from timer thread |
joeroop | 4:cd87e2050344 | 360 | */ |
joeroop | 2:324dc8b89365 | 361 | void thread_temp(void const *args){ |
joeroop | 2:324dc8b89365 | 362 | osEvent evt; |
joeroop | 2:324dc8b89365 | 363 | int32_t sig; |
joeroop | 2:324dc8b89365 | 364 | int seconds = -1; |
joeroop | 2:324dc8b89365 | 365 | float temp = 0.0; |
joeroop | 2:324dc8b89365 | 366 | while(1){ |
joeroop | 2:324dc8b89365 | 367 | evt = Thread::signal_wait(0); |
joeroop | 2:324dc8b89365 | 368 | sig = evt.value.signals; |
joeroop | 2:324dc8b89365 | 369 | switch(sig){ |
joeroop | 2:324dc8b89365 | 370 | case COOKING: |
joeroop | 4:cd87e2050344 | 371 | if(!(seconds++ % TEMP_INTERVAL_S)){ //increase the temp if meets the interval |
joeroop | 4:cd87e2050344 | 372 | temp+= TEMP_INCREASE_F; |
joeroop | 2:324dc8b89365 | 373 | }else{ |
joeroop | 2:324dc8b89365 | 374 | sig = 0x0; //set to zero so don't print since no changes |
joeroop | 2:324dc8b89365 | 375 | } |
joeroop | 2:324dc8b89365 | 376 | break; |
joeroop | 2:324dc8b89365 | 377 | case WAITING: |
joeroop | 2:324dc8b89365 | 378 | case DONE: |
joeroop | 2:324dc8b89365 | 379 | seconds = -1; |
joeroop | 2:324dc8b89365 | 380 | temp = 0.0; |
joeroop | 2:324dc8b89365 | 381 | break; |
joeroop | 2:324dc8b89365 | 382 | } |
joeroop | 2:324dc8b89365 | 383 | if(sig){ |
joeroop | 2:324dc8b89365 | 384 | message_t *msg = mpool.alloc(); //allocate a new message |
joeroop | 4:cd87e2050344 | 385 | if(msg != NULL){ |
joeroop | 4:cd87e2050344 | 386 | msg->state = (state_t)0; //don't pass a value |
joeroop | 4:cd87e2050344 | 387 | msg->type = TEMP_VAL; |
joeroop | 4:cd87e2050344 | 388 | msg->data.temp = seconds > 0 ? temp+9.0/5.0*therm.read()+32.0 : 0.0; |
joeroop | 4:cd87e2050344 | 389 | queue.put(msg); |
joeroop | 4:cd87e2050344 | 390 | } |
joeroop | 2:324dc8b89365 | 391 | } |
joeroop | 2:324dc8b89365 | 392 | } |
joeroop | 2:324dc8b89365 | 393 | } |
joeroop | 4:cd87e2050344 | 394 | /* |
joeroop | 4:cd87e2050344 | 395 | * Simple sound thread using pwm to buzz when cooking timer is finished |
joeroop | 4:cd87e2050344 | 396 | */ |
joeroop | 2:324dc8b89365 | 397 | void thread_sound(void const *args){ |
joeroop | 2:324dc8b89365 | 398 | osEvent evt; |
joeroop | 2:324dc8b89365 | 399 | int32_t sig; |
joeroop | 2:324dc8b89365 | 400 | while(1){ |
joeroop | 2:324dc8b89365 | 401 | evt = Thread::signal_wait(0); |
joeroop | 2:324dc8b89365 | 402 | sig = evt.value.signals; |
joeroop | 2:324dc8b89365 | 403 | switch(sig){ |
joeroop | 2:324dc8b89365 | 404 | case DONE: |
joeroop | 2:324dc8b89365 | 405 | spkr.period(1.0/5000); |
joeroop | 2:324dc8b89365 | 406 | spkr=0.5; |
joeroop | 2:324dc8b89365 | 407 | Thread::wait(1000); |
joeroop | 2:324dc8b89365 | 408 | spkr=0.0; |
joeroop | 1:896789dcc911 | 409 | break; |
joeroop | 1:896789dcc911 | 410 | } |
joeroop | 1:896789dcc911 | 411 | } |
joeroop | 1:896789dcc911 | 412 | } |
joeroop | 4:cd87e2050344 | 413 | /* |
joeroop | 4:cd87e2050344 | 414 | * Helper function to thread_led used to blink led |
joeroop | 4:cd87e2050344 | 415 | */ |
joeroop | 1:896789dcc911 | 416 | void blink_led(void const *args){ |
joeroop | 1:896789dcc911 | 417 | led1 = !led1; |
joeroop | 1:896789dcc911 | 418 | } |
joeroop | 4:cd87e2050344 | 419 | /* |
joeroop | 4:cd87e2050344 | 420 | * Thread led to blink the light when cooking and stop when done |
joeroop | 4:cd87e2050344 | 421 | */ |
joeroop | 1:896789dcc911 | 422 | void thread_led(void const *args){ |
joeroop | 1:896789dcc911 | 423 | RtosTimer timer(blink_led, osTimerPeriodic); |
joeroop | 1:896789dcc911 | 424 | osEvent evt; |
joeroop | 1:896789dcc911 | 425 | int32_t sig; |
joeroop | 0:3a19dcea1a01 | 426 | while(1){ |
joeroop | 1:896789dcc911 | 427 | evt = Thread::signal_wait(0); //will time out then loop not needed |
joeroop | 1:896789dcc911 | 428 | sig = evt.value.signals; |
joeroop | 1:896789dcc911 | 429 | switch(sig){ |
joeroop | 1:896789dcc911 | 430 | case COOKING: |
joeroop | 1:896789dcc911 | 431 | timer.start(250); |
joeroop | 1:896789dcc911 | 432 | break; |
joeroop | 1:896789dcc911 | 433 | case DONE: |
joeroop | 1:896789dcc911 | 434 | timer.stop(); |
joeroop | 1:896789dcc911 | 435 | led1 = 0; |
joeroop | 1:896789dcc911 | 436 | break; |
joeroop | 1:896789dcc911 | 437 | } |
joeroop | 1:896789dcc911 | 438 | } |
joeroop | 1:896789dcc911 | 439 | } |
joeroop | 2:324dc8b89365 | 440 |