/************************************************************************** * * Copyright (c) 2019-2023 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 AlarmMgmt.c * * @author (last) James Walter Taylor * @date (last) 25-Jul-2023 * * @author (original) Sean Nash * @date (original) 07-Nov-2019 * ***************************************************************************/ #include "mibspi.h" #define __ALARM_MGMT_C__ #include "AlarmLamp.h" #include "CPLD.h" #include "FPGA.h" #include "InternalADC.h" #include "OperationModes.h" #include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" /** * @addtogroup AlarmManagement * @{ */ // ********** private definitions ********** /// Interval to control lamp and audio and to publish alarm status data. #define ALARM_STATUS_PUBLISH_INTERVAL ( ALARM_LAMP_AND_AUDIO_CONTROL_INTERVAL_MS / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) at which the alarm information is published on the CAN bus. #define ALARM_INFO_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) Alarms are blocked after the return of AC power. #define ALARM_BLOCKED_COUNT_AFTER_AC_RETURN ( 10*MS_PER_SECOND / TASK_GENERAL_INTERVAL ) #define ALARM_SILENCE_EXPIRES_IN_SECS (60) ///< Alarm silence expiration time in seconds. #define SUPERVISOR_ALARM_KEY 0xD2C3B4A5 ///< 32-bit key required for clear all alarms request. #define LOWEST_ALARM_SUB_RANK 999 ///< Lowest alarm sub-rank that can be set. #define ALARM_NOT_BLOCKED 0 ///< Alarm blocked timer value that indicates no alarm block // *** This declaration will cause a compiler error if ALARM_TABLE does not have same # of alarms as the Alarm_List enumeration. U08 alarmTableSizeAssertion[ ( ( sizeof( ALARM_TABLE ) / sizeof( ALARM_T ) ) == NUM_OF_ALARM_IDS ? 1 : -1 ) ]; // *** This declaration will cause a compiler error if ALARM_RANK_TABLE does not have same # of alarms as the Alarm_List enumeration. U08 alarmRankTableSizeAssertion[ ( ( sizeof( ALARM_RANK_TABLE ) / sizeof( ALARM_RANK_T ) ) == NUM_OF_ALARM_IDS ? 1 : -1 ) ]; /// A blank alarm data record for alarms that do not include alarm data when triggered. const ALARM_DATA_T BLANK_ALARM_DATA = { ALARM_DATA_TYPE_NONE, 0 }; /// Pin SPI3-CS0 - re-purposed as output GPIO for backup alarm audio enable. #define BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK 0x00000001 // Backup alarm audio enable/disable macros #define SET_BACKUP_AUDIO_ENABLE() {mibspiREG3->PC3 |= BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK;} ///< Macro to enable backup alarm audio. #define CLR_BACKUP_AUDIO_ENABLE() {mibspiREG3->PC3 &= ~BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK;} ///< Macro to disable backup alarm audio. #define ALARM_AUDIO_TEST_TONE 4 ///< Alarm audio state for continuous test tone. #define ALARM_AUDIO_CURRENT_LG_MIN_MA 50.0F ///< Minimum audio current (low gain) during test tone self-test (in mA). #define ALARM_AUDIO_CURRENT_LG_MAX_MA 20.0F ///< Maximum audio current (low gain) during no tone self-test (in mA). #define ALARM_AUDIO_MAX_TEST_TIME_MS 1000 ///< Maximum time for audio current to reach threshold in test. #define MAX_ALARM_AUDIO_VOLUME_INDEX 0 ///< Index for maximum alarm audio volume. #define MIN_ALARM_AUDIO_VOLUME_INDEX (MAX_ALARM_VOLUME_LEVEL - 1 ) ///< Index for minimum alarm audio volume. /// Alarm priority ranking record. typedef struct { ALARM_ID_T alarmID; ///< ID of highest priority alarm in this priority category U32 subRank; ///< Sub-rank of this alarm S32 timeSinceTriggeredMS; ///< Time (in ms) since this alarm was triggered } ALARM_PRIORITY_RANKS_T; /// Enumeration of alarm audio self-test states. typedef enum Alarm_Lamp_Self_Test_States { ALARM_AUDIO_SELF_TEST_STATE_START = 0, ///< Start state of alarm audio self-test. ALARM_AUDIO_SELF_TEST_STATE_PRIMARY, ///< Test tone state of alarm audio self-test. ALARM_AUDIO_SELF_TEST_STATE_NO_TONE, ///< No tone state of alarm audio self-test. ALARM_AUDIO_SELF_TEST_STATE_COMPLETE, ///< Completed state of alarm audio self-test. NUM_OF_ALARM_AUDIO_SELF_TEST_STATES ///< Number of states in alarm audio self-test. } ALARM_AUDIO_SELF_TEST_STATE_T; /// Enumeration of alarm audio volume factors. typedef enum Alarm_Audio_Volume_Factors { ALARM_AUDIO_VOLUME_GAIN = 0, ///< Gain setting for alarm audio volume. ALARM_AUDIO_VOLUME_DIVIDER, ///< Divider setting for alarm audio volume. NUM_OF_ALARM_AUDIO_VOLUME_FACTORS ///< Number of alarm audio volume factors. } ALARM_AUDIO_VOLUME_FACTOR_T; /// Lookup table to determine appropriate divider for a given alarm audio volume level. const U08 ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[MAX_ALARM_VOLUME_LEVEL][NUM_OF_ALARM_AUDIO_VOLUME_FACTORS] = { { 1, 0 }, { 1, 1 }, { 3, 1 }, { 3, 2 }, { 4, 2 } }; // ********** private data ********** static BOOL alarmIsActive[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm static BOOL alarmIsDetected[ NUM_OF_ALARM_IDS ]; ///< Table - current state of each alarm condition (detected or cleared) static OVERRIDE_U32_T alarmStartedAt[ NUM_OF_ALARM_IDS ]; ///< Table - when alarm became active for each alarm (if active) or zero (if inactive) static U32 alarmStatusPublicationTimerCounter = 0; ///< Used to schedule alarm status publication to CAN bus. static U32 alarmInfoPublicationTimerCounter = 0; ///< Used to schedule alarm information publication to CAN bus. static U32 audioTestStartTime; ///< Start time of audio alarm current self-test. static U32 alarmsBlockedTimer = 0; ///< Countdown timer used to temporarily block new alarms from being initiated /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T alarmStatusPublishInterval = { ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL, 0 }; /// Interval (in task intervals) at which to publish alarm information to CAN bus. static OVERRIDE_U32_T alarmInfoPublishInterval = { ALARM_INFO_PUB_INTERVAL, ALARM_INFO_PUB_INTERVAL, ALARM_INFO_PUB_INTERVAL, 0 }; /// Alarm audio attenuation level (0..4 where 0 = max volume and 4 = min volume). static OVERRIDE_U32_T alarmAudioVolumeLevel = { MAX_ALARM_VOLUME_ATTENUATION, MAX_ALARM_VOLUME_ATTENUATION, MAX_ALARM_VOLUME_ATTENUATION, 0 }; static OVERRIDE_F32_T alarmPrimaryAudioCurrentHG = { 0.0, 0.0, 0.0, 0 }; /// Alarm audio current (high gain) measured at ADC. static OVERRIDE_F32_T alarmPrimaryAudioCurrentLG = { 0.0, 0.0, 0.0, 0 }; /// Alarm audio current (low gain) measured at ADC. static OVERRIDE_F32_T alarmBackupAudioCurrent = { 0.0, 0.0, 0.0, 0 }; /// Alarm backup audio current measured at ADC. static COMP_ALARM_STATUS_T alarmStatus; ///< Record for the current composite alarm status. static ALARM_PRIORITY_RANKS_T alarmPriorityFIFO[ NUM_OF_ALARM_PRIORITIES ]; ///< FIFO - first activated or highest sub-rank alarm in each alarm priority category. static BOOL alarmUserRecoveryActionEnabled[ NUMBER_OF_ALARM_USER_ACTIONS ]; ///< Alarm user recovery actions enabled flags. static BOOL alarmButtonBlockers[ NUM_OF_ALARM_BUTTON_BLOCKERS ]; ///< Flags indicating whether alarm table or state properties are blocking alarm buttons for UI. static ALARM_AUDIO_SELF_TEST_STATE_T alarmAudioSelfTestState; ///< Current state of the alarm audio self tests. static BOOL alarmAudioTestToneRequested; ///< Flag indicates whether alarm audio test tone should be output. static BOOL resumeBlockedByAlarmProperty; ///< Flag indicates whether treatment resumption is currently blocked by alarm property. static BOOL alarmNoRetrigger; ///< Flag indicates whether some alarms should be prevented from re-triggering after being cleared by rinseback or end-tx options // ********** private function prototypes ********** static void activateAlarm( ALARM_ID_T alarm ); static void monitorAlarms( void ); static void updateAlarmsState( void ); static void setAlarmLamp( void ); static void setAlarmAudio( void ); static void updateAlarmsSilenceStatus( void ); static void updateAlarmsFlags( void ); static BOOL clearAllRecoverableAlarms( ALARM_USER_ACTION_T action ); static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ); static U32 getAlarmStartTime( ALARM_ID_T alarmID ); static void publishAlarmInfo( void ); /*********************************************************************//** * @brief * The initAlarmMgmt function initializes the AlarmMgmt module. * @details Inputs: none * @details Outputs: AlarmMgmt module initialized. * @return none *************************************************************************/ void initAlarmMgmt( void ) { ALARM_PRIORITY_T p; ALARM_ID_T a; ALARM_BUTTON_BLOCKER_T b; // Disable backup audio CLR_BACKUP_AUDIO_ENABLE(); // Initialize alarm states and start time stamps for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { alarmIsActive[ a ] = FALSE; alarmIsDetected[ a ] = FALSE;; alarmStartedAt[ a ].data = 0; alarmStartedAt[ a ].ovData = 0; alarmStartedAt[ a ].ovInitData = 0; alarmStartedAt[ a ].override = OVERRIDE_RESET; } // Initialize alarm FIFOs for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) { alarmPriorityFIFO[ p ].alarmID = ALARM_ID_NO_ALARM; alarmPriorityFIFO[ p ].subRank = LOWEST_ALARM_SUB_RANK; alarmPriorityFIFO[ p ].timeSinceTriggeredMS = 0; } // Initialize alarm button blocker flags for ( b = (ALARM_BUTTON_BLOCKER_T)0; b < NUM_OF_ALARM_BUTTON_BLOCKERS; b++ ) { alarmButtonBlockers[ b ] = FALSE; } // Initialize composite alarm state alarmStatus.alarmsState = ALARM_PRIORITY_NONE; alarmStatus.alarmsSilenced = FALSE; alarmStatus.alarmsSilenceStart = 0; alarmStatus.alarmsSilenceExpiresIn = 0; alarmStatus.alarmsEscalatesIn = 0; alarmStatus.alarmsToEscalate = FALSE; alarmStatus.alarmTop = ALARM_ID_NO_ALARM; alarmStatus.topAlarmConditionDetected = FALSE; alarmStatus.systemFault = FALSE; alarmStatus.stop = FALSE; alarmStatus.lampOn = FALSE; alarmStatus.noClear = FALSE; alarmStatus.noResume = FALSE; alarmStatus.noRinseback = FALSE; alarmStatus.noEndTreatment = FALSE; alarmStatus.noBloodRecirc = FALSE; alarmStatus.noDialRecirc = FALSE; alarmStatus.ok = FALSE; alarmsBlockedTimer = 0; alarmAudioTestToneRequested = FALSE; resumeBlockedByAlarmProperty = FALSE; alarmNoRetrigger = FALSE; alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; } /*********************************************************************//** * @brief * The execAlarmMgmt function executes the alarm management functions to be * done periodically. The composite alarm state is updated, alarm lamp and * audio patterns are updated, and status is sent out to the rest of the system. * @details Inputs: none * @details Outputs: none * @return none *************************************************************************/ void execAlarmMgmt( void ) { monitorAlarms(); updateAlarmsState(); updateAlarmsFlags(); updateAlarmsSilenceStatus(); // Publish alarm status and information at interval publishAlarmInfo(); // Block new machine alarms during power fail recovery if ( alarmsBlockedTimer > 0 ) { alarmsBlockedTimer--; } } /*********************************************************************//** * @brief * The activateAlarm function activates a given alarm. * @details Inputs: none * @details Outputs: alarmIsActive[], alarmStartedAt[], alarmStatus is updated * @param alarm ID of alarm to activate * @return none *************************************************************************/ static void activateAlarm( ALARM_ID_T alarm ) { // Verify valid alarm index if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { // No need to do anything if alarm is already active, but if condition was cleared then re-trigger alarm if ( ( FALSE == alarmIsActive[ alarm ] ) || ( ( FALSE == alarmIsDetected[ alarm ] ) && ( FALSE == ALARM_TABLE[ alarm ].alarmConditionClearImmed ) ) ) { // If alarms are silenced and this new alarm is of higher or same priority, end silence due to new alarm if ( ( ALARM_TABLE[ alarm ].alarmPriority > ALARM_TABLE[ alarmStatus.alarmTop ].alarmPriority ) || ( ( ALARM_TABLE[ alarm ].alarmPriority == ALARM_TABLE[ alarmStatus.alarmTop ].alarmPriority ) && ( ALARM_TABLE[ alarm ].alarmSubRank < ALARM_TABLE[ alarmStatus.alarmTop ].alarmSubRank ) ) ) { alarmStatus.alarmsSilenced = FALSE; } // If alarm status was that no alarms currently active, set this alarm as top alarm until status formally updated later if ( ALARM_ID_NO_ALARM == alarmStatus.alarmTop ) { alarmStatus.alarmTop = alarm; } // If alarm stops, set that status immediately (don't wait for status update function) if ( TRUE == ALARM_TABLE[ alarm ].alarmStops ) { alarmStatus.stop = TRUE; } // If alarm is a fault (and not in service mode), request transition to fault mode if ( ( TRUE == ALARM_TABLE[ alarm ].alarmIsFault ) && ( getCurrentOperationMode() != MODE_SERV ) ) { requestNewOperationMode( MODE_FAUL ); } // Activate alarm alarmIsActive[ alarm ] = TRUE; alarmStartedAt[ alarm ].data = getMSTimerCount(); alarmIsDetected[ alarm ] = TRUE; // If alarm has clear condition immediately property, clear condition now if ( TRUE == ALARM_TABLE[ alarm ].alarmConditionClearImmed ) { clearAlarmCondition( alarm ); } // If alarm has stop property, signal stop now if ( TRUE == ALARM_TABLE[ alarm ].alarmStops ) { initiateAlarmAction( ALARM_ACTION_STOP ); } } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, alarm ) } } /*********************************************************************//** * @brief * The activateAlarmNoData function activates a given alarm. Also, an alarm * message is broadcast to the rest of the system. This function will * include given data in the broadcast message for logging. * @details Inputs: none * @details Outputs: alarm triggered message sent, alarm activated * @param alarm ID of alarm to activate * @return none *************************************************************************/ void activateAlarmNoData( ALARM_ID_T alarm ) { activateAlarm2Data( alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA, FALSE ); } /*********************************************************************//** * @brief * The activateAlarm1Data function activates a given alarm. Also, an alarm * message is broadcast to the rest of the system. This function will * include given data in the broadcast message for logging. * @details Inputs: none * @details Outputs: alarm triggered message sent, alarm activated * @param alarm ID of alarm to activate * @param alarmData supporting data to include in alarm msg * @return none *************************************************************************/ void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ) { activateAlarm2Data( alarm, alarmData, BLANK_ALARM_DATA, FALSE ); } /*********************************************************************//** * @brief * The activateAlarm2Data function activates a given alarm. Also, an alarm * message is broadcast to the rest of the system. This function will * include two given data in the broadcast message for logging. * @details Inputs: alarmsBlockedTimer, determines blocked alarm conditions * @details Outputs: alarm triggered message sent, alarm activated * @param alarm ID of alarm to activate * @param alarmData1 supporting data to include in alarm msg * @param alarmData2 supporting data to include in alarm msg * @param outside flag indicates whether alarm is originating from outside HD f/w * @return none *************************************************************************/ void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2, BOOL outside ) { // Block if new alarms are occur during loss of AC power if ( ( TRUE == getCPLDACPowerLossDetected() ) ) { alarmsBlockedTimer = ALARM_BLOCKED_COUNT_AFTER_AC_RETURN; } // Sanity check, verify valid alarm index if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { // if the block timer is 0 OR we have an unblockable alarm if ( ( ALARM_NOT_BLOCKED == alarmsBlockedTimer ) || ( ALARM_ID_HD_AC_POWER_LOST == alarm ) || ( ALARM_ID_HD_AC_POWER_LOST_IN_TREATMENT == alarm ) ) { // do not re-trigger alarm if blocked by property if ( ( FALSE == alarmNoRetrigger ) || ( ( ALARM_TABLE[ alarm ].alarmNoRetrigOnRB != TRUE ) && ( ALARM_TABLE[ alarm ].alarmNoRetrigOnEndTx != TRUE ) ) ) { HD_OP_MODE_T opMode = getCurrentOperationMode(); TREATMENT_STATE_T ts = getTreatmentState(); // do not trigger alarm if blocked by current mode/state if ( ( ( ALARM_TABLE[ alarm ].alarmBlockRinseback != TRUE ) || ( opMode != MODE_TREA ) || ( ts != TREATMENT_RINSEBACK_STATE ) || ( TRUE == outside ) ) && ( ( ALARM_TABLE[ alarm ].alarmBlockEndTx != TRUE ) || ( opMode != MODE_POST ) || ( TRUE == outside )) ) { // Broadcast alarm and data if alarm not already active if ( FALSE == alarmIsActive[ alarm ] ) { ALARM_TRIGGERED_PAYLOAD_T data; data.alarm = (U32)alarm; data.almDataType1 = (U32)alarmData1.dataType; data.almData1 = alarmData1.data.uInt.data; data.almDataType2 = (U32)alarmData2.dataType; data.almData2 = alarmData2.data.uInt.data; data.almPriority = ALARM_TABLE[ alarm ].alarmPriority; data.almRank = ALARM_TABLE[ alarm ].alarmSubRank; data.almClrTopOnly = ALARM_TABLE[ alarm ].alarmClearOnly; broadcastData( MSG_ID_ALARM_TRIGGERED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&data, sizeof( ALARM_TRIGGERED_PAYLOAD_T ) ); // Send information for UI to log to treatment log if ( ( TRUE == ALARM_TABLE[ alarm ].alarmTreatmentLog ) && ( MODE_TREA == getCurrentOperationMode() ) ) { sendTreatmentLogAlarmEventData( alarm, alarmData1, alarmData2 ); } } activateAlarm( alarm ); } } } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, alarm ) } } /*********************************************************************//** * @brief * The clearAlarmCondition function clears a given alarm's condition detected * flag. Also an alarm message is broadcast to the rest of the system. * @details Inputs: none * @details Outputs: alarmIsDetected[] * @param alarm ID of alarm to clear condition for * @return none *************************************************************************/ void clearAlarmCondition( ALARM_ID_T alarm ) { // Verify given alarm if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { // Clear alarm condition and broadcast alarm condition clear if not already cleared if ( TRUE == alarmIsDetected[ alarm ] ) { ALARM_ID_DATA_PUBLISH_T data; data.alarmID = (U32)alarm; alarmIsDetected[ alarm ] = FALSE; broadcastData( MSG_ID_ALARM_CONDITION_CLEARED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); } } } /*********************************************************************//** * @brief * The clearAlarm function clears a given alarm if it is recoverable. Also * an alarm message is broadcast to the rest of the system. * @details Inputs: none * @details Outputs: AlarmStatusTable[], alarmIsActive[], alarmStartedAt[], * alarmIsDetected[] * @param alarm ID of alarm to clear * @return none *************************************************************************/ void clearAlarm( ALARM_ID_T alarm ) { // Verify given alarm if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { // Verify alarm can be cleared if ( FALSE == ALARM_TABLE[ alarm ].alarmNoClear ) { // Clear alarm and broadcast alarm clear if not already cleared if ( TRUE == alarmIsActive[ alarm ] ) { ALARM_ID_DATA_PUBLISH_T data; data.alarmID = (U32) alarm; broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); alarmIsActive[ alarm ] = FALSE; clearAlarmCondition( alarm ); alarmStartedAt[ alarm ].data = 0; } } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, alarm ) } } /*********************************************************************//** * @brief * The clearNoRetriggerFlag function clears the no re-trigger flag. * @details Inputs: none * @details Outputs: alarmNoRetrigger * @return none *************************************************************************/ void clearNoRetriggerFlag( void ) { alarmNoRetrigger = FALSE; } /*********************************************************************//** * @brief * The clearNoRetriggerFlag function returns the no re-trigger flag. * @details Inputs: alarmNoRetrigger * @details Outputs: none * @return alarmNoRetrigger *************************************************************************/ BOOL getNoRetriggerFlag( void ) { return alarmNoRetrigger; } /*********************************************************************//** * @brief * The setAlarmUserActionEnabled function enables/disables specific alarm * recovery user actions while in specific modes. Ack option is always * potentially enabled - automatically enabled as appropriate by updateAlarmsFlags(). * @details Inputs: none * @details Outputs: * @param action ID of user alarm recovery action to enable/disable * @param enabled set to TRUE to enable action, FALSE to disable * @return none *************************************************************************/ void setAlarmUserActionEnabled( ALARM_USER_ACTION_T action, BOOL enabled ) { if ( action < NUMBER_OF_ALARM_USER_ACTIONS ) { alarmUserRecoveryActionEnabled[ action ] = enabled; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_USER_ACTION, (U32)action ) } } /*********************************************************************//** * @brief * The signalAlarmSilence function handles an alarm silence request from * the user. * @details Inputs: none * @details Outputs: alarm silence status updated * @param cmd ID of user command (1=silence, 0=cancel silence) * @return none *************************************************************************/ void signalAlarmSilence( ALARM_SILENCE_CMD_T cmd ) { if ( ALARM_SILENCE_CMD_START == cmd ) { if ( FALSE == alarmStatus.alarmsSilenced ) { alarmStatus.alarmsSilenced = TRUE; alarmStatus.alarmsSilenceStart = getMSTimerCount(); alarmStatus.alarmsSilenceExpiresIn = ALARM_SILENCE_EXPIRES_IN_SECS; } } else { if ( TRUE == alarmStatus.alarmsSilenced ) { alarmStatus.alarmsSilenced = FALSE; alarmStatus.alarmsSilenceStart = 0; alarmStatus.alarmsSilenceExpiresIn = 0; } } } /*********************************************************************//** * @brief * The signalAlarmUserActionInitiated function clears all non-recoverable alarms * and initiates selected user action. * @details Inputs: none * @details Outputs: * @param action ID of user's selected action to initiate * @return none *************************************************************************/ void signalAlarmUserActionInitiated( ALARM_USER_ACTION_T action ) { BOOL allRecAlarmsCleared = TRUE; // Clear recoverable alarms on user action if ( ( action < NUMBER_OF_ALARM_USER_ACTIONS ) && ( action != ALARM_USER_ACTION_END_TREATMENT ) ) // end tx action must be confirmed first { ALARM_ID_T a = alarmStatus.alarmTop; if ( ALARM_USER_ACTION_ACK == action ) { // If user acknowledged alarm w/ clear only property, just clear that alarm if ( TRUE == ALARM_TABLE[ a ].alarmClearOnly ) { clearAlarm( a ); } // Otherwise we must be in mode/state where ack was only option - so clear all like other options else { allRecAlarmsCleared = clearAllRecoverableAlarms( action ); } } else { allRecAlarmsCleared = clearAllRecoverableAlarms( action ); } } // Initiate user selected action switch ( action ) { case ALARM_USER_ACTION_RESUME: if ( TRUE == allRecAlarmsCleared ) { // only resume if we've cleared all recoverable alarms initiateAlarmAction( ALARM_ACTION_RESUME ); } break; case ALARM_USER_ACTION_RINSEBACK: initiateAlarmAction( ALARM_ACTION_RINSEBACK ); break; case ALARM_USER_ACTION_END_TREATMENT: // Send message to UI to get user confirmation to end treatment - action initiated only upon receipt of user confirmation from UI addConfirmationRequest( GENERIC_CONFIRM_ID_TREATMENT_END, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); break; case ALARM_USER_ACTION_ACK: initiateAlarmAction( ALARM_ACTION_ACK ); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_USER_ACTION, action ); break; } } /*********************************************************************//** * @brief * The isAlarmActive function determines whether a given alarm is currently * active. * @details Inputs: alarmIsActive[] * @details Outputs: none * @param alarm ID of alarm to check * @return TRUE if given alarm is active, FALSE if not *************************************************************************/ BOOL isAlarmActive( ALARM_ID_T alarm ) { BOOL result = FALSE; if ( alarm < NUM_OF_ALARM_IDS ) { result = alarmIsActive[ alarm ]; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED, (U32)alarm ); } return result; } /*********************************************************************//** * @brief * The isAlarmConditionDetected function determines whether a given alarm * condition is currently detected. * @details Inputs: alarmIsDetected[] * @details Outputs: none * @param alarm ID of alarm to check * @return TRUE if given alarm is active, FALSE if not *************************************************************************/ BOOL isAlarmConditionDetected( ALARM_ID_T alarm ) { BOOL result = FALSE; if ( alarm < NUM_OF_ALARM_IDS ) { if ( ( TRUE == alarmIsActive[ alarm ] ) && ( TRUE == alarmIsDetected[ alarm ] ) ) { result = TRUE; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED, (U32)alarm ); } return result; } /*********************************************************************//** * @brief * The isAnyAlarmActive function determines whether any alarm is currently * active. * @details Inputs: alarmStatus * @details Outputs: none * @return TRUE if any alarm is active, FALSE if not *************************************************************************/ BOOL isAnyAlarmActive( void ) { BOOL result = ( alarmStatus.alarmTop != ALARM_ID_NO_ALARM ? TRUE : FALSE ); return result; } /*********************************************************************//** * @brief * The isBloodRecircBlocked function determines whether any currently * active alarm is blocking blood re-circulation. * @details Inputs: alarmStatus * @details Outputs: none * @return TRUE if any active alarm prevents blood re-circulation, FALSE if not *************************************************************************/ BOOL isBloodRecircBlocked( void ) { return alarmStatus.noBloodRecirc; } /*********************************************************************//** * @brief * The isDialysateRecircBlocked function determines whether any currently * active alarm is blocking dialysate re-circulation. * @details Inputs: alarmStatus * @details Outputs: none * @return TRUE if any active alarm prevents dialysate re-circulation, FALSE if not *************************************************************************/ BOOL isDialysateRecircBlocked( void ) { return alarmStatus.noDialRecirc; } /*********************************************************************//** * @brief * The doesAlarmStatusIndicateEndTxOnly function determines whether any currently * active alarm has ( stop && noRes && /noET ) property, that is end treatment is * the only choice from full stop. * @details Inputs: alarmStatus * @details Outputs: none * @return TRUE if any active alarm has stop property, FALSE if not *************************************************************************/ BOOL doesAlarmStatusIndicateEndTxOnly( void ) { return ( ( ( TRUE == alarmStatus.noResume ) && ( TRUE == alarmStatus.noRinseback ) && ( TRUE == alarmStatus.stop ) && ( TRUE == alarmStatus.noBloodRecirc ) && ( FALSE == alarmStatus.noEndTreatment ) ) ? TRUE : FALSE ); } /*********************************************************************//** * @brief * The doesAlarmStatusIndicateStop function determines whether any currently * active alarm has stop property. * @details Inputs: alarmStatus * @details Outputs: none * @return TRUE if any active alarm has stop property, FALSE if not *************************************************************************/ BOOL doesAlarmStatusIndicateStop( void ) { return alarmStatus.stop; } /*********************************************************************//** * @brief * The doesAlarmIndicateNoResume function determines whether any currently * active alarm has treatment resume blocked property. * @details Inputs: resumeBlockedByAlarmProperty * @details Outputs: none * @return TRUE if any active alarm has no resume property, FALSE if not *************************************************************************/ BOOL doesAlarmIndicateNoResume( void ) { return resumeBlockedByAlarmProperty; } /*********************************************************************//** * @brief * The getCurrentAlarmStatePriority function determines the current alarm * state priority (NONE, LOW, MEDIUM, or HIGH). * @details Inputs: alarmStatus * @details Outputs: none * @return current alarm state priority *************************************************************************/ ALARM_PRIORITY_T getCurrentAlarmStatePriority( void ) { return alarmStatus.alarmsState; } /*********************************************************************//** * @brief * The isAlarmRecoverable function determines whether a given alarm is * recoverable. * @details Inputs: ALARM_TABLE[] * @details Outputs: none * @param alarm ID of alarm to check * @return TRUE if given alarm is recoverable, FALSE if not *************************************************************************/ BOOL isAlarmRecoverable( ALARM_ID_T alarm ) { BOOL result = ( TRUE == ALARM_TABLE[ alarm ].alarmNoClear ? FALSE : TRUE ); return result; } /*********************************************************************//** * @brief * The setAlarmAudioVolume function sets the current alarm audio volume level. * @details Inputs: none * @details Outputs: alarmAudioVolumeLevel * @param volumeLevel level of volume requested (1..5) * @return none *************************************************************************/ void setAlarmAudioVolume( U32 volumeLevel ) { BOOL accepted = FALSE; U32 rejReason = REQUEST_REJECT_REASON_NONE; if ( ( volumeLevel > 0 ) && ( volumeLevel <= MAX_ALARM_VOLUME_LEVEL ) ) { sendTreatmentLogEventData( ALARM_AUDIO_VOLUME_CHANGED_EVENT, (F32)volumeLevel, (F32)getAlarmAudioVolume() ); // Convert volume level to attenuation level alarmAudioVolumeLevel.data = MAX_ALARM_VOLUME_LEVEL - volumeLevel; accepted = TRUE; } else { rejReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; } // Send response to UI sendAlarmAudioVolumeSetResponse( accepted, rejReason ); } /*********************************************************************//** * @brief * The handleActiveAlarmListRequest function processes the active alarms list * request from UI. * @details Inputs: alarmIsActive[] * @details Outputs: sent active alarms list to UI * @return none *************************************************************************/ void handleActiveAlarmListRequest( void ) { ACTIVE_ALARM_LIST_RESPONSE_PAYLOAD_T activeAlarmPayload; U32 index; U32 activeAlarmListIndex = 0; activeAlarmPayload.accepted = TRUE; activeAlarmPayload.rejectionReason = (U32)REQUEST_REJECT_REASON_NONE; // Blank alarm list initially for ( index = 0; index < MAX_ALARM_LIST_SIZE; index++ ) { activeAlarmPayload.activeAlarmList[ index ] = ALARM_ID_NO_ALARM; } // Fill alarm list from (up to) 10 highest priority active alarms if ( TRUE == isAnyAlarmActive() ) { for ( index = 0; index < NUM_OF_ALARM_IDS; index++ ) { if ( ( TRUE == isAlarmActive( ALARM_RANK_TABLE[ index ].alarmID ) ) && ( activeAlarmListIndex < MAX_ALARM_LIST_SIZE ) ) { activeAlarmPayload.activeAlarmList[ activeAlarmListIndex ] = ALARM_RANK_TABLE[ index ].alarmID; activeAlarmListIndex++; } } } sendActiveAlarmsList( activeAlarmPayload ); } /*********************************************************************//** * @brief * The handleResendActiveAlarmsRequest function processes the request to re-send * all active alarms. * @details Inputs: alarmIsActive[] * @details Outputs: none * @return none *************************************************************************/ void handleResendActiveAlarmsRequest( void ) { U32 index; if ( TRUE == isAnyAlarmActive() ) { for ( index = 0; index < NUM_OF_ALARM_IDS; index++ ) { if ( TRUE == isAlarmActive( (ALARM_ID_T)index ) ) { ALARM_TRIGGERED_PAYLOAD_T data; data.alarm = index; data.almDataType1 = BLANK_ALARM_DATA.dataType; data.almData1 = BLANK_ALARM_DATA.data.uInt.data; data.almDataType2 = BLANK_ALARM_DATA.dataType; data.almData2 = BLANK_ALARM_DATA.data.uInt.data; data.almPriority = ALARM_TABLE[ index ].alarmPriority; data.almRank = ALARM_TABLE[ index ].alarmSubRank; data.almClrTopOnly = ALARM_TABLE[ index ].alarmClearOnly; broadcastData( MSG_ID_ALARM_TRIGGERED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&data, sizeof( ALARM_TRIGGERED_PAYLOAD_T ) ); } } } } /*********************************************************************//** * @brief * The getAlarmStartTime function gets the active state of a given alarm. * @details Inputs: alarmStartedAt[] * @details Outputs: none * @param alarmID ID of alarm to check * @return The start time stamp of given alarm ID *************************************************************************/ static U32 getAlarmStartTime( ALARM_ID_T alarmID ) { U32 result = 0; if ( alarmID < NUM_OF_ALARM_IDS ) { if ( OVERRIDE_KEY == alarmStartedAt[ alarmID ].override ) { result = alarmStartedAt[ alarmID ].ovData; } else { result = alarmStartedAt[ alarmID ].data; } } else { activateAlarmNoData( ALARM_ID_HD_SOFTWARE_FAULT ); } return result; } /*********************************************************************//** * @brief * The monitorAlarms function monitors alarm audio current. * @details Inputs: none * @details Outputs: alarmPrimaryAudioCurrentHG * @return none *************************************************************************/ static void monitorAlarms( void ) { U32 volume = getAlarmAudioVolume(); alarmPrimaryAudioCurrentHG.data = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_HG ); alarmPrimaryAudioCurrentLG.data = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_LG ); alarmBackupAudioCurrent.data = getFPGABackupAlarmAudioCurrent(); // Check for user confirmation of end treatment alarm response if ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == getConfirmationRequestStatus( GENERIC_CONFIRM_ID_TREATMENT_END ) ) { clearAllRecoverableAlarms( ALARM_USER_ACTION_END_TREATMENT ); initiateAlarmAction( ALARM_ACTION_END_TREATMENT ); } // TODO - Check current vs. expected audio output } /*********************************************************************//** * @brief * The updateAlarmsState function updates the alarms state and alarm to * display. * @details Inputs: alarmStatusTable[] * @details Outputs: alarmPriorityFIFO[], alarmStatus * @return none *************************************************************************/ static void updateAlarmsState( void ) { ALARM_PRIORITY_T highestPriority = ALARM_PRIORITY_NONE, p; ALARM_ID_T a; BOOL faultsActive = FALSE; BOOL dialysateRecircBlocked = FALSE; BOOL bloodRecircBlocked = FALSE; // Reset priority FIFOs so we can re-determine them below for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) { resetAlarmPriorityFIFO( p ); } // Update FIFOs and sub-ranks per active alarms table - for alarm ranking purposes to determine "top" alarm for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { if ( TRUE == alarmIsActive[ a ] ) { ALARM_PRIORITY_T almPriority = ALARM_TABLE[ a ].alarmPriority; U32 subRank = ALARM_TABLE[ a ].alarmSubRank; U32 msSinceTriggered = calcTimeSince( getAlarmStartTime( a ) ); // See if this alarm is higher rank than highest active alarm in this priority category so far (lower rank # = higher rank) if ( subRank <= alarmPriorityFIFO[ almPriority ].subRank ) { // If sub-rank is a tie, see which alarm was triggered first if ( subRank == alarmPriorityFIFO[ almPriority ].subRank ) { if ( (S32)msSinceTriggered > alarmPriorityFIFO[ almPriority ].timeSinceTriggeredMS ) { alarmPriorityFIFO[ almPriority ].alarmID = a; alarmPriorityFIFO[ almPriority ].subRank = subRank; alarmPriorityFIFO[ almPriority ].timeSinceTriggeredMS = (S32)msSinceTriggered; } } // Otherwise, this alarm simply outranks current candidate and wins outright else { alarmPriorityFIFO[ almPriority ].alarmID = a; alarmPriorityFIFO[ almPriority ].subRank = subRank; alarmPriorityFIFO[ almPriority ].timeSinceTriggeredMS = (S32)msSinceTriggered; } } // Track highest priority alarm found so far of all priority categories highestPriority = MAX( almPriority, highestPriority ); // Track whether any active faults have been found so far if ( TRUE == ALARM_TABLE[ a ].alarmIsFault ) { faultsActive = TRUE; } // Track whether any active alarms prevent dialysate re-circulation so far if ( TRUE == ALARM_TABLE[ a ].alarmNoDialysateRecirc ) { dialysateRecircBlocked = TRUE; } // Track whether any active alarms prevent blood re-circulation so far if ( TRUE == ALARM_TABLE[ a ].alarmNoBloodRecirc ) { bloodRecircBlocked = TRUE; } } } // Update alarm to display per highest priority FIFO alarmStatus.alarmsState = highestPriority; alarmStatus.alarmTop = alarmPriorityFIFO[ highestPriority ].alarmID; alarmStatus.topAlarmConditionDetected = alarmIsDetected[ alarmStatus.alarmTop ]; alarmStatus.systemFault = faultsActive; alarmStatus.noBloodRecirc = bloodRecircBlocked; alarmStatus.noDialRecirc = dialysateRecircBlocked; } /*********************************************************************//** * @brief * The setAlarmLamp function sets the alarm lamp pattern according to the * current state of alarms. * @details Inputs: none * @details Outputs: Alarm lamp patter set according to current alarms status. * @return none *************************************************************************/ static void setAlarmLamp( void ) { // Set alarm lamp pattern to appropriate pattern for current alarm state if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) { switch ( alarmStatus.alarmsState ) { case ALARM_PRIORITY_NONE: requestAlarmLampPattern( LAMP_PATTERN_OK ); break; case ALARM_PRIORITY_LOW: requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); break; case ALARM_PRIORITY_MEDIUM: requestAlarmLampPattern( LAMP_PATTERN_MED_ALARM ); break; case ALARM_PRIORITY_HIGH: if ( TRUE == ALARM_TABLE[ alarmStatus.alarmTop ].alarmIsFault ) { requestAlarmLampPattern( LAMP_PATTERN_FAULT ); } else { requestAlarmLampPattern( LAMP_PATTERN_HIGH_ALARM ); } break; default: requestAlarmLampPattern( LAMP_PATTERN_FAULT ); SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) break; } } // Execute alarm lamp controller execAlarmLamp(); // Set lamp on flag to match current state of alarm lamp if ( getCurrentAlarmLampPattern() != LAMP_PATTERN_MANUAL ) { alarmStatus.lampOn = getAlarmLampOn(); } else { alarmStatus.lampOn = FALSE; } } /*********************************************************************//** * @brief * The setAlarmAudio function sets the alarm audio pattern according to * the current state of alarms. * @details Inputs: alarmAudioTestToneRequested * @details Outputs: alarmAudioTestToneRequested * @return none *************************************************************************/ static void setAlarmAudio( void ) { U32 volume = getAlarmAudioVolume(); // If audio test in progress, play test tone. if ( TRUE == alarmAudioTestToneRequested ) { // Play test tone at min volume setAlarmAudioState( ALARM_AUDIO_TEST_TONE, ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[MAX_ALARM_AUDIO_VOLUME_INDEX][ALARM_AUDIO_VOLUME_GAIN], ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[MAX_ALARM_AUDIO_VOLUME_INDEX][ALARM_AUDIO_VOLUME_DIVIDER] ); // If we're in Fault mode, ensure audio test tone request is cancelled. if ( MODE_FAUL == getCurrentOperationMode() ) { alarmAudioTestToneRequested = FALSE; } } // If alarm silenced, play no alarm audio. else if ( ( ALARM_PRIORITY_NONE == alarmStatus.alarmsState ) || ( TRUE == alarmStatus.alarmsSilenced ) ) { setAlarmAudioState( ALARM_PRIORITY_NONE, ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[volume][ALARM_AUDIO_VOLUME_GAIN], ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[volume][ALARM_AUDIO_VOLUME_DIVIDER] ); } // Otherwise, play alarm audio as appropriate based on current alarm status else { if ( alarmStatus.alarmsState < NUM_OF_ALARM_PRIORITIES ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ALARM_AUDIO ) != SW_CONFIG_ENABLE_VALUE ) #endif { setAlarmAudioState( alarmStatus.alarmsState, ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[volume][ALARM_AUDIO_VOLUME_GAIN], ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[volume][ALARM_AUDIO_VOLUME_DIVIDER] ); } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_AUDIO_INVALID_ALARM_STATE, alarmStatus.alarmsState ) setAlarmAudioState( ALARM_PRIORITY_HIGH, ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[volume][ALARM_AUDIO_VOLUME_GAIN], ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[volume][ALARM_AUDIO_VOLUME_DIVIDER] ); } } } /*********************************************************************//** * @brief * The updateAlarmsSilenceStatus function updates the alarms silence state. * @details Inputs: alarmStatus * @details Outputs: alarmStatus * @return none *************************************************************************/ static void updateAlarmsSilenceStatus( void ) { // If alarms not silenced, reset alarms silence related properties if ( TRUE != alarmStatus.alarmsSilenced ) { alarmStatus.alarmsSilenceExpiresIn = 0; alarmStatus.alarmsSilenceStart = 0; } else { U32 timeSinceAlarmSilenceStart = calcTimeSince( alarmStatus.alarmsSilenceStart ) / MS_PER_SECOND; if ( timeSinceAlarmSilenceStart >= ALARM_SILENCE_EXPIRES_IN_SECS ) { alarmStatus.alarmsSilenceExpiresIn = 0; } else { alarmStatus.alarmsSilenceExpiresIn = ALARM_SILENCE_EXPIRES_IN_SECS - timeSinceAlarmSilenceStart; } // If alarms silence expires, end it if ( 0 == alarmStatus.alarmsSilenceExpiresIn ) { alarmStatus.alarmsSilenced = FALSE; } } } /*********************************************************************//** * @brief * The updateAlarmsFlags function updates the alarms flags of the alarms * status record. * @details Inputs: alarmStatus, alarmIsActive, ALARM_TABLE, alarmButtonBlockers * @details Outputs: alarmStatus, alarmUserRecoveryActionEnabled, * @return none *************************************************************************/ static void updateAlarmsFlags( void ) { BOOL systemFault = FALSE; BOOL stop = FALSE; BOOL noClear = FALSE; BOOL noResume = FALSE; BOOL noResumePerAlarmPropertyOnly = alarmNoRetrigger; // cannot resume if no re-trigger flag is set BOOL noRinseback = FALSE; BOOL noEndTreatment = FALSE; BOOL usrAckReq = FALSE; BOOL noMinimize = TRUE; HD_OP_MODE_T currentMode = getCurrentOperationMode(); ALARM_ID_T a; // Set user alarm recovery actions allowed by state flags alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_RESUME ] = ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RESUME ] ? FALSE : TRUE ); alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_RINSEBACK ] = ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RINSEBACK ] ? FALSE : TRUE ); alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_END_TREATMENT ] = ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_END_TREATMENT ] ? FALSE : TRUE ); // Reset user alarm recovery actions allowed by active alarms flags alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RESUME ] = FALSE; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RINSEBACK ] = FALSE; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_END_TREATMENT ] = FALSE; // Determine alarm flags for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { if ( TRUE == alarmIsActive[ a ] ) { systemFault = ( TRUE == ALARM_TABLE[ a ].alarmIsFault ? TRUE : systemFault ); stop = ( TRUE == ALARM_TABLE[ a ].alarmStops ? TRUE : stop ); noClear = ( TRUE == ALARM_TABLE[ a ].alarmNoClear ? TRUE : noClear ); noResumePerAlarmPropertyOnly = ( ALARM_TABLE[ a ].alarmNoResume ? TRUE : noResumePerAlarmPropertyOnly ); // Set user alarm recovery actions allowed flags alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RESUME ] |= ALARM_TABLE[ a ].alarmNoResume; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RINSEBACK ] |= ALARM_TABLE[ a ].alarmNoRinseback; alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_END_TREATMENT ] |= ALARM_TABLE[ a ].alarmNoEndTreatment; if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RESUME ] ) { noResume = ( TRUE == ALARM_TABLE[ a ].alarmNoResume ? TRUE : noResume ); } else { noResume = TRUE; } if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_RINSEBACK ] ) { noRinseback = ( TRUE == ALARM_TABLE[ a ].alarmNoRinseback ? TRUE : noRinseback ); } else { noRinseback = TRUE; } if ( TRUE == alarmUserRecoveryActionEnabled[ ALARM_USER_ACTION_END_TREATMENT ] ) { noEndTreatment = ( TRUE == ALARM_TABLE[ a ].alarmNoEndTreatment ? TRUE : noEndTreatment ); } else { noEndTreatment = TRUE; } } // If alarm active } // Alarm table loop // If top alarm condition not cleared, block resume if ( TRUE == alarmStatus.topAlarmConditionDetected ) { noResume = TRUE; } // If top alarm has clear only property or no other user options enabled for recoverable alarm and condition cleared, set user ack flag and block other flags if ( ( TRUE == ALARM_TABLE[ alarmStatus.alarmTop ].alarmClearOnly ) || ( ( FALSE == alarmStatus.noClear ) && ( TRUE == noResume ) && ( TRUE == noRinseback ) && ( TRUE == noEndTreatment ) && ( FALSE == alarmStatus.topAlarmConditionDetected ) ) ) { usrAckReq = TRUE; noResume = TRUE; noRinseback = TRUE; noEndTreatment = TRUE; } // If AC power is out, block all user options if ( TRUE == getCPLDACPowerLossDetected() ) { usrAckReq = FALSE; noResume = TRUE; noRinseback = TRUE; noEndTreatment = TRUE; } // If in Treatment-Stop state or Fault/Service/Standby Mode, allow user to minimize the alarm window if ( ( MODE_FAUL == currentMode ) || ( MODE_SERV == currentMode ) || ( MODE_STAN == currentMode ) || ( ( MODE_TREA == currentMode ) && ( TREATMENT_STOP_STATE == getTreatmentState() ) ) ) { noMinimize = FALSE; } // Set updated alarm flags alarmStatus.systemFault = systemFault; alarmStatus.stop = stop; alarmStatus.noClear = noClear; alarmStatus.noResume = noResume; alarmStatus.noRinseback = noRinseback; alarmStatus.noEndTreatment = noEndTreatment; alarmStatus.ok = usrAckReq; alarmStatus.noMinimize = noMinimize; alarmStatus.noReTrigger = alarmNoRetrigger; resumeBlockedByAlarmProperty = noResumePerAlarmPropertyOnly; } /*********************************************************************//** * @brief * The clearAllRecoverableAlarms function clears all currently active * recoverable alarms. * @details Inputs: ALARM_TABLE[] * @details Outputs: alarmNoRetrigger, alarmIsActive[] * @param action user action that prompted clearing of recoverable alarms * @return TRUE if all recoverable alarms cleared, FALSE if any left active *************************************************************************/ static BOOL clearAllRecoverableAlarms( ALARM_USER_ACTION_T action ) { BOOL result = TRUE; ALARM_ID_T a; // assigning to 1 in order to prevent ALARM_ID_NO_ALARM being cleared // which will cause a fault for ( a = ( ( ALARM_ID_T ) 1 ); a < NUM_OF_ALARM_IDS; a++ ) { // Clear alarm if alarm allowed to be cleared and not clear only (those are cleared individually) if ( ( FALSE == ALARM_TABLE[ a ].alarmNoClear ) && ( FALSE == ALARM_TABLE[ a ].alarmClearOnly ) ) { // Clear alarm if active and condition not active if ( ( TRUE == alarmIsActive[ a ] ) && ( ( TRUE == ALARM_TABLE[ a ].alarmConditionClearImmed ) || ( alarmIsDetected[ a ] != TRUE ) || ( action != ALARM_USER_ACTION_RESUME ) ) ) { // set no re-trigger flag if appropriate if ( ( ALARM_USER_ACTION_RINSEBACK == action ) && ( TRUE == ALARM_TABLE[ a ].alarmNoRetrigOnRB ) ) { // alarms with no re-trigger on rinseback property should set the no re-trigger flag alarmNoRetrigger = TRUE; } else if ( ( ALARM_USER_ACTION_END_TREATMENT == action ) && ( TRUE == ALARM_TABLE[ a ].alarmNoRetrigOnEndTx ) ) { // alarms with no re-trigger on end-tx property should set the no re-trigger flag alarmNoRetrigger = TRUE; } else if ( ALARM_USER_ACTION_ACK == action ) { if ( ( TRUE == ALARM_TABLE[ a ].alarmNoResume ) && ( TRUE == ALARM_TABLE[ a ].alarmNoRinseback ) ) { // alarms that only allow end-tx that occur in rinseback or recirc states of treatment mode should set the no re-trigger flag if ( ( MODE_TREA == getCurrentOperationMode() ) && ( ( TREATMENT_RINSEBACK_STATE == getCurrentSubMode() ) || ( TREATMENT_RECIRC_STATE == getCurrentSubMode() ) ) ) { alarmNoRetrigger = TRUE; } } } // clear this alarm clearAlarm( a ); } else if ( TRUE == alarmIsActive[ a ] ) { result = FALSE; // we didn't clear this alarm because condition still active } } } return result; } /*********************************************************************//** * @brief * The resetAlarmPriorityFIFO function resets a FIFO for a given alarm * priority. * @details Inputs: none * @details Outputs: alarmPriorityFIFO[] * @param priority priority of FIFO to reset * @return none *************************************************************************/ static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ) { // Verify priority if ( priority < NUM_OF_ALARM_PRIORITIES ) { alarmPriorityFIFO[ priority ].alarmID = ALARM_ID_NO_ALARM; alarmPriorityFIFO[ priority ].subRank = LOWEST_ALARM_SUB_RANK; alarmPriorityFIFO[ priority ].timeSinceTriggeredMS = -1; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, priority ) } } /*********************************************************************//** * @brief * The publishAlarmInfo function publishes alarm information and status * at the set intervals. * @details Inputs: alarmInfoPublicationTimerCounter, alarmButtonBlockers * @details Outputs: alarmStatusPublicationTimerCounter * @return none *************************************************************************/ static void publishAlarmInfo( void ) { // Publish alarm status at interval if ( ++alarmStatusPublicationTimerCounter >= getU32OverrideValue( &alarmStatusPublishInterval ) ) { // Lamp and audio timing sync'd with broadcast so UI can stay in sync with lamp rhythm setAlarmLamp(); setAlarmAudio(); broadcastAlarmStatus( alarmStatus ); alarmStatusPublicationTimerCounter = 0; } // Publish voltages monitor data on interval if ( ++alarmInfoPublicationTimerCounter >= getU32OverrideValue( &alarmInfoPublishInterval ) ) { ALARM_INFO_PAYLOAD_T data; data.audioVolume = MAX_ALARM_VOLUME_LEVEL - getAlarmAudioVolume(); // convert back to 1..5 volume level for publication data.audioCurrHG = getAlarmAudioPrimaryHighGainCurrent(); data.audioCurrLG = getAlarmAudioPrimaryLowGainCurrent(); data.backupAudioCurr = getAlarmAudioBackupCurrent(); data.safetyShutdown = isSafetyShutdownActivated(); data.acPowerLost = getCPLDACPowerLossDetected(); data.uiAlarmButtonBlocks[ ALARM_BUTTON_TABLE_BLOCK_RESUME ] = (U08)alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RESUME ]; data.uiAlarmButtonBlocks[ ALARM_BUTTON_TABLE_BLOCK_RINSEBACK ] = (U08)alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_RINSEBACK ]; data.uiAlarmButtonBlocks[ ALARM_BUTTON_TABLE_BLOCK_END_TREATMENT ] = (U08)alarmButtonBlockers[ ALARM_BUTTON_TABLE_BLOCK_END_TREATMENT ]; data.uiAlarmButtonBlocks[ ALARM_BUTTON_STATE_BLOCK_RESUME ] = (U08)alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_RESUME ]; data.uiAlarmButtonBlocks[ ALARM_BUTTON_STATE_BLOCK_RINSEBACK ] = (U08)alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_RINSEBACK ]; data.uiAlarmButtonBlocks[ ALARM_BUTTON_STATE_BLOCK_END_TREATMENT ] = (U08)alarmButtonBlockers[ ALARM_BUTTON_STATE_BLOCK_END_TREATMENT ]; broadcastData( MSG_ID_HD_ALARM_INFORMATION_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( ALARM_INFO_PAYLOAD_T ) ); alarmInfoPublicationTimerCounter = 0; } } /*********************************************************************//** * @brief * The getAlarmAudioVolume function gets the current alarm audio volume level. * @details Inputs: alarmAudioVolumeLevel * @details Outputs: none * @return the current alarm audio volume level. *************************************************************************/ U32 getAlarmAudioVolume( void ) { U32 result = alarmAudioVolumeLevel.data; #ifndef _RELEASE_ // Check the software configurations if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_ALARM_VOLUME_DEFAULT_LOW ) ) { result = MIN_ALARM_VOLUME_ATTENUATION; } #endif if ( OVERRIDE_KEY == alarmAudioVolumeLevel.override ) { result = alarmAudioVolumeLevel.ovData; } return result; } /*********************************************************************//** * @brief * The getAlarmAudioPrimaryHighGainCurrent function gets the current alarm * audio high gain current. * @details Inputs: alarmPrimaryAudioCurrentHG * @details Outputs: none * @return the current alarm audio high gain current (in mA). *************************************************************************/ F32 getAlarmAudioPrimaryHighGainCurrent( void ) { F32 result = alarmPrimaryAudioCurrentHG.data; if ( OVERRIDE_KEY == alarmPrimaryAudioCurrentHG.override ) { result = alarmPrimaryAudioCurrentHG.ovData; } return result; } /*********************************************************************//** * @brief * The getAlarmAudioPrimaryLowGainCurrent function gets the current alarm * audio low gain current. * @details Inputs: alarmPrimaryAudioCurrentLG * @details Outputs: none * @return the current alarm audio low gain current (in mA). *************************************************************************/ F32 getAlarmAudioPrimaryLowGainCurrent( void ) { F32 result = alarmPrimaryAudioCurrentLG.data; if ( OVERRIDE_KEY == alarmPrimaryAudioCurrentLG.override ) { result = alarmPrimaryAudioCurrentLG.ovData; } return result; } /*********************************************************************//** * @brief * The getAlarmAudioBackupCurrent function gets the current backup alarm * audio current. * @details Inputs: alarmBackupAudioCurrent * @details Outputs: none * @return the current backup alarm audio current (in mA). *************************************************************************/ F32 getAlarmAudioBackupCurrent( void ) { F32 result = alarmBackupAudioCurrent.data; if ( OVERRIDE_KEY == alarmBackupAudioCurrent.override ) { result = alarmBackupAudioCurrent.ovData; } return result; } /*********************************************************************//** * @brief * The execAlarmAudioSelfTest function outputs a test audio tone and * measures the audio current level. * @details Inputs: alarmAudioSelfTestState, audioTestStartTime * @details Outputs: audioTestStartTime, alarmAudioTestToneRequested * @return the current backup alarm audio current (in mA). *************************************************************************/ SELF_TEST_STATUS_T execAlarmAudioSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; F32 almLGCurrent = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_LG ); switch ( alarmAudioSelfTestState ) { case ALARM_AUDIO_SELF_TEST_STATE_START: if ( almLGCurrent < ALARM_AUDIO_CURRENT_LG_MAX_MA ) { audioTestStartTime = getMSTimerCount(); // Start test tone alarmAudioTestToneRequested = TRUE; setAlarmAudio(); alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_PRIMARY; } else { result = SELF_TEST_STATUS_FAILED; SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_ALARM_AUDIO_SELF_TEST_FAILURE, almLGCurrent, ALARM_AUDIO_CURRENT_LG_MAX_MA ); alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_COMPLETE; } break; case ALARM_AUDIO_SELF_TEST_STATE_PRIMARY: // Check if alarm audio current is sufficiently high indicating alarm tone is being output if ( almLGCurrent > ALARM_AUDIO_CURRENT_LG_MIN_MA ) { alarmAudioTestToneRequested = FALSE; audioTestStartTime = getMSTimerCount(); alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_NO_TONE; } else if ( TRUE == didTimeout( audioTestStartTime, ALARM_AUDIO_MAX_TEST_TIME_MS ) ) { alarmAudioTestToneRequested = FALSE; result = SELF_TEST_STATUS_FAILED; SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_ALARM_AUDIO_SELF_TEST_FAILURE, almLGCurrent, ALARM_AUDIO_CURRENT_LG_MIN_MA ); alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_COMPLETE; } break; case ALARM_AUDIO_SELF_TEST_STATE_NO_TONE: if ( almLGCurrent < ALARM_AUDIO_CURRENT_LG_MAX_MA ) { result = SELF_TEST_STATUS_PASSED; alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_COMPLETE; } else if ( TRUE == didTimeout( audioTestStartTime, ALARM_AUDIO_MAX_TEST_TIME_MS ) ) { result = SELF_TEST_STATUS_FAILED; SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_ALARM_AUDIO_SELF_TEST_FAILURE, almLGCurrent, ALARM_AUDIO_CURRENT_LG_MAX_MA ); alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_COMPLETE; } break; case ALARM_AUDIO_SELF_TEST_STATE_COMPLETE: alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; // Should only get here if re-starting self-tests. break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_ALARM_AUDIO_STATE, (U32)alarmAudioSelfTestState ) break; } return result; } /*********************************************************************//** * @brief * The resetAlarmAudioPOSTState function resets the alarm audio POST state. * @details Inputs: none * @details Outputs: alarmAudioSelfTestState * @return none *************************************************************************/ void resetAlarmAudioPOSTState( void ) { alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetAlarmStateOverride function overrides the state of the * alarm active state for a given alarm with the alarm management with * a given active state. * @details Inputs: none * @details Outputs: alarm activated or cleared * @param alarmID ID of alarm to activate or clear * @param value override state for the given alarm ID (1=activate, 0=clear) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetAlarmStateOverride( U32 alarmID, U32 state ) { BOOL result = FALSE; if ( alarmID < NUM_OF_ALARM_IDS ) { // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { if ( TRUE == state ) { activateAlarmNoData( (ALARM_ID_T)alarmID ); } else { clearAlarm( (ALARM_ID_T)alarmID ); } result = TRUE; } } return result; } /*********************************************************************//** * @brief * The testResetAlarmStateOverride function resets the override of the * state of the active state for a given alarm with the alarm management. * @details Inputs: none * @details Outputs: alarm cleared * @param alarmID ID of alarm to clear * @return TRUE if alarm clear successful, FALSE if not *************************************************************************/ BOOL testResetAlarmStateOverride( U32 alarmID ) { BOOL result = FALSE; if ( alarmID < NUM_OF_ALARM_IDS ) { // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { result = TRUE; clearAlarm( (ALARM_ID_T)alarmID ); } } return result; } /*********************************************************************//** * @brief * The testSetAlarmStartOverride function overrides the start time * for a given alarm with the alarm management with a given start time. * @details Inputs: none * @details Outputs: alarmStartedAt[] * @param alarmID ID of alarm to override start time for * @param value override time since start (in ms) for the given alarm ID * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetAlarmStartOverride( U32 alarmID, U32 value ) { BOOL result = FALSE; if ( alarmID < NUM_OF_ALARM_IDS ) { // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { U32 tim = getMSTimerCount(); if ( tim > value ) { result = TRUE; alarmStartedAt[ alarmID ].ovData = ( tim - value ); alarmStartedAt[ alarmID ].override = OVERRIDE_KEY; } } } return result; } /*********************************************************************//** * @brief * The testResetAlarmStartOverride function resets the override of the * start time for a given alarm with the alarm management. * @details Inputs: none * @details Outputs: alarmStartedAt[] * @param alarmID ID of alarm to reset override of start time for * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetAlarmStartOverride( U32 alarmID ) { BOOL result = FALSE; if ( alarmID < NUM_OF_ALARM_IDS ) { // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { result = TRUE; alarmStartedAt[ alarmID ].override = OVERRIDE_RESET; alarmStartedAt[ alarmID ].ovData = alarmStartedAt[ alarmID ].ovInitData; } } return result; } /*********************************************************************//** * @brief * The testClearAllAlarms function clears all active alarms, even if they * are non-recoverable or faults. The caller of this function must provide * the correct 32-bit key. A Dialin user must also be logged into HD. * @details Inputs: none * @details Outputs: alarmIsActive[], alarmStartedAt[] * @param key 32-bit supervior alarm key required to perform this function * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testClearAllAlarms( U32 key ) { BOOL result = FALSE; // Verify key if ( SUPERVISOR_ALARM_KEY == key ) { // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { ALARM_ID_T a; // Clear all active alarms for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { if ( TRUE == alarmIsActive[ a ] ) { ALARM_ID_DATA_PUBLISH_T data; data.alarmID = (U32)a; broadcastData( MSG_ID_ALARM_CLEARED, COMM_BUFFER_OUT_CAN_HD_ALARM, (U08*)&data, sizeof( ALARM_ID_DATA_PUBLISH_T ) ); alarmIsActive[ a ] = FALSE; alarmStartedAt[ a ].data = 0; // Clear FIFO if this alarm was in it if ( alarmPriorityFIFO[ ALARM_TABLE[ a ].alarmPriority ].alarmID == a ) { resetAlarmPriorityFIFO( ALARM_TABLE[ a ].alarmPriority ); } } } result = TRUE; } } return result; } /*********************************************************************//** * @brief * The testSetAlarmStatusPublishIntervalOverride function sets the override of the * alarm status publication interval. * @details Inputs: none * @details Outputs: alarmStatusPublishInterval * @param ms milliseconds between alarm status broadcasts * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetAlarmStatusPublishIntervalOverride( U32 ms ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = ms / TASK_GENERAL_INTERVAL; result = TRUE; alarmStatusPublishInterval.ovData = intvl; alarmStatusPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetAlarmStatusPublishIntervalOverride function resets the override of the * alarm status publication interval. * @details Inputs: none * @details Outputs: alarmStatusPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetAlarmStatusPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmStatusPublishInterval.override = OVERRIDE_RESET; alarmStatusPublishInterval.ovData = alarmStatusPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetAlarmInfoPublishIntervalOverride function sets the override of the * alarm information publication interval. * @details Inputs: none * @details Outputs: alarmInfoPublishInterval * @param ms milliseconds between alarm info broadcasts * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetAlarmInfoPublishIntervalOverride( U32 ms ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = ms / TASK_GENERAL_INTERVAL; result = TRUE; alarmInfoPublishInterval.ovData = intvl; alarmInfoPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetAlarmInfoPublishIntervalOverride function resets the override of the * alarm information publication interval. * @details Inputs: none * @details Outputs: alarmInfoPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetAlarmInfoPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmInfoPublishInterval.override = OVERRIDE_RESET; alarmInfoPublishInterval.ovData = alarmInfoPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetAlarmAudioVolumeLevelOverride function sets the override of the * alarm audio volume. * @details Inputs: none * @details Outputs: alarmAudioVolumeLevel * @param volume volume level (1..5) of alarm audio * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetAlarmAudioVolumeLevelOverride( U32 volume ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmAudioVolumeLevel.ovData = MAX_ALARM_VOLUME_LEVEL - volume; alarmAudioVolumeLevel.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetAlarmAudioVolumeLevelOverride function resets the override of the * alarm audio volume. * @details Inputs: none * @details Outputs: alarmAudioVolumeLevel * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetAlarmAudioVolumeLevelOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmAudioVolumeLevel.override = OVERRIDE_RESET; alarmAudioVolumeLevel.ovData = alarmAudioVolumeLevel.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetPrimaryAlarmAudioCurrentHGOverride function sets the override of the * alarm audio current (high gain) in mA. * @details Inputs: none * @details Outputs: alarmPrimaryAudioCurrentHG * @param mA milliamps measured from high gain channel of primary alarm audio * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetPrimaryAlarmAudioCurrentHGOverride( F32 mA ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmPrimaryAudioCurrentHG.ovData = mA; alarmPrimaryAudioCurrentHG.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetPrimaryAlarmAudioCurrentHGOverride function resets the override of the * alarm audio current (high gain). * @details Inputs: none * @details Outputs: alarmPrimaryAudioCurrentHG * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetPrimaryAlarmAudioCurrentHGOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmPrimaryAudioCurrentHG.override = OVERRIDE_RESET; alarmPrimaryAudioCurrentHG.ovData = alarmPrimaryAudioCurrentHG.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetPrimaryAlarmAudioCurrentLGOverride function sets the override of the * alarm audio current (low gain) in mA. * @details Inputs: none * @details Outputs: alarmPrimaryAudioCurrentLG * @param mA milliamps measured from low gain channel of primary alarm audio * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetPrimaryAlarmAudioCurrentLGOverride( F32 mA ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmPrimaryAudioCurrentLG.ovData = mA; alarmPrimaryAudioCurrentLG.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetPrimaryAlarmAudioCurrentLGOverride function resets the override of the * alarm audio current (low gain). * @details Inputs: none * @details Outputs: alarmPrimaryAudioCurrentLG * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetPrimaryAlarmAudioCurrentLGOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmPrimaryAudioCurrentLG.override = OVERRIDE_RESET; alarmPrimaryAudioCurrentLG.ovData = alarmPrimaryAudioCurrentLG.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetBackupAlarmAudioCurrentOverride function sets the override of the * alarm audio current (backup) in mA. * @details Inputs: none * @details Outputs: alarmBackupAudioCurrent * @param mA milliamps measured from backup channel of primary alarm audio * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetBackupAlarmAudioCurrentOverride( F32 mA ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmBackupAudioCurrent.ovData = mA; alarmBackupAudioCurrent.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBackupAlarmAudioCurrentOverride function resets the override of the * alarm audio current (backup). * @details Inputs: none * @details Outputs: alarmBackupAudioCurrent * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetBackupAlarmAudioCurrentOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; alarmBackupAudioCurrent.override = OVERRIDE_RESET; alarmBackupAudioCurrent.ovData = alarmBackupAudioCurrent.ovInitData; } return result; } /**@}*/