/**********************************************************************//** * * Copyright (c) 2020-2020 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 Valves.c * * @date 21-Apr-2020 * @author P. Montazemi * * @brief Valves source file. * **************************************************************************/ #include "FPGA.h" #include "SystemCommMessages.h" #include "TaskPriority.h" #include "Valves.h" /** * @addtogroup DGValves * @{ */ // ********** 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 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 // ********** 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 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( OVERRIDE_U32_T array[ NUM_OF_VALVES ] ); ///< convert array of U32 to U16 for statesValves preparation static void publishValvesStates( void ); static DATA_GET_PROTOTYPE( U32, getPublishValvesStatesInterval ); /*********************************************************************//** * @brief * The initValves function initializes the Valves module. * @details * Inputs : none * Outputs : Valves module initialized * @return none *************************************************************************/ void initValves( void ) { U32 i; // initialize commanded valve states 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; } commandedValvesStates = fromU32ArrayToU16( valveStates ); setFPGAValveStates( commandedValvesStates ); // initially set all valves to de-energized state via FPGA valvesStatesPublicationTimerCounter = 0; // reset valves states publication timer } /*********************************************************************//** * @brief * The execValves function executes the valves driver. * @details * Inputs : valvesStates, valveStateMismatchCounter * Outputs : valvesStates, valveStateMismatchCounter * @return none *************************************************************************/ void execValves( void ) { U16 readValvesStates = getFPGAValveStates(); // get valves states from FPGA // verify read back FPGA valve states match last commanded valve states if ( readValvesStates != commandedValvesStates ) { valveStateMismatchCounter++; // increment valve state mismatch counter by 1 if ( valveStateMismatchCounter > MAX_VALVE_STATE_MISMATCH_COUNT ) { activateAlarmNoData( ALARM_ID_VALVE_CONTROL_FAILURE ); } } else { valveStateMismatchCounter = 0; } // set valves states (via FPGA) to currently commanded states commandedValvesStates = fromU32ArrayToU16( valveStates ); setFPGAValveStates( commandedValvesStates ); // publish valve states on interval publishValvesStates(); } /*********************************************************************//** * @brief * The checkValveStateName function checks the validity of requested valve \n * state name for given valve. * @details * Inputs : none * 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. *************************************************************************/ static BOOL checkValveStateName( VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName ) { BOOL result = FALSE; // initialize result flag to FALSE switch ( valveStateName ) { case VALVE_STATE_OPEN: if ( ( valveID == VPI ) || ( valveID == VBF ) || ( valveID == VSP ) ) { result = TRUE; } break; case VALVE_STATE_CLOSED: if ( ( valveID == VPI ) || ( valveID == VBF ) || ( valveID == VSP ) ) { result = TRUE; } 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; case VALVE_STATE_NOFILL_C_TO_NO: if ( valveID == VPO ) { result = TRUE; } break; case VALVE_STATE_FILL_C_TO_NC: if ( valveID == VPO ) { result = TRUE; } break; case VALVE_STATE_DRAIN_C_TO_NO: if ( ( valveID == VDR ) || ( valveID == VRC ) ) { result = TRUE; } break; case VALVE_STATE_RECIRC_C_TO_NC: if ( ( valveID == VDR ) || ( valveID == VRC ) ) { result = TRUE; } break; case VALVE_STATE_R1_C_TO_NO: if ( ( valveID == VRO ) || ( valveID == VRI ) ) { result = TRUE; } break; case VALVE_STATE_R1_C_TO_NC: if ( ( valveID == VRD ) || ( valveID == VRF ) ) { result = TRUE; } break; case VALVE_STATE_R2_C_TO_NO: if ( ( valveID == VRD ) || ( valveID == VRF ) ) { result = TRUE; } break; case VALVE_STATE_R2_C_TO_NC: if ( ( valveID == VRO ) || ( valveID == VRI ) ) { result = TRUE; } break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_STATE_NAME, valveStateName ) break; } return result; } /*********************************************************************//** * @brief * The getPublishValveStateInterval function gets the valves states \n * publication interval. * @details * Inputs : valvesStatesPublishInterval * Outputs : none * @return the current valves states publication interval (in task intervals) *************************************************************************/ U32 getPublishValvesStatesInterval( void ) { U32 result = valvesStatesPublishInterval.data; if ( OVERRIDE_KEY == valvesStatesPublishInterval.override ) { result = valvesStatesPublishInterval.ovData; } return result; } /*********************************************************************//** * @brief * The fromU32ArrayToU16 function converts an array of U32 valve states \n * to U16 valvesStates that can be passed to FPGA for setting valves. * @details * Inputs : valveStates[] * Outputs : none * @return converted U16 bit field for currently commanded valve states *************************************************************************/ U16 fromU32ArrayToU16( OVERRIDE_U32_T array[ NUM_OF_VALVES ] ) { U16 result = ALL_VALVES_DEENERGIZED; // start result flag as all valves de-energized U32 i; // flag valves that are currently commanded to be energized for ( i = 0; i < NUM_OF_VALVES; i++) { result |= ( getValveState( i ) == ENERGIZED ? 0x0001 << i : 0 ); } return result; } /*********************************************************************//** * @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 * @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 ) { U32 vState = DEENERGIZED; // initialize valve state to de-energized switch ( valveStateName ) { case VALVE_STATE_OPEN: vState = ENERGIZED; break; case VALVE_STATE_CLOSED: vState = DEENERGIZED; break; case VALVE_STATE_OPEN_C_TO_NO: vState = DEENERGIZED; break; case VALVE_STATE_DRAIN_C_TO_NC: vState = ENERGIZED; break; case VALVE_STATE_NOFILL_C_TO_NO: vState = DEENERGIZED; break; case VALVE_STATE_FILL_C_TO_NC: vState = ENERGIZED; break; case VALVE_STATE_DRAIN_C_TO_NO: vState = DEENERGIZED; break; case VALVE_STATE_RECIRC_C_TO_NC: vState = ENERGIZED; break; case VALVE_STATE_R1_C_TO_NO: vState = DEENERGIZED; break; case VALVE_STATE_R1_C_TO_NC: vState = ENERGIZED; break; case VALVE_STATE_R2_C_TO_NO: vState = DEENERGIZED; break; case VALVE_STATE_R2_C_TO_NC: vState = ENERGIZED; break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_STATE_NAME, valveStateName ) break; } return vState; } /*********************************************************************//** * @brief * The setValveState function sets the valve state for given valve. * @details * Inputs : none * Outputs : none * @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. *************************************************************************/ BOOL setValveState( VALVES_T valveID, VALVE_STATE_NAMES_T valveStateName ) { BOOL result = FALSE; // initialize result flag to FALSE if ( checkValveStateName ( valveID, valveStateName ) ) { valveStates[ valveID ].data = convertValveStateNameToValveState( valveStateName ); result = TRUE; } return result; } /*********************************************************************//** * @brief * The getValveState function gets the current valve state for given valve. * @details * Inputs : valveStates[] * Outputs : none * @param valveID : ID of valve to get state for. * @return the current valve state for given valve *************************************************************************/ U32 getValveState( U32 valveID ) { U32 valveState = DEENERGIZED; if ( valveID < NUM_OF_VALVES ) { if ( OVERRIDE_KEY == valveStates[ valveID ].override ) { valveState = valveStates[ valveID ].ovData; } else { valveState = valveStates[ valveID ].data; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_VALVES_INVALID_VALVE_ID, valveID ) } return valveState; } /*********************************************************************//** * @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. * @return none *************************************************************************/ static void publishValvesStates( void ) { // publish valve state on interval if ( ++valvesStatesPublicationTimerCounter >= getPublishValvesStatesInterval() ) { broadcastValvesStates( getFPGAValveStates() ); valvesStatesPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetValvesStatesPublishIntervalOverride function overrides the \n * valves states publish interval. * @details * Inputs : none * Outputs : valvesStatesPublishInterval * @param value : override valves states publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetValvesStatesPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; result = TRUE; valvesStatesPublishInterval.ovData = intvl; valvesStatesPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetValvesStatesPublishIntervalOverride function resets the override \n * of the valves states publish interval. * @details * Inputs : none * Outputs : valvesStatesPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetValvesStatesPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; valvesStatesPublishInterval.override = OVERRIDE_RESET; valvesStatesPublishInterval.ovData = valvesStatesPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetValveStateOverride function overrides the value of the \n * specified valve with a given value. * Inputs : none * 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 *************************************************************************/ BOOL testSetValveStateOverride( U32 valveID, U32 value ) { BOOL result = FALSE; if ( valveID < NUM_OF_VALVES ) { if ( TRUE == isTestingActivated() ) { result = TRUE; valveStates[ valveID ].ovData = value; valveStates[ valveID ].override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetValveStateOverride function resets the override of the \n * specified valve. * @details * Inputs : none * Outputs : valves[] * @param valveID : ID of valve to reset override state for * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetValveStateOverride( U32 valveID ) { BOOL result = FALSE; if ( valveID < NUM_OF_VALVES ) { if ( TRUE == isTestingActivated() ) { result = TRUE; valveStates[ valveID ].override = OVERRIDE_RESET; valveStates[ valveID ].ovData = valveStates[ valveID ].ovInitData; } } return result; } /**@}*/