#include "gio.h" #include "reg_het.h" #include "Common.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" #include "UVReactors.h" /** * @addtogroup UV Reactors * @{ */ // ********** private definitions ********** #define INLET_UV_REACTOR_ENABLE_PIN 0 ///< Inlet UV reactor GPIO pin number (enable pin). #define OUTLET_UV_REACTOR_ENABLE_PIN 1 ///< Outlet UV reactor GPIO pin number (enable Pin). #define INLET_UV_REACTOR_INDICATION_PIN 0x1A ///< Inlet UV reactor N2HET1 pin number (health check). #define OUTLET_UV_REACTOR_INDICATION_PIN 0x0B ///< Outlet UV reactor N2HET1 pin number (health check). #define UV_REACTORS_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< UV reactors data publication time interval. /// Self test wait time after enabling the reactors and before checking for their health in ms. #define SELF_TEST_DELAY_TIME 1000 #define MAX_ALLOWED_UNHEALTHY_REACTOR_COUNTER ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< UV reactors max counter to be unhealthy. /// UV reactors self test states typedef enum self_tests { UV_REACTORS_SELF_TEST_OFF = 0, ///< UV reactors self test state off UV_REACTORS_SELF_TEST_CHECK_HEALTH, ///< UV reactors self test check health UV_REACTORS_SELF_TEST_COMPLETE, ///< UV reactors self test complete NUM_OF_UV_REACTORS_SELF_TEST_STATES, ///< Number of UV reactors self test states } UV_REACTORS_SELF_TEST_STATE_T; /// UV reactors exec states typedef enum exec_states { UV_REACTOR_STATE_OFF = 0, ///< UV reactor state off UV_REACTOR_STATE_ON, ///< UV reactor state on NUM_OF_UV_REACTOR_STATES, ///< Number of UV reactor states } UV_REACTOR_STATE_T; /// UV reactor status typedef struct { UV_REACTOR_STATE_T execState; ///< UV reactor executive state PIN_SIGNAL_STATE_T pinSignalState; ///< UV reactor pin signal state SWITCH_STATES_T switchState; ///< UV reactor turn on/turn off state U32 reactorEnablePin; ///< UV reactor enable pin of GIO port A U32 reactorHealthStatusPin; ///< UV reactor status pin of N2HET1 U32 reactorUnhealthyCounter; ///< UV reactor counter of the number of times it is unhealthy in a row OVERRIDE_U32_T healthStatus; ///< UV reactor current health status } UV_REACTOR_STATUS_T; // ********** private data ********** static UV_REACTOR_STATUS_T reactorsStatus[ NUM_OF_UV_REACTORS ]; ///< UV reactors status array static UV_REACTORS_SELF_TEST_STATE_T uvReactorsSelfTestStates = UV_REACTORS_SELF_TEST_OFF; ///< UV reactors self test state static SELF_TEST_STATUS_T uvReactosSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; ///< Valves self test result static OVERRIDE_U32_T uvReactorsDataPublishInterval = { UV_REACTORS_DATA_PUB_INTERVAL, UV_REACTORS_DATA_PUB_INTERVAL, 0, 0 }; ///< UV reactors data publish interval static U32 dataPublishCounter = 0; ///< UV reactors data publish counter static U32 selfTestElapsedTime = 0; ///< UV reactors self test elapsed time // Self test functions static UV_REACTORS_SELF_TEST_STATE_T handleUVReactorsSelfTestOff( void ); static UV_REACTORS_SELF_TEST_STATE_T handleUVReactorsSelfTestCheckHealth( void ); // Exec functions static UV_REACTOR_STATE_T handleUVReactorStateOff( UV_REACTORS_T reactor ); static UV_REACTOR_STATE_T handleUVReactorStateOn( UV_REACTORS_T reactor ); // Support functions static BOOL isReactorHealthy( UV_REACTORS_T reactor ); static void setReactorEnableStatus( UV_REACTORS_T reactor, PIN_SIGNAL_STATE_T state ); static void publishUVReactorsData( void ); static U32 getPublishUVReactorsDataInterval( void ); /*********************************************************************//** * @brief * The initUVReactors function initializes the UV reactors module. * @details Inputs: uvReactosSelfTestResult, dataPublishCounter, * reactorsStatus, selfTestStates * @details Outputs: uvReactosSelfTestResult, dataPublishCounter, * reactorsStatus, selfTestStates * @return none *************************************************************************/ void initUVReactors( void ) { UV_REACTORS_T reactor; uvReactosSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; uvReactorsSelfTestStates = UV_REACTORS_SELF_TEST_OFF; dataPublishCounter = 0; // Initialize the UV reactors. These values are specific to the inlet and outlet reactor // so they cannot be in a for loop reactorsStatus[ INLET_UV_REACTOR ].reactorEnablePin = INLET_UV_REACTOR_ENABLE_PIN; reactorsStatus[ INLET_UV_REACTOR ].reactorHealthStatusPin = INLET_UV_REACTOR_INDICATION_PIN; reactorsStatus[ OUTLET_UV_REACTOR ].reactorEnablePin = OUTLET_UV_REACTOR_ENABLE_PIN; reactorsStatus[ OUTLET_UV_REACTOR ].reactorHealthStatusPin = OUTLET_UV_REACTOR_INDICATION_PIN; // Initialize the common values in the UV reactors for( reactor = INLET_UV_REACTOR; reactor < NUM_OF_UV_REACTORS; reactor++ ) { reactorsStatus[ reactor ].pinSignalState = PIN_SIGNAL_LOW; reactorsStatus[ reactor ].execState = UV_REACTOR_STATE_OFF; reactorsStatus[ reactor ].switchState = TURN_OFF; reactorsStatus[ reactor ].reactorUnhealthyCounter = 0; } } /*********************************************************************//** * @brief * The execUVReactorsSelfTest function executes the UV reactors self test. * @details Inputs: FuvReactorsSelfTestStates * @details Outputs: uvReactorsSelfTestStates * @return Status of self test *************************************************************************/ SELF_TEST_STATUS_T execUVReactorsSelfTest( void ) { switch ( uvReactorsSelfTestStates ) { case UV_REACTORS_SELF_TEST_OFF: uvReactorsSelfTestStates = handleUVReactorsSelfTestOff(); break; case UV_REACTORS_SELF_TEST_CHECK_HEALTH: uvReactorsSelfTestStates = handleUVReactorsSelfTestCheckHealth(); break; case UV_REACTORS_SELF_TEST_COMPLETE: // Done with self test, do nothing. break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_UV_REACTORS_INVALID_SELF_TEST_STATE, uvReactorsSelfTestStates ); uvReactorsSelfTestStates = UV_REACTORS_SELF_TEST_COMPLETE; break; } return uvReactosSelfTestResult; } /*********************************************************************//** * @brief * The execUVReactos function executes the UV reactors exec states. * @details Inputs: reactorsStatus * @details Outputs: reactorsStatus * @return none *************************************************************************/ void execUVReactos( void ) { UV_REACTORS_T reactor; for ( reactor = INLET_UV_REACTOR; reactor < NUM_OF_UV_REACTORS; reactor++ ) { switch ( reactorsStatus[ reactor ].execState ) { case UV_REACTOR_STATE_OFF: reactorsStatus[ reactor ].execState = handleUVReactorStateOff( reactor ); break; case UV_REACTOR_STATE_ON: reactorsStatus[ reactor ].execState = handleUVReactorStateOn( reactor ); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_UV_REACTORS_INVALID_EXEC_STATE, reactorsStatus[ reactor ].execState ); reactorsStatus[ reactor].execState = UV_REACTOR_STATE_OFF; break; } } // Publish all reactors data once publishUVReactorsData(); } /*********************************************************************//** * @brief * The getUVReactorHealth function returns the health status of a UV reactor. * @details Inputs: reactorsStatus * @details Outputs: none * @param reactor to return its health * @return returns the health of the requested UV reactor *************************************************************************/ BOOL getUVReactorHealth( UV_REACTORS_T reactor ) { BOOL health = FALSE; // Check if the reactor selected is in range if ( reactor < NUM_OF_UV_REACTORS ) { // Check if the health is in override or not if ( reactorsStatus[ reactor ].healthStatus.override == OVERRIDE_KEY ) { health = reactorsStatus[ reactor ].healthStatus.ovData; } else { health = reactorsStatus[ reactor ].healthStatus.data; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_UV_REACTORS_INVALID_REACTOR_SELECTD, reactor ) } return health; } /*********************************************************************//** * @brief * The turnOnUVReactor function turns on the selected UV reactor per request. * @details Inputs: reactorsStatus * @details Outputs: reactorsStatus * @param reactor to turn on * @return returns TRUE if the reactor was not already on *************************************************************************/ BOOL turnOnUVReactor( UV_REACTORS_T reactor ) { BOOL result = FALSE; // Check if the called reactor is in range. Otherwise, raise an alarm if ( reactor < NUM_OF_UV_REACTORS ) { if ( TURN_OFF == reactorsStatus[ reactor ].switchState ) { reactorsStatus[ reactor ].switchState = TURN_ON; result = TRUE; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_UV_REACTORS_INVALID_REACTOR_SELECTD, reactor ) } return result; } /*********************************************************************//** * @brief * The turnOffUVReactor function turns off the selected UV reactor per request. * @details Inputs: reactorsStatus * @details Outputs: reactorsStatus * @param reactor to turn off * @return returns TRUE if the reactor was not already off *************************************************************************/ BOOL turnOffUVReactor( UV_REACTORS_T reactor ) { BOOL result = FALSE; // Check if the called reactor is in range if ( reactor < NUM_OF_UV_REACTORS ) { reactorsStatus[ reactor ].switchState = TURN_OFF; result = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_UV_REACTORS_INVALID_REACTOR_SELECTD, reactor ) } return result; } /*********************************************************************//** * @brief * The handleUVReactorsSelfTestOff function handles the self test off state. * @details Inputs: selfTestElapsedTime * @details Outputs: selfTestElapsedTime * @return returns the next state of the self test state machine *************************************************************************/ static UV_REACTORS_SELF_TEST_STATE_T handleUVReactorsSelfTestOff( void ) { UV_REACTORS_SELF_TEST_STATE_T state = UV_REACTORS_SELF_TEST_CHECK_HEALTH; // Enable both the reactors and set the timer to check the health of the reactors after time elapsed setReactorEnableStatus( INLET_UV_REACTOR, PIN_SIGNAL_HIGH ); setReactorEnableStatus( OUTLET_UV_REACTOR, PIN_SIGNAL_HIGH ); selfTestElapsedTime = getMSTimerCount(); return state; } /*********************************************************************//** * @brief * The handleUVReactorsSelfTestCheckHealth function handles the self test * check health state. * @details Inputs: selfTestElapsedTime, uvReactosSelfTestResult * @details Outputs: uvReactosSelfTestResult * @return returns the next state of the self test state machine *************************************************************************/ static UV_REACTORS_SELF_TEST_STATE_T handleUVReactorsSelfTestCheckHealth( void ) { UV_REACTORS_SELF_TEST_STATE_T state = UV_REACTORS_SELF_TEST_CHECK_HEALTH; if ( TRUE == didTimeout( selfTestElapsedTime, SELF_TEST_DELAY_TIME ) ) { // Get the health status of the reactors BOOL isInletHealthy = isReactorHealthy( INLET_UV_REACTOR ); BOOL isOutletHealthy = isReactorHealthy( OUTLET_UV_REACTOR ); // Check if both of them are healthy and if not, raise an alarm if ( TRUE == isInletHealthy && TRUE == isOutletHealthy ) { uvReactosSelfTestResult = SELF_TEST_STATUS_PASSED; } else { uvReactosSelfTestResult = SELF_TEST_STATUS_FAILED; // Check which reactor has not been healthy and raise an alarm if ( FALSE == isInletHealthy ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_UV_REACTOR_NOT_HEALTHY, INLET_UV_REACTOR ); } else { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_UV_REACTOR_NOT_HEALTHY, OUTLET_UV_REACTOR ); } } // Turn off the UV reactors once the test is finished setReactorEnableStatus( INLET_UV_REACTOR, PIN_SIGNAL_LOW ); setReactorEnableStatus( OUTLET_UV_REACTOR, PIN_SIGNAL_LOW ); state = UV_REACTORS_SELF_TEST_COMPLETE; } return state; } /*********************************************************************//** * @brief * The handleUVReactorStateOff function handles the off state. * @details Inputs: reactorsStatus * @details Outputs: none * @param reactor to check its state * @return returns the next state of the exec state machine *************************************************************************/ static UV_REACTOR_STATE_T handleUVReactorStateOff( UV_REACTORS_T reactor ) { UV_REACTOR_STATE_T state = UV_REACTOR_STATE_OFF; // If the a reactor is requested to be on and it is off, turn it on // and change the state if( TURN_ON == reactorsStatus[ reactor ].switchState ) { setReactorEnableStatus( reactor, PIN_SIGNAL_HIGH ); state = UV_REACTOR_STATE_ON; } return state; } /*********************************************************************//** * @brief * The handleUVReactorStateOn function handles the on state. * @details Inputs: reactorsStatus * @details Outputs: reactorsStatus * @param reactor to checks it status * @return returns the next state of the exec state machine *************************************************************************/ static UV_REACTOR_STATE_T handleUVReactorStateOn( UV_REACTORS_T reactor ) { UV_REACTOR_STATE_T state = UV_REACTOR_STATE_ON; reactorsStatus[ reactor ].healthStatus.data = (U32)isReactorHealthy( reactor ); // Check if the reactor is healthy if ( FALSE == getUVReactorHealth( reactor ) ) { // Check if the reactor has been unhealthy for the defined duration if ( ++reactorsStatus[ reactor ].reactorUnhealthyCounter > MAX_ALLOWED_UNHEALTHY_REACTOR_COUNTER ) { // The reactor has been unhealthy for a certain amount of time SET_ALARM_WITH_1_U32_DATA( ALARM_ID_UV_REACTOR_NOT_HEALTHY, reactor ); // Done with health. turn off the reactor and go to off state reactorsStatus[ reactor ].reactorUnhealthyCounter = 0; reactorsStatus[ reactor ].switchState = TURN_OFF; } } else { // If the reactor is healthy, zero out the counter reactorsStatus[ reactor ].reactorUnhealthyCounter = 0; } // Check if it has been requested to turn off a reactor if( TURN_OFF == reactorsStatus[ reactor ].switchState ) { setReactorEnableStatus( reactor, PIN_SIGNAL_LOW ); state = UV_REACTOR_STATE_OFF; } return state; } /*********************************************************************//** * @brief * The setReactorEnableStatus function sets a reactor to enable or * disable state. * @details Inputs: reactorsStatus * @details Outputs: none * @param reactor to set it enable status * @param state to set the reactor (high or low) * @return none *************************************************************************/ static void setReactorEnableStatus( UV_REACTORS_T reactor, PIN_SIGNAL_STATE_T state ) { // Set the GIO pin to enable or disable gioSetBit( gioPORTA, reactorsStatus[ reactor ].reactorEnablePin, state ); // Update the pin signal state reactorsStatus[ reactor ].pinSignalState = state; } /*********************************************************************//** * @brief * The isReactorHealthy function checks the health status of a reactor. * @details Inputs: reactorsStatus * @details Outputs: none * @param reactor to check its health * @return returns TRUE if the reactor is healthy otherwise a FALSE *************************************************************************/ static BOOL isReactorHealthy( UV_REACTORS_T reactor ) { return (BOOL)gioGetBit( hetPORT1, reactorsStatus[ reactor ].reactorHealthStatusPin ); } /*********************************************************************//** * @brief * The getPublishValvesDataInterval function gets the data publish interval * @details Inputs: uvReactorsDataPublishInterval * @details Outputs: none * @return returns data publish interval *************************************************************************/ static U32 getPublishUVReactorsDataInterval( void ) { U32 result = uvReactorsDataPublishInterval.data; if ( OVERRIDE_KEY == uvReactorsDataPublishInterval.override ) { result = uvReactorsDataPublishInterval.ovData; } return result; } /*********************************************************************//** * @brief * The publishUVReactorsData function publishes the UV reactors data. * @details Inputs: dataPublishCounter, reactorsStatus * @details Outputs: dataPublishCounter * @return none *************************************************************************/ static void publishUVReactorsData( void ) { if ( ++dataPublishCounter > getPublishUVReactorsDataInterval() ) { UV_REACTORS_DATA_T uvReactorsData; // Publish the reactors health status uvReactorsData.inletUVReactorHealthStatus = reactorsStatus[ INLET_UV_REACTOR ].reactorHealthStatusPin; uvReactorsData.outletUVReactorHealthStatus = reactorsStatus[ OUTLET_UV_REACTOR ].reactorHealthStatusPin; uvReactorsData.inletUVReactorState = reactorsStatus[ INLET_UV_REACTOR ].execState; uvReactorsData.outletUVReactorHealthStatus = reactorsStatus[ OUTLET_UV_REACTOR ].execState; broadcastUVReactorsData( &uvReactorsData ); dataPublishCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetReactorsDataPublishInterval function overrides the UV * reactors data publish interval. * @details Inputs: uvReactorsDataPublishInterval * @details Outputs: uvReactorsDataPublishInterval * @param value which is override value for the UV reactors data publish * interval * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetReactorsDataPublishInterval( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_GENERAL_INTERVAL; result = TRUE; uvReactorsDataPublishInterval.ovData = intvl; uvReactorsDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetReactorsDataPublishInterval function resets the override * of the UV reactors publish interval. * @details Inputs: uvReactorsDataPublishInterval * @details Outputs: uvReactorsDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetReactorsDataPublishInterval( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; uvReactorsDataPublishInterval.override = OVERRIDE_RESET; uvReactorsDataPublishInterval.ovData = uvReactorsDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetUVReactorHealthOverride function overrides the UV reactors * health * @details Inputs: reactorsStatus * @details Outputs: reactorsStatus * @param reactor that its health will be overridden * @param health which is high for healthy on and low for not healthy * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetUVReactorHealthOverride( U32 reactor, BOOL health ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() && (UV_REACTORS_T)reactor < NUM_OF_UV_REACTORS ) { reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.ovInitData = reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.data; reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.override = OVERRIDE_KEY; reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.ovData = (U32)health; result = TRUE; } return result; } /*********************************************************************//** * @brief * The testResetUVReactorHealthOverride function resets the override * of the UV reactors health * @details Inputs: reactorsStatus * @details Outputs: reactorsStatus * @param reactor that its health will be reset * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetUVReactorHealthOverride( U32 reactor ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() && (UV_REACTORS_T)reactor < NUM_OF_UV_REACTORS ) { reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.override = OVERRIDE_RESET; reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.ovData = reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.ovInitData; result = TRUE; } return result; } /**@}*/