/************************************************************************** * * Copyright (c) 2024-2024 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) 30-Jul-2024 * * @author (original) Sean * @date (original) 30-Jul-2024 * ***************************************************************************/ #include "AlarmLamp.h" #include "CpldInterface.h" #include "Messaging.h" #include "TaskGeneral.h" #include "Timers.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 ********** static OVERRIDE_U32_T currentLampPattern; ///< Current alarm lamp pattern (overrideable). 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. static BOOL alarmLampOn = FALSE; ///< Flag indicates whether an any lamp is currently on. /// Two step alarm lamp patterns (repeating). const struct LampPatterns LAMP_PATTERNS[ 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 unit. * @details \b Inputs: none * @details \b Outputs: AlarmLamp unit initialized. * @return none *************************************************************************/ void initAlarmLamp( void ) { currentLampPattern.data = LAMP_PATTERN_MANUAL; currentLampPattern.ovData = LAMP_PATTERN_FAULT; currentLampPattern.ovInitData = LAMP_PATTERN_FAULT; currentLampPattern.override = OVERRIDE_RESET; pendingLampPattern = LAMP_PATTERN_MANUAL; currentLampPatternStep = 0; lampPatternStepTimer = 0; alarmLampOn = FALSE; alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_START; alarmLampSelfTestStepTimerCount = 0; } /*********************************************************************//** * @brief * The execAlarmLamp function executes the alarm lamp service to output * the currently set lamp pattern. * @details \b Inputs: pendingLampPattern, currentLampPattern, lampPatternStepTimer, * lampPatterns. * @details \b 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 += ALARM_LAMP_AND_AUDIO_CONTROL_INTERVAL_MS; } // Control alarm lamp to currently set pattern (unless we are in manual pattern) if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) { // If pattern step duration has elapsed, move to next step if ( lampPatternStepTimer >= LAMP_PATTERNS[ 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 \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given lamp patter ID invalid. * @details \b Inputs: none * @details \b Outputs: pendingLampPattern * @param lampPattern new lamp pattern being requested * @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_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_LAMP_INVALID_PATTERN_REQUESTED, lampPattern ) } } /*********************************************************************//** * @brief * The getCurrentAlarmLampPattern function gets the current alarm lamp * pattern in effect. * @details \b Inputs: currentLampPattern * @details \b 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 getAlarmLampOn function gets the current alarm lamp on flag. * @details \b Inputs: alarmLampOn * @details \b Outputs: none * @return TRUE if the alarm lamp is currently on, FALSE if not *************************************************************************/ BOOL getAlarmLampOn( void ) { return alarmLampOn; } /*********************************************************************//** * @brief * The execAlarmLampTest function executes the alarm lamp self-test state machine. * @note This function should be called periodically until a pass or fail * result is returned. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if current alarm lamp self-test * state is invalid. * @details \b Inputs: alarmLampSelfTestState, alarmLampSelfTestStepTimerCount * @details \b 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 are doing self-test again alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_START; break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_LAMP_INVALID_SELF_TEST_STATE, alarmLampSelfTestState ) result = SELF_TEST_STATUS_FAILED; break; } return result; } /*********************************************************************//** * @brief * The resetAlarmLampPOSTState function resets the alarm lamp self-test state. * @details \b Inputs: none * @details \b Outputs: alarmLampSelfTestState * @return none *************************************************************************/ void resetAlarmLampPOSTState( void ) { alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_START; } /*********************************************************************//** * @brief * The setAlarmLampToPatternStep function sets the lamp LEDs according to the * current lamp pattern and lamp pattern step. * @details \b Inputs: lampPatterns[], currentLampPatternStep * @details \b 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; alarmLampOn = FALSE; lampPatternStepTimer = 0; if ( LAMP_PATTERNS[ getCurrentAlarmLampPattern() ].green[ currentLampPatternStep ] == LAMP_STATE_ON ) { green = PIN_SIGNAL_HIGH; alarmLampOn = TRUE; } if ( LAMP_PATTERNS[ getCurrentAlarmLampPattern() ].blue[ currentLampPatternStep ] == LAMP_STATE_ON ) { blue = PIN_SIGNAL_HIGH; alarmLampOn = TRUE; } if ( LAMP_PATTERNS[ getCurrentAlarmLampPattern() ].red[ currentLampPatternStep ] == LAMP_STATE_ON ) { red = PIN_SIGNAL_HIGH; alarmLampOn = TRUE; } #ifndef TASK_TIMING_OUTPUT_ENABLED setCPLDLampGreen( green ); setCPLDLampBlue( blue ); setCPLDLampRed( red ); #endif } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testAlarmLampPatternOverride function overrides the current * alarm lamp pattern with a given pattern. * @details \b Inputs: none * @details \b Outputs: currentLampPattern * @param message Override message from Dialin which includes the alarm * lamp pattern to override to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testAlarmLampPatternOverride( MESSAGE_T *message ) { BOOL result = u32Override( message, ¤tLampPattern, 0, NUM_OF_LAMP_PATTERNS - 1 ); return result; } /**@}*/