Index: firmware/App/Controllers/BloodLeak.c =================================================================== diff -u -rf1157c760b320bf088921a25eb78e973d6341578 -reb0949253d49058defea55b07876920d887d7f78 --- firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision f1157c760b320bf088921a25eb78e973d6341578) +++ firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision eb0949253d49058defea55b07876920d887d7f78) @@ -140,7 +140,7 @@ U32 length; ///< Blood leak sensor expected response length in bytes. U32 timeoutMS; ///< Blood leak sensor receive timeout in milliseconds. U32 commandResp; ///< Blood leak sensor command response back. - U08 commandRetryCount; ///< Blood leak sensor command retry count. + U08 commandRqstCount; ///< Blood leak sensor command request count. BOOL isCmdRespRdy; ///< Blood leak sensor is command response ready flag. } EMB_MODE_CMD_T; @@ -204,6 +204,7 @@ static U32 getAvailableEmbModeQueueCount( void ); static void enqueueInfoEmbModeCmds( void ); static U16 getBloodLeakRxBytesAvailable( void ); +static void resetEmbModeCmdRqstCount( U08 cmd ); /*********************************************************************//** * @brief @@ -269,8 +270,7 @@ 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); - + initTimeWindowedCount( TIME_WINDOWED_COUNT_BLOOD_LEAK_COMM_ERROR, MAX_BLOOD_LEAK_COMM_FAILURES, MAX_BLOOD_LEAK_COMM_FAILURES_WINDOW_MS ); } /*********************************************************************//** @@ -360,7 +360,7 @@ * zeroed. * @details Inputs: bloodLeakEmbModeCmdEnqueueCount * @details Outputs: bloodLeakEmbModeHasZeroBeenRqustd, - * bloodLeakEmbModeCmdEnqueueCount + * bloodLeakEmbModeCmdEnqueueCount, bloodLeakSelfTestStatus * @return TRUE if the zero commands were successfully queued otherwise, FALSE *************************************************************************/ BOOL zeroBloodLeak( void ) @@ -371,16 +371,16 @@ { status = TRUE; bloodLeakEmbModeHasZeroBeenRqustd = TRUE; + // Since the zero commands have been queued, reset the counter + bloodLeakEmbModeCmdEnqueueCount = 0; + bloodLeakSelfTestStatus = SELF_TEST_STATUS_IN_PROGRESS; // Enqueue the zero and self test sequence (Z->G->Z->Q->T) enqueueEmbModeCmd( Z_EMB_MODE_CMD ); enqueueEmbModeCmd( G_EMB_MODE_CMD ); enqueueEmbModeCmd( Z_EMB_MODE_CMD ); enqueueEmbModeCmd( Q_EMB_MODE_CMD ); enqueueEmbModeCmd( T_EMB_MODE_CMD ); - - // Since the zero commands have been queued, reset the counter - bloodLeakEmbModeCmdEnqueueCount = 0; } else if ( ++bloodLeakEmbModeCmdEnqueueCount > BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { @@ -392,6 +392,24 @@ /*********************************************************************//** * @brief + * The hasBloodLeakZeroSequenceFailed function returns TURE if the number + * of times the zero sequence has failed. + * @details Inputs: bloodLeakEmbModeCmd + * @details Outputs: none + * @return TRUE if zero sequence failed otherwise, FALSE + *************************************************************************/ +BOOL hasBloodLeakZeroSequenceFailed( void ) +{ + // The zero sequence contains Z->G->Z->Q->T and each of the commands has a request counter but for checking whether the + // zero sequence has failed only the Z command is checked. When the zero sequence is enqueued, all of the them enqueued so they are + // at the same request count number. + BOOL status = ( bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRqstCount > BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ? TRUE : FALSE ); + + return status; +} + +/*********************************************************************//** + * @brief * The exitBloodLeakNormalState requests that the blood leak sensor to exit * its normal state. * @details Inputs: bloodLeakState @@ -453,7 +471,7 @@ } else if ( ( TRUE == bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].isCmdRespRdy ) && ( BLOOD_LEAK_EMB_MODE_FAIL_ASCII == cmdResp ) ) { - if ( ++bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) + if ( bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandRqstCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { // Enqueue the commands to set the embedded mode and request the set point of the blood leak sensor // Since set point was requested in the init function as well, both are requested here because we have to be @@ -474,8 +492,8 @@ if ( ( getCurrentOperationMode() != MODE_INIT ) && ( TRUE == isEmbModeReady ) ) { - bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandRetryCount = 0; - state = BLOOD_LEAK_CHECK_SET_POINT_STATE; + resetEmbModeCmdRqstCount( CS_EMB_MODE_CMD ); + state = BLOOD_LEAK_CHECK_SET_POINT_STATE; } return state; @@ -497,7 +515,7 @@ if ( ( bloodLeakSetPoint != bloodLeakCalRecord.setPoint ) && ( TRUE == isCommandRespReady ) ) { - if ( ++bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) + if ( bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandRqstCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { enqueueEmbModeCmd( D_EMB_MODE_CMD ); } @@ -513,8 +531,8 @@ } else if ( TRUE == isCommandRespReady ) { - bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandRetryCount = 0; - state = BLOOD_LEAK_INIT_STATE; + resetEmbModeCmdRqstCount( D_EMB_MODE_CMD ); + state = BLOOD_LEAK_INIT_STATE; } return state; @@ -613,20 +631,20 @@ if ( FALSE == hasCmdSqncFailed ) { // Done with zero sequence, transition to other states - bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRetryCount = 0; - bloodLeakEmbModeHasZeroBeenRqustd = FALSE; - bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; - state = BLOOD_LEAK_NORMAL_STATE; + bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRqstCount = 0; + bloodLeakEmbModeHasZeroBeenRqustd = FALSE; + bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; + state = BLOOD_LEAK_NORMAL_STATE; } // If not successful, retry if we've not run out - else if ( bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRetryCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) + else if ( bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRqstCount < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) { if ( TRUE == zeroBloodLeak() ) { // Check if the zero sequence has been successfully enqueued // If the command retry of one of the commands in the zero sequence failed, it means all of them have failed // So in this condition only the Z command is checked - bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRetryCount++; + bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandRqstCount++; // TODO remove } } // If out of retries, fault @@ -1399,6 +1417,7 @@ * @details Inputs: none * @details Outputs: bloodLeakEmbModeCmdQRearIndex, bloodLeakEmbModeCmdQCount * bloodLeakEmbModeCmdQ, bloodLeakEmbModeCmd + * @param cmd the command to enqueue * @return none *************************************************************************/ static void enqueueEmbModeCmd( U08 cmd ) @@ -1408,11 +1427,27 @@ bloodLeakEmbModeCmdQ[ bloodLeakEmbModeCmdQRearIndex ] = cmd; bloodLeakEmbModeCmdQRearIndex = INC_WRAP( bloodLeakEmbModeCmdQRearIndex, 0, BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE - 1 ); bloodLeakEmbModeCmd[ cmd ].isCmdRespRdy = FALSE; + + bloodLeakEmbModeCmd[ cmd ].commandRqstCount++; bloodLeakEmbModeCmdQCount++; } /*********************************************************************//** * @brief + * The resetEmbModeCmdRqstCount function resets embedded mode command request + * count. + * @details Inputs: none + * @details Outputs: bloodLeakEmbModeCmd + * @param cmd the command to reset its request count + * @return none + *************************************************************************/ +static void resetEmbModeCmdRqstCount( U08 cmd ) +{ + bloodLeakEmbModeCmd[ cmd ].commandRqstCount = 0; +} + +/*********************************************************************//** + * @brief * The dequeueEmbModeCmd function dequeues the embedded mode command. * @details Inputs: none * @details Outputs: bloodLeakEmbModeCmdQFrontIndex, bloodLeakEmbModeCmdQCount Index: firmware/App/Controllers/BloodLeak.h =================================================================== diff -u -rf1157c760b320bf088921a25eb78e973d6341578 -reb0949253d49058defea55b07876920d887d7f78 --- firmware/App/Controllers/BloodLeak.h (.../BloodLeak.h) (revision f1157c760b320bf088921a25eb78e973d6341578) +++ firmware/App/Controllers/BloodLeak.h (.../BloodLeak.h) (revision eb0949253d49058defea55b07876920d887d7f78) @@ -55,6 +55,7 @@ void execBloodLeak( void ); void execBloodLeakEmbModeCommand( void ); BOOL zeroBloodLeak( void ); +BOOL hasBloodLeakZeroSequenceFailed( void ); void exitBloodLeakNormalState( void ); Index: firmware/App/Controllers/Bubble.c =================================================================== diff -u -ra7821aff3dc204a060233b0753253ec04d020557 -reb0949253d49058defea55b07876920d887d7f78 --- firmware/App/Controllers/Bubble.c (.../Bubble.c) (revision a7821aff3dc204a060233b0753253ec04d020557) +++ firmware/App/Controllers/Bubble.c (.../Bubble.c) (revision eb0949253d49058defea55b07876920d887d7f78) @@ -55,7 +55,7 @@ /// Interval (in ms) at which to publish air bubble detectors data on CAN bus. static OVERRIDE_U32_T bubblesDataPublishInterval = { BUBBLE_PUB_INTERVAL, BUBBLE_PUB_INTERVAL, 0, 0 }; -static U32 bubblesDataPublicationTimerCounter = 0; ///< Timer counter used to schedule air bubble detectors data publication to CAN bus. +static U32 bubblesDataPublicationTimerCounter; ///< Timer counter used to schedule air bubble detectors data publication to CAN bus. // ********** private function prototypes ********** @@ -75,7 +75,7 @@ { BUBBLES_T bubble; - for (bubble = ADV; bubble < NUM_OF_BUBBLES; bubble++) + for ( bubble = ADV; bubble < NUM_OF_BUBBLES; bubble++ ) { bubblesState[ bubble ] = BUBBLE_NORMAL_STATE; bubblesStatus[ bubble ].data = BUBBLE_NOT_DETECTED; Index: firmware/App/Modes/SelfTests.c =================================================================== diff -u -r5fcae5901d466789c329256f5532cf64be549c83 -reb0949253d49058defea55b07876920d887d7f78 --- firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision 5fcae5901d466789c329256f5532cf64be549c83) +++ firmware/App/Modes/SelfTests.c (.../SelfTests.c) (revision eb0949253d49058defea55b07876920d887d7f78) @@ -91,6 +91,8 @@ #define PRESSURE_CHECK_START_PRESSURE_TOLERANCE_MMHG 10.0F ///< Prior to dry pressure leak test, arterial and venous pressure sensors should read zero +/- this tolerance. #define MAX_EMPTY_RESERVOIR_WEIGHT_G 15.0F ///< Maximum reservoir weight to be considered empty for cartridge pressure leak test. +#define BLOOD_LEAK_DETECTOR_DEBUBBLE_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Blood leak detector debubble timeout in milliseconds. + // ********** private data ********** static NO_CART_SELF_TESTS_STATE_T currentNoCartSelfTestsState; ///< Current state of the no cartridge self-tests state machine. @@ -125,6 +127,7 @@ static U32 selfTestStartTime; ///< Starting time of self-test (in ms). static U32 selfTestPreviousPublishDataTime; ///< Last time self-test time data is being published (in ms). static U32 syringeOcclusionDelayStartTime; ///< Used to calculate the 1 second delay time before check for prime occlusion. +static U32 bloodLeakDebubbleStartTimeMS; ///< Blood leak detector debubble start time in milliseconds. static BOOL useHeparin; ///< Flag indicates the user of heparin. @@ -163,6 +166,7 @@ static WET_SELF_TESTS_STATE_T handleWetSelfTestSetupState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestBubblesState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestPrimeCheckState( void ); +static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorDebubbleState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementSetupState( void ); static WET_SELF_TESTS_STATE_T handleWetSelfTestFirstDisplacementState( void ); @@ -580,6 +584,7 @@ isValvesSettingSent = FALSE; selfTestStartTime = getMSTimerCount(); selfTestPreviousPublishDataTime = getMSTimerCount(); + bloodLeakDebubbleStartTimeMS = getMSTimerCount(); // Pumps should be off signalBloodPumpHardStop(); @@ -635,6 +640,10 @@ currentWetSelfTestsState = handleWetSelfTestPrimeCheckState(); break; + case WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_DEBUBBLE_STATE: + currentWetSelfTestsState = handleWetSelfTestBloodLeakDetectorDebubbleState(); + break; + case WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE: currentWetSelfTestsState = handleWetSelfTestBloodLeakDetectorState(); break; @@ -1657,19 +1666,6 @@ { state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; } - else - { -#ifndef _RELEASE_ - if ( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_SELF_TEST ) ) ) - { - state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; - } - else -#endif - { - activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_ZERO_SEQUENCE_FAILED ); - } - } } else { @@ -1687,23 +1683,79 @@ /*********************************************************************//** * @brief + * The handleWetSelfTestBloodLeakDetectorDebubbleState function runs the + * dialin pump in bypass mode to remove the potential bubbles from the + * blood leak detector prior to command another zero sequence. + * @details Inputs: bloodLeakDebubbleStartTimeMS + * @details Outputs: none + * @return the next state of wet self-tests state machine + *************************************************************************/ +static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorDebubbleState( void ) +{ + WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_DEBUBBLE_STATE; + + if ( TRUE == didTimeout( bloodLeakDebubbleStartTimeMS, BLOOD_LEAK_DETECTOR_DEBUBBLE_TIMEOUT_MS ) ) + { + if ( TRUE == zeroBloodLeak() ) + { + state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; + } + } + + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + state = WET_SELF_TESTS_STOPPED_STATE; + setupForSelfTestsStop(); + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleWetSelfTestBloodLeakDetectorState function handles zeroing and * self-test for blood leak detector. * @details Inputs: none - * @details Outputs: next self-test state + * @details Outputs: bloodLeakDebubbleStartTimeMS, settleStartTime, + * isValvesSettingSent * @return the next state of wet self-tests state machine *************************************************************************/ static WET_SELF_TESTS_STATE_T handleWetSelfTestBloodLeakDetectorState( void ) { WET_SELF_TESTS_STATE_T state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_STATE; + SELF_TEST_STATUS_T status = getBloodLeakSelfTestStatus(); - if ( SELF_TEST_STATUS_PASSED == getBloodLeakSelfTestStatus() ) + if ( SELF_TEST_STATUS_PASSED == status ) { settleStartTime = getMSTimerCount(); isValvesSettingSent = FALSE; state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; } + else if ( SELF_TEST_STATUS_FAILED == status ) + { + if ( TRUE == hasBloodLeakZeroSequenceFailed() ) + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_ZERO_SEQUENCE_FAILED ); + } + else + { + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + bloodLeakDebubbleStartTimeMS = getMSTimerCount(); + state = WET_SELF_TESTS_BLOOD_LEAK_DETECTOR_DEBUBBLE_STATE; + } + } +#ifndef _RELEASE_ + if ( ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_SELF_TEST ) ) ) + { + settleStartTime = getMSTimerCount(); + isValvesSettingSent = FALSE; + state = WET_SELF_TESTS_FIRST_DISPLACEMENT_SETUP_STATE; + } +#endif + if ( TRUE == doesAlarmStatusIndicateStop() ) { state = WET_SELF_TESTS_STOPPED_STATE;