/************************************************************************** * * Copyright (c) 2019-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 AlarmLamp.c * * @author (last) Sean * @date (last) 27-Feb-2020 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 * ***************************************************************************/ #include "CPLD.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" #include "AlarmLamp.h" /** * @addtogroup AlarmLamp * @{ */ // ********** private definitions ********** #define NUM_OF_ALARM_LAMP_PATTERN_SEQUENCE_STEPS 2 ///< Number of steps in an alarm lamp pattern sequence. /// Enumeration of alarm lamp color states. typedef enum LampStates { LAMP_STATE_OFF = 0, ///< Alarm lamp color (R, G, or B) is off. LAMP_STATE_ON, ///< Alarm lamp color (R, G, or B) is on. NUM_OF_LAMP_STATES ///< Number of alarm lamp color states. } LAMP_STATE_T; /// Alarm lamp pattern record struct LampPatterns { U32 duration[ NUM_OF_ALARM_LAMP_PATTERN_SEQUENCE_STEPS ]; ///< Duration (in ms) of the 2 step alarm lamp pattern sequence. LAMP_STATE_T green[ NUM_OF_ALARM_LAMP_PATTERN_SEQUENCE_STEPS ]; ///< Lamp color state of the 2 step alarm lamp pattern sequence for green. LAMP_STATE_T blue[ NUM_OF_ALARM_LAMP_PATTERN_SEQUENCE_STEPS ]; ///< Lamp color state of the 2 step alarm lamp pattern sequence for blue. LAMP_STATE_T red[ NUM_OF_ALARM_LAMP_PATTERN_SEQUENCE_STEPS ]; ///< Lamp color state of the 2 step alarm lamp pattern sequence for red. }; /// Enumeration of alarm lamp self-test states. typedef enum Alarm_Lamp_Self_Test_States { ALARM_LAMP_SELF_TEST_STATE_START = 0, ///< Start state of alarm lamp self-test. ALARM_LAMP_SELF_TEST_STATE_RED, ///< Red state of alarm lamp self-test. ALARM_LAMP_SELF_TEST_STATE_YELLOW, ///< Yellow state of alarm lamp self-test. ALARM_LAMP_SELF_TEST_STATE_GREEN, ///< Green state of alarm lamp self-test. ALARM_LAMP_SELF_TEST_STATE_COMPLETE, ///< Completed state of alarm lamp self-test. NUM_OF_ALARM_LAMP_SELF_TEST_STATES ///< Number of states in alarm lamp self-test. } ALARM_LAMP_SELF_TEST_STATE_T; #define POST_LAMP_STEP_TIME_MS 1000 ///< Duration (in ms) for each alarm lamp self-test step. // ********** private data ********** /// Current alarm lamp pattern (overrideable). static OVERRIDE_U32_T currentLampPattern = { LAMP_PATTERN_MANUAL, LAMP_PATTERN_FAULT, LAMP_PATTERN_FAULT, 0 }; static LAMP_PATTERN_T pendingLampPattern = LAMP_PATTERN_MANUAL; ///< Pending alarm lamp pattern. static U32 currentLampPatternStep = 0; ///< Current alarm lamp pattern step. static U32 lampPatternStepTimer = 0; ///< Timer counter for current alarm lamp pattern step. /// Two step alarm lamp patterns (repeating). const struct LampPatterns lampPatterns[ NUM_OF_LAMP_PATTERNS ] = { { { 500, 500 }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_OFF, LAMP_STATE_OFF } }, // LAMP_PATTERN_OFF { { 500, 500 }, { LAMP_STATE_ON, LAMP_STATE_ON }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_OFF, LAMP_STATE_OFF } }, // LAMP_PATTERN_OK { { 250, 250 }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_ON, LAMP_STATE_OFF } }, // LAMP_PATTERN_FAULT { { 250, 250 }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_ON, LAMP_STATE_OFF } }, // LAMP_PATTERN_HIGH_ALARM { { 1000, 1000 }, { LAMP_STATE_ON, LAMP_STATE_OFF }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_ON, LAMP_STATE_OFF } }, // LAMP_PATTERN_MED_ALARM { { 500, 500 }, { LAMP_STATE_ON, LAMP_STATE_ON }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_ON, LAMP_STATE_ON } }, // LAMP_PATTERN_LOW_ALARM { { 0, 0 }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_OFF, LAMP_STATE_OFF }, { LAMP_STATE_OFF, LAMP_STATE_OFF } } // LAMP_PATTERN_MANUAL }; static ALARM_LAMP_SELF_TEST_STATE_T alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_START; ///< Current alarm lamp self-test state. static U32 alarmLampSelfTestStepTimerCount = 0; ///< timer counter for current alarm lamp self-test state. // ********** private function prototypes ********** static void setAlarmLampToPatternStep( void ); /*********************************************************************//** * @brief * The initAlarmLamp function initializes the AlarmLamp module. * @details * Inputs : none * Outputs : AlarmLamp module initialized. * @return none *************************************************************************/ void initAlarmLamp( void ) { pendingLampPattern = LAMP_PATTERN_MANUAL; currentLampPatternStep = 0; lampPatternStepTimer = 0; alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_START; alarmLampSelfTestStepTimerCount = 0; } /*********************************************************************//** * @brief * The execAlarmLamp function executes the alarm lamp service for the * current lamp pattern. * @details * Inputs : pendingLampPattern, currentLampPattern, lampPatternStepTimer, * lampPatterns. * Outputs : currentLampPattern * @return none *************************************************************************/ void execAlarmLamp( void ) { // if starting a new lamp pattern, reset pattern variables if ( pendingLampPattern != currentLampPattern.data ) { currentLampPattern.data = pendingLampPattern; currentLampPatternStep = 0; setAlarmLampToPatternStep(); } // otherwise, increment pattern timer else { lampPatternStepTimer += TASK_GENERAL_INTERVAL; } // control alarm lamp to currently set pattern (unless we're in manual pattern) if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) { // if pattern step duration has elapsed, move to next step if ( lampPatternStepTimer >= lampPatterns[ getCurrentAlarmLampPattern() ].duration[ currentLampPatternStep ] ) { // increment pattern step currentLampPatternStep++; if ( currentLampPatternStep >= NUM_OF_LAMP_STATES ) { currentLampPatternStep = 0; } // set lamps according to pattern step setAlarmLampToPatternStep(); } } } /*********************************************************************//** * @brief * The requestAlarmLampPattern function sets a request for a new lamp pattern. * @details * Inputs : none * Outputs : pendingLampPattern * @param lampPattern new lamp pattern * @return none *************************************************************************/ void requestAlarmLampPattern( LAMP_PATTERN_T lampPattern ) { if ( lampPattern < NUM_OF_LAMP_PATTERNS ) { pendingLampPattern = lampPattern; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_LAMP_INVALID_PATTERN_REQUESTED, lampPattern ) } } /*********************************************************************//** * @brief * The getCurrentAlarmLampPattern function gets the current alarm lamp * pattern in effect. * @details * Inputs : currentLampPattern * Outputs : none * @return currentLampPattern *************************************************************************/ LAMP_PATTERN_T getCurrentAlarmLampPattern( void ) { LAMP_PATTERN_T result = (LAMP_PATTERN_T)currentLampPattern.data; if ( OVERRIDE_KEY == currentLampPattern.override ) { result = (LAMP_PATTERN_T)currentLampPattern.ovData; } return result; } /*********************************************************************//** * @brief * The execAlarmLampTest function executes the alarm lamp test. * This function should be called periodically until a pass or fail * result is returned. * @details * Inputs : alarmLampSelfTestState, alarmLampSelfTestStepTimerCount * Outputs : alarmLampSelfTestState, alarmLampSelfTestStepTimerCount * @return in progress, passed, or failed *************************************************************************/ SELF_TEST_STATUS_T execAlarmLampTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; switch ( alarmLampSelfTestState ) { case ALARM_LAMP_SELF_TEST_STATE_START: alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_RED; alarmLampSelfTestStepTimerCount = getMSTimerCount(); setCPLDLampRed( PIN_SIGNAL_HIGH ); break; case ALARM_LAMP_SELF_TEST_STATE_RED: if ( TRUE == didTimeout( alarmLampSelfTestStepTimerCount, POST_LAMP_STEP_TIME_MS ) ) { alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_YELLOW; alarmLampSelfTestStepTimerCount = getMSTimerCount(); setCPLDLampGreen( PIN_SIGNAL_HIGH ); // green + red = yellow } break; case ALARM_LAMP_SELF_TEST_STATE_YELLOW: if ( TRUE == didTimeout( alarmLampSelfTestStepTimerCount, POST_LAMP_STEP_TIME_MS ) ) { alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_GREEN; alarmLampSelfTestStepTimerCount = getMSTimerCount(); setCPLDLampRed( PIN_SIGNAL_LOW ); } break; case ALARM_LAMP_SELF_TEST_STATE_GREEN: if ( TRUE == didTimeout( alarmLampSelfTestStepTimerCount, POST_LAMP_STEP_TIME_MS ) ) { alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_COMPLETE; setCPLDLampGreen( PIN_SIGNAL_LOW ); requestAlarmLampPattern( LAMP_PATTERN_OK ); result = SELF_TEST_STATUS_PASSED; } break; case ALARM_LAMP_SELF_TEST_STATE_COMPLETE: // if we get called in this state, assume we're doing self-test again alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_START; break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_LAMP_INVALID_SELF_TEST_STATE, alarmLampSelfTestState ) result = SELF_TEST_STATUS_FAILED; break; } return result; } /*********************************************************************//** * @brief * The setAlarmLampToPatternStep function sets the lamps according to the * current lamp pattern and lamp pattern step. * @details * Inputs : lampPatterns[], currentLampPatternStep * Outputs : lampPatternStepTimer reset. Lamps set per current pattern. * @return none *************************************************************************/ static void setAlarmLampToPatternStep( void ) { PIN_SIGNAL_STATE_T green = PIN_SIGNAL_LOW; PIN_SIGNAL_STATE_T blue = PIN_SIGNAL_LOW; PIN_SIGNAL_STATE_T red = PIN_SIGNAL_LOW; lampPatternStepTimer = 0; if ( lampPatterns[ getCurrentAlarmLampPattern() ].green[ currentLampPatternStep ] == LAMP_STATE_ON ) { green = PIN_SIGNAL_HIGH; } if ( lampPatterns[ getCurrentAlarmLampPattern() ].blue[ currentLampPatternStep ] == LAMP_STATE_ON ) { blue = PIN_SIGNAL_HIGH; } if ( lampPatterns[ getCurrentAlarmLampPattern() ].red[ currentLampPatternStep ] == LAMP_STATE_ON ) { red = PIN_SIGNAL_HIGH; } #ifndef TASK_TIMING_OUTPUT_ENABLED setCPLDLampGreen( green ); setCPLDLampBlue( blue ); setCPLDLampRed( red ); #endif } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetCurrentLampPatternOverride function overrides the state of the * current alarm lamp pattern with a given pattern. * @details * Inputs : none * Outputs : currentLampPattern * @param value override state for the alarm lamp pattern * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetCurrentLampPatternOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; currentLampPattern.ovData = value; currentLampPattern.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetCurrentLampPatternOverride function resets the override of the * state of the alarm lamp pattern. * @details * Inputs : none * Outputs : currentLampPattern * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetCurrentLampPatternOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; currentLampPattern.override = OVERRIDE_RESET; currentLampPattern.ovData = currentLampPattern.ovInitData; } return result; } /**@}*/