Index: firmware/App/Controllers/BloodLeak.c =================================================================== diff -u -r57f9f2d3b4c109c952034003c77a315bb3c41717 -r9391789fb7dbb9c0a03fbacd0c3acc37edbb9880 --- firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 57f9f2d3b4c109c952034003c77a315bb3c41717) +++ firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 9391789fb7dbb9c0a03fbacd0c3acc37edbb9880) @@ -59,6 +59,7 @@ #define BLOOD_LEAK_SELF_TEST_CMD_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Blood leak self test command timeout in milliseconds. #define BLOOD_LEAK_BETWEEN_ZERO_ST_WAIT_MS 250 ///< Blood leak wait time in between zero and self test commands in milliseconds. #define DATA_PUBLISH_COUNTER_START_COUNT 60 ///< Data publish counter start count. +#define BLOOD_LEAK_DETECT_RECOVERY_MIN_TIME_MS ( 2 * MS_PER_SECOND ) ///< Blood leak blood detect recovery minimum time in milliseconds. // Embedded mode defines #define BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH 6 ///< Blood leak embedded mode command sequence length. @@ -92,9 +93,6 @@ #define BLOOD_LEAK_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Blood leak embedded mode FPGA error timeout in milliseconds. #define BLOOD_LEAK_RXFIFO_COUNT_MASK 0x03FF ///< Mask high order bits of blood leak sensor rx count -#define MAX_BLOOD_LEAK_COMM_FAILURES_WINDOW_MS ( 1 * SEC_PER_MIN * MS_PER_SECOND ) ///< Blood Leak comm failures window -#define MAX_BLOOD_LEAK_COMM_FAILURES 10 ///< Blood Leak maximum comm failures per MAX_BLOOD_LEAK_COMM_FAILURES_WINDOW_MS - /// Defined states for the blood leak detector state machine. typedef enum BloodLeakStates { @@ -103,6 +101,7 @@ BLOOD_LEAK_INIT_STATE, ///< Init state. BLOOD_LEAK_CHECK_ZERO_AND_SELF_TEST_STATE, ///< Blood leak check for zero and self test commands state. BLOOD_LEAK_NORMAL_STATE, ///< Normal state. + BLOOD_LEAK_RECOVER_BLOOD_DETECT_STATE, ///< Blood leak recover blood detect state. NUM_OF_BLOOD_LEAK_STATES ///< Number of blood leak detector states. } BLOOD_LEAK_STATE_T; @@ -159,6 +158,7 @@ static U08 bloodLeakSetPointSequence[ BLOOD_LEAK_SET_POINT_SEQ_MAX_LENGTH ][ 2 ]; ///< Blood leak set point sequence array. static HD_BLOOD_LEAK_SENSOR_CAL_RECORD_T bloodLeakCalRecord; ///< Blood leak calibration record structure. static BOOL bloodLeakExitNormalRequested; ///< Blood leak exit normal state requested. +static U32 bloodLeakRecoveryStartTimeMS; ///< Blood leak recovery start time in milliseconds. // Embedded mode variables static BOOL bloodLeakSignalEmbModeReq; ///< Blood leak signal embedded mode has been requested. @@ -188,6 +188,7 @@ static BLOOD_LEAK_STATE_T handleBloodLeakInitState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakCheckZeroAndSelfTestState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakNormalState( void ); +static BLOOD_LEAK_STATE_T handleBloodLeakRecoverBloodDetectState( void ); static BLOOD_LEAK_EMB_MODE_STATE_T handleBloodLeakEmbModeWaitForCommandState( void ); static BLOOD_LEAK_EMB_MODE_STATE_T handleBloodLeakEmbModeSendCommandState( void ); @@ -205,6 +206,8 @@ static void enqueueInfoEmbModeCmds( void ); static U16 getBloodLeakRxBytesAvailable( void ); static void resetEmbModeCmdRqstCount( U08 cmd ); +static BLOOD_LEAK_STATUS_T getFPGABloodDetectProcessedStatus( void ); +static BOOL isDialysateLineInBypass( void ); /*********************************************************************//** * @brief @@ -219,7 +222,7 @@ * bloodLeakEmbModeRespBuffer, bloodLeakEmbModeRespIndex, * bloodLeakExitNormalRequested, bloodLeakEmbModeCmdSeqLength, * bloodLeakEmbModeHasRxRqstBeenSent, bloodLeakEmbModeInfoCmdEnqLastTimeStamp, - * bloodLeakEmbModeInfoCmdCounter + * bloodLeakEmbModeInfoCmdCounter, bloodLeakRecoveryStartTimeMS, * @return none *************************************************************************/ void initBloodLeak( void ) @@ -252,6 +255,7 @@ bloodLeakEmbModeCmdEnqueueCount = 0; bloodLeakEmbModeInfoCmdEnqLastTimeStamp = getMSTimerCount(); bloodLeakEmbModeInfoCmdCounter = 0; + bloodLeakRecoveryStartTimeMS = getMSTimerCount(); // Set the blood leak embedded mode command queue to zero memset( bloodLeakEmbModeCmdQ, 0x0, BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE ); @@ -268,9 +272,6 @@ // Enqueue the commands to set the embedded mode and request the set point of the blood leak sensor enqueueEmbModeCmd( CS_EMB_MODE_CMD ); enqueueEmbModeCmd( D_EMB_MODE_CMD ); - - // initialize FPGA comm failures windowed timer count - initTimeWindowedCount( TIME_WINDOWED_COUNT_BLOOD_LEAK_COMM_ERROR, MAX_BLOOD_LEAK_COMM_FAILURES, MAX_BLOOD_LEAK_COMM_FAILURES_WINDOW_MS ); } /*********************************************************************//** @@ -311,6 +312,10 @@ bloodLeakState = handleBloodLeakNormalState(); break; + case BLOOD_LEAK_RECOVER_BLOOD_DETECT_STATE: + bloodLeakState = handleBloodLeakRecoverBloodDetectState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_BLOOD_LEAK_STATE, bloodLeakState ) bloodLeakState = BLOOD_LEAK_INIT_STATE; @@ -654,69 +659,60 @@ * @details Inputs: bloodLeakStatus, bloodLeakPersistenceCtr, * bloodLeakExitNormalRequested * @details Outputs: bloodLeakStatus, bloodLeakPersistenceCtr, - * bloodLeakExitNormalRequested, bloodLeakEmbModeHasZeroBeenRqustd + * bloodLeakExitNormalRequested, bloodLeakEmbModeHasZeroBeenRqustd, + * bloodLeakRecoveryStartTimeMS * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakNormalState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_NORMAL_STATE; - // If the blood leak status bit is low (0) it means blood has not been detected, otherwise, blood has been detected - bloodLeakStatus.data = ( BLOOD_LEAK_STATUS_BIT_LOW == getFPGABloodLeakStatus() ? BLOOD_LEAK_NOT_DETECTED : BLOOD_LEAK_DETECTED ); + bloodLeakStatus.data = getFPGABloodDetectProcessedStatus(); -#ifdef DIALYZER_REPRIME_ENABLED -// exempt blood leak alarm while performing a dialyzer de-prime as air will be pushed past sensor and appear to be blood -if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( DIALYSIS_DIALYZER_REPRIME_STATE == getDialysisState() ) ) -{ - bloodLeakPersistenceCtr = 0; -} -else -{ -#endif - if ( STATE_OPEN == getSwitchStatus( PUMP_TRACK_SWITCH ) ) { // If the pump track on open, zero the persistent counter to not check the blood leak alarm bloodLeakPersistenceCtr = 0; } - // Check status reading and act upon - // Only check the blood detection in treatment mode and service mode for testing in manufacturing - if ( ( BLOOD_LEAK_DETECTED == getBloodLeakStatus() ) && ( ( MODE_TREA == getCurrentOperationMode() ) || ( MODE_SERV == getCurrentOperationMode() ) ) ) + switch ( getCurrentOperationMode() ) { - if ( ++bloodLeakPersistenceCtr > BLOOD_LEAK_PERSISTENCE ) - { - bloodLeakPersistenceCtr = BLOOD_LEAK_PERSISTENCE; -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) -#endif + case MODE_TREA: + case MODE_SERV: + if ( FALSE == isDialysateLineInBypass() ) { - activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); - exitBloodLeakNormalState(); // so we don't keep triggering after user clears it (rinseback or end tx). - } - } - } - else // Blood leak not detected - { - if ( bloodLeakPersistenceCtr > 0 ) - { - bloodLeakPersistenceCtr--; - } - else - { + if ( BLOOD_LEAK_DETECTED == getBloodLeakStatus() ) + { + if ( ++bloodLeakPersistenceCtr > BLOOD_LEAK_PERSISTENCE ) + { + bloodLeakPersistenceCtr = BLOOD_LEAK_PERSISTENCE; #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif - { - clearAlarmCondition( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT ); + bloodLeakRecoveryStartTimeMS = getMSTimerCount(); + state = BLOOD_LEAK_RECOVER_BLOOD_DETECT_STATE; + } + } + } + else if ( bloodLeakPersistenceCtr > 0 ) + { + bloodLeakPersistenceCtr--; + } + else + { + clearAlarmCondition( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); + clearAlarmCondition( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT ); + } } - } + + default: + // Do nothing. Do not check for blood in other modes. + break; } -#ifdef DIALYZER_REPRIME_ENABLED -} -#endif - if ( TRUE == bloodLeakExitNormalRequested ) { bloodLeakExitNormalRequested = FALSE; @@ -734,6 +730,53 @@ /*********************************************************************//** * @brief + * The handleBloodLeakRecoverBloodDetectState function handles the blood + * leak recover blood detect state. + * @details Inputs: bloodLeakStatus, bloodLeakRecoveryStartTimeMS, + * bloodLeakEmbModeHasZeroBeenRqustd, bloodLeakExitNormalRequested + * @details Outputs: bloodLeakStatus, bloodLeakRecoveryStartTimeMS, + * bloodLeakPersistenceCtr, bloodLeakEmbModeHasZeroBeenRqustd, + * bloodLeakExitNormalRequested + * @return next state + *************************************************************************/ +static BLOOD_LEAK_STATE_T handleBloodLeakRecoverBloodDetectState( void ) +{ + BLOOD_LEAK_STATE_T state = BLOOD_LEAK_RECOVER_BLOOD_DETECT_STATE; + + bloodLeakStatus.data = getFPGABloodDetectProcessedStatus(); + + if ( BLOOD_LEAK_NOT_DETECTED == getBloodLeakStatus() ) + { + if ( TRUE == didTimeout( bloodLeakRecoveryStartTimeMS, BLOOD_LEAK_DETECT_RECOVERY_MIN_TIME_MS ) ) + { + // Blood has not been detected for the specified period of time so clear the alarm condition + clearAlarmCondition( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT ); + } + } + else + { + bloodLeakRecoveryStartTimeMS = getMSTimerCount(); + } + + if ( isAlarmActive( ALARM_ID_HD_BLOOD_LEAK_RECOVERING_PLEASE_WAIT ) != TRUE ) + { + // Once the user hit resume, transition back to normal state to continue detecting for blood + // Reset the blood detect counter prior to transitioning back + bloodLeakPersistenceCtr = 0; + state = BLOOD_LEAK_NORMAL_STATE; + } + else if ( TRUE == bloodLeakEmbModeHasZeroBeenRqustd ) + { + // Check whether zeroing the sensor has been requested or not if yes, transition to zero command state otherwise, stay in this state + bloodLeakEmbModeHasZeroBeenRqustd = FALSE; + state = BLOOD_LEAK_CHECK_ZERO_AND_SELF_TEST_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The getBloodLeakStatus function gets the current reading for the blood * leak detector. * @details Inputs: bloodLeakStatus @@ -1056,17 +1099,10 @@ bloodLeakEmbModeRespBuffer[ 0 ] = BLOOD_LEAK_EMB_MODE_FAIL_ASCII; convertString2Integer( bloodLeakEmbModeRqstedCmd, length ); - sendBloodLeakEmbeddedModeCommandResponse( bloodLeakEmbModeRqstedCmd, length, bloodLeakEmbModeRespBuffer ); - if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_BLOOD_LEAK_COMM_ERROR ) ) - { - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_BLOOD_LEAK_FPGA_FAULT, (U32)bloodLeakEmbModeRqstedCmd, (U32)MAX_BLOOD_LEAK_COMM_FAILURES_WINDOW_MS ) - } - bloodLeakEmbModeRqstedCmd = NU_EMB_MODE_CMD; state = BLOOD_LEAK_EMB_MODE_WAIT_FOR_COMAND_STATE; - } return state; @@ -1542,7 +1578,41 @@ return getFPGABloodLeakRxFIFOCount() & BLOOD_LEAK_RXFIFO_COUNT_MASK; } +/*********************************************************************//** + * @brief + * The getFPGABloodDetectProcessedStatus function returns the status of the + * blood detect from FPGA meaning the status that is read from the sensor. + * @details Inputs: none + * @details Outputs: none + * @return BLOOD_LEAK_NOT_DETECTED if blood has not been detected otherwise, + * BLOOD_LEAK_DETECTED + *************************************************************************/ +static BLOOD_LEAK_STATUS_T getFPGABloodDetectProcessedStatus( void ) +{ + // If the blood leak status bit is low (0) it means blood has not been detected, otherwise, blood has been detected + return ( BLOOD_LEAK_STATUS_BIT_LOW == getFPGABloodLeakStatus() ? BLOOD_LEAK_NOT_DETECTED : BLOOD_LEAK_DETECTED ); +} +/*********************************************************************//** + * @brief + * The isDialysateLineInBypass function checks and returns whether the + * dialysate line is in bypass mode or not. + * @details Inputs: none + * @details Outputs: none + * @return TRUE if the dialysate line is in bypass otherwise, FALSE + *************************************************************************/ +static BOOL isDialysateLineInBypass( void ) +{ + BOOL status = TRUE; + + status &= ( VALVE_POSITION_C_CLOSE == getValvePosition( VDI ) ? TRUE : FALSE ); + status &= ( VALVE_POSITION_C_CLOSE == getValvePosition( VDO ) ? TRUE : FALSE ); + status &= ( getMeasuredDialInPumpSpeed() <= NEARLY_ZERO ? TRUE : FALSE ); + + return status; +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/