Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -rf308cc4c35eab630ebbbde405cfe47d049afeafb -r0ff3afb455342a5abde4bb3e6a99819c9ed05164 --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision f308cc4c35eab630ebbbde405cfe47d049afeafb) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 0ff3afb455342a5abde4bb3e6a99819c9ed05164) @@ -8,7 +8,7 @@ * @file Valves.c * * @author (last) Quang Nguyen -* @date (last) 21-Jul-2020 +* @date (last) 26-Aug-2020 * * @author (original) Sean * @date (original) 06-May-2020 @@ -27,51 +27,54 @@ // ********** private definitions ********** -#define DEENERGIZED 0 ///< 0 for de-energized valve -#define ENERGIZED 1 ///< 1 for energized valve -#define ALL_VALVES_DEENERGIZED 0x0000 ///< 0 in U16 bit field for all valves +#define DEENERGIZED 0 ///< 0 for de-energized valve. +#define ENERGIZED 1 ///< 1 for energized valve. +#define ALL_VALVES_DEENERGIZED 0x0000 ///< 0 in U16 bit field for all valves. -#define MAX_VALVE_STATE_MISMATCH_COUNT 3 ///< maximum number of times commanded valves state can fail to match read back valve states in a row. +#define MAX_VALVE_STATE_MISMATCH_COUNT 3 ///< Maximum number of times commanded valves state can fail to match read back valve states in a row. -/// Default publication interval for valves states -#define VALVES_STATE_PUB_INTERVAL ( 500 / TASK_PRIORITY_INTERVAL ) ///< interval ( ms / task time) at which valves states are published on CAN bus +#define VALVES_STATE_PUB_INTERVAL ( 500 / TASK_PRIORITY_INTERVAL ) ///< Interval ( ms / task time) at which valves states are published on CAN bus. // ********** private data ********** -static U32 valvesStatesPublicationTimerCounter = 0; ///< used to schedule valve state publication to CAN bus -static U16 commandedValvesStates = ALL_VALVES_DEENERGIZED; ///< initialize commanded valves states bit field. -static U32 valveStateMismatchCounter = 0; ///< initialize valve state mismatch counter +static U32 valvesStatesPublicationTimerCounter = 0; ///< Timer counter used to schedule valve state publication to CAN bus. +static U16 commandedValvesStates = ALL_VALVES_DEENERGIZED; ///< Initialize commanded valves states bit field. +static U32 valveStateMismatchCounter = 0; ///< Initialize valve state mismatch counter. +static U32 pendingValveStateChanges[ NUM_OF_VALVES ]; ///< Delayed (pending) valve state changes. +static U32 pendingValveStateChangeCountDowns[ NUM_OF_VALVES ]; ///< Delayed (pending) valve state change count down timers (in task intervals). -static OVERRIDE_U32_T valveStates[ NUM_OF_VALVES ]; ///< Currently commanded valves states -static OVERRIDE_U32_T valvesStatesPublishInterval = { VALVES_STATE_PUB_INTERVAL, VALVES_STATE_PUB_INTERVAL, 0, 0 }; ///< interval (in ms/task interval) at which to publish valves state to CAN bus +static OVERRIDE_U32_T valveStates[ NUM_OF_VALVES ]; ///< Currently commanded valves states. +static OVERRIDE_U32_T valvesStatesPublishInterval = { VALVES_STATE_PUB_INTERVAL, VALVES_STATE_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms/task interval) at which to publish valves state to CAN bus. // ********** private function prototypes ********** -static BOOL checkValveStateName( VALVES_T valve, VALVE_STATE_NAMES_T valveStateName ); ///< check validity of requested valve state name for given valve -static U32 convertValveStateNameToValveState(VALVE_STATE_NAMES_T valveStateName); ///< Convert valve state name to de-/energized valve state -static U16 fromU32ArrayToU16( void ); ///< convert array of U32 to U16 for statesValves preparation +static BOOL checkValveStateName( VALVES_T valve, VALVE_STATE_NAMES_T valveStateName ); +static U32 convertValveStateNameToValveState(VALVE_STATE_NAMES_T valveStateName); +static U16 fromU32ArrayToU16( void ); static void publishValvesStates( void ); -static DATA_GET_PROTOTYPE( U32, getPublishValvesStatesInterval ); +static U32 getPublishValvesStatesInterval( void ); /*********************************************************************//** * @brief * The initValves function initializes the Valves module. - * @details - * Inputs : none - * Outputs : Valves module initialized + * @details Inputs: none + * @details Outputs: Valves module initialized * @return none *************************************************************************/ void initValves( void ) { U32 i; // initialize commanded valve states - for (i = 0; i < NUM_OF_VALVES; i++) + for ( i = 0; i < NUM_OF_VALVES; i++ ) { valveStates[ i ].data = DEENERGIZED; valveStates[ i ].ovInitData = DEENERGIZED; valveStates[ i ].ovData = DEENERGIZED; - valveStates[ i ].override = OVERRIDE_RESET; + valveStates[ i ].override = OVERRIDE_RESET; + + pendingValveStateChanges[ i ] = DEENERGIZED; + pendingValveStateChangeCountDowns[ i ] = 0; } commandedValvesStates = fromU32ArrayToU16(); setFPGAValveStates( commandedValvesStates ); // initially set all valves to de-energized state via FPGA @@ -82,16 +85,16 @@ /*********************************************************************//** * @brief * The execValves function executes the valves driver. - * @details - * Inputs : valvesStates, valveStateMismatchCounter - * Outputs : valvesStates, valveStateMismatchCounter + * @details Inputs: valvesStates, valveStateMismatchCounter + * @details Outputs: valvesStates, valveStateMismatchCounter * @return none *************************************************************************/ void execValves( void ) -{ +{ + U32 i; U16 readValvesStates = getFPGAValveStates(); // get valves states from FPGA - // verify read back FPGA valve states match last commanded valve states + // Verify read back FPGA valve states match last commanded valve states if ( readValvesStates != commandedValvesStates ) { valveStateMismatchCounter++; // increment valve state mismatch counter by 1 @@ -103,23 +106,36 @@ else { valveStateMismatchCounter = 0; + } + + // Handle pending delayed valve state changes + for ( i = 0; i < NUM_OF_VALVES; i++ ) + { + if ( pendingValveStateChangeCountDowns[ i ] > 0 ) + { + pendingValveStateChangeCountDowns[ i ]--; + if ( 0 == pendingValveStateChangeCountDowns[ i ] ) + { + valveStates[ i ].data = pendingValveStateChanges[ i ]; + pendingValveStateChanges[ i ] = DEENERGIZED; + } + } } - // set valves states (via FPGA) to currently commanded states + // Set valves states (via FPGA) to currently commanded states commandedValvesStates = fromU32ArrayToU16(); setFPGAValveStates( commandedValvesStates ); - // publish valve states on interval + // Publish valve states on interval publishValvesStates(); } /*********************************************************************//** * @brief - * The checkValveStateName function checks the validity of requested valve \n + * The checkValveStateName function checks the validity of requested valve * state name for given valve. - * @details - * Inputs : none - * Outputs : none + * @details Inputs: none + * @details Outputs: none * @param valveID ID of valve to check a valve state name for * @param valveStateName valve state name to check for given valve ID * @return TRUE if given valveStateName is appropriate for given valve ID, FALSE if not. @@ -135,29 +151,50 @@ { result = TRUE; } +#ifndef V_2_SYSTEM + if ( ( VRD1 == valveID ) || ( VRD2 == valveID ) ) + { + result = TRUE; + } +#endif break; case VALVE_STATE_CLOSED: if ( ( valveID == VPI ) || ( valveID == VBF ) || ( valveID == VSP ) ) { result = TRUE; } +#ifndef V_2_SYSTEM + if ( ( VRD1 == valveID ) || ( VRD2 == valveID ) ) + { + result = TRUE; + } +#endif break; - case VALVE_STATE_OPEN_C_TO_NO: - if ( valveID == VPD ) - { - result = TRUE; - } - break; - - case VALVE_STATE_DRAIN_C_TO_NC: - if ( valveID == VPD ) - { - result = TRUE; - } - break; - +#ifndef V_2_SYSTEM + case VALVE_STATE_OPEN_C_TO_NC: + if ( VPD == valveID ) + { + result = TRUE; + } + break; +#else + case VALVE_STATE_OPEN_C_TO_NO: + if ( VPD == valveID ) + { + result = TRUE; + } + break; + + case VALVE_STATE_DRAIN_C_TO_NC: + if ( VPD == valveID ) + { + result = TRUE; + } + break; +#endif + case VALVE_STATE_NOFILL_C_TO_NO: if ( valveID == VPO ) { @@ -177,6 +214,12 @@ { result = TRUE; } +#ifndef V_2_SYSTEM + if ( VPD == valveID ) + { + result = TRUE; + } +#endif break; case VALVE_STATE_RECIRC_C_TO_NC: @@ -224,14 +267,12 @@ /*********************************************************************//** * @brief - * The getPublishValveStateInterval function gets the valves states \n - * publication interval. - * @details - * Inputs : valvesStatesPublishInterval - * Outputs : none + * The getPublishValveStateInterval function gets the valves states publication interval. + * @details Inputs: valvesStatesPublishInterval + * @details Outputs: none * @return the current valves states publication interval (in task intervals) *************************************************************************/ -U32 getPublishValvesStatesInterval( void ) +static U32 getPublishValvesStatesInterval( void ) { U32 result = valvesStatesPublishInterval.data; @@ -245,14 +286,13 @@ /*********************************************************************//** * @brief - * The fromU32ArrayToU16 function converts an array of U32 valve states \n + * The fromU32ArrayToU16 function converts an array of U32 valve states * to U16 valvesStates that can be passed to FPGA for setting valves. - * @details - * Inputs : valveStates[] - * Outputs : none + * @details Inputs: valveStates[] + * @details Outputs: none * @return converted U16 bit field for currently commanded valve states *************************************************************************/ -U16 fromU32ArrayToU16( void ) +static U16 fromU32ArrayToU16( void ) { U16 result = ALL_VALVES_DEENERGIZED; // start result flag as all valves de-energized U32 i; @@ -270,13 +310,12 @@ * @brief * The convertValveStateNameToValveState function converts valve state \n * name to its corresponding de-energized (0) or energized (1) valve state. - * @details - * Inputs : none - * Outputs : none + * @details Inputs: none + * @details Outputs: none * @param valveStateName valve state name enumeration to convert to energized/de-energized * @return converted valve state for given valve state name *************************************************************************/ -U32 convertValveStateNameToValveState( VALVE_STATE_NAMES_T valveStateName ) +static U32 convertValveStateNameToValveState( VALVE_STATE_NAMES_T valveStateName ) { U32 vState = DEENERGIZED; // initialize valve state to de-energized @@ -290,13 +329,19 @@ vState = DEENERGIZED; break; +#ifdef V_2_SYSTEM case VALVE_STATE_OPEN_C_TO_NO: vState = DEENERGIZED; break; case VALVE_STATE_DRAIN_C_TO_NC: vState = ENERGIZED; break; +#else + case VALVE_STATE_OPEN_C_TO_NC: + vState = ENERGIZED; + break; +#endif case VALVE_STATE_NOFILL_C_TO_NO: vState = DEENERGIZED; @@ -341,11 +386,10 @@ /*********************************************************************//** * @brief * The setValveState function sets the valve state for given valve. - * @details - * Inputs : none - * Outputs : none + * @details Inputs: none + * @details Outputs: valveStates[], pendingValveStateChanges[], pendingValveStateChangeCountDowns[] * @param valveID ID of valve to set state for - * @param valveStateName Name of valve state to set given valve to + * @param valveStateName name of valve state to set given valve to * @return TRUE if new valve state is set for given valve ID, FALSE if not. *************************************************************************/ BOOL setValveState( VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName ) @@ -354,26 +398,66 @@ if ( valveID < NUM_OF_VALVES ) { - if ( checkValveStateName ( valveID, valveStateName ) ) + if ( checkValveStateName( valveID, valveStateName ) ) { valveStates[ valveID ].data = convertValveStateNameToValveState( valveStateName ); result = TRUE; + // If a delayed state change is pending for this valve, cancel it + pendingValveStateChanges[ valveID ] = DEENERGIZED; + pendingValveStateChangeCountDowns[ valveID ] = 0; } } else { - // TODO - s/w fault + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) } return result; +} + +/*********************************************************************//** + * @brief + * The setValveStateDelayed function sets the valve state for given valve + * after a given delay. + * @details Inputs: pendingValveStateChangeCountDowns[] + * @details Outputs: pendingValveStateChangeCountDowns[], pendingValveStateChangeCountDowns[] + * @param valveID ID of valve to set state for + * @param valveStateName name of valve state to set given valve to + * @param delayMs delay duration (in ms) before actuation + * @return TRUE if new valve state is set for given valve ID, FALSE if not. + *************************************************************************/ +BOOL setValveStateDelayed( VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName, U32 delayMs ) +{ + BOOL result = FALSE; // initialize result flag to FALSE + + if ( valveID < NUM_OF_VALVES ) + { + if ( checkValveStateName( valveID, valveStateName ) ) + { + // If a delayed state change is already pending for this valve, execute it now before setting a new delayed state change + if ( pendingValveStateChangeCountDowns[ valveID ] > 0 ) + { + valveStates[ valveID ].data = pendingValveStateChanges[ valveID ]; + } + // Set delayed valve state change + pendingValveStateChanges[ valveID ] = convertValveStateNameToValveState( valveStateName ); + pendingValveStateChangeCountDowns[ valveID ] = delayMs / TASK_PRIORITY_INTERVAL; + result = TRUE; + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) + } + + return result; } /*********************************************************************//** * @brief * The getValveState function gets the current valve state for given valve. - * @details - * Inputs : valveStates[] - * Outputs : none + * @details Inputs: valveStates[] + * @details Outputs: none * @param valveID ID of valve to get state for * @return the current valve state for given valve *************************************************************************/ @@ -402,11 +486,9 @@ /*********************************************************************//** * @brief - * The publishValvesStates function publishes DG valves states at the \n - * set interval. - * @details - * Inputs : valvesStatesPublicationTimerCounter - * Outputs : DG valves states are published to CAN bus on interval. + * The publishValvesStates function publishes DG valves states at the set interval. + * @details Inputs: valvesStatesPublicationTimerCounter + * @details Outputs: DG valves states are published to CAN bus on interval. * @return none *************************************************************************/ static void publishValvesStates( void ) @@ -418,19 +500,19 @@ valvesStatesPublicationTimerCounter = 0; } } + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ + - /*********************************************************************//** * @brief - * The testSetValvesStatesPublishIntervalOverride function overrides the \n + * The testSetValvesStatesPublishIntervalOverride function overrides the * valves states publish interval. - * @details - * Inputs : none - * Outputs : valvesStatesPublishInterval + * @details Inputs: none + * @details Outputs: valvesStatesPublishInterval * @param value override valves states publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -452,11 +534,10 @@ /*********************************************************************//** * @brief - * The testResetValvesStatesPublishIntervalOverride function resets the override \n + * The testResetValvesStatesPublishIntervalOverride function resets the override * of the valves states publish interval. - * @details - * Inputs : none - * Outputs : valvesStatesPublishInterval + * @details Inputs: none + * @details Outputs: valvesStatesPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetValvesStatesPublishIntervalOverride( void ) @@ -475,10 +556,10 @@ /*********************************************************************//** * @brief - * The testSetValveStateOverride function overrides the value of the \n + * The testSetValveStateOverride function overrides the value of the * specified valve with a given value. - * Inputs : none - * Outputs : valves[] + * @details Inputs: none + * @details Outputs: valves[] * @param valveID ID of valve to override for * @param value override value for the given valve ID * @return TRUE if override successful, FALSE if not @@ -502,11 +583,9 @@ /*********************************************************************//** * @brief - * The testResetValveStateOverride function resets the override of the \n - * specified valve. - * @details - * Inputs : none - * Outputs : valves[] + * The testResetValveStateOverride function resets the override of the specified valve. + * @details Inputs: none + * @details Outputs: valves[] * @param valveID ID of valve to reset override state for * @return TRUE if override successful, FALSE if not *************************************************************************/