Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r44c977966ab7cfecbfbf5110e6abe4ec45ebab62 -r0ff3afb455342a5abde4bb3e6a99819c9ed05164 --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 44c977966ab7cfecbfbf5110e6abe4ec45ebab62) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 0ff3afb455342a5abde4bb3e6a99819c9ed05164) @@ -7,8 +7,8 @@ * * @file Valves.c * -* @author (last) Sean Nash -* @date (last) 19-Aug-2020 +* @author (last) Quang Nguyen +* @date (last) 26-Aug-2020 * * @author (original) Sean * @date (original) 06-May-2020 @@ -39,7 +39,9 @@ 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 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. @@ -55,9 +57,8 @@ /*********************************************************************//** * @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 ) @@ -70,7 +71,10 @@ 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 @@ -81,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 @@ -102,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 * 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. @@ -134,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 ) { @@ -176,6 +214,12 @@ { result = TRUE; } +#ifndef V_2_SYSTEM + if ( VPD == valveID ) + { + result = TRUE; + } +#endif break; case VALVE_STATE_RECIRC_C_TO_NC: @@ -224,9 +268,8 @@ /*********************************************************************//** * @brief * The getPublishValveStateInterval function gets the valves states publication interval. - * @details - * Inputs : valvesStatesPublishInterval - * Outputs : none + * @details Inputs: valvesStatesPublishInterval + * @details Outputs: none * @return the current valves states publication interval (in task intervals) *************************************************************************/ static U32 getPublishValvesStatesInterval( void ) @@ -245,9 +288,8 @@ * @brief * 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 *************************************************************************/ static U16 fromU32ArrayToU16( void ) @@ -268,9 +310,8 @@ * @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 *************************************************************************/ @@ -288,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; @@ -339,9 +386,8 @@ /*********************************************************************//** * @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 * @return TRUE if new valve state is set for given valve ID, FALSE if not. @@ -356,22 +402,62 @@ { 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 *************************************************************************/ @@ -401,9 +487,8 @@ /*********************************************************************//** * @brief * The publishValvesStates function publishes DG valves states at the set interval. - * @details - * Inputs : valvesStatesPublicationTimerCounter - * Outputs : DG valves states are published to CAN bus on interval. + * @details Inputs: valvesStatesPublicationTimerCounter + * @details Outputs: DG valves states are published to CAN bus on interval. * @return none *************************************************************************/ static void publishValvesStates( void ) @@ -426,9 +511,8 @@ * @brief * 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,9 +536,8 @@ * @brief * 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,8 +558,8 @@ * @brief * 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 @@ -501,9 +584,8 @@ /*********************************************************************//** * @brief * The testResetValveStateOverride function resets the override of the specified valve. - * @details - * Inputs : none - * Outputs : valves[] + * @details Inputs: none + * @details Outputs: valves[] * @param valveID ID of valve to reset override state for * @return TRUE if override successful, FALSE if not *************************************************************************/