/**********************************************************************//** * * 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 "AlarmMgmt.h" #include "FPGA.h" #include #include "OperationModes.h" #include "stdbool.h" #include "SystemCommMessages.h" #include "TaskPriority.h" #include "Timers.h" #include "Valves.h" /** * @addtogroup DGValves * @{ */ // ********** private definitions ********** #define DEENERGIZED 0 /// 0 for de-energized valve #define ENERGIZED 1 /// 1 for energized valve #define INIT_VALVES_STATES 0 /// 0 in U16 initial state of all valves /// 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 U16 valvesStates = INIT_VALVES_STATES; ///< initialize valves states for FPGA to set static U32 valvesStatesPublicationTimerCounter = 0; ///< used to schedule valve state publication to CAN bus static U16 currentValvesStates = INIT_VALVES_STATES; ///< initialize current valves states static U08 valveStateMismatchCounter = 0; ///< initialize valve state mismatch counter static OVERRIDE_U32_T valves[ NUM_OF_VALVES ]; ///< Current 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 valveState ); ///< check validity of requested valve state name for given valve static U32 convertValveStateNameToValveState(VALVE_STATE_NAMES_T valveState); ///< 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 ) { // initialize current valves states (for both override and actual) U08 i; for (i = 0; i < NUM_OF_VALVES; i++) { valves[ i ].data = DEENERGIZED; valves[ i ].ovInitData = DEENERGIZED; valves[ i ].ovData = DEENERGIZED; valves[ i ].override = OVERRIDE_RESET; } setFPGAValveStates( INIT_VALVES_STATES ); // 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 * Outputs : valvesStates * @return none *************************************************************************/ void execValves( void ) { if ( valveStateMismatchCounter < 2 ) { valvesStates = getFPGAValveStates(); // get valves states from FPGA // Check if valves states from FPGA (valvesStates) equals current valves states (valves) if ( valvesStates != currentValvesStates ) { valvesStates = currentValvesStates; valveStateMismatchCounter++; // increment valve state mismatch counter by 1 } else // valvesStates from FPGA match valves' current states { valveStateMismatchCounter = 0; // reset valve state mismatch counter because valves and valvesStates match } } else // if requested valve state does not match FPGA-provided valve state three (3) times in row { activateAlarmNoData( ALARM_ID_VALVE_EXEC_COUNTER_ERROR ); } currentValvesStates = fromU32ArrayToU16( valves ); setFPGAValveStates( valvesStates ); // set valves states via FPGA to current valves states publishValvesStates(); // publish valves states on interval } /*********************************************************************//** * @brief * The checkValveStateName function checks the validity of requested valve \n * state name for given valve. * @details * Inputs : valve, valveState * Outputs : none * @return none *************************************************************************/ static BOOL checkValveStateName( VALVES_T valve, VALVE_STATE_NAMES_T valveState ) { BOOL result = FALSE; // initialize result flag to FALSE switch ( valveState ) { case VALVE_STATE_OPEN: if ( ( valve == VPI ) || ( valve == VBF ) || ( valve == VSP ) ) { result = TRUE; } break; case VALVE_STATE_CLOSED: if ( ( valve == VPI ) || ( valve == VBF ) || ( valve == VSP ) ) { result = TRUE; } break; case VALVE_STATE_OPEN_C_TO_NO: if ( valve == VPD ) { result = TRUE; } break; case VALVE_STATE_DRAIN_C_TO_NC: if ( valve == VPD ) { result = TRUE; } break; case VALVE_STATE_NOFILL_C_TO_NO: if ( valve == VPO ) { result = TRUE; } break; case VALVE_STATE_FILL_C_TO_NC: if ( valve == VPO ) { result = TRUE; } break; case VALVE_STATE_DRAIN_C_TO_NO: if ( ( valve == VDR ) || ( valve == VRC ) ) { result = TRUE; } break; case VALVE_STATE_RECIRC_C_TO_NC: if ( ( valve == VDR ) || ( valve == VRC ) ) { result = TRUE; } break; case VALVE_STATE_R1_C_TO_NO: if ( ( valve == VRO ) || ( valve == VRI ) ) { result = TRUE; } break; case VALVE_STATE_R1_C_TO_NC: if ( ( valve == VRD ) || ( valve == VRF ) ) { result = TRUE; } break; case VALVE_STATE_R2_C_TO_NO: if ( ( valve == VRD ) || ( valve == VRF ) ) { result = TRUE; } break; case VALVE_STATE_R2_C_TO_NC: if ( ( valve == VRO ) || ( valve == VRI ) ) { result = TRUE; } break; default: activateAlarmNoData( ALARM_ID_VALVE_STATE_CHECK_ERROR ); 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 : none * Outputs : none * @return converted U16 valvesStates *************************************************************************/ U16 fromU32ArrayToU16( OVERRIDE_U32_T array[ NUM_OF_VALVES ] ) { U16 result = 0; // initialize result flag to 0 U08 i; for ( i = 0; i < NUM_OF_VALVES; i++) { result |= ( getValveState( i ) == 1 ? 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 * @return converted U32 vState *************************************************************************/ U32 convertValveStateNameToValveState(VALVE_STATE_NAMES_T valveState) { U32 vState = DEENERGIZED; // initialize valve state to de-energized switch (valveState) { 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: activateAlarmNoData( ALARM_ID_VALVE_ERROR ); break; } return vState; } /*********************************************************************//** * @brief * The setValveState function sets the valve state for given valve. * @details * Inputs : none * Outputs : none * @return TRUE if new valve state is set for given valve *************************************************************************/ BOOL setValveState( VALVES_T valve, VALVE_STATE_NAMES_T valveState ) { BOOL result = FALSE; // initialize result flag to FALSE if ( checkValveStateName ( valve, valveState ) ) { valves[ valve ].data = convertValveStateNameToValveState( valveState ); // not done on override to allow DG state machine to set valves states back to real values result = TRUE; } return result; } /*********************************************************************//** * @brief * The getValveState function gets the current valve state for given valve. * @details * Inputs : valveState * Outputs : none * @return the current valve state for given valve. *************************************************************************/ U32 getValveState( U32 valve ) { U08 valveState = DEENERGIZED; if ( valve < NUM_OF_VALVES ) { if ( OVERRIDE_KEY == valves[ valve ].override ) { valveState = valves[ valve ].ovData; } else { valveState = valves[ valve ].data; } } else { activateAlarmNoData( ALARM_ID_VALVE_ERROR ); } 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 * @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 valve : 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 valve, U32 value ) { BOOL result = FALSE; if ( valve < NUM_OF_VALVES ) { if ( TRUE == isTestingActivated() ) { result = TRUE; valves[ valve ].ovData = value; valves[ valve ].override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetValveStateOverride function resets the override of the \n * specified valve. * @details * Inputs : none * Outputs : valves[] * @param value : ID of valve to reset override state for * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testResetValveStateOverride( U32 valve ) { BOOL result = FALSE; if ( valve < NUM_OF_VALVES ) { if ( TRUE == isTestingActivated() ) { result = TRUE; valves[ valve ].override = OVERRIDE_RESET; valves[ valve ].ovData = valves[ valve ].ovInitData; } } return result; } /**@}*/