homework 7

Dependencies:   mbed-rtos mbed C12832_lcd LM75B

Committer:
gatedClock
Date:
Thu Sep 12 22:51:30 2013 +0000
Revision:
121:c9d28cd59460
Parent:
120:64a969984af2
Child:
122:69e32460b543
Child:
123:c8ea8f59455b
mutexed cControl.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gatedClock 0:fcca4db7b32a 1 /*----------------------------------------------//------------------------------
gatedClock 0:fcca4db7b32a 2 student : m-moore
gatedClock 0:fcca4db7b32a 3 class : rtos
gatedClock 10:2b0a9fc39109 4 directory : RTOS_HW_07
gatedClock 0:fcca4db7b32a 5 file : main.cpp
gatedClock 0:fcca4db7b32a 6 ----description---------------------------------//------------------------------
gatedClock 70:7c0743c28b11 7 gotchyas
gatedClock 70:7c0743c28b11 8 1. using pc.printf inside a ticker routine will freeze the routine.
gatedClock 71:4a5f256ecf7c 9 2. using queues (get, put) will not work within a ticker routine.
gatedClock 76:74c454c9d75b 10 3. Ticker has a bug. http://mbed.org/questions/1563/Mbed-Tickerfunction-hangs-system-from-re/
gatedClock 80:e3e1a2161435 11
gatedClock 80:e3e1a2161435 12 improvements
gatedClock 80:e3e1a2161435 13 countdown timer needs to be sync'd to start button press.
gatedClock 87:147e2b08fae6 14 this could not be done, use granularity setting instead.
gatedClock 80:e3e1a2161435 15
gatedClock 120:64a969984af2 16 global variables considerations (mutex)
gatedClock 120:64a969984af2 17 the global variables associated with joystick button presses are
gatedClock 120:64a969984af2 18 in the structure 'tButtons' (instance 'giButtons'). ISRs store that a
gatedClock 120:64a969984af2 19 button has been pressed in this struct, and since mutex can not be called
gatedClock 120:64a969984af2 20 within an interrupt, no mutex is used on these buttons.
gatedClock 120:64a969984af2 21 only the ISRs are 'authorized' to set those variables, and the bottom-half
gatedClock 120:64a969984af2 22 of the ISRs, 'threadButtonStateManager', is authorized to clear them once
gatedClock 120:64a969984af2 23 'threadButtonStateManager' has forwarded the fact that the buttons were
gatedClock 120:64a969984af2 24 pressed. I don't expect there to be any collision of writing the variables.
gatedClock 120:64a969984af2 25
gatedClock 120:64a969984af2 26
gatedClock 120:64a969984af2 27
gatedClock 120:64a969984af2 28
gatedClock 80:e3e1a2161435 29
gatedClock 0:fcca4db7b32a 30 -----includes-----------------------------------//----------------------------*/
gatedClock 0:fcca4db7b32a 31 #include "mbed.h" // mbed class.
gatedClock 10:2b0a9fc39109 32 #include "rtos.h" // rtos class.
gatedClock 39:4e7e4d935a87 33 #include "LM75B.h" // thermometer class.
gatedClock 10:2b0a9fc39109 34 #include "C12832_lcd.h" // LCD class.
gatedClock 0:fcca4db7b32a 35 //---defines------------------------------------//------------------------------
gatedClock 9:cfdb9aa5857c 36 #define LCD1 lcd.locate(0, 0); // LCD line 1.
gatedClock 9:cfdb9aa5857c 37 #define LCD2 lcd.locate(0,11); // LCD line 2.
gatedClock 9:cfdb9aa5857c 38 #define LCD3 lcd.locate(0,22); // LCD line 3.
gatedClock 9:cfdb9aa5857c 39
gatedClock 10:2b0a9fc39109 40
gatedClock 66:4a0006fa5cc1 41 #define DEBOUNCEmS 16 // debounce wait in mS.
gatedClock 19:92b11e30aaaf 42 #define uS_TIMEOUT 100 // Timer uS timeout.
gatedClock 19:92b11e30aaaf 43 #define LBSIG 1 // left button signal code.
gatedClock 33:34c1bef3c4ff 44 #define PIPEuS 1000 // pipeline clock period.
gatedClock 19:92b11e30aaaf 45 #define SLOWCLOCKuS 500000 // slow-clock period.
gatedClock 39:4e7e4d935a87 46 #define TEMPCLOCKS 1 // temperature-measuring period in S.
gatedClock 26:bff592483cb1 47 #define PIPEDATASIZE 8 // dimension of tPipeData.
gatedClock 44:d16e813e61ef 48 #define THREAD_1_WAITmS 400 // thread 1 wait in mS.
gatedClock 99:a3e8344024c0 49 #define THREAD_2_WAITmS 40 // LCD thread wait.
gatedClock 67:1d9c85a4c3c1 50 #define THREAD_3_WAITmS 80 // thread 3 wait in mS.
gatedClock 66:4a0006fa5cc1 51 #define THREAD_4_WAITmS 1 // thread 4 wait in mS.
gatedClock 121:c9d28cd59460 52 #define THREAD_5_WAITmS 1 // FSM thread wait.
gatedClock 44:d16e813e61ef 53 #define HB_MODULO 1024 // heartbeat modulo divisor.
gatedClock 50:2928c3cbdcc3 54
gatedClock 54:b0e7352d2516 55 #define MSG_INC_TIME 0x01
gatedClock 54:b0e7352d2516 56 #define MSG_DEC_TIME 0x02
gatedClock 58:ec630b6dd9b1 57 #define MSG_START 0x04
gatedClock 58:ec630b6dd9b1 58 #define MSG_STOP 0x08
gatedClock 58:ec630b6dd9b1 59 #define MSG_OPEN 0x10
gatedClock 58:ec630b6dd9b1 60 #define MSG_CLOSED 0x20
gatedClock 57:0432c68ad232 61
gatedClock 78:7df160e0db7b 62 #define FSM_IDLE 0x01 // cook-state state-machine.
gatedClock 78:7df160e0db7b 63 #define FSM_COOK 0x02 // cook-state state-machine.
gatedClock 78:7df160e0db7b 64 #define FSM_PAUSE 0x04 // cook-state state-machine.
gatedClock 78:7df160e0db7b 65 #define FSM_CONTINUE 0x08 // cook-state state-machine.
gatedClock 78:7df160e0db7b 66 #define FSM_DONE 0x10 // cook-state state-machine.
gatedClock 65:e39360da5929 67
gatedClock 71:4a5f256ecf7c 68 #define RT_PRELOAD 0x01 // remaining-time preload.
gatedClock 71:4a5f256ecf7c 69 #define RT_DECREMENT 0x02 // remaining-time decrement.
gatedClock 71:4a5f256ecf7c 70 #define RT_PAUSE 0x03 // remaining-time don't change.
gatedClock 71:4a5f256ecf7c 71 #define RT_CLEAR 0x04 // remaining-time set to zero.
gatedClock 71:4a5f256ecf7c 72
gatedClock 97:ee840478d6b3 73 #define TEMP_READ 0x01 // temperature synthesizer control.
gatedClock 97:ee840478d6b3 74 #define TEMP_CALC 0x02 // temperature synthesizer control.
gatedClock 97:ee840478d6b3 75 #define TEMP_FREEZE 0x03 // temperature synthesizer control.
gatedClock 94:551b1df4b10c 76
gatedClock 86:388c2b4b7cf5 77 #define GRANULARITY 0x400 // 1-second countdown ticker granularity.
gatedClock 88:0b1b812945eb 78 #define MAXSECONDS 180 // maximum microwave-on time.
gatedClock 89:290c96cd027f 79 #define BEEPTIME 3 // beep duration in S.
gatedClock 94:551b1df4b10c 80 #define BEEPFREQ 300 // beep frequency in Hz.
gatedClock 86:388c2b4b7cf5 81
gatedClock 99:a3e8344024c0 82 #define TIMEINC 10 // time increment in seconds.
gatedClock 0:fcca4db7b32a 83 //--global_definitions--------------------------//------------------------------
gatedClock 26:bff592483cb1 84 struct tButtons // button ISR updates.
gatedClock 26:bff592483cb1 85 {
gatedClock 26:bff592483cb1 86 char cLeftButton; // cooktime +60S.
gatedClock 26:bff592483cb1 87 char cRightButton; // cooktime -60S.
gatedClock 26:bff592483cb1 88 char cTopButton; // start cook.
gatedClock 26:bff592483cb1 89 char cBottomButton; // stop cook.
gatedClock 58:ec630b6dd9b1 90 char cCenterButton; // center button pressed.
gatedClock 53:8c2baf5623c8 91 char cDoorOpen; // door open.
gatedClock 26:bff592483cb1 92 };
gatedClock 34:b449d2a7c786 93
gatedClock 71:4a5f256ecf7c 94 struct tRemainingTime // remaining time related.
gatedClock 71:4a5f256ecf7c 95 {
gatedClock 71:4a5f256ecf7c 96 char cControl; // countdown control.
gatedClock 110:a3b95ccfaed6 97 char cBeepEnable; // beep control.
gatedClock 120:64a969984af2 98 int dTotalTime; // initialize to this.
gatedClock 120:64a969984af2 99 int dRemainingTime; // the countdown value.
gatedClock 120:64a969984af2 100 };
gatedClock 120:64a969984af2 101
gatedClock 120:64a969984af2 102 struct tMagnetron // magnetron control.
gatedClock 120:64a969984af2 103 {
gatedClock 118:d0e057d79acc 104 char cMagnetron; // magnetron blink control.
gatedClock 118:d0e057d79acc 105 char cCarousel; // carousel blink control.
gatedClock 71:4a5f256ecf7c 106 };
gatedClock 71:4a5f256ecf7c 107
gatedClock 80:e3e1a2161435 108 struct tLCD // LCD related.
gatedClock 80:e3e1a2161435 109 {
gatedClock 80:e3e1a2161435 110 int dTotalCookTime; // display time in seconds.
gatedClock 80:e3e1a2161435 111 int dRemainingTime; // display time in seconds.
gatedClock 80:e3e1a2161435 112 float fCelsius; // temperature in celsius.
gatedClock 80:e3e1a2161435 113 };
gatedClock 80:e3e1a2161435 114
gatedClock 104:5e49dbe5038a 115 Queue<int, 1> queueModTotalTime; // modify total time.
gatedClock 104:5e49dbe5038a 116 Queue<int, 1> queueUpdateFSM; // tell FSM what button was pressed.
gatedClock 61:8026a9fc0cf1 117 Queue<int, 1> queueUpdateRemainingTime; // message to update remaining time.
gatedClock 71:4a5f256ecf7c 118 Queue<int, 1> queueSetRemainingTime; // tell countdown it's start time.
gatedClock 94:551b1df4b10c 119 Queue<int, 1> queueTemperatureControl; // control the temperature synthesizer.
gatedClock 97:ee840478d6b3 120 Queue<int, 1> queueSuppressTimeAdjust; // total time control.
gatedClock 98:156298be5ba2 121 Queue<int, 1> queueClearTotalTime; // total time control.
gatedClock 0:fcca4db7b32a 122 //--global_variables----------------------------//------------------------------
gatedClock 108:da479434bd7d 123 tButtons giButtons; // ISR button updates.
gatedClock 71:4a5f256ecf7c 124 tRemainingTime giRemainingTime; // structure instance.
gatedClock 120:64a969984af2 125 tMagnetron giMagnetron; // structure instance.
gatedClock 80:e3e1a2161435 126 tLCD giLCD; // structure instance.
gatedClock 0:fcca4db7b32a 127 //--global_instances----------------------------//------------------------------
gatedClock 55:17f3354da63a 128 Serial pc(USBTX, USBRX); // PuTTY terminal communication.
gatedClock 39:4e7e4d935a87 129 LM75B temperature(p28,p27); // on-board thermometer.
gatedClock 9:cfdb9aa5857c 130 C12832_LCD lcd; // LCD object.
gatedClock 53:8c2baf5623c8 131 DigitalOut led0(LED4); // magnetron.
gatedClock 39:4e7e4d935a87 132 DigitalOut led1(LED3);
gatedClock 39:4e7e4d935a87 133 DigitalOut led2(LED2);
gatedClock 39:4e7e4d935a87 134 DigitalOut led3(LED1);
gatedClock 91:b54500888b67 135 DigitalOut speaker(p26); // speaker device.
gatedClock 0:fcca4db7b32a 136
gatedClock 0:fcca4db7b32a 137 InterruptIn iJoyStickUp (p15); // joystick up rising edge.
gatedClock 0:fcca4db7b32a 138 InterruptIn iJoyStickDown (p12); // joystick down rising edge.
gatedClock 0:fcca4db7b32a 139 InterruptIn iJoyStickLeft (p13); // joystick left rising edge.
gatedClock 0:fcca4db7b32a 140 InterruptIn iJoyStickRight (p16); // joystick right rising edge.
gatedClock 0:fcca4db7b32a 141 InterruptIn iJoyStickCenter(p14); // 1 if joystick middle pressed.
gatedClock 66:4a0006fa5cc1 142
gatedClock 66:4a0006fa5cc1 143 Timer debounceTimer; // button debounce timer.
gatedClock 89:290c96cd027f 144 Timer beepTimer; // beep-duration timer.
gatedClock 94:551b1df4b10c 145 Timer temperatureTimer; // how often to raise temperature.
gatedClock 106:5137c38345d3 146
gatedClock 50:2928c3cbdcc3 147 Ticker tickerButtonStateManager; // manage the button states.
gatedClock 101:33dc62b6b728 148 Ticker tickerCookCountdown; // remaining cook time.
gatedClock 101:33dc62b6b728 149 Ticker tickerBeep; // beeper ticker.
gatedClock 117:b9e18163c282 150 Ticker tickerBlinkMagnetron; // magnetron LED blinker.
gatedClock 117:b9e18163c282 151 Ticker tickerBlinkCarousel; // caroulsel LED blinker.
gatedClock 121:c9d28cd59460 152
gatedClock 121:c9d28cd59460 153 Mutex mutexControl; // for giRemainingTime.cControl.
gatedClock 0:fcca4db7b32a 154 //-------prototypes-----------------------------//------------------------------
gatedClock 49:56f790977983 155
gatedClock 19:92b11e30aaaf 156 void slowClock(); // 1Hz or thereabouts.
gatedClock 49:56f790977983 157
gatedClock 9:cfdb9aa5857c 158 void initialization(); // initialize settings.
gatedClock 13:21f27ba467c2 159
gatedClock 13:21f27ba467c2 160 void ISRleftButtonRising(); // cook-time increase.
gatedClock 13:21f27ba467c2 161 void ISRleftButtonFalling(); // button-release debounce.
gatedClock 13:21f27ba467c2 162 void ISRrightButtonRising(); // cook-time decrease.
gatedClock 13:21f27ba467c2 163 void ISRrightButtonFalling(); // button-release debounce.
gatedClock 13:21f27ba467c2 164 void ISRtopButtonRising(); // cook start.
gatedClock 13:21f27ba467c2 165 void ISRtopButtonFalling(); // button-release debounce.
gatedClock 13:21f27ba467c2 166 void ISRbottomButtonRising(); // cook stop.
gatedClock 13:21f27ba467c2 167 void ISRbottomButtonFalling(); // button-release debounce.
gatedClock 13:21f27ba467c2 168 void ISRcenterButtonRising(); // door state toggle.
gatedClock 13:21f27ba467c2 169 void ISRcenterButtonFalling(); // button-release debounce.
gatedClock 16:db7f0b3b2605 170 void disableSignalWaiting(); // break from signal waiting.
gatedClock 39:4e7e4d935a87 171
gatedClock 54:b0e7352d2516 172 void threadButtonStateManager(void const *args);
gatedClock 50:2928c3cbdcc3 173 void threadTotalTimeControl(void const *args);
gatedClock 57:0432c68ad232 174 void threadCookStateFSM(void const *args);
gatedClock 71:4a5f256ecf7c 175 void tickCookRemainingTime(); // remaining time countdown.
gatedClock 50:2928c3cbdcc3 176
gatedClock 40:7afff79f0d8b 177 void temperatureThread(void const *args); // temperature measurement.
gatedClock 42:266d5bbbfd19 178 void LCDthread (void const *args); // LCD display thread.
gatedClock 103:c5e24ac35a25 179
gatedClock 101:33dc62b6b728 180 void tickerBeeper(); // beep oscillator.
gatedClock 117:b9e18163c282 181 void tickerMagnetron(); // blink magnetron LED.
gatedClock 117:b9e18163c282 182 void tickerCarousel(); // blink carousel LED.
gatedClock 0:fcca4db7b32a 183 //==============================================//==============================
gatedClock 0:fcca4db7b32a 184 int main(void)
gatedClock 0:fcca4db7b32a 185 {
gatedClock 16:db7f0b3b2605 186
gatedClock 112:465958b0e94e 187 initialization(); // initialize variables.
gatedClock 112:465958b0e94e 188
gatedClock 112:465958b0e94e 189 // ISR setup.
gatedClock 14:d3bb343cd5b2 190 iJoyStickLeft.rise (&ISRleftButtonRising);
gatedClock 14:d3bb343cd5b2 191 iJoyStickLeft.fall (&ISRleftButtonFalling);
gatedClock 9:cfdb9aa5857c 192
gatedClock 14:d3bb343cd5b2 193 iJoyStickRight.rise(&ISRrightButtonRising);
gatedClock 14:d3bb343cd5b2 194 iJoyStickRight.fall(&ISRrightButtonFalling);
gatedClock 14:d3bb343cd5b2 195
gatedClock 14:d3bb343cd5b2 196 iJoyStickUp.rise (&ISRtopButtonRising);
gatedClock 14:d3bb343cd5b2 197 iJoyStickUp.fall (&ISRtopButtonFalling);
gatedClock 9:cfdb9aa5857c 198
gatedClock 14:d3bb343cd5b2 199 iJoyStickDown.rise (&ISRbottomButtonRising);
gatedClock 14:d3bb343cd5b2 200 iJoyStickDown.fall (&ISRbottomButtonFalling);
gatedClock 7:9fbd1d540863 201
gatedClock 14:d3bb343cd5b2 202 iJoyStickCenter.rise(&ISRcenterButtonRising);
gatedClock 14:d3bb343cd5b2 203 iJoyStickCenter.fall(&ISRcenterButtonFalling);
gatedClock 9:cfdb9aa5857c 204
gatedClock 66:4a0006fa5cc1 205 debounceTimer.start(); // kick-off debounce timer.
gatedClock 66:4a0006fa5cc1 206
gatedClock 102:5735d9cbad00 207
gatedClock 112:465958b0e94e 208 // kick-off tickers.
gatedClock 112:465958b0e94e 209 tickerCookCountdown.attach_us(&tickCookRemainingTime,1000000/GRANULARITY);
gatedClock 112:465958b0e94e 210 tickerBeep.attach_us (&tickerBeeper ,2000);
gatedClock 117:b9e18163c282 211 tickerBlinkMagnetron.attach_us(&tickerMagnetron,250000);
gatedClock 117:b9e18163c282 212 tickerBlinkCarousel.attach_us(&tickerCarousel,250000);
gatedClock 64:255295f1d782 213
gatedClock 112:465958b0e94e 214 // kick-off threads.
gatedClock 70:7c0743c28b11 215 Thread thread_1(temperatureThread ,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
gatedClock 112:465958b0e94e 216 Thread thread_2(LCDthread ,NULL,osPriorityNormal,DEFAULT_STACK_SIZE,NULL);
gatedClock 70:7c0743c28b11 217 Thread thread_3(threadTotalTimeControl ,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
gatedClock 112:465958b0e94e 218 Thread thread_4(threadButtonStateManager,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
gatedClock 70:7c0743c28b11 219 Thread thread_5(threadCookStateFSM ,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL);
gatedClock 70:7c0743c28b11 220
gatedClock 52:8ba6a0c91a89 221
gatedClock 112:465958b0e94e 222 while(1) Thread::wait(10000); // execute microwave controller.
gatedClock 19:92b11e30aaaf 223 }
gatedClock 19:92b11e30aaaf 224 /*----------------------------------------------//----------------------------*/
gatedClock 59:5e45b5e4a874 225
gatedClock 59:5e45b5e4a874 226 // this serves as the bottom-half for all of the button-press IRSs.
gatedClock 59:5e45b5e4a874 227 // it sends button-status messages to other threads, and it also
gatedClock 59:5e45b5e4a874 228 // clears the button-state globals to prepare them for the next
gatedClock 59:5e45b5e4a874 229 // button press.
gatedClock 59:5e45b5e4a874 230
gatedClock 59:5e45b5e4a874 231
gatedClock 54:b0e7352d2516 232 void threadButtonStateManager(void const *args)
gatedClock 50:2928c3cbdcc3 233 {
gatedClock 56:18cff6eb91db 234 int dMessage; // message.
gatedClock 50:2928c3cbdcc3 235
gatedClock 54:b0e7352d2516 236 while(1) // thread loop.
gatedClock 67:1d9c85a4c3c1 237 {
gatedClock 54:b0e7352d2516 238 //--- // TOTAL TIME CONTROL.
gatedClock 56:18cff6eb91db 239
gatedClock 56:18cff6eb91db 240 // encoded integers will be sent,
gatedClock 56:18cff6eb91db 241 // not pointers.
gatedClock 50:2928c3cbdcc3 242
gatedClock 108:da479434bd7d 243 if (giButtons.cLeftButton) // total time increment button.
gatedClock 50:2928c3cbdcc3 244 {
gatedClock 54:b0e7352d2516 245 dMessage = MSG_INC_TIME; // set message.
gatedClock 120:64a969984af2 246 queueModTotalTime.put((int *) dMessage,1);
gatedClock 108:da479434bd7d 247 giButtons.cLeftButton = 0; // clear the button state.
gatedClock 50:2928c3cbdcc3 248 }
gatedClock 67:1d9c85a4c3c1 249
gatedClock 108:da479434bd7d 250 if (giButtons.cRightButton) // total time decrement button.
gatedClock 50:2928c3cbdcc3 251 {
gatedClock 54:b0e7352d2516 252 dMessage = MSG_DEC_TIME; // set message.
gatedClock 120:64a969984af2 253 queueModTotalTime.put((int *) dMessage,1);
gatedClock 108:da479434bd7d 254 giButtons.cRightButton = 0; // clear the button state.
gatedClock 50:2928c3cbdcc3 255 }
gatedClock 67:1d9c85a4c3c1 256
gatedClock 59:5e45b5e4a874 257 //--- // COOK-STATE FSM.
gatedClock 59:5e45b5e4a874 258
gatedClock 108:da479434bd7d 259 if (giButtons.cTopButton) // start-cook button.
gatedClock 58:ec630b6dd9b1 260 {
gatedClock 59:5e45b5e4a874 261 dMessage = MSG_START; // set message.
gatedClock 120:64a969984af2 262 queueUpdateFSM.put((int *) dMessage,1);
gatedClock 108:da479434bd7d 263 giButtons.cTopButton = 0; // clear the button state.
gatedClock 58:ec630b6dd9b1 264 }
gatedClock 67:1d9c85a4c3c1 265
gatedClock 108:da479434bd7d 266 if (giButtons.cBottomButton) // stop-cook button.
gatedClock 58:ec630b6dd9b1 267 {
gatedClock 59:5e45b5e4a874 268 dMessage = MSG_STOP; // set message.
gatedClock 120:64a969984af2 269 queueUpdateFSM.put((int *) dMessage,1);
gatedClock 108:da479434bd7d 270 giButtons.cBottomButton = 0; // clear the button state.
gatedClock 58:ec630b6dd9b1 271 }
gatedClock 67:1d9c85a4c3c1 272
gatedClock 108:da479434bd7d 273 if (giButtons.cCenterButton) // door-state-toggle.
gatedClock 58:ec630b6dd9b1 274 {
gatedClock 108:da479434bd7d 275 dMessage = giButtons.cDoorOpen; // determined in ISR.
gatedClock 120:64a969984af2 276 queueUpdateFSM.put((int *) dMessage,1);
gatedClock 108:da479434bd7d 277 giButtons.cCenterButton = 0; // clear the button state.
gatedClock 58:ec630b6dd9b1 278 }
gatedClock 59:5e45b5e4a874 279 //---
gatedClock 58:ec630b6dd9b1 280
gatedClock 54:b0e7352d2516 281 Thread::wait(THREAD_4_WAITmS); // multitasking.
gatedClock 54:b0e7352d2516 282 } // thread loop.
gatedClock 54:b0e7352d2516 283 } // threadButtonStateManager.
gatedClock 50:2928c3cbdcc3 284 /*----------------------------------------------//----------------------------*/
gatedClock 51:e5ec74c49b01 285 // total time controller.
gatedClock 51:e5ec74c49b01 286 void threadTotalTimeControl(void const *args)
gatedClock 50:2928c3cbdcc3 287 {
gatedClock 51:e5ec74c49b01 288 static int dTotalTime = 0; // total time variable.
gatedClock 60:e10bf95bbc96 289 int dMessage; // message.
gatedClock 97:ee840478d6b3 290 int dSuppress; // 1 to suppress operation.
gatedClock 51:e5ec74c49b01 291 osEvent queueEvent; // queue event.
gatedClock 115:6390d9b9be07 292
gatedClock 97:ee840478d6b3 293 dSuppress = 0; // initialize.
gatedClock 97:ee840478d6b3 294
gatedClock 50:2928c3cbdcc3 295 while(1) // thread loop.
gatedClock 50:2928c3cbdcc3 296 {
gatedClock 98:156298be5ba2 297 // if FSM tells this to clear
gatedClock 98:156298be5ba2 298 // the total time.
gatedClock 98:156298be5ba2 299 queueEvent = queueClearTotalTime.get(1);
gatedClock 98:156298be5ba2 300 if (queueEvent.status == osEventMessage)
gatedClock 98:156298be5ba2 301 {
gatedClock 98:156298be5ba2 302 dTotalTime = 0;
gatedClock 115:6390d9b9be07 303 queueSetRemainingTime.put((int *) dTotalTime,1);
gatedClock 98:156298be5ba2 304 giRemainingTime.dTotalTime = dTotalTime;
gatedClock 98:156298be5ba2 305 }
gatedClock 98:156298be5ba2 306
gatedClock 97:ee840478d6b3 307
gatedClock 97:ee840478d6b3 308 // suppression mail from FSM.
gatedClock 97:ee840478d6b3 309 queueEvent = queueSuppressTimeAdjust.get(1);
gatedClock 97:ee840478d6b3 310 if (queueEvent.status == osEventMessage)
gatedClock 97:ee840478d6b3 311 {
gatedClock 97:ee840478d6b3 312 dSuppress = (int) queueEvent.value.p;
gatedClock 97:ee840478d6b3 313 }
gatedClock 97:ee840478d6b3 314
gatedClock 113:8111b9cd15ce 315
gatedClock 55:17f3354da63a 316 queueEvent = queueModTotalTime.get(1); // get message.
gatedClock 51:e5ec74c49b01 317 if (queueEvent.status == osEventMessage)
gatedClock 51:e5ec74c49b01 318 {
gatedClock 56:18cff6eb91db 319 dMessage = (int) queueEvent.value.p; // interpret as integer, not pointer.
gatedClock 54:b0e7352d2516 320
gatedClock 97:ee840478d6b3 321 if (!dSuppress) // increment total time.
gatedClock 99:a3e8344024c0 322 if (dMessage == MSG_INC_TIME) dTotalTime += TIMEINC;
gatedClock 54:b0e7352d2516 323
gatedClock 97:ee840478d6b3 324 if (!dSuppress) // decrement total time.
gatedClock 99:a3e8344024c0 325 if (dMessage == MSG_DEC_TIME) dTotalTime -= TIMEINC;
gatedClock 65:e39360da5929 326
gatedClock 65:e39360da5929 327 // saturations.
gatedClock 65:e39360da5929 328 if (dTotalTime > 180) dTotalTime = 180;
gatedClock 65:e39360da5929 329 if (dTotalTime < 0) dTotalTime = 0;
gatedClock 65:e39360da5929 330
gatedClock 115:6390d9b9be07 331 queueSetRemainingTime.put((int *) dTotalTime,1);
gatedClock 75:c2894d531f42 332 giRemainingTime.dTotalTime = dTotalTime;
gatedClock 51:e5ec74c49b01 333 }
gatedClock 97:ee840478d6b3 334
gatedClock 81:12bc26973cb8 335
gatedClock 50:2928c3cbdcc3 336 Thread::wait(THREAD_3_WAITmS); // multitasking.
gatedClock 50:2928c3cbdcc3 337 } // thread loop.
gatedClock 50:2928c3cbdcc3 338 } // threadTotalTimeControl.
gatedClock 33:34c1bef3c4ff 339 /*----------------------------------------------//----------------------------*/
gatedClock 57:0432c68ad232 340 void threadCookStateFSM(void const *args) // cook-cycle FSM.
gatedClock 57:0432c68ad232 341 {
gatedClock 113:8111b9cd15ce 342 int dFSMstate = FSM_IDLE; // state of this FSM.
gatedClock 113:8111b9cd15ce 343 int dFSMstateLast = FSM_IDLE; // previous FSM state.
gatedClock 113:8111b9cd15ce 344 int dButtonState = 0; // received button state.
gatedClock 113:8111b9cd15ce 345 int dRemainingTime = 0; // received remaining time.
gatedClock 62:48e7c196e2a5 346
gatedClock 113:8111b9cd15ce 347 int dButtonStart = 0; // received button state.
gatedClock 113:8111b9cd15ce 348 int dButtonStop = 0; // received button state.
gatedClock 113:8111b9cd15ce 349 int dDoorOpen = 0; // received door state.
gatedClock 113:8111b9cd15ce 350
gatedClock 81:12bc26973cb8 351 osEvent queueEvent; // from button state manager.
gatedClock 113:8111b9cd15ce 352
gatedClock 89:290c96cd027f 353 beepTimer.start(); // run the beep timer.
gatedClock 106:5137c38345d3 354
gatedClock 113:8111b9cd15ce 355 // constantly read live temperature.
gatedClock 94:551b1df4b10c 356 queueTemperatureControl.put((int *) TEMP_READ,1);
gatedClock 94:551b1df4b10c 357
gatedClock 57:0432c68ad232 358 while(1) // thread loop.
gatedClock 57:0432c68ad232 359 {
gatedClock 113:8111b9cd15ce 360
gatedClock 74:4debb8f2e21d 361 switch (dFSMstate) // cook-mode state machine.
gatedClock 62:48e7c196e2a5 362 {
gatedClock 82:73fa3fe8a217 363 //---
gatedClock 73:44739860198b 364 case FSM_IDLE : // IDLE.
gatedClock 73:44739860198b 365 {
gatedClock 120:64a969984af2 366 giMagnetron.cMagnetron = 0; // highest priority.
gatedClock 120:64a969984af2 367 giMagnetron.cCarousel = 0; // turn on carousel.
gatedClock 119:e14b0f6e97cb 368
gatedClock 75:c2894d531f42 369 if (dFSMstate != dFSMstateLast) // if just entered state.
gatedClock 114:fbe9ef1630c1 370 {
gatedClock 114:fbe9ef1630c1 371 // live read of temperature,
gatedClock 114:fbe9ef1630c1 372 // allow total time adjustments,
gatedClock 114:fbe9ef1630c1 373 // clear total time.
gatedClock 114:fbe9ef1630c1 374
gatedClock 94:551b1df4b10c 375 queueTemperatureControl.put((int *) TEMP_READ,1);
gatedClock 97:ee840478d6b3 376 queueSuppressTimeAdjust.put((int*) 0,1);
gatedClock 98:156298be5ba2 377 queueClearTotalTime.put ((int*) 1,1);
gatedClock 75:c2894d531f42 378 }
gatedClock 80:e3e1a2161435 379
gatedClock 119:e14b0f6e97cb 380
gatedClock 119:e14b0f6e97cb 381
gatedClock 114:fbe9ef1630c1 382 // set global LCD data.
gatedClock 80:e3e1a2161435 383 giLCD.dTotalCookTime = giRemainingTime.dTotalTime;
gatedClock 80:e3e1a2161435 384 giLCD.dRemainingTime = 0; // suppress remaining time display.
gatedClock 114:fbe9ef1630c1 385
gatedClock 114:fbe9ef1630c1 386 // remaining time loaded with total time.
gatedClock 121:c9d28cd59460 387 mutexControl.lock();
gatedClock 121:c9d28cd59460 388 giRemainingTime.cControl = RT_PRELOAD;
gatedClock 121:c9d28cd59460 389 mutexControl.unlock();
gatedClock 76:74c454c9d75b 390 dFSMstateLast = dFSMstate; // determine next state.
gatedClock 114:fbe9ef1630c1 391
gatedClock 114:fbe9ef1630c1 392 // to FSM_COOK if the start button was
gatedClock 114:fbe9ef1630c1 393 // pressed, the door is closed, and the
gatedClock 114:fbe9ef1630c1 394 // remaining time is more than zero.
gatedClock 114:fbe9ef1630c1 395
gatedClock 75:c2894d531f42 396 if ((dButtonStart == 1) && (dDoorOpen == 0) && (giRemainingTime.dTotalTime > 0)) dFSMstate = FSM_COOK;
gatedClock 73:44739860198b 397 break;
gatedClock 73:44739860198b 398 }
gatedClock 82:73fa3fe8a217 399 //---
gatedClock 73:44739860198b 400 case FSM_COOK : // COOK.
gatedClock 73:44739860198b 401 {
gatedClock 120:64a969984af2 402 giMagnetron.cMagnetron = 1; // highest priority.
gatedClock 120:64a969984af2 403 giMagnetron.cCarousel = 1; // turn on carousel.
gatedClock 119:e14b0f6e97cb 404
gatedClock 75:c2894d531f42 405 if (dFSMstate != dFSMstateLast) // if just entered state.
gatedClock 75:c2894d531f42 406 {
gatedClock 119:e14b0f6e97cb 407
gatedClock 119:e14b0f6e97cb 408
gatedClock 114:fbe9ef1630c1 409 // start decrementing remaining time.
gatedClock 114:fbe9ef1630c1 410 // temperature synthesizer is now
gatedClock 114:fbe9ef1630c1 411 // calculating the temperature,
gatedClock 114:fbe9ef1630c1 412 // user can no longer adjust total time.
gatedClock 121:c9d28cd59460 413 mutexControl.lock();
gatedClock 75:c2894d531f42 414 giRemainingTime.cControl = RT_DECREMENT;
gatedClock 121:c9d28cd59460 415 mutexControl.unlock();
gatedClock 94:551b1df4b10c 416 queueTemperatureControl.put((int *) TEMP_CALC,1);
gatedClock 97:ee840478d6b3 417 queueSuppressTimeAdjust.put((int*) 1,1);
gatedClock 75:c2894d531f42 418 }
gatedClock 80:e3e1a2161435 419
gatedClock 114:fbe9ef1630c1 420 // update global LCD data.
gatedClock 80:e3e1a2161435 421 giLCD.dTotalCookTime = giRemainingTime.dTotalTime;
gatedClock 80:e3e1a2161435 422 giLCD.dRemainingTime = giRemainingTime.dRemainingTime;
gatedClock 114:fbe9ef1630c1 423
gatedClock 80:e3e1a2161435 424
gatedClock 80:e3e1a2161435 425
gatedClock 76:74c454c9d75b 426
gatedClock 76:74c454c9d75b 427 dFSMstateLast = dFSMstate; // determine next state.
gatedClock 114:fbe9ef1630c1 428
gatedClock 114:fbe9ef1630c1 429 // pause on door-open if remaining time.
gatedClock 114:fbe9ef1630c1 430
gatedClock 78:7df160e0db7b 431 if ((dDoorOpen == 1) && (dRemainingTime > 0)) dFSMstate = FSM_PAUSE;
gatedClock 78:7df160e0db7b 432 else
gatedClock 114:fbe9ef1630c1 433
gatedClock 114:fbe9ef1630c1 434 // stop button -> idle state.
gatedClock 76:74c454c9d75b 435 if (dButtonStop) dFSMstate = FSM_IDLE;
gatedClock 78:7df160e0db7b 436 else
gatedClock 114:fbe9ef1630c1 437
gatedClock 114:fbe9ef1630c1 438 // beeper state once countdown complete.
gatedClock 78:7df160e0db7b 439 if (dRemainingTime <= 0) dFSMstate = FSM_DONE;
gatedClock 73:44739860198b 440 break;
gatedClock 73:44739860198b 441 }
gatedClock 82:73fa3fe8a217 442 //---
gatedClock 73:44739860198b 443 case FSM_PAUSE : // PAUSE.
gatedClock 73:44739860198b 444 {
gatedClock 120:64a969984af2 445 giMagnetron.cMagnetron = 0; // highest priority.
gatedClock 120:64a969984af2 446 giMagnetron.cCarousel = 0; // turn on carousel.
gatedClock 75:c2894d531f42 447
gatedClock 75:c2894d531f42 448 if (dFSMstate != dFSMstateLast) // if just entered state.
gatedClock 75:c2894d531f42 449 {
gatedClock 114:fbe9ef1630c1 450 // suspend synthesized temperature calculation.
gatedClock 97:ee840478d6b3 451 queueTemperatureControl.put((int *) TEMP_FREEZE,1);
gatedClock 75:c2894d531f42 452 }
gatedClock 80:e3e1a2161435 453
gatedClock 114:fbe9ef1630c1 454 // update LCD globals.
gatedClock 80:e3e1a2161435 455 giLCD.dTotalCookTime = giRemainingTime.dTotalTime;
gatedClock 80:e3e1a2161435 456 giLCD.dRemainingTime = giRemainingTime.dRemainingTime;
gatedClock 80:e3e1a2161435 457
gatedClock 80:e3e1a2161435 458
gatedClock 121:c9d28cd59460 459 mutexControl.lock();
gatedClock 114:fbe9ef1630c1 460 giRemainingTime.cControl = RT_PAUSE;// pause remaining time countdown.
gatedClock 121:c9d28cd59460 461 mutexControl.unlock();
gatedClock 114:fbe9ef1630c1 462
gatedClock 114:fbe9ef1630c1 463 dFSMstateLast = dFSMstate; // determine next state.
gatedClock 114:fbe9ef1630c1 464
gatedClock 114:fbe9ef1630c1 465
gatedClock 114:fbe9ef1630c1 466 // continue if user hits start button,
gatedClock 114:fbe9ef1630c1 467 // and the door is closed, and there
gatedClock 114:fbe9ef1630c1 468 // is some remaining time.
gatedClock 114:fbe9ef1630c1 469
gatedClock 78:7df160e0db7b 470 if ((dButtonStart == 1) && (dDoorOpen == 0) && (giRemainingTime.dTotalTime > 0)) dFSMstate = FSM_CONTINUE;
gatedClock 75:c2894d531f42 471 else
gatedClock 114:fbe9ef1630c1 472
gatedClock 114:fbe9ef1630c1 473 // to idle if user hits stop button.
gatedClock 78:7df160e0db7b 474 if (dButtonStop) dFSMstate = FSM_IDLE;
gatedClock 73:44739860198b 475 break;
gatedClock 73:44739860198b 476 }
gatedClock 78:7df160e0db7b 477
gatedClock 82:73fa3fe8a217 478 //---
gatedClock 79:4286319e48b4 479 case FSM_CONTINUE : // CONTINUE.
gatedClock 78:7df160e0db7b 480 {
gatedClock 120:64a969984af2 481 giMagnetron.cMagnetron = 1; // highest priority.
gatedClock 120:64a969984af2 482 giMagnetron.cCarousel = 1; // turn on carousel.
gatedClock 78:7df160e0db7b 483
gatedClock 78:7df160e0db7b 484 if (dFSMstate != dFSMstateLast) // if just entered state.
gatedClock 78:7df160e0db7b 485 {
gatedClock 114:fbe9ef1630c1 486 // continue calculating synthetic temperature.
gatedClock 97:ee840478d6b3 487 queueTemperatureControl.put((int *) TEMP_CALC,1);
gatedClock 78:7df160e0db7b 488 }
gatedClock 80:e3e1a2161435 489
gatedClock 114:fbe9ef1630c1 490 // update LCD globals.
gatedClock 80:e3e1a2161435 491 giLCD.dTotalCookTime = giRemainingTime.dTotalTime;
gatedClock 80:e3e1a2161435 492 giLCD.dRemainingTime = giRemainingTime.dRemainingTime;
gatedClock 114:fbe9ef1630c1 493
gatedClock 80:e3e1a2161435 494
gatedClock 114:fbe9ef1630c1 495 // continue decrementing time.
gatedClock 121:c9d28cd59460 496 mutexControl.lock();
gatedClock 78:7df160e0db7b 497 giRemainingTime.cControl = RT_DECREMENT;
gatedClock 121:c9d28cd59460 498 mutexControl.unlock();
gatedClock 114:fbe9ef1630c1 499
gatedClock 114:fbe9ef1630c1 500 dFSMstateLast = dFSMstate; // determine next state.
gatedClock 114:fbe9ef1630c1 501
gatedClock 114:fbe9ef1630c1 502 // beep state when no more time.
gatedClock 114:fbe9ef1630c1 503
gatedClock 78:7df160e0db7b 504 if (dRemainingTime <= 0) dFSMstate = FSM_DONE;
gatedClock 78:7df160e0db7b 505 else
gatedClock 114:fbe9ef1630c1 506 // user stop causes jump to idle.
gatedClock 78:7df160e0db7b 507 if (dButtonStop) dFSMstate = FSM_IDLE;
gatedClock 79:4286319e48b4 508 else
gatedClock 114:fbe9ef1630c1 509 // back to pause if door open,
gatedClock 114:fbe9ef1630c1 510 // and there's remaining time.
gatedClock 79:4286319e48b4 511 if ((dDoorOpen == 1) && (dRemainingTime > 0)) dFSMstate = FSM_PAUSE;
gatedClock 78:7df160e0db7b 512 break;
gatedClock 78:7df160e0db7b 513 }
gatedClock 78:7df160e0db7b 514
gatedClock 78:7df160e0db7b 515
gatedClock 82:73fa3fe8a217 516 //---
gatedClock 73:44739860198b 517 case FSM_DONE : // DONE.
gatedClock 73:44739860198b 518 {
gatedClock 120:64a969984af2 519 giMagnetron.cMagnetron = 0; // highest priority.
gatedClock 120:64a969984af2 520 giMagnetron.cCarousel = 0; // turn on carousel.
gatedClock 119:e14b0f6e97cb 521
gatedClock 75:c2894d531f42 522 if (dFSMstate != dFSMstateLast) // if just entered state.
gatedClock 75:c2894d531f42 523 {
gatedClock 114:fbe9ef1630c1 524 // freeze synthetic temperature.
gatedClock 97:ee840478d6b3 525 queueTemperatureControl.put((int *) TEMP_FREEZE,1);
gatedClock 114:fbe9ef1630c1 526 giRemainingTime.cBeepEnable = 1; // initiate beep.
gatedClock 89:290c96cd027f 527 beepTimer.reset(); // clear the beep timer.
gatedClock 75:c2894d531f42 528 }
gatedClock 80:e3e1a2161435 529
gatedClock 114:fbe9ef1630c1 530 // update LCD globals.
gatedClock 80:e3e1a2161435 531 giLCD.dTotalCookTime = giRemainingTime.dTotalTime;
gatedClock 80:e3e1a2161435 532 giLCD.dRemainingTime = giRemainingTime.dRemainingTime;
gatedClock 121:c9d28cd59460 533
gatedClock 121:c9d28cd59460 534 mutexControl.lock();
gatedClock 114:fbe9ef1630c1 535 giRemainingTime.cControl = RT_CLEAR;// clear remaining time. (needed?)
gatedClock 121:c9d28cd59460 536 mutexControl.unlock();
gatedClock 114:fbe9ef1630c1 537
gatedClock 114:fbe9ef1630c1 538 dFSMstateLast = dFSMstate; // determine next state.
gatedClock 80:e3e1a2161435 539
gatedClock 114:fbe9ef1630c1 540 // to idle once beeper is done.
gatedClock 110:a3b95ccfaed6 541 if (beepTimer.read() >= BEEPTIME) {dFSMstate = FSM_IDLE; giRemainingTime.cBeepEnable = 0;}
gatedClock 114:fbe9ef1630c1 542 else dFSMstate = FSM_DONE; // (else stay here).
gatedClock 73:44739860198b 543 break;
gatedClock 73:44739860198b 544 }
gatedClock 82:73fa3fe8a217 545 //---
gatedClock 73:44739860198b 546 default : {dFSMstate = FSM_IDLE; break;}
gatedClock 73:44739860198b 547
gatedClock 62:48e7c196e2a5 548 }
gatedClock 73:44739860198b 549
gatedClock 63:63f362bcc2ac 550
gatedClock 75:c2894d531f42 551
gatedClock 75:c2894d531f42 552 queueEvent = queueUpdateFSM.get(1); // threadButtonStateManager
gatedClock 60:e10bf95bbc96 553 if (queueEvent.status == osEventMessage)// update state variable.
gatedClock 60:e10bf95bbc96 554 {
gatedClock 61:8026a9fc0cf1 555 // interpret as integer, not pointer.
gatedClock 61:8026a9fc0cf1 556 dButtonState = (int) queueEvent.value.p;
gatedClock 63:63f362bcc2ac 557
gatedClock 63:63f362bcc2ac 558 if (dButtonState == MSG_START)
gatedClock 63:63f362bcc2ac 559 {
gatedClock 114:fbe9ef1630c1 560 dButtonStart = 1; // copy-in start info.
gatedClock 63:63f362bcc2ac 561 dButtonStop = 0;
gatedClock 114:fbe9ef1630c1 562 if (dDoorOpen) dButtonStart = 0; // cancel start if door open.
gatedClock 63:63f362bcc2ac 563 }
gatedClock 63:63f362bcc2ac 564 if (dButtonState == MSG_STOP)
gatedClock 63:63f362bcc2ac 565 {
gatedClock 114:fbe9ef1630c1 566 dButtonStart = 0; // copy-in stop state.
gatedClock 63:63f362bcc2ac 567 dButtonStop = 1;
gatedClock 114:fbe9ef1630c1 568 queueClearTotalTime.put((int*) 1,1);// clear total time on stop.
gatedClock 63:63f362bcc2ac 569 }
gatedClock 63:63f362bcc2ac 570
gatedClock 114:fbe9ef1630c1 571 if (dButtonState == MSG_OPEN) // if the door opens, clear current 'start' state.
gatedClock 114:fbe9ef1630c1 572 {
gatedClock 79:4286319e48b4 573 dDoorOpen = 1;
gatedClock 79:4286319e48b4 574 dButtonStart = 0;
gatedClock 63:63f362bcc2ac 575 }
gatedClock 63:63f362bcc2ac 576
gatedClock 114:fbe9ef1630c1 577 if (dButtonState == MSG_CLOSED) // detect door closed.
gatedClock 63:63f362bcc2ac 578 {
gatedClock 63:63f362bcc2ac 579 dDoorOpen = 0;
gatedClock 63:63f362bcc2ac 580 }
gatedClock 63:63f362bcc2ac 581
gatedClock 61:8026a9fc0cf1 582 }
gatedClock 90:d9bb516141f1 583 else // no queue update available.
gatedClock 90:d9bb516141f1 584 {
gatedClock 90:d9bb516141f1 585 dButtonStart = 0;
gatedClock 90:d9bb516141f1 586 dButtonStop = 0;
gatedClock 90:d9bb516141f1 587 }
gatedClock 75:c2894d531f42 588
gatedClock 75:c2894d531f42 589 // fetch from global scope.
gatedClock 75:c2894d531f42 590 dRemainingTime = giRemainingTime.dRemainingTime;
gatedClock 69:55b836e8ced7 591
gatedClock 57:0432c68ad232 592 Thread::wait(THREAD_5_WAITmS); // multitasking.
gatedClock 57:0432c68ad232 593 } // thread loop.
gatedClock 57:0432c68ad232 594 } // threadCookStateFSM.
gatedClock 57:0432c68ad232 595 /*----------------------------------------------//----------------------------*/
gatedClock 0:fcca4db7b32a 596 void initialization(void) // program initializations.
gatedClock 0:fcca4db7b32a 597 {
gatedClock 112:465958b0e94e 598 led1 = 0;
gatedClock 112:465958b0e94e 599 giButtons.cDoorOpen = 0; // initialize with door closed.
gatedClock 112:465958b0e94e 600 giRemainingTime.cBeepEnable =0;
gatedClock 120:64a969984af2 601 giMagnetron.cMagnetron = 0;
gatedClock 120:64a969984af2 602 giMagnetron.cCarousel = 0;
gatedClock 0:fcca4db7b32a 603 }
gatedClock 0:fcca4db7b32a 604 /*----------------------------------------------//----------------------------*/
gatedClock 26:bff592483cb1 605 void ISRleftButtonRising(void) // cooktime plus 60s.
gatedClock 1:9188d4668a88 606 {
gatedClock 66:4a0006fa5cc1 607 if (debounceTimer.read_ms() > DEBOUNCEmS)
gatedClock 108:da479434bd7d 608 giButtons.cLeftButton = 1; // detect left button.
gatedClock 9:cfdb9aa5857c 609
gatedClock 66:4a0006fa5cc1 610 debounceTimer.reset(); // begin debounce period.
gatedClock 11:9cae003da12b 611 }
gatedClock 1:9188d4668a88 612 /*----------------------------------------------//----------------------------*/
gatedClock 15:5eaa2ab1d00d 613 void ISRleftButtonFalling(void) // button-release debounce.
gatedClock 1:9188d4668a88 614 {
gatedClock 66:4a0006fa5cc1 615 debounceTimer.reset(); // begin debounce period.
gatedClock 11:9cae003da12b 616 }
gatedClock 2:665ffa57031f 617 /*----------------------------------------------//----------------------------*/
gatedClock 26:bff592483cb1 618 void ISRrightButtonRising(void) // cooktime -60s.
gatedClock 12:e40272e1fd8f 619 {
gatedClock 66:4a0006fa5cc1 620 if (debounceTimer.read_ms() > DEBOUNCEmS)
gatedClock 108:da479434bd7d 621 giButtons.cRightButton = 1; // detect right button.
gatedClock 12:e40272e1fd8f 622
gatedClock 66:4a0006fa5cc1 623 debounceTimer.reset(); // begin debounce period.
gatedClock 12:e40272e1fd8f 624 }
gatedClock 12:e40272e1fd8f 625 /*----------------------------------------------//----------------------------*/
gatedClock 15:5eaa2ab1d00d 626 void ISRrightButtonFalling(void) // button-release debounce.
gatedClock 12:e40272e1fd8f 627 {
gatedClock 66:4a0006fa5cc1 628 debounceTimer.reset(); // begin debounce period.
gatedClock 12:e40272e1fd8f 629 }
gatedClock 12:e40272e1fd8f 630 /*----------------------------------------------//----------------------------*/
gatedClock 26:bff592483cb1 631 void ISRtopButtonRising(void) // cook start.
gatedClock 12:e40272e1fd8f 632 {
gatedClock 66:4a0006fa5cc1 633 if (debounceTimer.read_ms() > DEBOUNCEmS)
gatedClock 108:da479434bd7d 634 giButtons.cTopButton = 1; // detect top button.
gatedClock 12:e40272e1fd8f 635
gatedClock 66:4a0006fa5cc1 636 debounceTimer.reset(); // begin debounce period.
gatedClock 12:e40272e1fd8f 637 }
gatedClock 12:e40272e1fd8f 638 /*----------------------------------------------//----------------------------*/
gatedClock 15:5eaa2ab1d00d 639 void ISRtopButtonFalling(void) // button-release debounce.
gatedClock 12:e40272e1fd8f 640 {
gatedClock 66:4a0006fa5cc1 641 debounceTimer.reset(); // begin debounce period.
gatedClock 12:e40272e1fd8f 642 }
gatedClock 12:e40272e1fd8f 643 /*----------------------------------------------//----------------------------*/
gatedClock 53:8c2baf5623c8 644 // front-end control of magnetron off.
gatedClock 53:8c2baf5623c8 645 // due to physical danger, the magnetron is turned off immediately
gatedClock 53:8c2baf5623c8 646 // upon off-button press, in the interrupt that it generates.
gatedClock 53:8c2baf5623c8 647
gatedClock 26:bff592483cb1 648 void ISRbottomButtonRising(void) // cook stop.
gatedClock 12:e40272e1fd8f 649 {
gatedClock 66:4a0006fa5cc1 650 if (debounceTimer.read_ms() > DEBOUNCEmS)
gatedClock 66:4a0006fa5cc1 651 {
gatedClock 66:4a0006fa5cc1 652 led0 = 0; // magnetron off.
gatedClock 108:da479434bd7d 653 giButtons.cBottomButton = 1; // detect bottom button.
gatedClock 66:4a0006fa5cc1 654 }
gatedClock 66:4a0006fa5cc1 655 debounceTimer.reset(); // begin debounce period.
gatedClock 66:4a0006fa5cc1 656 }
gatedClock 12:e40272e1fd8f 657 /*----------------------------------------------//----------------------------*/
gatedClock 15:5eaa2ab1d00d 658 void ISRbottomButtonFalling(void) // button-release debounce.
gatedClock 12:e40272e1fd8f 659 {
gatedClock 66:4a0006fa5cc1 660 debounceTimer.reset(); // begin debounce period.
gatedClock 12:e40272e1fd8f 661 }
gatedClock 12:e40272e1fd8f 662 /*----------------------------------------------//----------------------------*/
gatedClock 53:8c2baf5623c8 663 // front-end control of magnetron off.
gatedClock 53:8c2baf5623c8 664 // due to physical danger, the magnetron is turned off immediately
gatedClock 53:8c2baf5623c8 665 // upon detection of an open door.
gatedClock 53:8c2baf5623c8 666
gatedClock 26:bff592483cb1 667 void ISRcenterButtonRising(void) // toggle door state.
gatedClock 12:e40272e1fd8f 668 {
gatedClock 66:4a0006fa5cc1 669 if (debounceTimer.read_ms() > DEBOUNCEmS)
gatedClock 66:4a0006fa5cc1 670 {
gatedClock 108:da479434bd7d 671 if (giButtons.cDoorOpen == MSG_OPEN) // calculate door state.
gatedClock 108:da479434bd7d 672 giButtons.cDoorOpen = MSG_CLOSED;
gatedClock 66:4a0006fa5cc1 673 else
gatedClock 108:da479434bd7d 674 giButtons.cDoorOpen = MSG_OPEN;
gatedClock 53:8c2baf5623c8 675
gatedClock 59:5e45b5e4a874 676 // magnetron off.
gatedClock 108:da479434bd7d 677 if (giButtons.cDoorOpen == MSG_OPEN) led0 = 0;
gatedClock 58:ec630b6dd9b1 678
gatedClock 108:da479434bd7d 679 giButtons.cCenterButton = 1;
gatedClock 66:4a0006fa5cc1 680 }
gatedClock 66:4a0006fa5cc1 681 debounceTimer.reset(); // begin debounce period.
gatedClock 12:e40272e1fd8f 682 }
gatedClock 12:e40272e1fd8f 683 /*----------------------------------------------//----------------------------*/
gatedClock 15:5eaa2ab1d00d 684 void ISRcenterButtonFalling(void) // button-release debounce.
gatedClock 12:e40272e1fd8f 685 {
gatedClock 66:4a0006fa5cc1 686 debounceTimer.reset(); // begin debounce period.
gatedClock 12:e40272e1fd8f 687 }
gatedClock 115:6390d9b9be07 688 /*----------------------------------------------//----------------------------*/
gatedClock 115:6390d9b9be07 689
gatedClock 115:6390d9b9be07 690 // this will measure live temperature, or calculate it to be
gatedClock 115:6390d9b9be07 691 // increasing at 1/6 degree per second, or freeze it.
gatedClock 115:6390d9b9be07 692
gatedClock 115:6390d9b9be07 693
gatedClock 40:7afff79f0d8b 694 void temperatureThread(void const *args) // temperature measurement.
gatedClock 39:4e7e4d935a87 695 {
gatedClock 94:551b1df4b10c 696 int dTempControl = 0; // temperature control.
gatedClock 115:6390d9b9be07 697 float fLastMeasuredTemperature = 0.0; // last physically-measured temperature.
gatedClock 115:6390d9b9be07 698 float fCelsius; // synthetic temperature.
gatedClock 94:551b1df4b10c 699 osEvent queueEvent; // from button state manager.
gatedClock 94:551b1df4b10c 700
gatedClock 45:e3207684e841 701 while(1) // thread loop.
gatedClock 45:e3207684e841 702 {
gatedClock 94:551b1df4b10c 703 // obtain temperature command.
gatedClock 94:551b1df4b10c 704 queueEvent = queueTemperatureControl.get(1);
gatedClock 94:551b1df4b10c 705 if (queueEvent.status == osEventMessage)
gatedClock 94:551b1df4b10c 706 {
gatedClock 94:551b1df4b10c 707 dTempControl = (int) queueEvent.value.p;
gatedClock 94:551b1df4b10c 708 }
gatedClock 94:551b1df4b10c 709
gatedClock 94:551b1df4b10c 710 if (dTempControl == TEMP_READ)
gatedClock 95:7e391a5951d1 711 {
gatedClock 107:7de171a8464e 712 fCelsius = temperature.read(); // physical measurement.
gatedClock 107:7de171a8464e 713 fLastMeasuredTemperature = fCelsius;
gatedClock 95:7e391a5951d1 714 }
gatedClock 94:551b1df4b10c 715
gatedClock 115:6390d9b9be07 716 if (dTempControl == TEMP_CALC) // calculate synthetic temperature.
gatedClock 115:6390d9b9be07 717 fCelsius = ((float) (giRemainingTime.dTotalTime - giRemainingTime.dRemainingTime) /
gatedClock 115:6390d9b9be07 718 (float) 6.0) + fLastMeasuredTemperature;
gatedClock 97:ee840478d6b3 719
gatedClock 115:6390d9b9be07 720 giLCD.fCelsius = fCelsius; // to global scope for LCD.
gatedClock 97:ee840478d6b3 721
gatedClock 45:e3207684e841 722 Thread::wait(THREAD_1_WAITmS); // multitasking.
gatedClock 45:e3207684e841 723 } // thread loop.
gatedClock 45:e3207684e841 724 } // temperatureThread.
gatedClock 42:266d5bbbfd19 725 /*----------------------------------------------//----------------------------*/
gatedClock 42:266d5bbbfd19 726 void LCDthread(void const *args) // LCD display thread.
gatedClock 42:266d5bbbfd19 727 {
gatedClock 67:1d9c85a4c3c1 728
gatedClock 67:1d9c85a4c3c1 729 static int dLCDtotalCookTimeSec = 0; // sample current values.
gatedClock 67:1d9c85a4c3c1 730 static int dCookTimeRemainingSec = 0;
gatedClock 67:1d9c85a4c3c1 731 static float fLCDcelsius = 0.0;
gatedClock 67:1d9c85a4c3c1 732
gatedClock 67:1d9c85a4c3c1 733 // remember previous values.
gatedClock 67:1d9c85a4c3c1 734 static int dLCDtotalCookTimeSecLast = 0;
gatedClock 67:1d9c85a4c3c1 735 static int dCookTimeRemainingSecLast = 0;
gatedClock 67:1d9c85a4c3c1 736 static float fLCDcelsiusLast = 0.0;
gatedClock 67:1d9c85a4c3c1 737
gatedClock 44:d16e813e61ef 738 while(1) // thread loop.
gatedClock 44:d16e813e61ef 739 {
gatedClock 67:1d9c85a4c3c1 740 // don't allow the values to
gatedClock 67:1d9c85a4c3c1 741 // change in the middle of the
gatedClock 67:1d9c85a4c3c1 742 // below else the anti-blink
gatedClock 67:1d9c85a4c3c1 743 // code won't work.
gatedClock 80:e3e1a2161435 744 dLCDtotalCookTimeSec = giLCD.dTotalCookTime;
gatedClock 80:e3e1a2161435 745 dCookTimeRemainingSec = giLCD.dRemainingTime;
gatedClock 80:e3e1a2161435 746 fLCDcelsius = giLCD.fCelsius;
gatedClock 116:15084f54baf9 747
gatedClock 67:1d9c85a4c3c1 748 // clear display only when
gatedClock 67:1d9c85a4c3c1 749 // necessary, in order to avoid
gatedClock 67:1d9c85a4c3c1 750 // 'blinkieness'.
gatedClock 67:1d9c85a4c3c1 751 if (dLCDtotalCookTimeSec != dLCDtotalCookTimeSecLast ||
gatedClock 67:1d9c85a4c3c1 752 dCookTimeRemainingSec != dCookTimeRemainingSecLast ||
gatedClock 67:1d9c85a4c3c1 753 fLCDcelsius != fLCDcelsiusLast)
gatedClock 67:1d9c85a4c3c1 754 lcd.cls();
gatedClock 42:266d5bbbfd19 755
gatedClock 44:d16e813e61ef 756 LCD1; // line 1.
gatedClock 67:1d9c85a4c3c1 757 lcd.printf(" total cook time: %d",dLCDtotalCookTimeSec);
gatedClock 42:266d5bbbfd19 758
gatedClock 44:d16e813e61ef 759 LCD2; // line 2.
gatedClock 67:1d9c85a4c3c1 760 lcd.printf(" remaing cook time: %d",dCookTimeRemainingSec);
gatedClock 42:266d5bbbfd19 761
gatedClock 44:d16e813e61ef 762 LCD3; // line 3.
gatedClock 67:1d9c85a4c3c1 763 lcd.printf(" temperature : %5.3f",fLCDcelsius);
gatedClock 67:1d9c85a4c3c1 764
gatedClock 67:1d9c85a4c3c1 765 // pipeline variables.
gatedClock 67:1d9c85a4c3c1 766 dLCDtotalCookTimeSecLast = dLCDtotalCookTimeSec;
gatedClock 67:1d9c85a4c3c1 767 dCookTimeRemainingSecLast = dCookTimeRemainingSec;
gatedClock 67:1d9c85a4c3c1 768 fLCDcelsiusLast = fLCDcelsius;
gatedClock 42:266d5bbbfd19 769
gatedClock 44:d16e813e61ef 770 Thread::wait(THREAD_2_WAITmS); // multitasking.
gatedClock 44:d16e813e61ef 771 } // thread loop.
gatedClock 44:d16e813e61ef 772 } // LCDthread.
gatedClock 42:266d5bbbfd19 773 /*----------------------------------------------//----------------------------*/
gatedClock 71:4a5f256ecf7c 774
gatedClock 88:0b1b812945eb 775 // cook remaining time countdown counter.
gatedClock 88:0b1b812945eb 776 // possibly due to a bug in Ticker
gatedClock 88:0b1b812945eb 777 // http://mbed.org/questions/1563/Mbed-Tickerfunction-hangs-system-from-re/
gatedClock 88:0b1b812945eb 778 // I've been unable to detach/attach this routine in order to reset its phase
gatedClock 88:0b1b812945eb 779 // when I tried it at a 1s resolution. In order to provide the human perception
gatedClock 88:0b1b812945eb 780 // of an immediate restart, I've increased the ticker frequency by the factor
gatedClock 88:0b1b812945eb 781 // 'GRANULARITY' and likewise divide that factor out when this routine
gatedClock 88:0b1b812945eb 782 // promotes the remaining time to the global variable.
gatedClock 88:0b1b812945eb 783
gatedClock 104:5e49dbe5038a 784 // communication is via a global instance of struct tRemainingTime.
gatedClock 104:5e49dbe5038a 785
gatedClock 71:4a5f256ecf7c 786 void tickCookRemainingTime(void) // cook-cycle countdown.
gatedClock 71:4a5f256ecf7c 787 {
gatedClock 71:4a5f256ecf7c 788 static int dRemainingTime = 0; // remaining time in seconds.
gatedClock 88:0b1b812945eb 789 int dMaximum; // MAXSECONDS * GRANULARITY.
gatedClock 121:c9d28cd59460 790 char cControl; // local copy.
gatedClock 88:0b1b812945eb 791
gatedClock 88:0b1b812945eb 792 dMaximum = MAXSECONDS * GRANULARITY; // precalculate.
gatedClock 75:c2894d531f42 793
gatedClock 121:c9d28cd59460 794 mutexControl.lock();
gatedClock 121:c9d28cd59460 795 cControl = giRemainingTime.cControl;
gatedClock 121:c9d28cd59460 796 mutexControl.unlock();
gatedClock 121:c9d28cd59460 797
gatedClock 121:c9d28cd59460 798 switch (cControl) // control processing.
gatedClock 71:4a5f256ecf7c 799 {
gatedClock 88:0b1b812945eb 800
gatedClock 72:b4d0c0aa3c26 801 case RT_PRELOAD : // preload with total time.
gatedClock 71:4a5f256ecf7c 802 {
gatedClock 88:0b1b812945eb 803 // the 'GRANULARITY - 1' factor
gatedClock 88:0b1b812945eb 804 // compensates for integer division
gatedClock 88:0b1b812945eb 805 // dropping the right-of-decimal result,
gatedClock 88:0b1b812945eb 806 // that occuring at the bottom of this
gatedClock 88:0b1b812945eb 807 // routine.
gatedClock 88:0b1b812945eb 808 dRemainingTime = (giRemainingTime.dTotalTime * GRANULARITY) + (GRANULARITY - 1);
gatedClock 71:4a5f256ecf7c 809 break;
gatedClock 71:4a5f256ecf7c 810 }
gatedClock 88:0b1b812945eb 811
gatedClock 72:b4d0c0aa3c26 812 case RT_DECREMENT : // count-down.
gatedClock 71:4a5f256ecf7c 813 {
gatedClock 72:b4d0c0aa3c26 814 dRemainingTime--;
gatedClock 71:4a5f256ecf7c 815 break;
gatedClock 71:4a5f256ecf7c 816 }
gatedClock 71:4a5f256ecf7c 817
gatedClock 72:b4d0c0aa3c26 818 case RT_PAUSE : // suspend countdown.
gatedClock 69:55b836e8ced7 819 {
gatedClock 72:b4d0c0aa3c26 820 dRemainingTime = dRemainingTime;
gatedClock 71:4a5f256ecf7c 821 break;
gatedClock 71:4a5f256ecf7c 822 }
gatedClock 71:4a5f256ecf7c 823
gatedClock 72:b4d0c0aa3c26 824 case RT_CLEAR : // clear countdown.
gatedClock 71:4a5f256ecf7c 825 {
gatedClock 100:fd7006aa3d05 826 dRemainingTime = 0;
gatedClock 71:4a5f256ecf7c 827 break;
gatedClock 71:4a5f256ecf7c 828 }
gatedClock 69:55b836e8ced7 829
gatedClock 72:b4d0c0aa3c26 830 default : // saturate, just in case.
gatedClock 72:b4d0c0aa3c26 831 {
gatedClock 72:b4d0c0aa3c26 832 }
gatedClock 75:c2894d531f42 833 } // control processing.
gatedClock 71:4a5f256ecf7c 834
gatedClock 88:0b1b812945eb 835 // saturate value.
gatedClock 88:0b1b812945eb 836 if (dRemainingTime > dMaximum) dRemainingTime = dMaximum;
gatedClock 88:0b1b812945eb 837 if (dRemainingTime < 0) dRemainingTime = 0;
gatedClock 88:0b1b812945eb 838
gatedClock 75:c2894d531f42 839 // promote to global scope.
gatedClock 86:388c2b4b7cf5 840 giRemainingTime.dRemainingTime = dRemainingTime/GRANULARITY;
gatedClock 70:7c0743c28b11 841
gatedClock 70:7c0743c28b11 842 } // cookRemainingTime.
gatedClock 69:55b836e8ced7 843 /*----------------------------------------------//----------------------------*/
gatedClock 117:b9e18163c282 844 void tickerBeeper(void) // beep when giRemainingTime.
gatedClock 92:be8d69aba1fc 845 {
gatedClock 101:33dc62b6b728 846 static char cState = 0;
gatedClock 110:a3b95ccfaed6 847 if (giRemainingTime.cBeepEnable)
gatedClock 101:33dc62b6b728 848 {
gatedClock 101:33dc62b6b728 849 if (cState) {speaker = 1; cState = 0;}
gatedClock 101:33dc62b6b728 850 else {speaker = 0; cState = 1;}
gatedClock 101:33dc62b6b728 851 }
gatedClock 101:33dc62b6b728 852 }
gatedClock 101:33dc62b6b728 853 /*----------------------------------------------//----------------------------*/
gatedClock 118:d0e057d79acc 854 void tickerMagnetron(void) // magnetron enunciator.
gatedClock 117:b9e18163c282 855 {
gatedClock 120:64a969984af2 856 if (giMagnetron.cMagnetron) led0 = !led0;
gatedClock 118:d0e057d79acc 857 else led0 = 0;
gatedClock 117:b9e18163c282 858 }
gatedClock 69:55b836e8ced7 859
gatedClock 117:b9e18163c282 860 /*----------------------------------------------//----------------------------*/
gatedClock 118:d0e057d79acc 861 void tickerCarousel(void) // carousel enunciator.
gatedClock 117:b9e18163c282 862 {
gatedClock 120:64a969984af2 863 if (giMagnetron.cCarousel) led1 = !led1;
gatedClock 118:d0e057d79acc 864 else led1 = 0;
gatedClock 117:b9e18163c282 865 }
gatedClock 117:b9e18163c282 866 /*----------------------------------------------//----------------------------*/
gatedClock 117:b9e18163c282 867
gatedClock 117:b9e18163c282 868
gatedClock 117:b9e18163c282 869
gatedClock 117:b9e18163c282 870
gatedClock 117:b9e18163c282 871
gatedClock 117:b9e18163c282 872
gatedClock 117:b9e18163c282 873
gatedClock 117:b9e18163c282 874
gatedClock 117:b9e18163c282 875
gatedClock 117:b9e18163c282 876
gatedClock 117:b9e18163c282 877
gatedClock 117:b9e18163c282 878
gatedClock 117:b9e18163c282 879
gatedClock 117:b9e18163c282 880
gatedClock 117:b9e18163c282 881
gatedClock 117:b9e18163c282 882
gatedClock 117:b9e18163c282 883
gatedClock 117:b9e18163c282 884