Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r34767560b0e6574c26f5b86628e12f6bdddbd760 -r766708fceb0bdf1af8c7897df29d4f5036bfd3db --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 34767560b0e6574c26f5b86628e12f6bdddbd760) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 766708fceb0bdf1af8c7897df29d4f5036bfd3db) @@ -19,7 +19,8 @@ #define __ALARM_MGMT_C__ -#include "AlarmLamp.h" +#include "AlarmLamp.h" +#include "FPGA.h" #include "OperationModes.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" @@ -31,51 +32,74 @@ */ // ********** 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 ) -#define ALARM_STATUS_PUBLISH_INTERVAL (250 / TASK_GENERAL_INTERVAL) ///< Default interval to publish alarm status data. - #define ALARM_SILENCE_EXPIRES_IN_SECS (60) ///< Alarm silence expiration time in seconds. +#define ALARM_SILENCE_REQUESTED 1 ///< User cmd to request alarm silence (1=silence, 0=cancel silence). -#define SUPERVISOR_ALARM_KEY 0xD2C3B4A5 ///< 32-bit key required for clear all alarms request. +#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. -// *** This declaration will cause a compiler error if alarmTable does not have same # of alarms as the Alarm_List enumeration. +// *** 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 ) ]; /// 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 assignment for backup alarm audio enable -#define BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK 0x00000001 ///< pin SPI3-CS0 - re-purposed as output GPIO for back audio enable. -// backup alarm audio enable/disable macros +// Pin assignment for backup alarm audio enable +#define BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK 0x00000001 ///< Pin SPI3-CS0 - re-purposed as output GPIO for back audio enable. +// 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 CLR_BACKUP_AUDIO_ENABLE() {mibspiREG3->PC3 &= ~BACKUP_AUDIO_ENABLE_SPI3_PORT_MASK;} ///< Macro to disable backup alarm audio. + +/// 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; // ********** private data ********** -/// interval (in ms) 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 }; - static U32 alarmStatusPublicationTimerCounter = 0; ///< Used to schedule alarm status publication to CAN bus. -static BOOL alarmIsActive[ NUM_OF_ALARM_IDS ]; ///< table - current state of each alarm -static OVERRIDE_U32_T alarmStartedAt[ NUM_OF_ALARM_IDS ]; ///< table - when alarm became active for each alarm (if active) or zero (if inactive) -static COMP_ALARM_STATUS_T alarmStatus; ///< Record for the current composite alarm status. -static ALARM_ID_T alarmPriorityFIFO[ NUM_OF_ALARM_PRIORITIES ]; ///< FIFO - first activated alarm in each alarm priority category. +/// Table - current state of each alarm +static BOOL alarmIsActive[ NUM_OF_ALARM_IDS ]; +/// Table - current state of each alarm condition (detected or cleared) +static BOOL alarmIsDetected[ NUM_OF_ALARM_IDS ]; +/// Table - when alarm became active for each alarm (if active) or zero (if inactive) +static OVERRIDE_U32_T alarmStartedAt[ NUM_OF_ALARM_IDS ]; + +/// Record for the current composite alarm status. +static COMP_ALARM_STATUS_T alarmStatus; + +/// FIFO - first activated or highest sub-rank alarm in each alarm priority category. +static ALARM_PRIORITY_RANKS_T alarmPriorityFIFO[ NUM_OF_ALARM_PRIORITIES ]; + +/// Alarm user recovery actions enabled flags. +static BOOL alarmUserRecoveryActionEnabled[ NUMBER_OF_ALARM_USER_ACTIONS ]; + +static U32 alarmAudioVolumeLevel = 3; //MIN_ALARM_VOLUME_ATTENUATION; ///< Set alarm audio volume attenuation level (0..4 - lower level = higher gain). // ********** private function prototypes ********** static void activateAlarm( ALARM_ID_T alarm ); 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 U32 getAlarmStartTime( U32 alarmID ); -static U32 getPublishAlarmStatusInterval( void ); +static U32 getAlarmStartTime( ALARM_ID_T alarmID ); /*********************************************************************//** * @brief @@ -89,45 +113,51 @@ ALARM_PRIORITY_T p; ALARM_ID_T a; - // disable backup audio + // Disable backup audio CLR_BACKUP_AUDIO_ENABLE(); - // initialize alarm states and start time stamps + // Initialize alarm states and start time stamps for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { - alarmIsActive[ a ] = FALSE; + 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.topAlarmConditionnDetected = 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.usrACKRequired = FALSE; } /*********************************************************************//** * @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: alarmStatusTable[], alarmTable[] + * @details Inputs: alarmStatusTable[], ALARM_TABLE[] * @details Outputs: alarmStatus * @return none *************************************************************************/ @@ -137,10 +167,12 @@ updateAlarmsState(); updateAlarmsFlags(); updateAlarmsSilenceStatus(); - setAlarmLampAndAudio(); - // publish alarm status at interval - if ( ++alarmStatusPublicationTimerCounter >= getPublishAlarmStatusInterval() ) - { + // Publish alarm status at interval + if ( ++alarmStatusPublicationTimerCounter >= ALARM_STATUS_PUBLISH_INTERVAL ) + { + // Lamp and audio timing sync'd with broadcast so UI can stay in sync with lamp rhythm + setAlarmLamp(); + setAlarmAudio(); broadcastAlarmStatus( alarmStatus ); alarmStatusPublicationTimerCounter = 0; } @@ -156,24 +188,33 @@ *************************************************************************/ 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 + // No need to do anything if alarm is already active if ( FALSE == alarmIsActive[ alarm ] ) { - // if alarms silenced, end silence due to new alarm + // If alarms silenced, end silence due to new alarm alarmStatus.alarmsSilenced = FALSE; - // if alarm is a fault, request transition to fault mode + // If alarm is a fault, request transition to fault mode if ( TRUE == ALARM_TABLE[ alarm ].alarmIsFault ) { -#ifndef RM46_EVAL_BOARD_TARGET requestNewOperationMode( MODE_FAUL ); -#endif } - // activate alarm - alarmIsActive[ alarm ] = TRUE; - alarmStartedAt[ alarm ].data = getMSTimerCount(); + // 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 @@ -194,7 +235,7 @@ *************************************************************************/ void activateAlarmNoData( ALARM_ID_T alarm ) { - // broadcast alarm and data if alarm not already active + // Broadcast alarm and data if alarm not already active if ( FALSE == alarmIsActive[ alarm ] ) { broadcastAlarmTriggered( (U16)alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA ); @@ -227,7 +268,7 @@ *************************************************************************/ void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ) { - // broadcast alarm and data if alarm not already active + // Broadcast alarm and data if alarm not already active if ( FALSE == alarmIsActive[ alarm ] ) { broadcastAlarmTriggered( (U16)alarm, alarmData, BLANK_ALARM_DATA ); @@ -261,7 +302,7 @@ *************************************************************************/ void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2 ) { - // broadcast alarm and data if alarm not already active + // Broadcast alarm and data if alarm not already active if ( FALSE == alarmIsActive[ alarm ] ) { broadcastAlarmTriggered( (U16)alarm, alarmData1, alarmData2 ); @@ -279,33 +320,59 @@ } #endif #endif -} - +} + +/*********************************************************************//** + * @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 ] ) + { + alarmIsDetected[ alarm ] = FALSE; + broadcastAlarmConditionCleared( alarm ); + } + } +} + /*********************************************************************//** * @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[] + * @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 + // Verify alarm can be cleared if ( FALSE == ALARM_TABLE[ alarm ].alarmNoClear ) { - // clear alarm and broadcast alarm clear if not already cleared + // Clear alarm and broadcast alarm clear if not already cleared if ( TRUE == alarmIsActive[ alarm ] ) { broadcastAlarmCleared( alarm ); - alarmIsActive[ alarm ] = FALSE; + alarmIsActive[ alarm ] = FALSE; + alarmIsDetected[ alarm ] = FALSE; + alarmStartedAt[ alarm ].data = 0; - // clear FIFO if this alarm was in it - if ( alarmPriorityFIFO[ ALARM_TABLE[ alarm ].alarmPriority ] == alarm ) + // Clear FIFO if this alarm was in it + if ( alarmPriorityFIFO[ ALARM_TABLE[ alarm ].alarmPriority ].alarmID == alarm ) { resetAlarmPriorityFIFO( ALARM_TABLE[ alarm ].alarmPriority ); } @@ -329,6 +396,120 @@ } } +/*********************************************************************//** + * @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( U32 cmd ) +{ + if ( ALARM_SILENCE_REQUESTED == 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 top alarm, just clear that alarm + if ( TRUE == ALARM_TABLE[ a ].alarmUserAckRequired ) + { + 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: + // TODO - s/w fault? + break; + } +} + /*********************************************************************//** * @brief * The isAlarmActive function determines whether a given alarm is currently @@ -362,7 +543,7 @@ * @brief * The isAlarmRecoverable function determines whether a given alarm is * recoverable. -* @details Inputs: alarmTable[] +* @details Inputs: ALARM_TABLE[] * @details Outputs: none * @param alarm ID of alarm to check * @return TRUE if given alarm is recoverable, FALSE if not @@ -373,6 +554,22 @@ 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 ) +{ + if ( ( volumeLevel > 0 ) && ( volumeLevel <= MAX_ALARM_VOLUME_LEVEL ) ) + { // Convert volume level to attenuation level + alarmAudioVolumeLevel = MAX_ALARM_VOLUME_LEVEL - volumeLevel; + } +} /*********************************************************************//** * @brief @@ -382,7 +579,7 @@ * @param alarmID ID of alarm to check * @return The start time stamp of given alarm ID *************************************************************************/ -static U32 getAlarmStartTime( U32 alarmID ) +static U32 getAlarmStartTime( ALARM_ID_T alarmID ) { U32 result = 0; @@ -419,40 +616,63 @@ ALARM_ID_T a; BOOL faultsActive = FALSE; - // update FIFOs per active alarms 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 == alarmIsActive[a] ) { - ALARM_PRIORITY_T almPriority = ALARM_TABLE[ a ].alarmPriority; - if ( ALARM_ID_NO_ALARM == alarmPriorityFIFO[ almPriority ] ) - { - alarmPriorityFIFO[ almPriority ] = a; - } - highestPriority = MAX( almPriority, highestPriority ); + 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 ) { faultsActive = 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.alarmTop = alarmPriorityFIFO[ highestPriority ].alarmID; alarmStatus.systemFault = faultsActive; } /*********************************************************************//** * @brief - * The setAlarmLampAndAudio function sets the alarm lamp and audio patterns - * according to the current state of alarms. + * 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 ) @@ -485,45 +705,52 @@ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) break; } - alarmStatus.lampOn = getAlarmLampOn(); } + + // 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; } - - if ( TRUE == alarmStatus.alarmsSilenced ) - { - // TODO - no audio - } - else // alarms not silenced - { - switch ( alarmStatus.alarmsState ) - { - case ALARM_PRIORITY_NONE: - // TODO - no audio - break; - - case ALARM_PRIORITY_LOW: - // TODO - low priority audio - break; - - case ALARM_PRIORITY_MEDIUM: - // TODO - medium priority audio - break; - - case ALARM_PRIORITY_HIGH: - // TODO - high priority audio - break; - - default: - // TODO - high priority audio - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_LAMP_INVALID_ALARM_STATE, alarmStatus.alarmsState ) - break; - } - } } +/*********************************************************************//** + * @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 ) +{ + if ( TRUE == alarmStatus.alarmsSilenced ) + { + setAlarmAudioState( ALARM_PRIORITY_NONE, alarmAudioVolumeLevel ); + } + else // Alarms not silenced + { + if ( alarmStatus.alarmsState < NUM_OF_ALARM_PRIORITIES ) + { +#ifndef DISABLE_ALARM_AUDIO + setAlarmAudioState( alarmStatus.alarmsState, alarmAudioVolumeLevel ); +#endif + } + 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, alarmAudioVolumeLevel ); + } + } +} + /*********************************************************************//** * @brief * The updateAlarmsSilenceStatus function updates the alarms silence state. @@ -533,7 +760,7 @@ *************************************************************************/ static void updateAlarmsSilenceStatus( void ) { - // if alarms not silenced, reset alarms silence related properties + // If alarms not silenced, reset alarms silence related properties if ( TRUE != alarmStatus.alarmsSilenced ) { alarmStatus.alarmsSilenceExpiresIn = 0; @@ -551,7 +778,7 @@ { alarmStatus.alarmsSilenceExpiresIn = ALARM_SILENCE_EXPIRES_IN_SECS - timeSinceAlarmSilenceStart; } - // if alarms silence expires, end it + // If alarms silence expires, end it if ( 0 == alarmStatus.alarmsSilenceExpiresIn ) { alarmStatus.alarmsSilenced = FALSE; @@ -562,7 +789,7 @@ /*********************************************************************//** * @brief * The handleAlarmEscalations function handles alarm escalation. - * @details Inputs: alarmIsActive[], alarmTable[] + * @details Inputs: alarmIsActive[], ALARM_TABLE[] * @details Outputs: alarm(s) escalated when appropriate * @return none *************************************************************************/ @@ -572,42 +799,42 @@ ALARM_ID_T nextAlarmToEscalate = ALARM_ID_NO_ALARM; ALARM_ID_T a; - // update escalations + // Update escalations for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { if ( TRUE == alarmIsActive[ a ] ) { - // does active alarm escalate? + // 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? + // Time to escalate? if ( msRemaining <= 0 ) { activateAlarmNoData( ALARM_TABLE[ a ].alarmEscalatesTo ); clearAlarm( a ); } else - { // no candidates for alarm escalation yet? + { // No candidates for alarm escalation yet? if ( ALARM_ID_NO_ALARM == nextAlarmToEscalate ) { secsToEscalate = secsRemaining; nextAlarmToEscalate = a; } - // sooner candidate for alarm escalation? + // Sooner candidate for alarm escalation? else if ( secsRemaining < secsToEscalate ) { secsToEscalate = secsRemaining; nextAlarmToEscalate = a; } } - } // if alarm escalates - } // if alarm active - } // alarm table loop + } // If alarm escalates + } // If alarm active + } // Alarm table loop - // update alarm escalation properties + // Update alarm escalation properties if ( TRUE == alarmStatus.systemFault || ALARM_ID_NO_ALARM == nextAlarmToEscalate ) { alarmStatus.alarmsToEscalate = FALSE; @@ -637,32 +864,95 @@ BOOL noRinseback = FALSE; BOOL noEndTreatment = FALSE; BOOL noNewTreatment = FALSE; - ALARM_ID_T a; + BOOL usrAckReq = FALSE; + ALARM_ID_T a; - // determine alarm flags + // 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 ); - noResume = ( TRUE == ALARM_TABLE[ a ].alarmNoResume ? TRUE : noResume ); - noRinseback = ( TRUE == ALARM_TABLE[ a ].alarmNoRinseback ? TRUE : noRinseback ); - noEndTreatment = ( TRUE == ALARM_TABLE[ a ].alarmNoEndTreatment ? TRUE : noEndTreatment ); - noNewTreatment = ( TRUE == ALARM_TABLE[ a ].alarmNoNewTreatment ? TRUE : noNewTreatment ); - - } // if alarm active - } // alarm table loop - - // set updated alarm flags + noClear = ( TRUE == ALARM_TABLE[ a ].alarmNoClear ? TRUE : noClear ); + noNewTreatment = ( TRUE == ALARM_TABLE[ a ].alarmNoNewTreatment ? TRUE : noNewTreatment ); + // 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.topAlarmConditionnDetected ) + { + noResume = TRUE; + noRinseback = TRUE; + } + + // If top alarm requires user ack 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 ].alarmUserAckRequired ) || + ( ( FALSE == alarmStatus.noClear ) && ( noResume ) && ( noRinseback ) && ( noEndTreatment ) && + ( FALSE == alarmStatus.topAlarmConditionnDetected ) ) ) + { + usrAckReq = TRUE; + noResume = TRUE; + noRinseback = TRUE; + noEndTreatment = TRUE; + } + + // Set updated alarm flags alarmStatus.systemFault = systemFault; alarmStatus.stop = stop; alarmStatus.noClear = noClear; alarmStatus.noResume = noResume; alarmStatus.noRinseback = noRinseback; alarmStatus.noEndTreatment = noEndTreatment; alarmStatus.noNewTreatment = noNewTreatment; + alarmStatus.usrACKRequired = usrAckReq; +} + +/*********************************************************************//** + * @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 ); + } + } } /*********************************************************************//** @@ -676,94 +966,27 @@ *************************************************************************/ 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_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_FIFO_TO_RESET, priority ) } } -/*********************************************************************//** - * @brief - * The getPublishAlarmStatusInterval function gets the alarm status - * publication interval. - * @details Inputs: alarmStatusPublishInterval - * @details Outputs: none - * @return the current alarm status publication interval (in ms). - *************************************************************************/ -U32 getPublishAlarmStatusInterval( void ) -{ - U32 result = alarmStatusPublishInterval.data; - - if ( OVERRIDE_KEY == alarmStatusPublishInterval.override ) - { - result = alarmStatusPublishInterval.ovData; - } - - return result; -} - /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief - * The testSetAlarmStatusPublishIntervalOverride function overrides the - * alarm status publish interval. - * @details Inputs: none - * @details Outputs: alarmStatusPublishInterval - * @param value override blood flow data publish interval with (in ms) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetAlarmStatusPublishIntervalOverride( U32 value ) -{ - BOOL result = FALSE; - - // verify tester has logged in with HD - if ( TRUE == isTestingActivated() ) - { - U32 intvl = value / 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 publish interval. - * @details Inputs: none - * @details Outputs: alarmStatusPublishInterval - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetAlarmStatusPublishIntervalOverride( void ) -{ - BOOL result = FALSE; - - // verify tester has logged in with HD - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - alarmStatusPublishInterval.override = OVERRIDE_RESET; - alarmStatusPublishInterval.ovData = alarmStatusPublishInterval.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @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. @@ -779,7 +1002,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { - // verify tester has logged in with HD + // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { if ( TRUE == state ) @@ -812,7 +1035,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { - // verify tester has logged in with HD + // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { result = TRUE; @@ -839,7 +1062,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { - // verify tester has logged in with HD + // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { U32 tim = getMSTimerCount(); @@ -871,7 +1094,7 @@ if ( alarmID < NUM_OF_ALARM_IDS ) { - // verify tester has logged in with HD + // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { result = TRUE; @@ -897,24 +1120,24 @@ { BOOL result = FALSE; - // verify key + // Verify key if ( SUPERVISOR_ALARM_KEY == key ) { - // verify tester has logged in with HD + // Verify tester has logged in with HD if ( TRUE == isTestingActivated() ) { ALARM_ID_T a; - // clear all active alarms + // Clear all active alarms for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) { if ( TRUE == alarmIsActive[ a ] ) { broadcastAlarmCleared( a ); alarmIsActive[ a ] = FALSE; alarmStartedAt[ a ].data = 0; - // clear FIFO if this alarm was in it - if ( alarmPriorityFIFO[ ALARM_TABLE[ a ].alarmPriority ] == a ) + // Clear FIFO if this alarm was in it + if ( alarmPriorityFIFO[ ALARM_TABLE[ a ].alarmPriority ].alarmID == a ) { resetAlarmPriorityFIFO( ALARM_TABLE[ a ].alarmPriority ); }