homework 7

Dependencies:   mbed-rtos mbed C12832_lcd LM75B

Committer:
gatedClock
Date:
Fri Sep 13 00:30:31 2013 +0000
Revision:
126:70439be77e75
Parent:
125:6b3a86e3c883
turn in for credit.

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