Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r379f78f1fad668d741b3ccf1e78c69f3fccc45b5 -r7ae6d3a29de6f544da89b10ce8041861a310f2a5 --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 379f78f1fad668d741b3ccf1e78c69f3fccc45b5) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision 7ae6d3a29de6f544da89b10ce8041861a310f2a5) @@ -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. @@ -69,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 @@ -85,10 +90,11 @@ * @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 @@ -100,13 +106,27 @@ 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(); } @@ -367,7 +387,7 @@ * @brief * The setValveState function sets the valve state for given valve. * @details Inputs: none - * @details Outputs: 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. @@ -382,14 +402,55 @@ { 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; } /*********************************************************************//**