homework 7
Dependencies: mbed-rtos mbed C12832_lcd LM75B
main.cpp
- Committer:
- gatedClock
- Date:
- 2013-09-12
- Revision:
- 101:33dc62b6b728
- Parent:
- 100:fd7006aa3d05
- Child:
- 102:5735d9cbad00
File content as of revision 101:33dc62b6b728:
/*----------------------------------------------//------------------------------ student : m-moore class : rtos directory : RTOS_HW_07 file : main.cpp ----description---------------------------------//------------------------------ gotchyas 1. using pc.printf inside a ticker routine will freeze the routine. 2. using queues (get, put) will not work within a ticker routine. 3. Ticker has a bug. http://mbed.org/questions/1563/Mbed-Tickerfunction-hangs-system-from-re/ improvements countdown timer needs to be sync'd to start button press. this could not be done, use granularity setting instead. -----includes-----------------------------------//----------------------------*/ #include "mbed.h" // mbed class. #include "rtos.h" // rtos class. #include "LM75B.h" // thermometer class. #include "C12832_lcd.h" // LCD class. //---defines------------------------------------//------------------------------ #define LCD1 lcd.locate(0, 0); // LCD line 1. #define LCD2 lcd.locate(0,11); // LCD line 2. #define LCD3 lcd.locate(0,22); // LCD line 3. #define DEBOUNCEmS 16 // debounce wait in mS. #define uS_TIMEOUT 100 // Timer uS timeout. #define LBSIG 1 // left button signal code. #define PIPEuS 1000 // pipeline clock period. #define SLOWCLOCKuS 500000 // slow-clock period. #define TEMPCLOCKS 1 // temperature-measuring period in S. #define PIPEDATASIZE 8 // dimension of tPipeData. #define THREAD_1_WAITmS 400 // thread 1 wait in mS. #define THREAD_2_WAITmS 40 // LCD thread wait. #define THREAD_3_WAITmS 80 // thread 3 wait in mS. #define THREAD_4_WAITmS 1 // thread 4 wait in mS. #define THREAD_5_WAITmS 100 // FSM thread wait. #define HB_MODULO 1024 // heartbeat modulo divisor. #define MSG_INC_TIME 0x01 #define MSG_DEC_TIME 0x02 #define MSG_START 0x04 #define MSG_STOP 0x08 #define MSG_OPEN 0x10 #define MSG_CLOSED 0x20 #define FSM_IDLE 0x01 // cook-state state-machine. #define FSM_COOK 0x02 // cook-state state-machine. #define FSM_PAUSE 0x04 // cook-state state-machine. #define FSM_CONTINUE 0x08 // cook-state state-machine. #define FSM_DONE 0x10 // cook-state state-machine. #define RT_PRELOAD 0x01 // remaining-time preload. #define RT_DECREMENT 0x02 // remaining-time decrement. #define RT_PAUSE 0x03 // remaining-time don't change. #define RT_CLEAR 0x04 // remaining-time set to zero. #define TEMP_READ 0x01 // temperature synthesizer control. #define TEMP_CALC 0x02 // temperature synthesizer control. #define TEMP_FREEZE 0x03 // temperature synthesizer control. #define GRANULARITY 0x400 // 1-second countdown ticker granularity. #define MAXSECONDS 180 // maximum microwave-on time. #define BEEPTIME 3 // beep duration in S. #define BEEPFREQ 300 // beep frequency in Hz. #define TIMEINC 10 // time increment in seconds. //--global_definitions--------------------------//------------------------------ struct tButtons // button ISR updates. { char cLeftButton; // cooktime +60S. char cRightButton; // cooktime -60S. char cTopButton; // start cook. char cBottomButton; // stop cook. char cCenterButton; // center button pressed. char cDoorOpen; // door open. }; struct tRemainingTime // remaining time related. { char cControl; // countdown control. int dTotalTime; // initialize to this. int dRemainingTime; // the countdown value. }; struct tLCD // LCD related. { int dTotalCookTime; // display time in seconds. int dRemainingTime; // display time in seconds. float fCelsius; // temperature in celsius. }; Queue<int, 1> queueModTotalTime; // message to modify total time. Queue<int, 1> queueUpdateFSM; // message to inform FSM. Queue<int, 1> queueUpdateRemainingTime; // message to update remaining time. Queue<int, 1> queueSetRemainingTime; // tell countdown it's start time. Queue<int, 1> queueFSMnewState; // latest FSM state. Queue<int, 1> queueSpeakerControl; // speaker control queue. Queue<int, 1> queueTemperatureControl; // control the temperature synthesizer. Queue<int, 1> queueSuppressTimeAdjust; // total time control. Queue<int, 1> queueClearTotalTime; // total time control. //--global_variables----------------------------//------------------------------ char gcSignalWaitEnable; // 1 to wait on a signal. char gcSlowClock; // slow-clock signal. char gcInitializePipeline; // 1 to initialize pipeline state. float gfCelsius; // from thermometer. tButtons gtButtons; // ISR button updates. tRemainingTime giRemainingTime; // structure instance. tLCD giLCD; // structure instance. int gdDiagTotalTime; char gcBeepEnable; //--global_instances----------------------------//------------------------------ Serial pc(USBTX, USBRX); // PuTTY terminal communication. LM75B temperature(p28,p27); // on-board thermometer. C12832_LCD lcd; // LCD object. DigitalOut led0(LED4); // magnetron. DigitalOut led1(LED3); DigitalOut led2(LED2); DigitalOut led3(LED1); DigitalOut speaker(p26); // speaker device. InterruptIn iJoyStickUp (p15); // joystick up rising edge. InterruptIn iJoyStickDown (p12); // joystick down rising edge. InterruptIn iJoyStickLeft (p13); // joystick left rising edge. InterruptIn iJoyStickRight (p16); // joystick right rising edge. InterruptIn iJoyStickCenter(p14); // 1 if joystick middle pressed. Timer debounceTimer; // button debounce timer. Timer beepTimer; // beep-duration timer. Timer temperatureTimer; // how often to raise temperature. Ticker tickerButtonStateManager; // manage the button states. Ticker tickerSlowClock; // generate a ~1Hz clock. Ticker tickerCookCountdown; // remaining cook time. Ticker tickerBeep; // beeper ticker. // Timer timerFSMdone; // duration of FSM 'done' state. //-------prototypes-----------------------------//------------------------------ void slowClock(); // 1Hz or thereabouts. void initialization(); // initialize settings. void ISRleftButtonRising(); // cook-time increase. void ISRleftButtonFalling(); // button-release debounce. void ISRrightButtonRising(); // cook-time decrease. void ISRrightButtonFalling(); // button-release debounce. void ISRtopButtonRising(); // cook start. void ISRtopButtonFalling(); // button-release debounce. void ISRbottomButtonRising(); // cook stop. void ISRbottomButtonFalling(); // button-release debounce. void ISRcenterButtonRising(); // door state toggle. void ISRcenterButtonFalling(); // button-release debounce. void disableSignalWaiting(); // break from signal waiting. void threadButtonStateManager(void const *args); void threadTotalTimeControl(void const *args); void threadCookStateFSM(void const *args); void tickCookRemainingTime(); // remaining time countdown. void temperatureThread(void const *args); // temperature measurement. void LCDthread (void const *args); // LCD display thread. void speakerThread(void const *args); // speaker thread. void tickerBeeper(); // beep oscillator. //==============================================//============================== int main(void) { char cLeftButtonState; // 1 means button was pressed. iJoyStickLeft.rise (&ISRleftButtonRising); iJoyStickLeft.fall (&ISRleftButtonFalling); iJoyStickRight.rise(&ISRrightButtonRising); iJoyStickRight.fall(&ISRrightButtonFalling); iJoyStickUp.rise (&ISRtopButtonRising); iJoyStickUp.fall (&ISRtopButtonFalling); iJoyStickDown.rise (&ISRbottomButtonRising); iJoyStickDown.fall (&ISRbottomButtonFalling); iJoyStickCenter.rise(&ISRcenterButtonRising); iJoyStickCenter.fall(&ISRcenterButtonFalling); debounceTimer.start(); // kick-off debounce timer. gcInitializePipeline = 1; // tell pipeline to initialize. initialization(); // initialize variables. gcSlowClock = 0; led1 = 0; gtButtons.cDoorOpen = 0; // initialize with door closed. gcBeepEnable =0; // timerFSMdone.start(); // start 'done' timer. // tickerSlowClock.attach_us(&slowClock ,SLOWCLOCKuS); tickerCookCountdown.attach_us(&tickCookRemainingTime,1000000/GRANULARITY); tickerBeep.attach_us(&tickerBeeper,2000); Thread thread_1(temperatureThread ,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL); Thread thread_2(LCDthread ,NULL,osPriorityHigh,DEFAULT_STACK_SIZE,NULL); Thread thread_3(threadTotalTimeControl ,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL); Thread thread_4(threadButtonStateManager,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL); // was osPriorityIdle Thread thread_5(threadCookStateFSM ,NULL,osPriorityIdle,DEFAULT_STACK_SIZE,NULL); //Thread thread_4(threadButtonStateManager); // the message-receiving threads need 'else' for message-receive-timeout. // int dSeconds; // dSeconds = 8; // speakerThread((void *) &dSeconds); while(1) { // pc.printf("\n\r gdDiagTotalTime %d",gdDiagTotalTime); Thread::wait(1000); } } /*----------------------------------------------//----------------------------*/ // this serves as the bottom-half for all of the button-press IRSs. // it sends button-status messages to other threads, and it also // clears the button-state globals to prepare them for the next // button press. void threadButtonStateManager(void const *args) { int dMessage; // message. while(1) // thread loop. { //--- // TOTAL TIME CONTROL. // encoded integers will be sent, // not pointers. if (gtButtons.cLeftButton) // total time increment button. { dMessage = MSG_INC_TIME; // set message. queueModTotalTime.put((int *) dMessage,1);// pretend it's a pointer. gtButtons.cLeftButton = 0; // clear the button state. } if (gtButtons.cRightButton) // total time decrement button. { dMessage = MSG_DEC_TIME; // set message. queueModTotalTime.put((int *) dMessage,1);// pretend it's a pointer. gtButtons.cRightButton = 0; // clear the button state. } //--- // COOK-STATE FSM. if (gtButtons.cTopButton) // start-cook button. { dMessage = MSG_START; // set message. queueUpdateFSM.put((int *) dMessage,1); // pretend it's a pointer. gtButtons.cTopButton = 0; // clear the button state. } if (gtButtons.cBottomButton) // stop-cook button. { dMessage = MSG_STOP; // set message. queueUpdateFSM.put((int *) dMessage,1); // pretend it's a pointer. gtButtons.cBottomButton = 0; // clear the button state. } if (gtButtons.cCenterButton) // door-state-toggle. { dMessage = gtButtons.cDoorOpen; // determined in ISR. queueUpdateFSM.put((int *) dMessage,1); // pretend it's a pointer. gtButtons.cCenterButton = 0; // clear the button state. } //--- Thread::wait(THREAD_4_WAITmS); // multitasking. } // thread loop. } // threadButtonStateManager. /*----------------------------------------------//----------------------------*/ // the incoming messages are mutually-exclusive. // total time controller. void threadTotalTimeControl(void const *args) { static int dTotalTime = 0; // total time variable. int dMessage; // message. int dSuppress; // 1 to suppress operation. osEvent queueEvent; // queue event. int dRC; dSuppress = 0; // initialize. while(1) // thread loop. { // if FSM tells this to clear // the total time. queueEvent = queueClearTotalTime.get(1); if (queueEvent.status == osEventMessage) { dTotalTime = 0; dRC = queueSetRemainingTime.put((int *) dTotalTime,1); giRemainingTime.dTotalTime = dTotalTime; } // suppression mail from FSM. queueEvent = queueSuppressTimeAdjust.get(1); if (queueEvent.status == osEventMessage) { dSuppress = (int) queueEvent.value.p; } queueEvent = queueModTotalTime.get(1); // get message. if (queueEvent.status == osEventMessage) { dMessage = (int) queueEvent.value.p; // interpret as integer, not pointer. if (!dSuppress) // increment total time. if (dMessage == MSG_INC_TIME) dTotalTime += TIMEINC; if (!dSuppress) // decrement total time. if (dMessage == MSG_DEC_TIME) dTotalTime -= TIMEINC; // saturations. if (dTotalTime > 180) dTotalTime = 180; if (dTotalTime < 0) dTotalTime = 0; dRC = queueSetRemainingTime.put((int *) dTotalTime,1); giRemainingTime.dTotalTime = dTotalTime; } Thread::wait(THREAD_3_WAITmS); // multitasking. } // thread loop. } // threadTotalTimeControl. /*----------------------------------------------//----------------------------*/ void threadCookStateFSM(void const *args) // cook-cycle FSM. { int dFSMstate = FSM_IDLE; // state of this FSM. int dFSMstateLast = FSM_IDLE; // previous FSM state. int dButtonState; // received button state. int dRemainingTime = 0; // received remaining time. int dButtonStart = 0; int dButtonStop = 0; int dDoorOpen = 0; int dBeepSeconds = 0; osEvent queueEvent; // from button state manager. beepTimer.start(); // run the beep timer. dBeepSeconds = BEEPTIME; // queueModTotalTime.put((int *) dMessage,1);// pre queueTemperatureControl.put((int *) TEMP_READ,1); while(1) // thread loop. { pc.printf("\n\r state: %d",dFSMstate); switch (dFSMstate) // cook-mode state machine. { //--- case FSM_IDLE : // IDLE. { led0 = 0; if (dFSMstate != dFSMstateLast) // if just entered state. { queueTemperatureControl.put((int *) TEMP_READ,1); queueSuppressTimeAdjust.put((int*) 0,1); queueClearTotalTime.put ((int*) 1,1); } giLCD.dTotalCookTime = giRemainingTime.dTotalTime; giLCD.dRemainingTime = 0; // suppress remaining time display. // giLCD.fCelsius = 0; giRemainingTime.cControl = RT_PRELOAD; dFSMstateLast = dFSMstate; // determine next state. if ((dButtonStart == 1) && (dDoorOpen == 0) && (giRemainingTime.dTotalTime > 0)) dFSMstate = FSM_COOK; break; } //--- case FSM_COOK : // COOK. { if (dFSMstate != dFSMstateLast) // if just entered state. { giRemainingTime.cControl = RT_DECREMENT; queueTemperatureControl.put((int *) TEMP_CALC,1); queueSuppressTimeAdjust.put((int*) 1,1); } giLCD.dTotalCookTime = giRemainingTime.dTotalTime; giLCD.dRemainingTime = giRemainingTime.dRemainingTime; // giLCD.fCelsius = 0; dFSMstateLast = dFSMstate; // determine next state. if ((dDoorOpen == 1) && (dRemainingTime > 0)) dFSMstate = FSM_PAUSE; else if (dButtonStop) dFSMstate = FSM_IDLE; else if (dRemainingTime <= 0) dFSMstate = FSM_DONE; break; } //--- case FSM_PAUSE : // PAUSE. { if (dFSMstate != dFSMstateLast) // if just entered state. { queueTemperatureControl.put((int *) TEMP_FREEZE,1); } giLCD.dTotalCookTime = giRemainingTime.dTotalTime; giLCD.dRemainingTime = giRemainingTime.dRemainingTime; // giLCD.fCelsius = 0; giRemainingTime.cControl = RT_PAUSE; // determine next state. dFSMstateLast = dFSMstate; if ((dButtonStart == 1) && (dDoorOpen == 0) && (giRemainingTime.dTotalTime > 0)) dFSMstate = FSM_CONTINUE; else if (dButtonStop) dFSMstate = FSM_IDLE; break; } //--- case FSM_CONTINUE : // CONTINUE. { if (dFSMstate != dFSMstateLast) // if just entered state. { queueTemperatureControl.put((int *) TEMP_CALC,1); } giLCD.dTotalCookTime = giRemainingTime.dTotalTime; giLCD.dRemainingTime = giRemainingTime.dRemainingTime; // giLCD.fCelsius = 0; giRemainingTime.cControl = RT_DECREMENT; // determine next state. dFSMstateLast = dFSMstate; if (dRemainingTime <= 0) dFSMstate = FSM_DONE; else if (dButtonStop) dFSMstate = FSM_IDLE; else if ((dDoorOpen == 1) && (dRemainingTime > 0)) dFSMstate = FSM_PAUSE; break; } //--- case FSM_DONE : // DONE. { led0 = 1; led3 = 0; if (dFSMstate != dFSMstateLast) // if just entered state. { queueTemperatureControl.put((int *) TEMP_FREEZE,1); Thread thread_beep(&speakerThread,(void *) &dBeepSeconds); beepTimer.reset(); // clear the beep timer. } giLCD.dTotalCookTime = giRemainingTime.dTotalTime; giLCD.dRemainingTime = giRemainingTime.dRemainingTime; // giLCD.fCelsius = 0; giRemainingTime.cControl = RT_CLEAR; // determine next state. dFSMstateLast = dFSMstate; if (beepTimer.read() >= BEEPTIME) dFSMstate = FSM_IDLE; else dFSMstate = FSM_DONE; led3 = 1; break; } //--- default : {dFSMstate = FSM_IDLE; break;} } queueEvent = queueUpdateFSM.get(1); // threadButtonStateManager if (queueEvent.status == osEventMessage)// update state variable. { // interpret as integer, not pointer. dButtonState = (int) queueEvent.value.p; if (dButtonState == MSG_START) { dButtonStart = 1; dButtonStop = 0; // if the door is open, ignore // and cancel 'start' state. if (dDoorOpen) dButtonStart = 0; } if (dButtonState == MSG_STOP) { dButtonStart = 0; dButtonStop = 1; queueClearTotalTime.put ((int*) 1,1); } if (dButtonState == MSG_OPEN) { // if the door opens, clear current 'start' state. dDoorOpen = 1; dButtonStart = 0; } if (dButtonState == MSG_CLOSED) { dDoorOpen = 0; } } else // no queue update available. { dButtonStart = 0; dButtonStop = 0; // dDoorOpen = 0; } // fetch from global scope. dRemainingTime = giRemainingTime.dRemainingTime; // pipeline variable. Thread::wait(THREAD_5_WAITmS); // multitasking. } // thread loop. } // threadCookStateFSM. /*----------------------------------------------//----------------------------*/ void slowClock(void) // 1Hz or thereabouts. { gcSlowClock = !gcSlowClock; // toggle clock. } /*----------------------------------------------//----------------------------*/ void initialization(void) // program initializations. { gcSignalWaitEnable = 1; } /*----------------------------------------------//----------------------------*/ void ISRleftButtonRising(void) // cooktime plus 60s. { if (debounceTimer.read_ms() > DEBOUNCEmS) gtButtons.cLeftButton = 1; // detect left button. debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ void ISRleftButtonFalling(void) // button-release debounce. { debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ void ISRrightButtonRising(void) // cooktime -60s. { if (debounceTimer.read_ms() > DEBOUNCEmS) gtButtons.cRightButton = 1; // detect right button. debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ void ISRrightButtonFalling(void) // button-release debounce. { debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ void ISRtopButtonRising(void) // cook start. { if (debounceTimer.read_ms() > DEBOUNCEmS) gtButtons.cTopButton = 1; // detect top button. debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ void ISRtopButtonFalling(void) // button-release debounce. { debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ // front-end control of magnetron off. // due to physical danger, the magnetron is turned off immediately // upon off-button press, in the interrupt that it generates. void ISRbottomButtonRising(void) // cook stop. { if (debounceTimer.read_ms() > DEBOUNCEmS) { led0 = 0; // magnetron off. gtButtons.cBottomButton = 1; // detect bottom button. } debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ void ISRbottomButtonFalling(void) // button-release debounce. { debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ // front-end control of magnetron off. // due to physical danger, the magnetron is turned off immediately // upon detection of an open door. void ISRcenterButtonRising(void) // toggle door state. { if (debounceTimer.read_ms() > DEBOUNCEmS) { if (gtButtons.cDoorOpen == MSG_OPEN) // calculate door state. gtButtons.cDoorOpen = MSG_CLOSED; else gtButtons.cDoorOpen = MSG_OPEN; // magnetron off. if (gtButtons.cDoorOpen == MSG_OPEN) led0 = 0; gtButtons.cCenterButton = 1; } debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ void ISRcenterButtonFalling(void) // button-release debounce. { debounceTimer.reset(); // begin debounce period. } /*----------------------------------------------//----------------------------*/ //==================================================== void temperatureThread(void const *args) // temperature measurement. { int dTempControl = 0; // temperature control. int dCurrentTimerMs; int dPreviousTimerMs; float fLastMeasuredTemperature; osEvent queueEvent; // from button state manager. dCurrentTimerMs = 0; dPreviousTimerMs = 0; fLastMeasuredTemperature = 0.0; // temperatureTimer.start(); while(1) // thread loop. { // obtain temperature command. queueEvent = queueTemperatureControl.get(1); if (queueEvent.status == osEventMessage) { dTempControl = (int) queueEvent.value.p; } if (dTempControl == TEMP_READ) { gfCelsius = temperature.read(); // physical measurement. fLastMeasuredTemperature = gfCelsius; // temperatureTimer.reset(); // reset timer while we're not using it. } if (dTempControl == TEMP_CALC) gfCelsius = ((float) (giRemainingTime.dTotalTime - giRemainingTime.dRemainingTime) / (float) 6.0) + fLastMeasuredTemperature; // gfCelsius = fLastMeasuredTemperature + (temperatureTimer.read_ms() / 6000.0); giLCD.fCelsius = gfCelsius; Thread::wait(THREAD_1_WAITmS); // multitasking. } // thread loop. } // temperatureThread. /*----------------------------------------------//----------------------------*/ void LCDthread(void const *args) // LCD display thread. { static int dLCDtotalCookTimeSec = 0; // sample current values. static int dCookTimeRemainingSec = 0; static float fLCDcelsius = 0.0; // remember previous values. static int dLCDtotalCookTimeSecLast = 0; static int dCookTimeRemainingSecLast = 0; static float fLCDcelsiusLast = 0.0; while(1) // thread loop. { // don't allow the values to // change in the middle of the // below else the anti-blink // code won't work. dLCDtotalCookTimeSec = giLCD.dTotalCookTime; dCookTimeRemainingSec = giLCD.dRemainingTime; fLCDcelsius = giLCD.fCelsius; // clear display only when // necessary, in order to avoid // 'blinkieness'. if (dLCDtotalCookTimeSec != dLCDtotalCookTimeSecLast || dCookTimeRemainingSec != dCookTimeRemainingSecLast || fLCDcelsius != fLCDcelsiusLast) lcd.cls(); LCD1; // line 1. lcd.printf(" total cook time: %d",dLCDtotalCookTimeSec); LCD2; // line 2. lcd.printf(" remaing cook time: %d",dCookTimeRemainingSec); LCD3; // line 3. lcd.printf(" temperature : %5.3f",fLCDcelsius); // pipeline variables. dLCDtotalCookTimeSecLast = dLCDtotalCookTimeSec; dCookTimeRemainingSecLast = dCookTimeRemainingSec; fLCDcelsiusLast = fLCDcelsius; Thread::wait(THREAD_2_WAITmS); // multitasking. } // thread loop. } // LCDthread. /*----------------------------------------------//----------------------------*/ // cook remaining time countdown counter. // possibly due to a bug in Ticker // http://mbed.org/questions/1563/Mbed-Tickerfunction-hangs-system-from-re/ // I've been unable to detach/attach this routine in order to reset its phase // when I tried it at a 1s resolution. In order to provide the human perception // of an immediate restart, I've increased the ticker frequency by the factor // 'GRANULARITY' and likewise divide that factor out when this routine // promotes the remaining time to the global variable. void tickCookRemainingTime(void) // cook-cycle countdown. { static int dRemainingTime = 0; // remaining time in seconds. int dMaximum; // MAXSECONDS * GRANULARITY. dMaximum = MAXSECONDS * GRANULARITY; // precalculate. switch (giRemainingTime.cControl) // control processing. { case RT_PRELOAD : // preload with total time. { // the 'GRANULARITY - 1' factor // compensates for integer division // dropping the right-of-decimal result, // that occuring at the bottom of this // routine. dRemainingTime = (giRemainingTime.dTotalTime * GRANULARITY) + (GRANULARITY - 1); break; } case RT_DECREMENT : // count-down. { dRemainingTime--; break; } case RT_PAUSE : // suspend countdown. { dRemainingTime = dRemainingTime; break; } case RT_CLEAR : // clear countdown. { dRemainingTime = 0; break; } default : // saturate, just in case. { } } // control processing. // saturate value. if (dRemainingTime > dMaximum) dRemainingTime = dMaximum; if (dRemainingTime < 0) dRemainingTime = 0; // promote to global scope. giRemainingTime.dRemainingTime = dRemainingTime/GRANULARITY; } // cookRemainingTime. /*----------------------------------------------//----------------------------*/ void speakerThread(void const * pSecondsBeep) { osEvent queueEvent; // from button state manager. int dLoop; int * pSeconds; int dSeconds; float fHalfSecond; // cycles per half-second. /* pSeconds = (int *) pSecondsBeep; dSeconds = *pSeconds; // dSeconds = 2; fHalfSecond = 0.5 / (float) BEEPFREQ; for (dLoop = 0; dLoop < (dSeconds * BEEPFREQ); dLoop++) { speaker = 1; wait(fHalfSecond); speaker = 0; wait(fHalfSecond); } */ } /*----------------------------------------------//----------------------------*/ void tickerBeeper(void) { static char cState = 0; if (gcBeepEnable) { if (cState) {speaker = 1; cState = 0;} else {speaker = 0; cState = 1;} } } /*----------------------------------------------//----------------------------*/