Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rbbded7df1d8e6087c5c7dc82d26294c0e0b1a2ef -r0d205f6ddf739549eb942d0b552b0a6790d4366f --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision bbded7df1d8e6087c5c7dc82d26294c0e0b1a2ef) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 0d205f6ddf739549eb942d0b552b0a6790d4366f) @@ -25,7 +25,7 @@ #include "ModeInitPOST.h" #include "ModeTreatment.h" #include "ModeTreatmentParams.h" -#include "OperationModes.h" +#include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemComm.h" #include "SystemCommMessages.h" @@ -58,12 +58,12 @@ // ********** private data ********** -// DG status -static DG_OP_MODE_T dgCurrentOpMode; ///< Current DG operation mode. +// DG status +static DG_OP_MODE_T dgCurrentOpMode; ///< Current DG operation mode. static U32 dgSubMode; ///< Current state (sub-mode) of current DG operation mode. -static BOOL dgStartCommandSent; ///< Flag indicates command to start DG has been sent. -static BOOL dgStarted; ///< Flag indicates whether we have commanded the DG to start or stop. -static BOOL dgTrimmerHeaterOn; ///< Flag indicates whether we have commanded the DG to start or stop the trimmer heater. +static BOOL dgStartCommandSent; ///< Flag indicates command to start DG has been sent. +static BOOL dgStarted; ///< Flag indicates whether we have commanded the DG to start or stop. +static BOOL dgTrimmerHeaterOn; ///< Flag indicates whether we have commanded the DG to start or stop the trimmer heater. // DG sensor data static F32 dgDialysateTemp; ///< Dialysate temperature reported by the DG. @@ -99,6 +99,9 @@ static DG_RESERVOIR_ID_T dgActiveReservoir; ///< Latest active reservoir reported by the DG. static DG_RESERVOIR_ID_T dgActiveReservoirSet; ///< Active reservoir commanded. +// Tdi temperature Monitor +static DG_TDI_TEMP_COUNTER_T dgTdiTempCounter; ///< DG Tdi temperature Counter. + static DG_DISINFECT_UI_STATES_T disinfectsStatus; ///< DG disinfects status. static DG_MIXING_RATIOS_T dgMixingRatios; ///< DG mixing ratios. static HEATERS_DATA_T dgHeatersData; ///< DG heaters data. @@ -125,12 +128,12 @@ U32 i, j; // NOTE: the active reservoir is set to reservoir 1 since DG will send active reservoir 1 as active on power up - dgStarted = FALSE; - dgTrimmerHeaterOn = FALSE; + dgStarted = FALSE; + dgTrimmerHeaterOn = FALSE; dgTrimmerTempSet = 0.0F; dgTrimmerTempCheckTimerCtr = 0; dgActiveReservoirSet = DG_RESERVOIR_2; - dgActiveReservoir = DG_RESERVOIR_2; + dgActiveReservoir = DG_RESERVOIR_2; dgDialysateTemp = 0.0F; dgCurrentOpMode = DG_MODE_INIT; dgSubMode = 0; @@ -174,17 +177,36 @@ lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_1 ] = 0.0F; lgLoadCellBackupReadingsTotal[ DG_RESERVOIR_2 ] = 0.0F; - initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_OUT_OF_TARGET_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS, DIALYSATE_TEMP_UPPER_MAX_SAFETY_TIMEOUT_MS ); - initPersistentAlarm( ALARM_ID_HD_NEW_LOAD_CELL_DATA_MESSAGE_NOT_RECEIVE, DG_DATA_FRESHNESS_TIMEOUT_MS, DG_DATA_FRESHNESS_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_NEW_DIALYSATE_TEMP_DATA_MESSAGE_NOT_RECEIVE, DG_DATA_FRESHNESS_TIMEOUT_MS, DG_DATA_FRESHNESS_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_NEW_RESERVOIRS_DATA_MESSAGE_NOT_RECEIVE, DG_DATA_FRESHNESS_TIMEOUT_MS, DG_DATA_FRESHNESS_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_DG_NEW_OPERATION_MODE_MESSAGE_NOT_RECEIVE, DG_DATA_FRESHNESS_TIMEOUT_MS, DG_DATA_FRESHNESS_TIMEOUT_MS ); + + resetTdiTempCounters(); } +/*********************************************************************//** + * @brief + * The resetTdiTempCounters function initializes the counter variables. + * @details Inputs: none + * @details Outputs: TdiTemperature counter variables initialized. + * @return none + *************************************************************************/ +void resetTdiTempCounters ( void ) +{ + //Initialize tdi temperature counter values + dgTdiTempCounter.tdiTempUpCounter = 0; + dgTdiTempCounter.tdiTempDownCounter = 0; + dgTdiTempCounter.prevTdiTempUpCounter = 0; + dgTdiTempCounter.prevTdiTempDownCounter = 0; + dgTdiTempCounter.clearAlarmStartTime = 0; + dgTdiTempCounter.dgPrevActiveReservoir = DG_RESERVOIR_2; + dgTdiTempCounter.dgCurrentActiveReservoir = DG_RESERVOIR_2; +} + /**********************************************************************//** * @brief * The checkDGDataFreshness function checks the condition @@ -459,14 +481,14 @@ /*********************************************************************//** * @brief - * The getDialysateTemperature function gets the latest dialysate temperature. - * @details Inputs: dgDialysateTemp + * The getDGDisinfectsStates function returns the DG disinfects readings. + * @details Inputs: none * @details Outputs: none - * @return the latest dialysate temperature + * @return the current DG disinfects readings *************************************************************************/ -F32 getDialysateTemperature( void ) +DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) { - return dgDialysateTemp; + return disinfectsStatus; } /*********************************************************************//** @@ -510,14 +532,14 @@ /*********************************************************************//** * @brief - * The getDGDisinfectsStates function returns the DG disinfects readings. - * @details Inputs: disinfectsStatus + * The getDialysateTemperature function returns the DG dialysate temperature. + * @details Inputs: dgDialysateTemp * @details Outputs: none - * @return the current DG disinfects readings + * @return the latest dialysate temperature *************************************************************************/ -DG_DISINFECT_UI_STATES_T getDGDisinfectsStates( void ) +F32 getDialysateTemperature( void ) { - return disinfectsStatus; + return dgDialysateTemp; } /*********************************************************************//** @@ -1263,32 +1285,88 @@ void checkDialysateTemperature( void ) { BOOL isTDiTempAboveHighSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_UPPER_MAX_SAFETY_LIMIT_C ? TRUE : FALSE ); - BOOL isTDiTempAboveLowSafety = ( dgDialysateTemp >= DIALYSATE_TEMP_UPPER_SAFETY_LIMIT_C ? TRUE : FALSE ); - BOOL isTDITempBelowLowSafety = ( dgDialysateTemp <= DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isTDiTempAboveLowSafety = ( dgDialysateTemp > DIALYSATE_TEMP_UPPER_SAFETY_LIMIT_C ? TRUE : FALSE ); + BOOL isTDITempBelowLowSafety = ( dgDialysateTemp < DIALYSATE_TEMP_LOWER_SAFETY_LIMIT_C ? TRUE : FALSE ); F32 TDiHigh = dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; BOOL isTDiTempAboveDialysateTarget = ( dgDialysateTemp >= TDiHigh ? TRUE : FALSE ); F32 TDiLow = dgTrimmerTempSet - DIALYSATE_TEMP_OUT_OF_TARGET_TOL_C; BOOL isTDiTempBelowDialysateTarget = ( dgDialysateTemp <= TDiLow ? TRUE : FALSE ); BOOL isTempBelowTrigger = (BOOL)( isTDITempBelowLowSafety || isTDiTempBelowDialysateTarget ); BOOL isTempAboveTrigger = (BOOL)( isTDiTempAboveLowSafety || isTDiTempAboveDialysateTarget ); + DG_RESERVOIR_ID_T currentActiveRes = getDGActiveReservoir(); #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DIALYSATE_TEMP_CHECK ) != SW_CONFIG_ENABLE_VALUE ) #endif { + BOOL alarmIsActive = isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ); + + if ( TRUE == isTempBelowTrigger ) + { + // clear alarm + if ( TRUE == alarmIsActive ) + { + if ( dgTdiTempCounter.clearAlarmStartTime == 0 ) + { + dgTdiTempCounter.clearAlarmStartTime = getMSTimerCount(); + } + else if ( TRUE == didTimeout(dgTdiTempCounter.clearAlarmStartTime, DIALYSATE_TEMP_CLEAR_TIMEOUT_MS ) ) + { + clearAlarmCondition( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ); + } + } + } + else + { + dgTdiTempCounter.clearAlarmStartTime = 0; + } + + // Tdi high temp alarm handling + if ( currentActiveRes != dgTdiTempCounter.dgPrevActiveReservoir ) + { + //Increment up count when temperature is exceeded the defined threshold + if ( TRUE == isTempAboveTrigger ) + { + //Increment up counter + dgTdiTempCounter.tdiTempUpCounter++; + } + // Initiate down Counter only when temperature is crossed the threshold. otherwise do not increment down counter + else if ( dgTdiTempCounter.tdiTempUpCounter > 0 ) + { + //Increment down counter when temperature dips below threshold + dgTdiTempCounter.tdiTempDownCounter++; + } + + //get current reservoir value + dgTdiTempCounter.dgCurrentActiveReservoir = currentActiveRes; + } + else + { + // last reservoir cycle temperature should have crossed the threshold level, + // to compute next reservoir cycle temperature rise count is greater than the previous one. + if ( (dgTdiTempCounter.prevTdiTempUpCounter != 0) && + (dgTdiTempCounter.tdiTempUpCounter >= dgTdiTempCounter.prevTdiTempUpCounter ) && + (dgTdiTempCounter.tdiTempDownCounter <= dgTdiTempCounter.prevTdiTempDownCounter ) ) + { + //Activate Alarm + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, dgDialysateTemp, dgTrimmerTempSet ); + } + // readiness for the next reservoir cycle + dgTdiTempCounter.prevTdiTempUpCounter = dgTdiTempCounter.tdiTempUpCounter; + dgTdiTempCounter.prevTdiTempDownCounter = dgTdiTempCounter.tdiTempDownCounter; + dgTdiTempCounter.tdiTempUpCounter = 0; + dgTdiTempCounter.tdiTempDownCounter = 0; + // assign last current reservoir to previous Active reservoir value once reservoir switch happened + dgTdiTempCounter.dgPrevActiveReservoir = dgTdiTempCounter.dgCurrentActiveReservoir; + } + // check clear condition first if ( TRUE == isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP ) ) { isTDiTempAboveHighSafety = ( dgDialysateTemp <= ( dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); } checkPersistentAlarm(ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP, isTDiTempAboveHighSafety, dgDialysateTemp, dgTrimmerTempSet ); - if ( TRUE == isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ) ) - { - isTempAboveTrigger = ( dgDialysateTemp <= ( dgTrimmerTempSet + DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); - } - checkPersistentAlarm(ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP, isTempAboveTrigger, dgDialysateTemp, dgTrimmerTempSet ); - if ( TRUE == isAlarmActive( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP ) ) { isTempBelowTrigger = ( dgDialysateTemp >= ( dgTrimmerTempSet - DIALYSATE_TEMP_OUT_OF_TARGET_CLEAR_TOL_C ) ? FALSE : TRUE ); Index: firmware/App/Services/AlarmMgmt.c =================================================================== diff -u -r885564dbf68d445e1c95a61b05ea66b6b0690c01 -r0d205f6ddf739549eb942d0b552b0a6790d4366f --- firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 885564dbf68d445e1c95a61b05ea66b6b0690c01) +++ firmware/App/Services/AlarmMgmt.c (.../AlarmMgmt.c) (revision 0d205f6ddf739549eb942d0b552b0a6790d4366f) @@ -260,6 +260,33 @@ /*********************************************************************//** * @brief + * The isACPowerLost function determines whether A/C power loss has + * been detected. This function sets the alarms blocked condition to + * allow smooth alarm recovery. + * + * @details Inputs: alarmStatus + * @details Outputs: alarmsBlockedTimer + * @return TRUE if A/C power loss alarm is in effect, FALSE if not + *************************************************************************/ +BOOL isACPowerLost( void ) +{ + BOOL result = TRUE; + + // Continue to block new alarms until the alarms are cleared. + if ( ( FALSE == isAlarmConditionDetected( ALARM_ID_HD_AC_POWER_LOST ) ) && + ( FALSE == isAlarmConditionDetected( ALARM_ID_HD_AC_POWER_LOST_IN_TREATMENT ) ) ) + { + result = FALSE; + } + else + { + alarmsBlockedTimer = ALARM_BLOCKED_COUNT_AFTER_AC_RETURN; + } + return result; +} + +/*********************************************************************//** + * @brief * The activateAlarm function activates a given alarm. * @details Inputs: none * @details Outputs: alarmIsActive[], alarmStartedAt[], alarmStatus is updated @@ -268,6 +295,11 @@ *************************************************************************/ static void activateAlarm( ALARM_ID_T alarm ) { + // Block new alarms, occuring during loss of AC power + if ( ( TRUE == getCPLDACPowerLossDetected() ) ) + { + alarmsBlockedTimer = ALARM_BLOCKED_COUNT_AFTER_AC_RETURN; + } // Verify valid alarm index if ( ( alarm > ALARM_ID_NO_ALARM ) && ( alarm < NUM_OF_ALARM_IDS ) ) { @@ -1383,6 +1415,9 @@ 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 @@ -1396,15 +1431,32 @@ { if ( ( TRUE == ALARM_TABLE[ a ].alarmNoResume ) && ( TRUE == ALARM_TABLE[ a ].alarmNoRinseback ) ) { // alarms that only allow end-tx that occur in rinseback or recirc states of treatment mode should set the no re-trigger flag - if ( ( MODE_TREA == getCurrentOperationMode() ) && - ( ( TREATMENT_RINSEBACK_STATE == getCurrentSubMode() ) || ( TREATMENT_RECIRC_STATE == getCurrentSubMode() ) ) ) + if ( ( MODE_TREA == mode ) && ( ( TREATMENT_RINSEBACK_STATE == sub ) || ( TREATMENT_RECIRC_STATE == sub ) ) ) { alarmNoRetrigger = TRUE; } } } - // clear this alarm - clearAlarm( a ); + // check special cases where we do not want to clear this alarm - otherwise, clear it + if ( ( ALARM_ID_DG_CREATING_DIALYSATE_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 if ( ( ( ALARM_ID_DG_FILL_CONDUCTIVITY_OUT_OF_RANGE == a ) || + ( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME == a ) || + ( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME == a ) ) && + ( alarmStatus.alarmTop != a ) ) + { + // do not clear this alarm unless it is top (user is specifically clearing this alarm) + result = FALSE; + } + else + { + // clear this alarm + clearAlarm( a ); + } } else if ( TRUE == alarmIsActive[ a ] ) {