Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -re6294e11f102440f7d825b697a31622ad0cdc370 -r9d21272d8c5c0b5f1d72bd5f0e9ef4e4ee41e764 --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision e6294e11f102440f7d825b697a31622ad0cdc370) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 9d21272d8c5c0b5f1d72bd5f0e9ef4e4ee41e764) @@ -1,14 +1,14 @@ /************************************************************************** * -* Copyright (c) 2019-2023 Diality Inc. - All Rights Reserved. +* Copyright (c) 2019-2025 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) Sean Nash -* @date (last) 18-May-2023 +* @author (last) Dara Navaei +* @date (last) 02-Apr-2025 * * @author (original) Sean Nash * @date (original) 07-Nov-2019 @@ -49,7 +49,9 @@ #define SUPERVISOR_ALARM_KEY 0xD2C3B4A5 ///< 32-bit key required for clear all alarms request. #define LOWEST_ALARM_SUB_RANK 999 ///< Lowest alarm sub-rank that can be set. -#define ALARM_NOT_BLOCKED 0 ///< Alarm blocked timer value that indicates no alarm block +#define ALARM_NOT_BLOCKED 0 ///< Alarm blocked timer value that indicates no alarm block + +#define MIN_TIME_BETWEEN_ALARM_ACTIONS_MS MS_PER_SECOND ///< Minimum time between user alarm actions (in ms). // *** 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 ) ]; @@ -82,7 +84,7 @@ } ALARM_PRIORITY_RANKS_T; /// Enumeration of alarm audio self-test states. -typedef enum Alarm_Lamp_Self_Test_States +typedef enum Alarm_Audio_Self_Test_States { ALARM_AUDIO_SELF_TEST_STATE_START = 0, ///< Start state of alarm audio self-test. ALARM_AUDIO_SELF_TEST_STATE_PRIMARY, ///< Test tone state of alarm audio self-test. @@ -117,19 +119,22 @@ static U32 alarmInfoPublicationTimerCounter = 0; ///< Used to schedule alarm information publication to CAN bus. static U32 audioTestStartTime; ///< Start time of audio alarm current self-test. static U32 alarmsBlockedTimer = 0; ///< Countdown timer used to temporarily block new alarms from being initiated +static U32 lastUserAlarmActionReceivedTime = 0; ///< Time of last alarm action by user received from the UI (ms timestamp). /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T alarmStatusPublishInterval = { ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL, ALARM_STATUS_PUBLISH_INTERVAL, 0 }; + /// Interval (in task intervals) at which to publish alarm information to CAN bus. static OVERRIDE_U32_T alarmInfoPublishInterval = { ALARM_INFO_PUB_INTERVAL, ALARM_INFO_PUB_INTERVAL, ALARM_INFO_PUB_INTERVAL, 0 }; + /// Alarm audio attenuation level (0..4 where 0 = max volume and 4 = min volume). static OVERRIDE_U32_T alarmAudioVolumeLevel = { MAX_ALARM_VOLUME_ATTENUATION, MAX_ALARM_VOLUME_ATTENUATION, MAX_ALARM_VOLUME_ATTENUATION, 0 }; -static OVERRIDE_F32_T alarmPrimaryAudioCurrentHG = { 0.0, 0.0, 0.0, 0 }; /// Alarm audio current (high gain) measured at ADC. +static OVERRIDE_F32_T 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 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 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. @@ -142,6 +147,7 @@ static BOOL alarmAudioTestToneRequested; ///< Flag indicates whether alarm audio test tone should be output. static BOOL resumeBlockedByAlarmProperty; ///< Flag indicates whether treatment resumption is currently blocked by alarm property. +static BOOL alarmNoRetrigger; ///< Flag indicates whether some alarms should be prevented from re-triggering after being cleared by rinseback or end-tx options // ********** private function prototypes ********** @@ -154,7 +160,7 @@ static void updateAlarmsSilenceStatus( void ); static void updateAlarmsFlags( void ); -static void clearAllRecoverableAlarms( void ); +static BOOL clearAllRecoverableAlarms( ALARM_USER_ACTION_T action ); static void resetAlarmPriorityFIFO( ALARM_PRIORITY_T priority ); static U32 getAlarmStartTime( ALARM_ID_T alarmID ); @@ -220,8 +226,10 @@ alarmStatus.ok = FALSE; alarmsBlockedTimer = 0; + lastUserAlarmActionReceivedTime = 0; alarmAudioTestToneRequested = FALSE; resumeBlockedByAlarmProperty = FALSE; + alarmNoRetrigger = FALSE; alarmAudioSelfTestState = ALARM_AUDIO_SELF_TEST_STATE_START; } @@ -356,7 +364,7 @@ *************************************************************************/ void activateAlarmNoData( ALARM_ID_T alarm ) { - activateAlarm2Data( alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA ); + activateAlarm2Data( alarm, BLANK_ALARM_DATA, BLANK_ALARM_DATA, FALSE ); } /*********************************************************************//** @@ -372,7 +380,7 @@ *************************************************************************/ void activateAlarm1Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData ) { - activateAlarm2Data( alarm, alarmData, BLANK_ALARM_DATA ); + activateAlarm2Data( alarm, alarmData, BLANK_ALARM_DATA, FALSE ); } /*********************************************************************//** @@ -384,41 +392,65 @@ * @details Outputs: alarm triggered message sent, alarm activated * @param alarm ID of alarm to activate * @param alarmData1 supporting data to include in alarm msg - * @param alarmData2 supporting data to include in alarm msg + * @param alarmData2 supporting data to include in alarm msg + * @param outside flag indicates whether alarm is originating from outside HD f/w * @return none *************************************************************************/ -void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2 ) -{ +void activateAlarm2Data( ALARM_ID_T alarm, ALARM_DATA_T alarmData1, ALARM_DATA_T alarmData2, BOOL outside ) +{ + // Block if new alarms are occur during loss of AC power + if ( ( TRUE == getCPLDACPowerLossDetected() ) ) + { + alarmsBlockedTimer = ALARM_BLOCKED_COUNT_AFTER_AC_RETURN; + } // Sanity check, verify valid alarm index if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { // if the block timer is 0 OR we have an unblockable alarm if ( ( ALARM_NOT_BLOCKED == alarmsBlockedTimer ) || ( ALARM_ID_HD_AC_POWER_LOST == alarm ) - || ( ALARM_ID_HD_AC_POWER_LOST_IN_TREATMENT == alarm ) ) - { - // Broadcast alarm and data if alarm not already active - if ( FALSE == alarmIsActive[ alarm ] ) + || ( ALARM_ID_HD_AC_POWER_LOST_IN_TREATMENT == alarm ) + || ( ALARM_ID_HD_DG_RESTARTED_FAULT == alarm ) ) + { // do not re-trigger alarm if blocked by property + if ( ( FALSE == alarmNoRetrigger ) || + ( ( ALARM_TABLE[ alarm ].alarmNoRetrigOnRB != TRUE ) && ( ALARM_TABLE[ alarm ].alarmNoRetrigOnEndTx != TRUE ) ) ) { - ALARM_TRIGGERED_PAYLOAD_T data; + HD_OP_MODE_T opMode = getCurrentOperationMode(); + TREATMENT_STATE_T ts = getTreatmentState(); - 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() ) ) + // do not trigger alarm if blocked by current mode/state + if ( ( ( ALARM_TABLE[ alarm ].alarmBlockRinseback != TRUE ) || ( opMode != MODE_TREA ) || ( ts != TREATMENT_RINSEBACK_STATE ) || ( TRUE == outside ) ) && + ( ( ALARM_TABLE[ alarm ].alarmBlockEndTx != TRUE ) || ( opMode != MODE_POST ) || ( TRUE == outside )) ) { - sendTreatmentLogAlarmEventData( alarm, alarmData1, alarmData2 ); - } - } - activateAlarm( alarm ); + // 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() ) ) + { + F32 data1; + F32 data2; + + memcpy( &data1, &alarmData1.data, sizeof( F32 ) ); + memcpy( &data2, &alarmData2.data, sizeof( F32 ) ); + sendTreatmentLogAlarmEventData( alarm, data1, data2 ); + } + } + activateAlarm( alarm ); + } + } } } else @@ -490,6 +522,30 @@ { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, alarm ) } +} + +/*********************************************************************//** + * @brief + * The clearNoRetriggerFlag function clears the no re-trigger flag. + * @details Inputs: none + * @details Outputs: alarmNoRetrigger + * @return none + *************************************************************************/ +void clearNoRetriggerFlag( void ) +{ + alarmNoRetrigger = FALSE; +} + +/*********************************************************************//** + * @brief + * The clearNoRetriggerFlag function returns the no re-trigger flag. + * @details Inputs: alarmNoRetrigger + * @details Outputs: none + * @return alarmNoRetrigger + *************************************************************************/ +BOOL getNoRetriggerFlag( void ) +{ + return alarmNoRetrigger; } /*********************************************************************//** @@ -549,62 +605,126 @@ /*********************************************************************//** * @brief * The signalAlarmUserActionInitiated function clears all non-recoverable alarms - * and initiates selected user action. - * @details Inputs: none - * @details Outputs: + * and initiates selected user action. User actions are debounced (must come + * at least 1 second after last). And user actions must be appropriate for current + * alarm state. + * @details Inputs: ALARM_TABLE[], alarmStatus, lastUserAlarmActionReceivedTime + * @details Outputs: alarmIsActive[], lastUserAlarmActionReceivedTime * @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 ) && ( action != ALARM_USER_ACTION_END_TREATMENT ) ) // end tx action must be confirmed first - { - ALARM_ID_T a = alarmStatus.alarmTop; + BOOL alarmActionIsValid = FALSE; - 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 + // Validate user selected action is appropriate per current alarm system status switch ( action ) { case ALARM_USER_ACTION_RESUME: - initiateAlarmAction( ALARM_ACTION_RESUME ); + if ( alarmStatus.noResume != TRUE ) + { + alarmActionIsValid = TRUE; + } break; case ALARM_USER_ACTION_RINSEBACK: - initiateAlarmAction( ALARM_ACTION_RINSEBACK ); + if ( alarmStatus.noRinseback != TRUE ) + { + alarmActionIsValid = TRUE; + } break; case ALARM_USER_ACTION_END_TREATMENT: - // Send message to UI to get user confirmation to end treatment - action initiated only upon receipt of user confirmation from UI - addConfirmationRequest( GENERIC_CONFIRM_ID_TREATMENT_END, GENERIC_CONFIRM_CMD_REQUEST_OPEN, 0 ); + if ( alarmStatus.noEndTreatment != TRUE ) + { + alarmActionIsValid = TRUE; + } break; case ALARM_USER_ACTION_ACK: - initiateAlarmAction( ALARM_ACTION_ACK ); + if ( TRUE == alarmStatus.ok ) + { + alarmActionIsValid = TRUE; + } break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_USER_ACTION, action ); break; } + + // Ignore alarm action if invalid or too soon after last one (essentially a debounce in case user double tapped a button) + if ( ( TRUE == alarmActionIsValid ) && ( calcTimeSince( lastUserAlarmActionReceivedTime ) >= MIN_TIME_BETWEEN_ALARM_ACTIONS_MS ) ) + { + GENERIC_CONFIRMATION_REQUEST_T genericConfRequest; + BOOL allRecAlarmsCleared = TRUE; + + // Clear recoverable alarms on user action + if ( action != ALARM_USER_ACTION_END_TREATMENT ) // end tx action must be confirmed first + { + ALARM_ID_T a = alarmStatus.alarmTop; + + if ( ALARM_USER_ACTION_ACK == action ) + { + // If user acknowledged alarm w/ clear only property, just clear that alarm + if ( TRUE == ALARM_TABLE[ a ].alarmClearOnly ) + { + clearAlarm( a ); + } + // Otherwise we must be in mode/state where ack was only option - so clear all like other options + else + { + allRecAlarmsCleared = clearAllRecoverableAlarms( action ); + } + } + else + { + allRecAlarmsCleared = clearAllRecoverableAlarms( action ); + } + } + + // Initiate user selected action + switch ( action ) + { + case ALARM_USER_ACTION_RESUME: + if ( TRUE == allRecAlarmsCleared ) + { // only resume if we've cleared all recoverable alarms + initiateAlarmAction( ALARM_ACTION_RESUME ); + } + break; + + case ALARM_USER_ACTION_RINSEBACK: + initiateAlarmAction( ALARM_ACTION_RINSEBACK ); + break; + + case ALARM_USER_ACTION_END_TREATMENT: + genericConfRequest.requestID = (U32)GENERIC_CONFIRM_ID_TREATMENT_END; + genericConfRequest.requestType = (U32)GENERIC_CONFIRM_CMD_REQUEST_OPEN; + genericConfRequest.rejectReason = 0; + genericConfRequest.genericPayload1 = 0.0F; + genericConfRequest.genericPayload2 = 0.0F; + genericConfRequest.genericPayload3 = 0.0F; + genericConfRequest.genericPayload4 = 0.0F; + + // Send message to UI to get user confirmation to end treatment - action initiated only upon receipt of user confirmation from UI + addConfirmationRequest( &genericConfRequest ); + break; + + case ALARM_USER_ACTION_ACK: + initiateAlarmAction( ALARM_ACTION_ACK ); + break; + +// This default cannot be reached in VectorCAST due to check above for alarmActionIsValid +#ifndef _VECTORCAST_ + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_ALARM_USER_ACTION, action ); + break; +#endif + } + } + + // Remember last time user selected an alarm action + lastUserAlarmActionReceivedTime = getMSTimerCount(); } /*********************************************************************//** @@ -703,6 +823,39 @@ /*********************************************************************//** * @brief + * The isRinseBackBlocked function determines whether any currently + * active alarm is blocking rinseback. + * @details Inputs: alarmStatus + * @details Outputs: none + * @return TRUE if any active alarm prevents rinseback, FALSE if not + *************************************************************************/ +BOOL isRinseBackBlocked( void ) +{ + return alarmStatus.noRinseback; +} + +/*********************************************************************//** + * @brief + * The doesAlarmStatusIndicateEndTxOnly function determines whether any currently + * active alarm has ( stop && noRes && /noET ) property, that is end treatment is + * the only choice from full stop. + * @details Inputs: alarmStatus + * @details Outputs: none + * @return TRUE if any active alarm has stop property, FALSE if not + *************************************************************************/ +BOOL doesAlarmStatusIndicateEndTxOnly( void ) +{ + return ( ( ( TRUE == alarmStatus.noResume ) && + ( TRUE == alarmStatus.noRinseback ) && + ( TRUE == alarmStatus.stop ) && + ( TRUE == alarmStatus.noBloodRecirc ) && + ( FALSE == alarmStatus.noEndTreatment ) + ) ? TRUE : FALSE + ); +} + +/*********************************************************************//** + * @brief * The doesAlarmStatusIndicateStop function determines whether any currently * active alarm has stop property. * @details Inputs: alarmStatus @@ -771,7 +924,6 @@ 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; @@ -906,9 +1058,11 @@ alarmBackupAudioCurrent.data = getFPGABackupAlarmAudioCurrent(); // Check for user confirmation of end treatment alarm response - if ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == getConfirmationRequestStatus( GENERIC_CONFIRM_ID_TREATMENT_END ) ) + if ( CONFIRMATION_REQUEST_STATUS_ACCEPTED == getConfirmationRequestStatus( GENERIC_CONFIRM_ID_TREATMENT_END, 0.0F, 0.0F, 0.0F, 0.0F ) ) { - clearAllRecoverableAlarms(); + // To avoid raising repeated alarm before reaching end treatment + setVenousBubbleDetectionEnabled( FALSE ); + clearAllRecoverableAlarms( ALARM_USER_ACTION_END_TREATMENT ); initiateAlarmAction( ALARM_ACTION_END_TREATMENT ); } @@ -1160,9 +1314,10 @@ BOOL stop = FALSE; BOOL noClear = FALSE; BOOL noResume = FALSE; - BOOL noResumePerAlarmPropertyOnly = FALSE; + BOOL noResumePerAlarmPropertyOnly = alarmNoRetrigger; // cannot resume if no re-trigger flag is set BOOL noRinseback = FALSE; - BOOL noEndTreatment = FALSE; + BOOL noEndTreatment = FALSE; + BOOL endTxOnlyAlarmActive = FALSE; BOOL usrAckReq = FALSE; BOOL noMinimize = TRUE; HD_OP_MODE_T currentMode = getCurrentOperationMode(); @@ -1213,6 +1368,13 @@ else { noEndTreatment = TRUE; + } + // if there are any active alarms that only allow end treatment, set flag so we can ensure we do not allow OK option. + if ( ( TRUE == ALARM_TABLE[ a ].alarmNoResume ) && + ( TRUE == ALARM_TABLE[ a ].alarmNoRinseback ) && + ( FALSE == ALARM_TABLE[ a ].alarmNoEndTreatment ) ) + { + endTxOnlyAlarmActive = TRUE; } } // If alarm active } // Alarm table loop @@ -1234,6 +1396,13 @@ noEndTreatment = TRUE; } + // if OK option enabled and there are any active alarms that only allow end treatment, block OK option and allow end treatment option (DEN-16594). + if ( ( TRUE == usrAckReq ) && ( TRUE == endTxOnlyAlarmActive ) ) + { + usrAckReq = FALSE; + noEndTreatment = FALSE; + } + // If AC power is out, block all user options if ( TRUE == getCPLDACPowerLossDetected() ) { @@ -1243,9 +1412,8 @@ 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() ) ) ) + // If in Treatment/Fault/Service/Standby Mode, allow user to minimize the alarm window + if ( ( MODE_FAUL == currentMode ) || ( MODE_SERV == currentMode ) || ( MODE_STAN == currentMode ) || ( MODE_TREA == currentMode ) ) { noMinimize = FALSE; } @@ -1259,6 +1427,7 @@ alarmStatus.noEndTreatment = noEndTreatment; alarmStatus.ok = usrAckReq; alarmStatus.noMinimize = noMinimize; + alarmStatus.noReTrigger = alarmNoRetrigger; resumeBlockedByAlarmProperty = noResumePerAlarmPropertyOnly; } @@ -1267,23 +1436,70 @@ * The clearAllRecoverableAlarms function clears all currently active * recoverable alarms. * @details Inputs: ALARM_TABLE[] - * @details Outputs: All currently active recoverable alarms are cleared - * @return none + * @details Outputs: alarmNoRetrigger, alarmIsActive[] + * @param action user action that prompted clearing of recoverable alarms + * @return TRUE if all recoverable alarms cleared, FALSE if any left active *************************************************************************/ -static void clearAllRecoverableAlarms( void ) +static BOOL clearAllRecoverableAlarms( ALARM_USER_ACTION_T action ) { + BOOL result = TRUE; ALARM_ID_T a; // assigning to 1 in order to prevent ALARM_ID_NO_ALARM being cleared // which will cause a fault - for ( a = ( ( ALARM_ID_T ) 1 ) ; a < NUM_OF_ALARM_IDS; a++ ) + for ( a = ( ( ALARM_ID_T ) 1 ); a < NUM_OF_ALARM_IDS; a++ ) { // Clear alarm if alarm allowed to be cleared and not clear only (those are cleared individually) if ( ( FALSE == ALARM_TABLE[ a ].alarmNoClear ) && ( FALSE == ALARM_TABLE[ a ].alarmClearOnly ) ) { - clearAlarm( a ); + // Clear alarm if active and condition not active + if ( ( TRUE == alarmIsActive[ a ] ) && + ( ( TRUE == ALARM_TABLE[ a ].alarmConditionClearImmed ) || ( alarmIsDetected[ a ] != TRUE ) || ( action != ALARM_USER_ACTION_RESUME ) ) ) + { + HD_OP_MODE_T mode = getCurrentOperationMode(); + U32 sub = getCurrentSubMode(); + + // set no re-trigger flag if appropriate + if ( ( ALARM_USER_ACTION_RINSEBACK == action ) && ( TRUE == ALARM_TABLE[ a ].alarmNoRetrigOnRB ) ) + { // alarms with no re-trigger on rinseback property should set the no re-trigger flag + alarmNoRetrigger = TRUE; + } + else if ( ( ALARM_USER_ACTION_END_TREATMENT == action ) && ( TRUE == ALARM_TABLE[ a ].alarmNoRetrigOnEndTx ) ) + { // alarms with no re-trigger on end-tx property should set the no re-trigger flag + alarmNoRetrigger = TRUE; + } + else if ( ALARM_USER_ACTION_ACK == action ) + { + if ( ( TRUE == ALARM_TABLE[ a ].alarmNoResume ) && ( TRUE == ALARM_TABLE[ a ].alarmNoRinseback ) ) + { // alarms that only allow end-tx that occur in rinseback or recirc states of treatment mode should set the no re-trigger flag + if ( ( MODE_TREA == mode ) && ( ( TREATMENT_RINSEBACK_STATE == sub ) || ( TREATMENT_RECIRC_STATE == sub ) ) ) + { + alarmNoRetrigger = TRUE; + } + } + } + // check special cases where we do not want to clear this alarm - otherwise, clear it + if ( ( ( ALARM_ID_DG_CREATING_DIALYSATE_PLEASE_WAIT == a ) || ( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT == a ) ) && + ( TRUE == alarmIsDetected[ a ] ) && ( mode != MODE_POST ) && + ( action != ALARM_USER_ACTION_RINSEBACK ) && ( action != ALARM_USER_ACTION_END_TREATMENT ) ) + { + // do not clear this alarm if condition not cleared first (unless treatment is over) + result = FALSE; + } + else + { + // clear this alarm + clearAlarm( a ); + } + } + else if ( TRUE == alarmIsActive[ a ] ) + { + result = FALSE; // we didn't clear this alarm because condition still active + } } } + + return result; } /*********************************************************************//** @@ -1661,7 +1877,7 @@ * 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 + * @param key 32-bit supervisor alarm key required to perform this function * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testClearAllAlarms( U32 key ) @@ -1676,6 +1892,10 @@ { ALARM_ID_T a; + // clear the flags when Dialin clears alarms + alarmNoRetrigger = FALSE; + resumeBlockedByAlarmProperty = FALSE; + // Clear all active alarms for ( a = ALARM_ID_NO_ALARM; a < NUM_OF_ALARM_IDS; a++ ) {