Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r6311eb9b65fdeec7a285d25e07f3932ac0fb6cf1 -rbd30744a51141ff5e56088eac67a9641866ab6cc --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 6311eb9b65fdeec7a285d25e07f3932ac0fb6cf1) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision bd30744a51141ff5e56088eac67a9641866ab6cc) @@ -1,618 +1,1441 @@ -/************************************************************************** - * - * Copyright (c) 2019-2019 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 Timers.c - * - * @date 07-Nov-2019 - * @author S. Nash - * - * @brief Alarm Management service module. Provides general alarm management \n - * functionality including support functions for triggering and clearing \n - * specific alarms. - * - **************************************************************************/ +/************************************************************************** +* +* Copyright (c) 2019-2022 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) Dara Navaei +* @date (last) 13-Jun-2022 +* +* @author (original) Sean Nash +* @date (original) 07-Nov-2019 +* +***************************************************************************/ -#include "Common.h" -#include "AlarmLamp.h" -#include "OperationModes.h" +#include "mibspi.h" + +#define __ALARM_MGMT_C__ + +#include "AlarmLamp.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 ) -#define ALARM_STATUS_PUBLISH_INTERVAL (500/TASK_GENERAL_INTERVAL) // 500ms / task interval +#define ALARM_SILENCE_EXPIRES_IN_SECS (60) ///< Alarm silence expiration time in seconds. -#pragma pack(push,1) -typedef struct -{ - ALARM_PRIORITY_T alarmPriority; // priority of alarm - U32 alarmEscalatesAfter; // time (s) after start when alarm will escalate if not cleared (zero indicates no escalation) - ALARM_ID_T alarmEscalatesTo; // ID of alarm that this alarm will escalate to (ALARM_ID_NO_ALARM indicates no esclation) - BOOL alarmIsFault; // alarm is a system fault? - BOOL alarmStops; // alarm activation should cause a controlled stop - BOOL alarmNoClear; // alarm cannot be cleared (unrecoverable)? - BOOL alarmNoResume; // alarm prevents treatment resume - BOOL alarmNoRinseback; // alarm prevents rinseback - BOOL alarmNoEndTreatment; // alarm prevents ending treatment - BOOL alarmNoNewTreatment; // alarm prevents any new treatments - BOOL alarmDialyzerBypass; // alarm activation should cause dialyzer bypass until cleared -} ALARM_T; -#pragma pack(pop) +#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 MAX_ALARM_LIST_SIZE 10 ///< Maximum number of active alarms inside alarm list. -const ALARM_T alarmTable[ NUM_OF_ALARM_IDS ] = -{ // Priority Esc Escalate To Fault Stops NoClr NoRes NoRin NoEnd NoNew Bypass - { ALARM_PRIORITY_NONE, 0, ALARM_ID_NO_ALARM, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_NO_ALARM - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_SOFTWARE_FAULT - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_STUCK_BUTTON_TEST_FAILED - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_FPGA_POST_TEST_FAILED - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_WATCHDOG_POST_TEST_FAILED - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE }, // ALARM_ID_UI_COMM_POST_FAILED - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_BLOOD_PUMP_MC_SPEED_CHECK - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_BLOOD_PUMP_ROTOR_SPEED_CHECK - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_IN_PUMP_MC_CURRENT_CHECK - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_IN_PUMP_MC_SPEED_CHECK - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_IN_PUMP_MC_DIRECTION_CHECK - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_IN_PUMP_ROTOR_SPEED_CHECK - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_OUT_PUMP_MC_CURRENT_CHECK - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_OUT_PUMP_MC_SPEED_CHECK - { ALARM_PRIORITY_MEDIUM, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_OUT_PUMP_MC_DIRECTION_CHECK - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, FALSE, TRUE , FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, // ALARM_ID_DIAL_OUT_PUMP_ROTOR_SPEED_CHECK - { ALARM_PRIORITY_HIGH, 0, ALARM_ID_NO_ALARM, TRUE, TRUE , TRUE , TRUE , TRUE , TRUE , TRUE , FALSE } // ALARM_ID_WATCHDOG_EXPIRED -}; +// *** 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 }; -const ALARM_DATA_T blankAlarmData = { 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_HG_MIN_MA 20.0F ///< Minimum audio current (high gain) during test tone self-test (in mA). // TODO - Why is HG so low? S/B same as LG I think. +#define ALARM_AUDIO_CURRENT_LG_MIN_MA 60.0F ///< Minimum audio current (low gain) during test 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 (MAX_ALARM_VOLUME_LEVEL - 1 ) ///< Index for maximum alarm audio volume. +#define MIN_ALARM_AUDIO_VOLUME_INDEX 0 ///< 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 + U32 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 lamp self-test. + ALARM_AUDIO_SELF_TEST_STATE_PRIMARY, ///< Red state of alarm lamp self-test. + ALARM_AUDIO_SELF_TEST_STATE_COMPLETE, ///< Completed state of alarm lamp self-test. + NUM_OF_ALARM_AUDIO_SELF_TEST_STATES ///< Number of states in alarm lamp 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 U32 alarmStatusPublicationTimerCounter = 0; // used to schedule alarm status publication to CAN bus -// interval (in ms) at which to publish alarm status to CAN bus -DATA_DECL( U32, AlarmStatusPub, alarmStatusPublishInterval, ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL ); +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. -DATA_ARRAY_DECL( BOOL, AlarmStates, NUM_OF_ALARM_IDS, alarmIsActive ); -DATA_ARRAY_DECL( U32, AlarmStarts, NUM_OF_ALARM_IDS, alarmStartedAt ); - -static COMP_ALARM_STATUS_T alarmStatus; - -static ALARM_ID_T alarmPriorityFIFO[ NUM_OF_ALARM_PRIORITIES ]; - +/// 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 }; +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. + +/// Current state of the alarm audio self tests. +static ALARM_AUDIO_SELF_TEST_STATE_T alarmAudioSelfTestState; +/// Flag indicates whether alarm audio test tone should be output. +static BOOL alarmAudioTestToneRequested; + // ********** private function prototypes ********** static void activateAlarm( ALARM_ID_T alarm ); - + +static void monitorAlarms( void ); static void updateAlarmsState( void ); -static void setAlarmLampAndAudio( void ); +static void setAlarmLamp( void ); +static void setAlarmAudio( void ); static void updateAlarmsSilenceStatus( void ); static void handleAlarmEscalations( void ); static void updateAlarmsFlags( void ); - + +static void clearAllRecoverableAlarms( void ); static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ); -static DATA_ARRAY_GET_PROTOTYPE( BOOL, getAlarmActive, alarmID ); -static DATA_ARRAY_GET_PROTOTYPE( U32, getAlarmStartTime, alarmID ); -static DATA_GET_PROTOTYPE( U32, getPublishAlarmStatusInterval ); +static U32 getAlarmStartTime( ALARM_ID_T alarmID ); + +static void publishAlarmInfo( void ); -/************************************************************************* - * @brief initAlarmMgmt +/*********************************************************************//** + * @brief * The initAlarmMgmt function initializes the AlarmMgmt module. - * @details - * Inputs : none - * Outputs : AlarmMgmt module initialized. - * @param none + * @details Inputs: none + * @details Outputs: AlarmMgmt module initialized. * @return none *************************************************************************/ void initAlarmMgmt( void ) { ALARM_PRIORITY_T p; - ALARM_ID_T a; + ALARM_ID_T a; - // initialize alarm states and start time stamps + // 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 ].data = FALSE; - alarmIsActive[ a ].ovData = FALSE; - alarmIsActive[ a ].ovInitData = TRUE; - alarmIsActive[ a ].override = OVERRIDE_RESET; + 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 + // Initialize alarm FIFOs for ( p = ALARM_PRIORITY_NONE; p < NUM_OF_ALARM_PRIORITIES; p++ ) { - alarmPriorityFIFO[ p ] = ALARM_ID_NO_ALARM; + alarmPriorityFIFO[ p ].alarmID = ALARM_ID_NO_ALARM; + alarmPriorityFIFO[ p ].subRank = LOWEST_ALARM_SUB_RANK; + alarmPriorityFIFO[ p ].timeSinceTriggeredMS = 0; } - // initialize composite alarm state + // Initialize composite alarm state alarmStatus.alarmsState = ALARM_PRIORITY_NONE; alarmStatus.alarmsSilenced = FALSE; alarmStatus.alarmsSilenceStart = 0; alarmStatus.alarmsSilenceExpiresIn = 0; alarmStatus.alarmsEscalatesIn = 0; - alarmStatus.alarmTop = ALARM_ID_NO_ALARM; + alarmStatus.alarmTop = ALARM_ID_NO_ALARM; + alarmStatus.topAlarmConditionDetected = FALSE; alarmStatus.systemFault = FALSE; - alarmStatus.stop = FALSE; + alarmStatus.stop = FALSE; + alarmStatus.lampOn = FALSE; alarmStatus.noClear = FALSE; alarmStatus.noResume = FALSE; alarmStatus.noRinseback = FALSE; - alarmStatus.noEndTreatment = FALSE; - alarmStatus.noNewTreatment = FALSE; - alarmStatus.bypassDialyzer = FALSE; + alarmStatus.noEndTreatment = FALSE; + alarmStatus.noBloodRecirc = FALSE; + alarmStatus.noDialRecirc = FALSE; + alarmStatus.ok = FALSE; + + alarmAudioTestToneRequested = FALSE; + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; } -/************************************************************************* - * @brief execAlarmMgmt - * The execAlarmMgmt function executes the alarm management functions to be \n - * done periodically. The composite alarm state is updated, alarm lamp and \n +/*********************************************************************//** + * @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 : larmStatusTable[], alarmTable[] - * Outputs : larmStatus - * @param none + * @details Inputs: alarmStatusTable[], ALARM_TABLE[] + * @details Outputs: alarmStatus * @return none *************************************************************************/ void execAlarmMgmt( void ) -{ +{ + monitorAlarms(); handleAlarmEscalations(); updateAlarmsState(); updateAlarmsFlags(); updateAlarmsSilenceStatus(); - setAlarmLampAndAudio(); - // publish alarm status at interval - if ( ++alarmStatusPublicationTimerCounter > getPublishAlarmStatusInterval() ) - { + // 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; } } -/************************************************************************* - * @brief activateAlarm +/*********************************************************************//** + * @brief * The activateAlarm function activates a given alarm. - * @details - * Inputs : none - * Outputs : alarmIsActive[], alarmStartedAt[] - * @param alarm : ID of alarm to activate + * @details Inputs: none + * @details Outputs: alarmIsActive[], alarmStartedAt[] + * @param alarm ID of alarm to activate * @return none *************************************************************************/ static void activateAlarm( ALARM_ID_T alarm ) { - // verify given alarm + // Verify given alarm if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { - // no need to do anything if alarm is already active - if ( FALSE == getAlarmActive( alarm ) ) - { - // if alarm is a fault, request transition to fault mode - if ( TRUE == alarmTable[ alarm ].alarmIsFault ) + // 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 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 alarms silenced, end silence due to new alarm + alarmStatus.alarmsSilenced = FALSE; + // 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 ].data = TRUE; - alarmStartedAt[ alarm ].data = getMSTimerCount(); -#ifdef DEBUG_ENABLED - { - // TODO - temporary debug code - remove later - char debugStr[ 256 ]; - sprintf( debugStr, "ALARM triggered:%5d \n", alarm ); - sendDebugData( (U08*)debugStr, strlen(debugStr) ); + // 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 ); } -#endif } } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, alarm ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, alarm ) } } -/************************************************************************* - * @brief activateAlarmNoData - * The activateAlarmNoData function activates a given alarm. Also, an alarm \n - * message is broadcast to the rest of the system. This function will \n +/*********************************************************************//** + * @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 - * Outputs : alarm triggered message sent, alarm activated - * @param alarm : ID of alarm to activate - * @param alarmData : supporting data to include in alarm msg + * @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 ) -{ - // broadcast alarm and data if alarm not already active - if ( FALSE == alarmIsActive[ alarm ].data ) - { - broadcastAlarmTriggered( (U16)alarm, blankAlarmData, blankAlarmData ); - } - activateAlarm( alarm ); +{ + activateAlarm2Data( alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA ); } -/************************************************************************* - * @brief activateAlarm1Data - * The activateAlarm1Data function activates a given alarm. Also, an alarm \n - * message is broadcast to the rest of the system. This function will \n +/*********************************************************************//** + * @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 - * Outputs : alarm triggered message sent, alarm activated - * @param alarm : ID of alarm to activate - * @param alarmData : supporting data to include in alarm msg + * @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 ) { - // broadcast alarm and data if alarm not already active - if ( FALSE == alarmIsActive[ alarm ].data ) - { - broadcastAlarmTriggered( (U16)alarm, alarmData, blankAlarmData ); - } - activateAlarm( alarm ); + activateAlarm2Data( alarm, alarmData, BLANK_ALARM_DATA ); } -/************************************************************************* - * @brief activateAlarm1Data - * The activateAlarm2Data function activates a given alarm. Also, an alarm \n - * message is broadcast to the rest of the system. This function will \n +/*********************************************************************//** + * @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 : none - * 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 + * @details Inputs: none + * @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 * @return none *************************************************************************/ void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2 ) { - // broadcast alarm and data if alarm not already active - if ( FALSE == alarmIsActive[ alarm ].data ) - { - broadcastAlarmTriggered( (U16)alarm, alarmData1, alarmData2 ); + // 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 ); -} - -/************************************************************************* - * @brief clearAlarm - * The clearAlarm function clears a given alarm if it is recoverable. Also \n +} + +/*********************************************************************//** + * @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 - * Outputs : AlarmStatusTable[] - * @param alarm : ID of alarm to clear + * @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 + // Verify given alarm if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { - // verify alarm can be cleared - if ( FALSE == alarmTable[ alarm ].alarmNoClear ) + // 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 ].data ) - { - broadcastAlarmCleared( alarm ); - alarmIsActive[ alarm ].data = FALSE; + // 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; - // clear FIFO if this alarm was in it - if ( alarmPriorityFIFO[ alarmTable[ alarm ].alarmPriority ] == alarm ) + // Clear FIFO if this alarm was in it + if ( alarmPriorityFIFO[ ALARM_TABLE[ alarm ].alarmPriority ].alarmID == alarm ) { - resetAlarmPriorityFIFO( alarmTable[ alarm ].alarmPriority ); + resetAlarmPriorityFIFO( ALARM_TABLE[ alarm ].alarmPriority ); } } } } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, alarm ) + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, alarm ) } } -/************************************************************************* - * @brief isAlarmActive - * The isAlarmActive function determines whether a given alarm is currently \n +/*********************************************************************//** + * @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 ) +{ + // Validate given action + if ( action < NUMBER_OF_ALARM_USER_ACTIONS ) + { + 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 + { + clearAllRecoverableAlarms(); + } + } + else + { + clearAllRecoverableAlarms(); + } + } + + // Initiate user selected action + switch ( action ) + { + case ALARM_USER_ACTION_RESUME: + initiateAlarmAction( ALARM_ACTION_RESUME ); + break; + + case ALARM_USER_ACTION_RINSEBACK: + initiateAlarmAction( ALARM_ACTION_RINSEBACK ); + break; + + case ALARM_USER_ACTION_END_TREATMENT: + initiateAlarmAction( ALARM_ACTION_END_TREATMENT ); + 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[] - * Outputs : none - * @param alarmID : ID of alarm to check + * @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 = getAlarmActive( alarm ); + BOOL result = alarmIsActive[ 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 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 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 processed the active alarms list +* request from UI. +* @details Inputs: alarmIsActive[] +* @details Outputs: sent active alarms list to UI +* @return none +*************************************************************************/ +void handleActiveAlarmListRequest( void ) +{ + BOOL accepted = TRUE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; + U32 activeAlarmList[ MAX_ALARM_LIST_SIZE ]; + U32 index; + U32 activeAlarmListIndex = 0; + + for ( index = 0; index < MAX_ALARM_LIST_SIZE; index++ ) + { + activeAlarmList[ index ] = ALARM_ID_NO_ALARM; + } + + 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 ) ) + { + activeAlarmList[ activeAlarmListIndex ] = ALARM_RANK_TABLE[ index ].alarmID; + activeAlarmListIndex++; + } + } + } + + sendActiveAlarmsList( accepted, rejReason, activeAlarmList, sizeof( activeAlarmList ) ); +} -/************************************************************************* - * @brief getAlarmActive - * The getAlarmActive function gets the active state of a given alarm. - * @details - * Inputs : alarmIsActive[] - * Outputs : none - * @param alarmID : ID of alarm to check - * @return TRUE if given alarm is active, FALSE if not - *************************************************************************/ -static DATA_ARRAY_GET( BOOL, getAlarmActive, alarmID, NUM_OF_ALARM_IDS-1, alarmIsActive, TRUE ) - -/************************************************************************* - * @brief getAlarmStartTime +/*********************************************************************//** + * @brief * The getAlarmStartTime function gets the active state of a given alarm. - * @details - * Inputs : alarmStartedAt[] - * Outputs : none - * @param alarmID : ID of alarm to check + * @details Inputs: alarmStartedAt[] + * @details Outputs: none + * @param alarmID ID of alarm to check * @return The start time stamp of given alarm ID *************************************************************************/ -static DATA_ARRAY_GET( U32, getAlarmStartTime, alarmID, NUM_OF_ALARM_IDS-1, alarmStartedAt, 0 ) +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: alarmStatusTable[] + * @details Outputs: alarmPriorityFIFO[], alarmStatus + * @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(); + + // TODO - Check current vs. expected audio output + + // Publish alarm information at interval + publishAlarmInfo(); +} -/************************************************************************* - * @brief updateAlarmsState - * The updateAlarmsState function updates the alarms state and alarm to \n +/*********************************************************************//** + * @brief + * The updateAlarmsState function updates the alarms state and alarm to * display. - * @details - * Inputs : alarmStatusTable[] - * Outputs : alarmPriorityFIFO[], alarmStatus - * @param none + * @details Inputs: alarmStatusTable[] + * @details Outputs: alarmPriorityFIFO[], alarmStatus * @return none *************************************************************************/ static void updateAlarmsState( void ) { ALARM_PRIORITY_T highestPriority = ALARM_PRIORITY_NONE; ALARM_ID_T a; - BOOL faultsActive = FALSE; + BOOL faultsActive = FALSE; + BOOL dialysateRecircBlocked = FALSE; + BOOL bloodRecircBlocked = FALSE; - // update FIFOs per alarm status table + // 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 == getAlarmActive(a) ) + if ( TRUE == alarmIsActive[ a ] ) { - ALARM_PRIORITY_T almPriority = alarmTable[ a ].alarmPriority; - if ( ALARM_ID_NO_ALARM == alarmPriorityFIFO[ almPriority ] ) + 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 + if ( subRank <= alarmPriorityFIFO[ almPriority ].subRank ) + { + // If sub-rank is a tie, see which alarm was triggered first + if ( subRank == alarmPriorityFIFO[ almPriority ].subRank ) + { + if ( msSinceTriggered > alarmPriorityFIFO[ almPriority ].timeSinceTriggeredMS ) + { + alarmPriorityFIFO[ almPriority ].alarmID = a; + alarmPriorityFIFO[ almPriority ].subRank = subRank; + alarmPriorityFIFO[ almPriority ].timeSinceTriggeredMS = msSinceTriggered; + } + } + // Otherwise, this alarm simply outranks current candidate and wins outright + else + { + alarmPriorityFIFO[ almPriority ].alarmID = a; + alarmPriorityFIFO[ almPriority ].subRank = subRank; + alarmPriorityFIFO[ almPriority ].timeSinceTriggeredMS = 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 ) { - alarmPriorityFIFO[ almPriority ] = a; - } - highestPriority = MAX( almPriority, highestPriority ); - if ( TRUE == alarmTable[ 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 + // Update alarm to display per highest priority FIFO alarmStatus.alarmsState = highestPriority; - alarmStatus.alarmTop = alarmPriorityFIFO[ highestPriority ]; - alarmStatus.systemFault = faultsActive; + alarmStatus.alarmTop = alarmPriorityFIFO[ highestPriority ].alarmID; + alarmStatus.topAlarmConditionDetected = alarmIsDetected[ alarmStatus.alarmTop ]; + alarmStatus.systemFault = faultsActive; + alarmStatus.noBloodRecirc = bloodRecircBlocked; + alarmStatus.noDialRecirc = dialysateRecircBlocked; } -/************************************************************************* - * @brief setAlarmLampAndAudio - * The setAlarmLampAndAudio function sets the alarm lamp and audio patterns \n - * according to the current state of alarms. - * @details - * Inputs : none - * Outputs : Alarm lamp patter set according to current alarms status. - * @param none +/*********************************************************************//** + * @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 setAlarmLampAndAudio( void ) -{ +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 ); - // TODO - no audio break; case ALARM_PRIORITY_LOW: requestAlarmLampPattern( LAMP_PATTERN_LOW_ALARM ); - // TODO - low priority audio break; case ALARM_PRIORITY_MEDIUM: requestAlarmLampPattern( LAMP_PATTERN_MED_ALARM ); - // TODO - medium priority audio break; case ALARM_PRIORITY_HIGH: - if ( TRUE == alarmTable[ alarmStatus.alarmTop ].alarmIsFault ) + if ( TRUE == ALARM_TABLE[ alarmStatus.alarmTop ].alarmIsFault ) { requestAlarmLampPattern( LAMP_PATTERN_FAULT ); } else { requestAlarmLampPattern( LAMP_PATTERN_HIGH_ALARM ); } - // TODO - high priority audio break; default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) + 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 updateAlarmsSilenceStatus +/*********************************************************************//** + * @brief + * The setAlarmAudio function sets the alarm audio pattern according to + * the current state of alarms. + * @details Inputs: none + * @details Outputs: Alarm audio patter set according to current alarms status. + * @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[MIN_ALARM_AUDIO_VOLUME_INDEX][ALARM_AUDIO_VOLUME_GAIN], + ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[MIN_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 ( 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 ) + { + setAlarmAudioState( alarmStatus.alarmsState, + ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[volume][ALARM_AUDIO_VOLUME_GAIN], + ALARM_AUDIO_DIVIDER_LOOKUP_TABLE[volume][ALARM_AUDIO_VOLUME_DIVIDER] ); + } + } + else +#endif + { + 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 : none - * Outputs : none - * @param none + * @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 handleAlarmEscalations +/*********************************************************************//** + * @brief * The handleAlarmEscalations function handles alarm escalation. - * @details - * Inputs : none - * Outputs : none - * @param none + * @details Inputs: alarmIsActive[], ALARM_TABLE[] + * @details Outputs: alarm(s) escalated when appropriate * @return none *************************************************************************/ static void handleAlarmEscalations( void ) { + U32 secsToEscalate = 0; + ALARM_ID_T nextAlarmToEscalate = ALARM_ID_NO_ALARM; + ALARM_ID_T a; + // Update escalations + for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) + { + if ( TRUE == alarmIsActive[ a ] ) + { + // Does active alarm escalate? + if ( ALARM_ID_NO_ALARM != ALARM_TABLE[ a ].alarmEscalatesTo ) + { + S32 msRemaining = (S32)ALARM_TABLE[ a ].alarmEscalatesAfter - (S32)calcTimeSince( getAlarmStartTime( a ) ); + S32 secsRemaining = ( msRemaining / MS_PER_SECOND ) + 1; + + // Time to escalate? + if ( msRemaining <= 0 ) + { + activateAlarmNoData( ALARM_TABLE[ a ].alarmEscalatesTo ); + clearAlarm( a ); + } + else + { // No candidates for alarm escalation yet? + if ( ALARM_ID_NO_ALARM == nextAlarmToEscalate ) + { + secsToEscalate = secsRemaining; + nextAlarmToEscalate = a; + } + // Sooner candidate for alarm escalation? + else if ( secsRemaining < secsToEscalate ) + { + secsToEscalate = secsRemaining; + nextAlarmToEscalate = a; + } + } + } // If alarm escalates + } // If alarm active + } // Alarm table loop + + // Update alarm escalation properties + if ( TRUE == alarmStatus.systemFault || ALARM_ID_NO_ALARM == nextAlarmToEscalate ) + { + alarmStatus.alarmsToEscalate = FALSE; + alarmStatus.alarmsEscalatesIn = 0; + } + else + { + alarmStatus.alarmsToEscalate = TRUE; + alarmStatus.alarmsEscalatesIn = secsToEscalate; + } } -/************************************************************************* - * @brief updateAlarmsFlags - * The updateAlarmsFlags function updates the alarms flags of the alarms \n +/*********************************************************************//** + * @brief + * The updateAlarmsFlags function updates the alarms flags of the alarms * status record. - * @details - * Inputs : none - * Outputs : none - * @param none + * @details Inputs: none + * @details Outputs: alarmStatus * @return none *************************************************************************/ static void updateAlarmsFlags( void ) { + BOOL systemFault = FALSE; + BOOL stop = FALSE; + BOOL noClear = FALSE; + BOOL noResume = FALSE; + BOOL noRinseback = FALSE; + BOOL noEndTreatment = FALSE; + BOOL usrAckReq = FALSE; + BOOL noMinimize = TRUE; + HD_OP_MODE_T currentMode = getCurrentOperationMode(); + ALARM_ID_T a; + // 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 ); + // Set user alarm recovery actions allowed flags + 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 and rinseback flags + if ( TRUE == alarmStatus.topAlarmConditionDetected ) + { + noResume = TRUE; + noRinseback = 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 ) && ( noResume ) && ( noRinseback ) && ( noEndTreatment ) && + ( FALSE == alarmStatus.topAlarmConditionDetected ) ) ) + { + usrAckReq = TRUE; + 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; +} + +/*********************************************************************//** + * @brief + * The clearAllRecoverableAlarms function clears all currently active + * recoverable alarms. + * @details Inputs: ALARM_TABLE[] + * @details Outputs: All currently active recoverable alarms are cleared + * @return none + *************************************************************************/ +static void clearAllRecoverableAlarms( void ) +{ + ALARM_ID_T a = alarmStatus.alarmTop; + + for ( a = ALARM_ID_HD_SOFTWARE_FAULT; a < NUM_OF_ALARM_IDS; a++ ) + { + // Is alarm recoverable? + if ( FALSE == ALARM_TABLE[ a ].alarmNoClear ) + { + clearAlarm( a ); + } + } } -/************************************************************************* - * @brief resetAlarmPriorityFIFO - * The resetAlarmPriorityFIFO function resets a FIFO for a given alarm \n +/*********************************************************************//** + * @brief + * The resetAlarmPriorityFIFO function resets a FIFO for a given alarm * priority. - * @details - * Inputs : none - * Outputs : alarmPriorityFIFO[] - * @param priority : priority of FIFO to reset + * @details Inputs: none + * @details Outputs: alarmPriorityFIFO[] + * @param priority priority of FIFO to reset * @return none *************************************************************************/ static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ) { - // verify priority + // Verify priority if ( priority < NUM_OF_ALARM_PRIORITIES ) { - alarmPriorityFIFO[ priority ] = ALARM_ID_NO_ALARM; + alarmPriorityFIFO[ priority ].alarmID = ALARM_ID_NO_ALARM; + alarmPriorityFIFO[ priority ].subRank = LOWEST_ALARM_SUB_RANK; + alarmPriorityFIFO[ priority ].timeSinceTriggeredMS = 0; } else { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, priority ) + 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 at the set + * interval. + * @details Inputs: + * @details Outputs: alarm information are published to CAN bus. + * @return none + *************************************************************************/ +static void publishAlarmInfo( void ) +{ + // 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(); + + broadcastData( MSG_ID_HD_ALARM_INFORMATION, 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 + * @details Outputs: none + * @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; + static U32 testStartTime; + + switch ( alarmAudioSelfTestState ) + { + case ALARM_AUDIO_SELF_TEST_STATE_START: + testStartTime = getMSTimerCount(); + // Start test tone + alarmAudioTestToneRequested = TRUE; + setAlarmAudio(); + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_PRIMARY; + break; + + case ALARM_AUDIO_SELF_TEST_STATE_PRIMARY: + { + F32 almHGCurrent = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_HG ); + F32 almLGCurrent = getIntADCVoltageConverted( INT_ADC_PRIMARY_ALARM_CURRENT_LG ); + + // Check if alarm audio current is sufficiently high indicating alarm tone is being output + if ( ( almHGCurrent > ALARM_AUDIO_CURRENT_HG_MIN_MA ) && + ( almLGCurrent > ALARM_AUDIO_CURRENT_LG_MIN_MA ) ) + { + alarmAudioTestToneRequested = FALSE; + result = SELF_TEST_STATUS_PASSED; + alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_COMPLETE; + } + else if ( TRUE == didTimeout( testStartTime, 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, almHGCurrent, almLGCurrent ); + 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: + // TODO - s/w fault + break; + } + + return result; +} -/************************************************************************* - * @brief getPublishAlarmStatusInterval - * The getPublishAlarmStatusInterval function gets the alarm status \n - * publication interval. - * @details - * Inputs : alarmStatusPublishInterval - * Outputs : none - * @param none - * @return the current alarm status publication interval (in ms). - *************************************************************************/ -DATA_GET( U32, getPublishAlarmStatusInterval, alarmStatusPublishInterval ) - /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ -/************************************************************************* - * @brief testSetAlarmStatusPublishIntervalOverride - * The testSetAlarmStatusPublishIntervalOverride function overrides the \n - * alarm status publish interval. - * @details - * Inputs : none - * Outputs : alarmStatusPublishInterval - * @param value : override blood flow data publish interval with (in ms) +/*********************************************************************//** + * @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 testSetAlarmStatusPublishIntervalOverride( U32 value ) +BOOL testSetAlarmStateOverride( U32 alarmID, U32 state ) { BOOL result = FALSE; - if ( TRUE == isTestingActivated() ) + if ( alarmID < NUM_OF_ALARM_IDS ) { - U32 intvl = value / TASK_GENERAL_INTERVAL; - - result = TRUE; - alarmStatusPublishInterval.ovData = intvl; - alarmStatusPublishInterval.override = OVERRIDE_KEY; + // 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 testResetAlarmStatusPublishIntervalOverride - * The testResetAlarmStatusPublishIntervalOverride function resets the override \n - * of the alarm status publish interval. - * @details - * Inputs : none - * Outputs : alarmStatusPublishInterval - * @return TRUE if override reset successful, FALSE if not +/*********************************************************************//** + * @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 testResetAlarmStatusPublishIntervalOverride( void ) +BOOL testResetAlarmStateOverride( U32 alarmID ) { BOOL result = FALSE; - if ( TRUE == isTestingActivated() ) + if ( alarmID < NUM_OF_ALARM_IDS ) { - result = TRUE; - alarmStatusPublishInterval.override = OVERRIDE_RESET; - alarmStatusPublishInterval.ovData = alarmStatusPublishInterval.ovInitData; + // Verify tester has logged in with HD + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + clearAlarm( (ALARM_ID_T)alarmID ); + } } return result; } -/************************************************************************* - * @brief testSetAlarmStateOverride and testResetAlarmStateOverride - * The testSetAlarmStateOverride function overrides the state of the \n - * alarm active state for a given alarm with the alarm management with \n - * a given active state. - * The testResetAlarmStateOverride function resets the override of the \n - * state of the active state for a given alarm with the alarm management. - * @details - * Inputs : none - * Outputs : alarmIsActive[] - * @param alarmID : ID of alarm to override active state for - * @param value : override state for the given alarm ID +/*********************************************************************//** + * @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 *************************************************************************/ -DATA_ARRAY_OVERRIDE_FUNC( BOOL, testSetAlarmStateOverride, testResetAlarmStateOverride, alarmIsActive, alarmID, NUM_OF_ALARM_IDS-1 ) - -/************************************************************************* - * @brief testSetAlarmStartOverride - * The testSetAlarmStartOverride function overrides the start time \n - * for a given alarm with the alarm management with a given start time. \n - * @details - * Inputs : none - * 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(); @@ -629,14 +1452,13 @@ return result; } -/************************************************************************* - * @brief testResetAlarmStartOverride - * The testResetAlarmStartOverride function resets the override of the \n +/*********************************************************************//** + * @brief + * The testResetAlarmStartOverride function resets the override of the * start time for a given alarm with the alarm management. - * @details - * Inputs : none - * Outputs : alarmStartedAt[] - * @param alarmID : ID of alarm to reset override of start time for + * @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 ) @@ -645,6 +1467,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { + // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { result = TRUE; @@ -654,6 +1477,328 @@ } 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; } - - + +/**@}*/