Index: firmware/App/Modes/Rinseback.c =================================================================== diff -u -r19476759e215857babf7ae7a69b32fdc08aef3d4 -r9ed01b26543fba3b0c2ed78534fb949b778d0355 --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 19476759e215857babf7ae7a69b32fdc08aef3d4) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 9ed01b26543fba3b0c2ed78534fb949b778d0355) @@ -37,18 +37,29 @@ // ********** private definitions ********** -#define TARGET_RINSEBACK_VOLUME_ML 300.0 ///< Target rinseback volume to deliver back to the patient (in mL). +#define TARGET_RINSEBACK_VOLUME_ML 300.0 ///< Target rinseback volume to deliver back to the patient (in mL). TODO - get from Systems when available +#define MAX_TOTAL_RINSEBACK_VOLUME_ML 400.0 ///< Maximum total rinseback volume allowed : main + all additionals (in mL). TODO - get from Systems when known +#define TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML 10.0 ///< Target rinseback volume for an additional volume request (in mL). #define RINSEBACK_FLOW_RATE_ADJ_ML_MIN 25 ///< Adjustment amount (in mL/min) to apply when user requests increase/decrease in flow rate. #define MIN_RINSEBACK_FLOW_RATE_ML_MIN 50 ///< Minimum rinseback flow rate (in mL/min). #define MAX_RINSEBACK_FLOW_RATE_ML_MIN 150 ///< Maximum rinseback flow rate (in mL/min). +#define MAX_RINSEBACK_VOLUME_PCT 1.2 ///< Maximum rinseback volume measured by independent means (as % of target). +/// Maximum time allowed for each additional rinseback volume delivery. +#define MAX_RINSEBACK_ADDITIONAL_TIME ( 15 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) + static const F32 RINSEBACK_FLOW_INTEGRATOR = 1.0 / (F32)( SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); // ********** private data ********** static RINSEBACK_STATE_T rinsebackState; ///< Current state of the rinseback sub-mode. static F32 cumulativeRinsebackVolume_mL; ///< Total cumulative rinseback volume (in mL). +static F32 additionalRinsebackVolume_mL; ///< Total volume (in mL) delivered so far for additional volume request. +static U32 rinsebackMotorCount; ///< The cumulative sum of BP motor encoder counts used for independent rinseback volume check. +static U32 rinsebackLastMotorCount; ///< The last BP motor encoder count read for independent rinseback volume check. +static F32 rinsebackVolumeDelivered_Safety; ///< The cumulative independent rinseback volume (in mL) calculated so far. +static U32 rinsebackAdditionalTimerCtr; ///< Timer counter for duration of an additional rinseback delivery. static BOOL rinsebackStopRequested; ///< Flag indicates alarm requesting to stop rinseback. static BOOL startRinsebackRequested; ///< Flag indicates user requesting rinseback start (confirming saline bag move to arterial line end). @@ -66,6 +77,9 @@ static void resetRinsebackFlags( void ); +static void setupForRinsebackDelivery( U32 rate ); +static void setupForRinsebackStopOrPause( void ); + static RINSEBACK_STATE_T handleRinsebackStopInitState( void ); static RINSEBACK_STATE_T handleRinsebackRunState( void ); static RINSEBACK_STATE_T handleRinsebackPausedState( void ); @@ -94,6 +108,11 @@ { rinsebackState = RINSEBACK_STOP_INIT_STATE; cumulativeRinsebackVolume_mL = 0.0; + additionalRinsebackVolume_mL = 0.0; + rinsebackMotorCount = 0; + rinsebackLastMotorCount = 0; + rinsebackVolumeDelivered_Safety = 0.0; + rinsebackAdditionalTimerCtr = 0; resetRinsebackFlags(); } @@ -146,6 +165,7 @@ signalBloodPumpHardStop(); signalDialOutPumpHardStop(); // TODO - stop Heparin pump + endAirTrapControl(); // Re-circulate dialysate side of dialyzer w/ heating to maintain temperature setDialInPumpTargetFlowRate( DIALYSATE_FLOW_RATE_FOR_RECIRC, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); @@ -154,6 +174,58 @@ /*********************************************************************//** * @brief + * The setupForRinsebackDelivery function sets actuators appropriately + * for rinseback states where delivery is in progress. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +static void setupForRinsebackDelivery( U32 rate ) +{ + // Open VBA and VBV valves to allow flow from saline bag and to patient venous line + setValvePosition( VBA, VALVE_POSITION_B_OPEN ); + setValvePosition( VBV, VALVE_POSITION_B_OPEN ); + // Start blood pump at rinseback flow rate + setBloodPumpTargetFlowRate( rate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + // Start air trap leveling control + startAirTrapControl(); +} + +/*********************************************************************//** + * @brief + * The setupForRinsebackStopOrPause function sets actuators appropriately + * for rinseback states where delivery is paused or stopped. + * @details Inputs: none + * @details Outputs: Blood pump stopped, arterial and venous lines closed, + * and air trap leveling control is stopped. + * @return none + *************************************************************************/ +static void setupForRinsebackStopOrPause( void ) +{ + // Stop blood pump + signalBloodPumpHardStop(); + // Close arterial and venous lines + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + // Stop air trap leveling control + endAirTrapControl(); +} + +/*********************************************************************//** + * @brief + * The getCurrentRinsebackState function returns the current state of the + * rinseback sub-mode. + * @details Inputs: rinsebackState + * @details Outputs: none + * @return rinsebackState + *************************************************************************/ +RINSEBACK_STATE_T getCurrentRinsebackState( void ) +{ + return rinsebackState; +} + +/*********************************************************************//** + * @brief * The execRinseback function executes the Rinseback sub-mode state machine. * @details Inputs: none * @details Outputs: none @@ -206,22 +278,19 @@ if ( TRUE == startRinsebackRequested ) { - // Open VBA and VBV valves to allow flow from saline bag and to patient venous line - setValvePosition( VBA, VALVE_POSITION_B_OPEN ); - setValvePosition( VBV, VALVE_POSITION_B_OPEN ); - // Start blood pump at rinseback flow rate - setBloodPumpTargetFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ), MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + startRinsebackRequested = FALSE; + setupForRinsebackDelivery( getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ) ); // From moment we start rinseback, we consider blood side of dialyzer no longer fully primed setBloodIsPrimed( FALSE ); result = RINSEBACK_RUN_STATE; } else if ( TRUE == backToTreatmentRequested ) { - // TODO - signal treatment mode to go back to treatment stop state + signalRinsebackToStopped(); } else if ( TRUE == endTreatmentRequested ) { - // TODO - signal treatment mode to go to treatment end state + signalRinsebackToEnd(); } return result; @@ -238,30 +307,40 @@ static RINSEBACK_STATE_T handleRinsebackRunState( void ) { RINSEBACK_STATE_T result = RINSEBACK_RUN_STATE; + U32 bldPumpMotorCount = getBloodPumpMotorCount(); + U32 bldPumpMotorDelta = u32DiffWithWrap( rinsebackLastMotorCount, bldPumpMotorCount ); - // TODO - update rinseback volume + // update rinseback volume delivered so far cumulativeRinsebackVolume_mL += ( getMeasuredBloodFlowRate() * RINSEBACK_FLOW_INTEGRATOR ); + // update independent calculated safety volume delivered so far + rinsebackMotorCount += bldPumpMotorDelta; + rinsebackLastMotorCount = bldPumpMotorCount; + rinsebackVolumeDelivered_Safety = ( (F32)rinsebackMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc - // Has rinseback completed? - if ( cumulativeRinsebackVolume_mL >= TARGET_RINSEBACK_VOLUME_ML ) + // Has rinseback completed or user requested to end rinseback? + if ( ( cumulativeRinsebackVolume_mL >= TARGET_RINSEBACK_VOLUME_ML ) || ( TRUE == endRinsebackRequested ) ) { - setRinsebackIsCompleted( TRUE ); + if ( FALSE == endRinsebackRequested ) + { + setRinsebackIsCompleted( TRUE ); + } + endRinsebackRequested = FALSE; + setupForRinsebackStopOrPause(); result = RINSEBACK_STOP_STATE; } // Has user or alarm requested rinseback pause? else if ( ( TRUE == pauseRinsebackRequested ) || ( TRUE == rinsebackStopRequested ) ) { - // TODO - BP off - // TODO - air trap control off - // TODO - VBA, VBV closed + pauseRinsebackRequested = FALSE; + rinsebackStopRequested = FALSE; + setupForRinsebackStopOrPause(); result = RINSEBACK_PAUSED_STATE; } - // Has user requested to end rinseback? - else if ( TRUE == endRinsebackRequested ) + // Has independent safety volume exceeded safety limit? + else if ( rinsebackVolumeDelivered_Safety > ( TARGET_RINSEBACK_VOLUME_ML * MAX_RINSEBACK_VOLUME_PCT ) ) { - // TODO - BP off - // TODO - air trap control off - // TODO - VBA, VBV closed + setRinsebackIsCompleted( TRUE ); + setupForRinsebackStopOrPause(); result = RINSEBACK_STOP_STATE; } // Otherwise, continue rinseback @@ -279,9 +358,12 @@ { rbRate -= RINSEBACK_FLOW_RATE_ADJ_ML_MIN; } + incrRinsebackFlowRateRequested = FALSE; + decrRinsebackFlowRateRequested = FALSE; if ( ( rbRate >= MIN_RINSEBACK_FLOW_RATE_ML_MIN ) && ( rbRate <= MAX_RINSEBACK_FLOW_RATE_ML_MIN ) ) { setTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE, rbRate ); + setBloodPumpTargetFlowRate( rbRate, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); } } @@ -305,11 +387,16 @@ if ( TRUE == resumeRinsebackRequested ) { - // TODO - VBA and VBV open - // TODO - BP on @ set rate - // TODO - air trap control on + resumeRinsebackRequested = FALSE; + setupForRinsebackDelivery( getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ) ); result = RINSEBACK_RUN_STATE; } + // Has user requested to end rinseback? + else if ( TRUE == endRinsebackRequested ) + { + endRinsebackRequested = FALSE; + result = RINSEBACK_STOP_STATE; + } return result; } @@ -331,6 +418,25 @@ { signalRinsebackToRecirc(); } + else if ( TRUE == additionalRinsebackRequested ) + { + additionalRinsebackRequested = FALSE; + if ( ( cumulativeRinsebackVolume_mL + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) + { + rinsebackAdditionalTimerCtr = 0; + additionalRinsebackVolume_mL = 0.0; + setupForRinsebackDelivery( MIN_RINSEBACK_FLOW_RATE_ML_MIN ); + result = RINSEBACK_RUN_ADDITIONAL_STATE; + } + } + else if ( TRUE == backToTreatmentRequested ) + { + signalRinsebackToStopped(); + } + else if ( TRUE == endTreatmentRequested ) + { + signalRinsebackToEnd(); + } return result; } @@ -346,7 +452,28 @@ static RINSEBACK_STATE_T handleRinsebackRunAdditionalState( void ) { RINSEBACK_STATE_T result = RINSEBACK_RUN_ADDITIONAL_STATE; + F32 rinsebackVolumeSinceLast = ( getMeasuredBloodFlowRate() * RINSEBACK_FLOW_INTEGRATOR ); + // update additional rinseback volume delivered so far + additionalRinsebackVolume_mL += rinsebackVolumeSinceLast; + cumulativeRinsebackVolume_mL += rinsebackVolumeSinceLast; + rinsebackAdditionalTimerCtr++; + + // Has additional rinseback completed or timed out? + if ( ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) || ( rinsebackAdditionalTimerCtr >= MAX_RINSEBACK_ADDITIONAL_TIME ) ) + { + setupForRinsebackStopOrPause(); + result = RINSEBACK_STOP_STATE; + } + // Has alarm requested stop? + else if( TRUE == rinsebackStopRequested ) + { + pauseRinsebackRequested = FALSE; + rinsebackStopRequested = FALSE; + setupForRinsebackStopOrPause(); + result = RINSEBACK_PAUSED_STATE; + } + return result; } @@ -630,8 +757,15 @@ if ( RINSEBACK_STOP_STATE == rinsebackState ) { - result = TRUE; - additionalRinsebackRequested = TRUE; + if ( ( cumulativeRinsebackVolume_mL + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) + { + result = TRUE; + additionalRinsebackRequested = TRUE; + } + else + { + *rejReason = REQUEST_REJECT_REASON_RINSEBACK_MAX_VOLUME_REACHED; + } } else { @@ -722,17 +856,4 @@ return result; } -/*********************************************************************//** - * @brief - * The getCurrentRinsebackState function returns the current state of the - * rinseback sub-mode. - * @details Inputs: rinsebackState - * @details Outputs: none - * @return rinsebackState - *************************************************************************/ -RINSEBACK_STATE_T getCurrentRinsebackState( void ) -{ - return rinsebackState; -} - /**@}*/