homework 7

Dependencies:   mbed-rtos mbed C12832_lcd LM75B

Committer:
gatedClock
Date:
Thu Sep 12 23:28:18 2013 +0000
Revision:
123:c8ea8f59455b
Parent:
121:c9d28cd59460
Child:
124:55c83dbeba2c
adding program description.

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