/************************************************************************** * * 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 * * @date 20-Sep-2019 * @author S. Nash * * @brief Controller for the alarm lamp. * **************************************************************************/ #include #include "CPLD.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" #include "AlarmLamp.h" // ********** private definitions ********** typedef enum LampStates { LAMP_STATE_OFF = 0, LAMP_STATE_ON, NUM_OF_LAMP_STATES } LAMP_STATE_T; // Lamp Pattern Record struct LampPatterns { U32 duration[NUM_OF_LAMP_STATES ]; // in ms LAMP_STATE_T green[ NUM_OF_LAMP_STATES ]; // green lamp state 1 and 2 LAMP_STATE_T blue[ NUM_OF_LAMP_STATES ]; // blue lamp state 1 and 2 LAMP_STATE_T red[ NUM_OF_LAMP_STATES ]; // red lamp state 1 and 2 }; typedef enum Alarm_Lamp_Self_Test_States { ALARM_LAMP_SELF_TEST_STATE_START = 0, ALARM_LAMP_SELF_TEST_STATE_RED, ALARM_LAMP_SELF_TEST_STATE_YELLOW, ALARM_LAMP_SELF_TEST_STATE_GREEN, ALARM_LAMP_SELF_TEST_STATE_COMPLETE, NUM_OF_ALARM_LAMP_SELF_TEST_STATES } ALARM_LAMP_SELF_TEST_STATE_T; #define POST_LAMP_STEP_TIME_MS 1000 // ms for each lamp color // ********** private data ********** DATA_DECL( LAMP_PATTERN_T, LampPattern, currentLampPattern, LAMP_PATTERN_MANUAL, LAMP_PATTERN_FAULT ); static LAMP_PATTERN_T pendingLampPattern = LAMP_PATTERN_MANUAL; static U32 currentLampPatternStep = 0; static U32 lampPatternStepTimer = 0; 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; static U32 alarmLampSelfTestStepTimerCount = 0; // ********** private function prototypes ********** static void setAlarmLampToPatternStep( void ); /************************************************************************* * @brief initAlarmLamp * The initAlarmLamp function initializes the AlarmLamp module. * @details * Inputs : none * Outputs : AlarmLamp module initialized. * @param none * @return none *************************************************************************/ void initAlarmLamp( void ) { pendingLampPattern = LAMP_PATTERN_MANUAL; currentLampPatternStep = 0; lampPatternStepTimer = 0; alarmLampSelfTestState = ALARM_LAMP_SELF_TEST_STATE_START; alarmLampSelfTestStepTimerCount = 0; } /************************************************************************* * @brief execAlarmLamp * The execAlarmLamp function executes the alarm lamp service for the \n * current lamp pattern. * @details * Inputs : pendingLampPattern, currentLampPattern, lampPatternStepTimer, \n * lampPatterns. * Outputs : * @param none * @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 requestAlarmLampPattern * 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_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_LAMP_INVALID_PATTERN_REQUESTED, lampPattern ) } } /************************************************************************* * @brief getCurrentAlarmLampPattern * The getCurrentAlarmLampPattern function gets the current alarm lamp \n * pattern in effect. * @details * Inputs : currentLampPattern * Outputs : none * @param none * @return currentLampPattern *************************************************************************/ DATA_GET( LAMP_PATTERN_T, getCurrentAlarmLampPattern, currentLampPattern ) /************************************************************************* * @brief execAlarmLampTest * The execAlarmLampTest function executes the alarm lamp test. \n * This function should be called periodically until a pass or fail \n * result is returned. * @details * Inputs : * Outputs : * @param none * @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_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_LAMP_INVALID_SELF_TEST_STATE, alarmLampSelfTestState ) result = SELF_TEST_STATUS_FAILED; break; } return result; } /************************************************************************* * @brief setAlarmLampToPatternStep * The setAlarmLampToPatternStep function sets the lamps according to the \n * current lamp pattern and lamp pattern step. * @details * Inputs : none * Outputs : lampPatternStepTimer reset. Lamps set per current pattern. * @param lampPattern : new lamp 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; } setCPLDLampGreen( green ); setCPLDLampBlue( blue ); setCPLDLampRed( red ); } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /************************************************************************* * @brief testSetCurrentLampPatternOverride and testResetCurrentLampPatternOverride * The testSetCurrentLampPatternOverride function overrides the state of the \n * current alarm lamp pattern with a given pattern. \n * The testResetCurrentLampPatternOverride function resets the override of the \n * state of the alarm lamp pattern. * @details * Inputs : none * Outputs : currentLampPattern * @param value : override state for the alarm lamp pattern * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( LAMP_PATTERN_T, testSetCurrentLampPatternOverride, testResetCurrentLampPatternOverride, currentLampPattern )