Index: App/Contollers/Buttons.c =================================================================== diff -u -r765d2c35118e202444e737c66c77faf9678cc87e -r29f1ba03faefd982327916590818a260a3e4aa48 --- App/Contollers/Buttons.c (.../Buttons.c) (revision 765d2c35118e202444e737c66c77faf9678cc87e) +++ App/Contollers/Buttons.c (.../Buttons.c) (revision 29f1ba03faefd982327916590818a260a3e4aa48) @@ -1,55 +1,74 @@ -/************************************************************************* -* -* Copyright Diality, Inc. 2019-2020. All Rights Reserved. -* 181 Technology, Ste. 150 -* Irvine, CA 92618 -* -* Project Denali -* -* @file Buttons.c -* -* @brief Monitor/Controller for the off and stop buttons. -* -* @date 20-Sep-2019 -* -*************************************************************************/ +/************************************************************************** + * + * Copyright (c) 2019-2019 Diality Inc. - All Rights Reserved. + * + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * @file Buttons.c + * + * @date 20-Sep-2019 + * @author S. Nash + * + * @brief Monitor/Controller for the off and stop buttons. + * + **************************************************************************/ #include "Common.h" #include "CPLD.h" -#include "TaskPriority.h" #include "OperationModes.h" +#include "SystemCommMessages.h" +#include "TaskPriority.h" +#include "Timers.h" #include "Buttons.h" // ********** private definitions ********** typedef enum Button_States { - BUTTON_STATE_RELEASED = 0, // Fault - BUTTON_STATE_PRESSED, // Service - NUM_OF_BUTTON_STATES + BUTTON_STATE_RELEASED = 0, + BUTTON_STATE_PRESSED, + NUM_OF_BUTTON_STATES } BUTTON_STATE_T; -#define OFF_REQUEST_PULSE_COUNT 4 -#define OFF_REQUEST_PULSE_INTVL 50 // ms +typedef enum Button_Self_Test_States +{ + BUTTON_SELF_TEST_STATE_START = 0, + BUTTON_SELF_TEST_STATE_IN_PROGRESS, + BUTTON_SELF_TEST_STATE_COMPLETE, + NUM_OF_BUTTON_SELF_TEST_STATES +} BUTTON_SELF_TEST_STATE_T; +#define OFF_REQUEST_PULSE_COUNT 4 +#define OFF_REQUEST_PULSE_INTVL 50 // ms +#define STOP_BUTTON_PENDING_TIMEOUT 500 // ms +#define STUCK_BUTTON_TIMEOUT 1000 // ms + +#define USER_CONFIRMED 1 +#define USER_REJECTED 0 + // ********** private data ********** static BUTTON_STATE_T offButtonState = BUTTON_STATE_RELEASED; static BUTTON_STATE_T prevOffButtonState = BUTTON_STATE_RELEASED; -static BOOL offButtonPressPending = FALSE; +static BOOL offButtonPressPending = FALSE; static BUTTON_STATE_T stopButtonState = BUTTON_STATE_RELEASED; static BUTTON_STATE_T prevStopButtonState = BUTTON_STATE_RELEASED; -static BOOL stopButtonPressPending = FALSE; +static BOOL stopButtonPressPending = FALSE; +static U32 stopButtonPendingTimer = 0; -static U32 offRequestPulseCount = 0; -static U32 offRequestPulseTimer = 0; +static U32 offRequestPulseCount = 0; +static U32 offRequestPulseTimer = 0; +static BUTTON_SELF_TEST_STATE_T buttonSelfTestState = BUTTON_SELF_TEST_STATE_START; +static U32 buttonSelfTestTimerCount = 0; + // ********** private function prototypes ********** static void handleOffButtonProcessing( void ); static void handleStopButtonProcessing( void ); -static void pulseOffRequestSignal( void ); +static BOOL isCurrentOpModeOkToTurnOff( void ); /************************************************************************* * @brief initButtons @@ -59,19 +78,23 @@ * Outputs : Buttons module initialized. * @param none * @return none -*************************************************************************/ + *************************************************************************/ void initButtons( void ) { - offButtonState = BUTTON_STATE_RELEASED; - prevOffButtonState = BUTTON_STATE_RELEASED; - offButtonPressPending = FALSE; + offButtonState = BUTTON_STATE_RELEASED; + prevOffButtonState = BUTTON_STATE_RELEASED; + offButtonPressPending = FALSE; - stopButtonState = BUTTON_STATE_RELEASED; - prevStopButtonState = BUTTON_STATE_RELEASED; - stopButtonPressPending = FALSE; + stopButtonState = BUTTON_STATE_RELEASED; + prevStopButtonState = BUTTON_STATE_RELEASED; + stopButtonPressPending = FALSE; + stopButtonPendingTimer = 0; - offRequestPulseCount = 0; - offRequestPulseTimer = 0; + offRequestPulseCount = 0; + offRequestPulseTimer = 0; + + buttonSelfTestState = BUTTON_SELF_TEST_STATE_START; + buttonSelfTestTimerCount = 0; } /************************************************************************* @@ -82,21 +105,21 @@ * Outputs : offButtonState, stopButtonState, prevOffButtonState, prevStopButtonState * @param none * @return none -*************************************************************************/ + *************************************************************************/ void execButtons( void ) { - PIN_SIGNAL_STATE_T off = getCPLDOffButton(); - PIN_SIGNAL_STATE_T stop = getCPLDStopButton(); + PIN_SIGNAL_STATE_T off = getCPLDOffButton(); + PIN_SIGNAL_STATE_T stop = getCPLDStopButton(); - // set current button states read from CPLD - offButtonState = ( off == PIN_SIGNAL_HIGH ? BUTTON_STATE_PRESSED : BUTTON_STATE_RELEASED ); - stopButtonState = ( stop == PIN_SIGNAL_HIGH ? BUTTON_STATE_PRESSED : BUTTON_STATE_RELEASED ); + // set current button states read from CPLD + offButtonState = ( off == PIN_SIGNAL_HIGH ? BUTTON_STATE_PRESSED : BUTTON_STATE_RELEASED ); + stopButtonState = ( stop == PIN_SIGNAL_HIGH ? BUTTON_STATE_PRESSED : BUTTON_STATE_RELEASED ); - // handle button state transitions for stop button - handleStopButtonProcessing(); + // handle button state transitions for stop button + handleStopButtonProcessing(); - // handle button state transitions for off button - handleOffButtonProcessing(); + // handle button state transitions for off button + handleOffButtonProcessing(); } /************************************************************************* @@ -109,15 +132,14 @@ * Outputs : stopButtonPressPending * @param button * @return true if the stop button is pressed, false if not -*************************************************************************/ + *************************************************************************/ BOOL isStopButtonPressed( void ) { - BOOL result = FALSE; + BOOL result = stopButtonPressPending; - result = stopButtonPressPending; - stopButtonPressPending = FALSE; + stopButtonPressPending = FALSE; - return result; + return result; } /************************************************************************* @@ -129,117 +151,180 @@ * Outputs : none * @param button * @return true if given button is pressed, false if not -*************************************************************************/ + *************************************************************************/ BOOL isButtonPressedRaw( BUTTON_T button ) { - BOOL result = FALSE; + BOOL result = FALSE; - switch (button) - { - case BUTTON_OFF: - if ( offButtonState == BUTTON_STATE_PRESSED ) - { - result = TRUE; - } - break; - case BUTTON_STOP: - if ( stopButtonState == BUTTON_STATE_PRESSED ) - { - result = TRUE; - } - break; - default: - // TODO - s/w fault - break; - } + switch ( button ) + { + case BUTTON_OFF: + if ( offButtonState == BUTTON_STATE_PRESSED ) + { + result = TRUE; + } + break; + case BUTTON_STOP: + if ( stopButtonState == BUTTON_STATE_PRESSED ) + { + result = TRUE; + } + break; + default: + // TODO - s/w fault + break; + } - return result; + return result; } /************************************************************************* * @brief userConfirmOffButton * The userConfirmOffButton function handles user confirmation of the off \n - * button. The off request will be initiated here. + * button. The off request will be initiated here if confirmed or cancelled \n + * if rejected by user. * @details - * Inputs : stopButtonState, prevStopButtonState + * Inputs : current operation mode * Outputs : stopButtonPressPending - * @param none + * @param response : 1 = confirmed, 0 = rejected * @return none -*************************************************************************/ -void userConfirmOffButton( void ) + *************************************************************************/ +void userConfirmOffButton( U08 response ) { - OP_MODE opMode = getCurrentOperationMode(); + // did user confirm? + if ( USER_CONFIRMED == response ) + { + if ( TRUE == isCurrentOpModeOkToTurnOff() ) + { + offButtonPressPending = TRUE; + offRequestPulseCount = OFF_REQUEST_PULSE_COUNT; + offRequestPulseTimer = 0; + } + } + else // user did not confirm + { + // for now, don't need to do anything to reject off button press + } +} - if ( ( opMode == MODE_STAN ) || ( opMode == MODE_SERV ) || ( opMode == MODE_FAUL ) ) - { - offButtonPressPending = TRUE; - offRequestPulseCount = OFF_REQUEST_PULSE_COUNT; - offRequestPulseTimer = 0; - } +/************************************************************************* + * @brief execStuckButtonTest + * The execStuckButtonTest function executes the stuck button test. \n + * This function should be called periodically until a pass or fail \n + * result is returned. + * @details + * Inputs : + * Outputs : + * @param none + * @return in progress, passed, or failed + *************************************************************************/ +SELF_TEST_STATUS_T execStuckButtonTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; + + switch ( buttonSelfTestState ) + { + case BUTTON_SELF_TEST_STATE_START: + buttonSelfTestState = BUTTON_SELF_TEST_STATE_IN_PROGRESS; + buttonSelfTestTimerCount = getMSTimerCount(); + // no break here so we pass through directly to in progress processing + + case BUTTON_SELF_TEST_STATE_IN_PROGRESS: + if ( ( offButtonState == BUTTON_STATE_RELEASED ) && ( stopButtonState == BUTTON_STATE_RELEASED ) ) + { + result = SELF_TEST_STATUS_PASSED; + buttonSelfTestState = BUTTON_SELF_TEST_STATE_COMPLETE; + } + else if ( TRUE == didTimeout( buttonSelfTestTimerCount, STUCK_BUTTON_TIMEOUT ) ) + { + result = SELF_TEST_STATUS_FAILED; + // TODO - trigger stuck button POST failure + buttonSelfTestState = BUTTON_SELF_TEST_STATE_COMPLETE; + } + // else just stay in progress and wait for next call + break; + + case BUTTON_SELF_TEST_STATE_COMPLETE: + // if we get called in this state, assume we're doing self test again + buttonSelfTestState = BUTTON_SELF_TEST_STATE_START; + break; + + default: + result = SELF_TEST_STATUS_FAILED; + // TODO - s/w fault + break; + } + + return result; } /************************************************************************* - * @brief handleOffButtonProcessing - * The handleOffButtonProcessing function checks for and processes off button \n - * activity. + * @brief isCurrentOpModeOkToTurnOff + * The isCurrentOpModeOkToTurnOff function determines whether the system can \n + * be turned off in current operation mode. * @details - * Inputs : offButtonState, prevOffButtonState - * Outputs : offButtonPressPending, offRequestPulseCount, offRequestPulseTimer + * Inputs : Current operation mode. + * Outputs : none * @param none - * @return none -*************************************************************************/ -static void handleOffButtonProcessing( void ) + * @return true if can turn system off in current mode, false if not + *************************************************************************/ +static BOOL isCurrentOpModeOkToTurnOff( void ) { - // handle button state transitions for off button - if ( offButtonState != prevOffButtonState ) - { - if ( offButtonState == BUTTON_STATE_PRESSED ) - { - OP_MODE opMode = getCurrentOperationMode(); + OP_MODE opMode = getCurrentOperationMode(); + BOOL result = FALSE; - // if off request in a valid mode, send to UI for user confirmation - if ( ( opMode == MODE_STAN ) || ( opMode == MODE_SERV ) || ( opMode == MODE_FAUL ) ) - { - // TODO - send off button to UI for user confirmation - // temporary - just pretend user confirmed for now - userConfirmOffButton(); - } - } - prevOffButtonState = offButtonState; - } + if ( ( opMode == MODE_STAN ) || ( opMode == MODE_SERV ) || ( opMode == MODE_FAUL ) ) + { + result = TRUE; + } - if ( TRUE == offButtonPressPending ) - { - offRequestPulseTimer += TASK_PRIORITY_INTERVAL; - if ( offRequestPulseTimer >= OFF_REQUEST_PULSE_INTVL ) - { - offRequestPulseTimer = 0; - offRequestPulseCount--; - if ( offRequestPulseCount == 0 ) - { - offButtonPressPending = false; - } - pulseOffRequestSignal(); - } - } + return result; } /************************************************************************* - * @brief pulseOffRequestSignal - * The pulseOffRequestSignal function pulses the off request signal. + * @brief handleOffButtonProcessing + * The handleOffButtonProcessing function checks for and processes off button \n + * activity. * @details - * Inputs : none - * Outputs : off request signal pulsed + * Inputs : offButtonState, prevOffButtonState + * Outputs : offButtonPressPending, offRequestPulseCount, offRequestPulseTimer * @param none * @return none -*************************************************************************/ -static void pulseOffRequestSignal( void ) + *************************************************************************/ +static void handleOffButtonProcessing( void ) { - U32 d; + // handle button state transitions for off button + if ( offButtonState != prevOffButtonState ) + { + if ( offButtonState == BUTTON_STATE_PRESSED ) + { + // if off request in a valid mode, send to UI for user confirmation + if ( TRUE == isCurrentOpModeOkToTurnOff() ) + { + // send off button to UI for user confirmation + sendOffButtonMsgToUI(); +#ifdef SIMULATE_UI + userConfirmOffButton( USER_CONFIRMED ); +#endif + } + } + prevOffButtonState = offButtonState; + } - setCPLDOffRequest( PIN_SIGNAL_HIGH ); - for ( d = 0; d < 1000; d++ ); // ok to block briefly because we're shutting down anyway - setCPLDOffRequest( PIN_SIGNAL_LOW ); + if ( TRUE == offButtonPressPending ) + { + offRequestPulseTimer += TASK_PRIORITY_INTERVAL; + if ( offRequestPulseTimer >= OFF_REQUEST_PULSE_INTVL ) + { + offRequestPulseTimer = 0; + offRequestPulseCount--; + if ( offRequestPulseCount == 0 ) + { + offButtonPressPending = false; + } + toggleCPLDOffRequest(); + } + } } /************************************************************************* @@ -251,18 +336,28 @@ * Outputs : stopButtonPressPending * @param none * @return none -*************************************************************************/ + *************************************************************************/ static void handleStopButtonProcessing( void ) { - // handle button state transitions for stop button if ( stopButtonState != prevStopButtonState ) - if ( stopButtonState != prevStopButtonState ) - { - if ( stopButtonState == BUTTON_STATE_PRESSED ) - { - stopButtonPressPending = TRUE; - } - prevStopButtonState = stopButtonState; - } + // handle button state transitions for stop button + if ( stopButtonState != prevStopButtonState ) + { + if ( stopButtonState == BUTTON_STATE_PRESSED ) + { + stopButtonPressPending = TRUE; + stopButtonPendingTimer = getMSTimerCount(); + } + prevStopButtonState = stopButtonState; + } + + // handle when a stop button press is pending + if ( TRUE == stopButtonPressPending ) + { + // if stop button not consumed within a reasonable time, s/w fault + if ( TRUE == didTimeout( stopButtonPendingTimer, STOP_BUTTON_PENDING_TIMEOUT ) ) + { + // TODO - s/w fault + } + } } -