Index: firmware/App/Modes/ModePostTreat.c =================================================================== diff -u -rcc4f8440e8ad7fa8f2ced2467d922be7422c344c -r29b362c485f28f45ef367342ac895e1c1907ac45 --- firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision cc4f8440e8ad7fa8f2ced2467d922be7422c344c) +++ firmware/App/Modes/ModePostTreat.c (.../ModePostTreat.c) (revision 29b362c485f28f45ef367342ac895e1c1907ac45) @@ -8,7 +8,7 @@ * @file ModePostTreat.c * * @author (last) Dara Navaei -* @date (last) 15-Feb-2022 +* @date (last) 31-Mar-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 @@ -49,23 +49,19 @@ /// Post-Treatment drain reservoirs state machine. typedef enum Drain_States { - DRAIN_FIRST_RESERVOIR_START_STATE = 0, ///< Drain first reservoir start state. - DRAIN_FIRST_RESERVOIR_STATE, ///< Drain first reservoir state. - DRAIN_SWITCH_RESERVOIR_STATE, ///< Switch reservoir state. - DRAIN_SECOND_RESERVOIR_STATE, ///< Drain second reservoir state. - DRAIN_COMPLETE_STATE, ///< Drain complete state. - NUM_OF_DRAIN_STATES ///< Number of drain states. + DRAIN_RESERVOIR_SWITCH_STATE = 0, ///< Switch reservoir state. + DRAIN_RESERVOIR_START_DRAIN_STATE, ///< Drain reservoir start drain state. + DRAIN_RESERVOIR_DRAIN_STATE, ///< Drain first reservoir state. + DRAIN_RESERVOIR_COMPLETE_STATE, ///< Drain complete state. + NUM_OF_DRAIN_STATES ///< Number of drain states. } DRAIN_STATE_T; // ********** private data ********** -static BOOL patientDisconnectionConfirmed = FALSE; ///< Flag indicates user confirms patient disconnection. -static BOOL disposableRemovalConfirmed = FALSE; ///< Flag indicates user confirms disposable removal. - -static BOOL isDrainStarted = FALSE; ///< Flag indicates a drain operation has been started. -static BOOL isDrainCompleted = FALSE; ///< Flag indicates drain has completed. -static BOOL rinseConcentrateLines = FALSE; ///< FLag indicates to rinse concentrate lines. - +static BOOL patientDisconnectionConfirmed; ///< Flag indicates user confirms patient disconnection. +static BOOL disposableRemovalConfirmed; ///< Flag indicates user confirms disposable removal. +static BOOL rinseConcentrateLines; ///< FLag indicates to rinse concentrate lines. +static BOOL isThisFirstDrain; ///< Flag to indicate whether this is the first time the reservoir is drained. static HD_POST_TREATMENT_STATE_T currentPostTreatmentState; ///< Current state of post-treatment mode state machine. static DRAIN_STATE_T currentDrainReservoirState; ///< Current drain reservoir state. static U32 postTreatmentPublishTimerCounter; ///< Timer counter used to schedule post-treatment data broadcast. @@ -82,28 +78,27 @@ static HD_POST_TREATMENT_STATE_T handlePostTreatmentVerifyState( void ); static void execDrainReservoirs( void ); -static BOOL isReservoirDrainStarted( void ); -static DRAIN_STATE_T handleDrainFirstReservoirStartState( void ); -static DRAIN_STATE_T handleDrainFirstReservoirState( void ); -static DRAIN_STATE_T handleDrainSwitchReservoirState( void ); -static DRAIN_STATE_T handleDrainSecondReservoirState( void ); +static DRAIN_STATE_T handleDrainReservoirSwitchState( void ); +static DRAIN_STATE_T handleDrainReservoirStartDrainState( void ); +static DRAIN_STATE_T handleDrainReservoirDrainState( void ); /*********************************************************************//** * @brief * The initPostTreatmentMode function initializes the Post-Treatment Mode module. * @details Inputs: none - * @details Outputs: Post-Treatment Mode module initialized. + * @details Outputs: patientDisconnectionConfirmed, disposableRemovalConfirmed, + * rinseConcentrateLines, isThisFirstDrain, currentPostTreatmentState, + * currentDrainReservoirState, postTreatmentPublishTimerCounter, treatmentLogData * @return none *************************************************************************/ void initPostTreatmentMode( void ) { - patientDisconnectionConfirmed = FALSE; - disposableRemovalConfirmed = FALSE; - isDrainStarted = FALSE; - isDrainCompleted = FALSE; - rinseConcentrateLines = FALSE; - currentPostTreatmentState = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; - currentDrainReservoirState = DRAIN_FIRST_RESERVOIR_START_STATE; + patientDisconnectionConfirmed = FALSE; + disposableRemovalConfirmed = FALSE; + rinseConcentrateLines = FALSE; + isThisFirstDrain = TRUE; + currentPostTreatmentState = HD_POST_TREATMENT_DRAIN_RESERVOIRS_STATE; + currentDrainReservoirState = DRAIN_RESERVOIR_SWITCH_STATE; postTreatmentPublishTimerCounter = 0; // Reset treatment log data @@ -145,6 +140,8 @@ collectTreatmentLogData(); + exitBloodLeakNormalState(); + return currentPostTreatmentState; } @@ -184,9 +181,12 @@ if ( ++postTreatmentPublishTimerCounter >= getU32OverrideValue( &postTreatmentModePublishInterval ) ) { - U32 state = (U32)currentPostTreatmentState; + POST_TREATMENT_STATE_DATA_T data; - broadcastData( MSG_ID_HD_POST_TREATMENT_STATE, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&state, sizeof( U32 ) ); + data.currentPostTreatmentState = (U32)currentPostTreatmentState; + data.currentPostTxDrainState = (U32)currentDrainReservoirState; + + broadcastData( MSG_ID_HD_POST_TREATMENT_STATE, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( POST_TREATMENT_STATE_DATA_T ) ); postTreatmentPublishTimerCounter = 0; } @@ -303,7 +303,7 @@ BOOL accepted = FALSE; REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_DRAIN_NOT_COMPLETE; - if ( DRAIN_COMPLETE_STATE == currentDrainReservoirState ) + if ( DRAIN_RESERVOIR_COMPLETE_STATE == currentDrainReservoirState ) { disposableRemovalConfirmed = TRUE; accepted = TRUE; @@ -341,8 +341,9 @@ execDrainReservoirs(); - if ( DRAIN_COMPLETE_STATE == currentDrainReservoirState ) + if ( DRAIN_RESERVOIR_COMPLETE_STATE == currentDrainReservoirState ) { + // Done with draining the reservoirs state = HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE; } @@ -359,22 +360,35 @@ *************************************************************************/ static HD_POST_TREATMENT_STATE_T handlePostTreatmentPatientDisconnectionState( void ) { - F32 const bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); - F32 const hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); - HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE; VALVE_T valve; - if ( STATE_CLOSED == getFPGADoorState() ) + F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); + HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_PATIENT_DISCONNECTION_STATE; + OPN_CLS_STATE_T frontDoor = getSwitchStatus( FRONT_DOOR ); + OPN_CLS_STATE_T pumpTrack = getSwitchStatus( PUMP_TRACK_SWITCH ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_SWITCHES_MONITOR ) ) { + frontDoor = STATE_CLOSED; + pumpTrack = STATE_CLOSED; + } +#endif + + if ( ( STATE_CLOSED == frontDoor ) && ( STATE_CLOSED == pumpTrack ) ) + { +#ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) { patientDisconnectionConfirmed = TRUE; } +#endif if ( TRUE == patientDisconnectionConfirmed ) { patientDisconnectionConfirmed = FALSE; - state = HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE; + state = HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE; for ( valve = VDI; valve < NUM_OF_VALVES; valve++ ) { @@ -393,7 +407,15 @@ } else { - activateAlarmNoData( ALARM_ID_CARTRIDGE_DOOR_OPENED ); + if ( STATE_OPEN == frontDoor ) + { + activateAlarmNoData( ALARM_ID_CARTRIDGE_DOOR_OPENED ); + } + + if ( STATE_OPEN == pumpTrack ) + { + activateAlarmNoData( ALARM_ID_PUMP_TRACK_LATCH_OPENED ); + } } return state; @@ -411,15 +433,17 @@ { HD_POST_TREATMENT_STATE_T state = HD_POST_TREATMENT_DISPOSABLE_REMOVAL_STATE; +#ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_INTERACTION ) ) { disposableRemovalConfirmed = TRUE; } +#endif if ( TRUE == disposableRemovalConfirmed ) { disposableRemovalConfirmed = FALSE; - state = HD_POST_TREATMENT_VERIFY_STATE; + state = HD_POST_TREATMENT_VERIFY_STATE; } return state; @@ -428,7 +452,7 @@ /*********************************************************************//** * @brief * The handlePostTreatmentVerifyState function verifies cartridge removed, - * syringe removed, and doors are closed before transition to standby mode. + * syringe removed before transition to standby mode. * @details Inputs: doors' status, syringe status, occlusion sensors value * @details Outputs: requested transition to standby mode * @return current state (sub-mode) @@ -446,28 +470,47 @@ isCartridgeRemoved = isCartridgeUnloaded(); } - if ( STATE_CLOSED == getFPGADoorState() ) + if ( FALSE == isCartridgeRemoved ) { - if ( FALSE == isCartridgeRemoved ) + activateAlarmNoData( ALARM_ID_CARTRIDGE_REMOVAL_FAILURE ); + } + else + { + clearAlarmCondition( ALARM_ID_CARTRIDGE_REMOVAL_FAILURE ); + } + + if ( TRUE == isSyringeDetected() ) + { +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - activateAlarmNoData( ALARM_ID_CARTRIDGE_REMOVAL_FAILURE ); + activateAlarmNoData( ALARM_ID_HD_SYRINGE_DETECTED ); } + } + else + { + clearAlarmCondition( ALARM_ID_HD_SYRINGE_DETECTED ); + } - if ( TRUE == isSyringeDetected() ) + // Wait for cartridge and syringe to be removed and for DG to finish any drains/fills. + if ( TRUE == isCartridgeRemoved ) + { + BOOL isSyringePumpDetected = isSyringeDetected(); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) ) { - activateAlarmNoData( ALARM_ID_HD_SYRINGE_DETECTED ); + isSyringePumpDetected = FALSE; } - // Wait for cartridge and syringe to be removed and for DG to finish any drains/fills. - if ( ( TRUE == isCartridgeRemoved ) && ( FALSE == isSyringeDetected() ) ) +#endif + + if ( FALSE == isSyringePumpDetected ) { cmdStopDG(); requestNewOperationMode( MODE_STAN ); } } - else - { - activateAlarmNoData( ALARM_ID_CARTRIDGE_DOOR_OPENED ); - } return HD_POST_TREATMENT_VERIFY_STATE; } @@ -483,80 +526,53 @@ { switch ( currentDrainReservoirState ) { - case DRAIN_FIRST_RESERVOIR_START_STATE: - currentDrainReservoirState = handleDrainFirstReservoirStartState(); + case DRAIN_RESERVOIR_SWITCH_STATE: + currentDrainReservoirState = handleDrainReservoirSwitchState(); break; - case DRAIN_FIRST_RESERVOIR_STATE: - currentDrainReservoirState = handleDrainFirstReservoirState(); + case DRAIN_RESERVOIR_START_DRAIN_STATE: + currentDrainReservoirState = handleDrainReservoirStartDrainState(); break; - case DRAIN_SWITCH_RESERVOIR_STATE: - currentDrainReservoirState = handleDrainSwitchReservoirState(); + case DRAIN_RESERVOIR_DRAIN_STATE: + currentDrainReservoirState = handleDrainReservoirDrainState(); break; - case DRAIN_SECOND_RESERVOIR_STATE: - currentDrainReservoirState = handleDrainSecondReservoirState(); + case DRAIN_RESERVOIR_COMPLETE_STATE: break; - case DRAIN_COMPLETE_STATE: - break; - default: - currentDrainReservoirState = DRAIN_FIRST_RESERVOIR_START_STATE; + currentDrainReservoirState = DRAIN_RESERVOIR_SWITCH_STATE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_POST_TREATMENT_RESERVOIR_MGMT_INVALID_STATE, currentDrainReservoirState ); break; } } /*********************************************************************//** * @brief - * The isReservoirDrainStarted function checks if reservoir drain has started. - * @details Inputs: none - * @details Outputs: processed drain command response - * @return TRUE if reservoir drain has started, otherwise FALSE - *************************************************************************/ -static BOOL isReservoirDrainStarted( void ) -{ - DG_CMD_RESPONSE_T dgCmdResp; - BOOL result = FALSE; - - if ( TRUE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) - { - if ( DG_CMD_REQUEST_REJECT_REASON_NONE == dgCmdResp.rejectCode ) - { - result = TRUE; - } - else - { - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, rinseConcentrateLines, TRUE ); - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The handleDrainReservoirOneState function sends command to DG to - * drain first reservoir. - * @details Inputs: none - * @details Outputs: drained reservoir one + * The handleDrainReservoirSwitchState function waits for DG to complete + * reservoir switch. + * @details Inputs: isThisFirstDrain + * @details Outputs: rinseConcentrateLines * @return next state *************************************************************************/ -static DRAIN_STATE_T handleDrainFirstReservoirStartState( void ) +static DRAIN_STATE_T handleDrainReservoirSwitchState( void ) { - DRAIN_STATE_T state = DRAIN_FIRST_RESERVOIR_START_STATE; + DRAIN_STATE_T state = DRAIN_RESERVOIR_SWITCH_STATE; if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) { - cmdSetDGActiveReservoir( DG_RESERVOIR_2 ); + // The first drain starts with setting the reservoir 2 as active and then the first reservoir is drained + DG_RESERVOIR_ID_T id = ( TRUE == isThisFirstDrain ? DG_RESERVOIR_2 : DG_RESERVOIR_1 ); + cmdSetDGActiveReservoir( id ); + if ( TRUE == hasDGCompletedReservoirSwitch() ) { - state = DRAIN_FIRST_RESERVOIR_STATE; - rinseConcentrateLines = TRUE; - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, rinseConcentrateLines, TRUE ); + // Check if the reservoir switch has been completed + // If this is the first drain, rinse the concentrate lines too + rinseConcentrateLines = ( TRUE == isThisFirstDrain ? TRUE : FALSE ); + state = DRAIN_RESERVOIR_START_DRAIN_STATE; } } @@ -565,97 +581,55 @@ /*********************************************************************//** * @brief - * The handleDrainFirstReservoirState function waits for DG to finish draining - * first reservoir and sends command to switch reservoir. - * @details Inputs: none - * @details Outputs: drained first reservoir + * The handleDrainReservoirStartDrainState function sends command to DG to + * send the drain command to DG. + * @details Inputs: rinseConcentrateLines + * @details Outputs: none * @return next state *************************************************************************/ -static DRAIN_STATE_T handleDrainFirstReservoirState( void ) +static DRAIN_STATE_T handleDrainReservoirStartDrainState( void ) { - DRAIN_STATE_T state = DRAIN_FIRST_RESERVOIR_STATE; + DRAIN_STATE_T state = DRAIN_RESERVOIR_START_DRAIN_STATE; - if ( TRUE == isReservoirDrainStarted() ) + if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) { - isDrainStarted = TRUE; - } + DG_CMD_RESPONSE_T dgCmdResp; - // Drain has started and DG goes to re-circ mode flush lines state means drain completed - if ( ( TRUE == isDrainStarted ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_LINES == getDGSubMode() ) ) - { - isDrainCompleted = TRUE; - } - - if ( TRUE == isDrainCompleted ) - { - if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) + // If DG is still in the Idle mode in the flush water state and the drain command has not been sent, send the drain command + if ( FALSE == getDGCommandResponse( DG_CMD_START_DRAIN, &dgCmdResp ) ) { - isDrainStarted = FALSE; - isDrainCompleted = FALSE; - state = DRAIN_SWITCH_RESERVOIR_STATE; - cmdSetDGActiveReservoir( getDGInactiveReservoir() ); + cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, rinseConcentrateLines, TRUE ); } } - - return state; -} - -/*********************************************************************//** - * @brief - * The handleDrainSwitchReservoirState function waits for DG to complete - * reservoir switch and sends drain command. - * @details Inputs: none - * @details Outputs: proceed to next state after DG switched reservoir - * @return next state - *************************************************************************/ -static DRAIN_STATE_T handleDrainSwitchReservoirState( void ) -{ - DRAIN_STATE_T state = DRAIN_SWITCH_RESERVOIR_STATE; - - if ( TRUE == hasDGCompletedReservoirSwitch() ) + else if ( DG_MODE_DRAI == getDGOpMode() ) { - state = DRAIN_SECOND_RESERVOIR_STATE; - rinseConcentrateLines = FALSE; - cmdStartDGDrain( DRAIN_RESERVOIR_TO_VOLUME_ML, TRUE, rinseConcentrateLines, TRUE ); + // If the drain has started, transition to drain state + state = DRAIN_RESERVOIR_DRAIN_STATE; } return state; } /*********************************************************************//** * @brief - * The handleDrainReservoirTwoState function waits for DG to finish draining - * second reservoir. - * @details Inputs: none - * @details Outputs: drained second reservoir + * The handleDrainReservoirDrainState function waits for DG to finish draining + * a reservoir. + * @details Inputs: isThisFirstDrain + * @details Outputs: isThisFirstDrain * @return next state *************************************************************************/ -static DRAIN_STATE_T handleDrainSecondReservoirState( void ) +static DRAIN_STATE_T handleDrainReservoirDrainState( void ) { - DRAIN_STATE_T state = DRAIN_SECOND_RESERVOIR_STATE; + DRAIN_STATE_T state = DRAIN_RESERVOIR_DRAIN_STATE; - if ( TRUE == isReservoirDrainStarted() ) + if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) { - isDrainStarted = TRUE; + // Decide which state should the state machine transition + state = ( TRUE == isThisFirstDrain ? DRAIN_RESERVOIR_SWITCH_STATE : DRAIN_RESERVOIR_COMPLETE_STATE ); + // At least the first reservoir has been drained so far so set the variable to false. + isThisFirstDrain = FALSE; } - // Drain has started and DG goes to generation idle mode flush lines state means drain completed - if ( ( TRUE == isDrainStarted ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_LINES == getDGSubMode() ) ) - { - isDrainCompleted = TRUE; - } - - if ( TRUE == isDrainCompleted ) - { - if ( ( DG_MODE_GENE == getDGOpMode() ) && ( DG_GEN_IDLE_MODE_STATE_FLUSH_WATER == getDGSubMode() ) ) - { - isDrainStarted = FALSE; - isDrainCompleted = FALSE; - rinseConcentrateLines = FALSE; - state = DRAIN_COMPLETE_STATE; - } - } - return state; }