Index: firmware/App/Modes/Rinseback.c =================================================================== diff -u -rc45ed31616b3b90de1d62d5c4b9db2339228371d -ra2a882ee989ef142887cd54a0f8311addaca812d --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision c45ed31616b3b90de1d62d5c4b9db2339228371d) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision a2a882ee989ef142887cd54a0f8311addaca812d) @@ -63,12 +63,12 @@ static U32 rinsebackRate_mL_min; ///< Rinseback rate to use/adjust for this current rinseback only. static U32 rinsebackTimerCtr; ///< Timer counter for time spent in rinseback sub-mode. -static F32 cumulativeRinsebackVolume_mL; ///< Total cumulative rinseback volume (in mL). +static OVERRIDE_F32_T cumulativeRinsebackVolume_mL = { 0.0, 0.0, 0.0, 0 }; ///< Total cumulative rinseback volume (in mL). +static OVERRIDE_F32_T rinsebackVolumeDelivered_Safety = { 0.0, 0.0, 0.0, 0 }; ///< The cumulative independent rinseback volume (in mL) calculated so far. static F32 targetRinsebackVolumePlusAdditional_mL; ///< Target rinseback volume w/ additional volume(s) added (in mL). static F32 additionalRinsebackVolume_mL; ///< Total volume (in mL) delivered so far for additional volume request. static S32 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 U32 rinsebackPublishTimerCtr; ///< Timer counter for determining interval for rinseback status to be published. @@ -90,6 +90,9 @@ static void setupForRinsebackDelivery( U32 rate ); static void setupForRinsebackStopOrPause( void ); +static F32 getRinsebackVolume( void ); +static F32 getRinsebackSafetyVolume( void ); + static RINSEBACK_STATE_T handleRinsebackStopInitState( void ); static RINSEBACK_STATE_T handleRinsebackRunState( void ); static RINSEBACK_STATE_T handleRinsebackPausedState( void ); @@ -122,11 +125,11 @@ rinsebackRate_mL_min = getTreatmentParameterU32( TREATMENT_PARAM_RINSEBACK_FLOW_RATE ); targetRinsebackVolumePlusAdditional_mL = TARGET_RINSEBACK_VOLUME_ML; rinsebackTimerCtr = 0; - cumulativeRinsebackVolume_mL = 0.0; + cumulativeRinsebackVolume_mL.data = 0.0; + rinsebackVolumeDelivered_Safety.data = 0.0; additionalRinsebackVolume_mL = 0.0; rinsebackMotorCount = 0; rinsebackLastMotorCount = getBloodPumpMotorCount(); - rinsebackVolumeDelivered_Safety = 0.0; rinsebackAdditionalTimerCtr = 0; rinsebackPublishTimerCtr = 0; resetRinsebackFlags(); @@ -230,6 +233,46 @@ /*********************************************************************//** * @brief + * The getRinsebackVolume function gets the calculated blood prime volume + * delivered. + * @details Inputs: cumulativeRinsebackVolume_mL + * @details Outputs: none + * @return the current rinseback volume delivered (in mL). + *************************************************************************/ +static F32 getRinsebackVolume( void ) +{ + F32 result = cumulativeRinsebackVolume_mL.data; + + if ( OVERRIDE_KEY == cumulativeRinsebackVolume_mL.override ) + { + result = cumulativeRinsebackVolume_mL.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getRinsebackSafetyVolume function gets the calculated independent + * blood prime volume delivered. + * @details Inputs: rinsebackVolumeDelivered_Safety + * @details Outputs: none + * @return the current rinseback safety volume delivered (in mL). + *************************************************************************/ +static F32 getRinsebackSafetyVolume( void ) +{ + F32 result = rinsebackVolumeDelivered_Safety.data; + + if ( OVERRIDE_KEY == rinsebackVolumeDelivered_Safety.override ) + { + result = rinsebackVolumeDelivered_Safety.ovData; + } + + return result; +} + +/*********************************************************************//** + * @brief * The getCurrentRinsebackState function returns the current state of the * rinseback sub-mode. * @details Inputs: rinsebackState @@ -343,10 +386,10 @@ rinsebackTimerCtr = 0; // Update rinseback volume delivered so far - cumulativeRinsebackVolume_mL += ( getMeasuredBloodFlowRate() * RINSEBACK_FLOW_INTEGRATOR ); + cumulativeRinsebackVolume_mL.data += ( getMeasuredBloodFlowRate() * RINSEBACK_FLOW_INTEGRATOR ); // update independent calculated safety volume delivered so far rinsebackMotorCount = u32BiDiffWithWrap( rinsebackLastMotorCount, getBloodPumpMotorCount() ) / BP_HALL_EDGE_COUNTS_PER_REV; - rinsebackVolumeDelivered_Safety = ( (F32)rinsebackMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc + rinsebackVolumeDelivered_Safety.data = ( (F32)rinsebackMotorCount * VOLUME_PER_BP_MOTOR_REV_ML ); // TODO - include upstream pressure compensation to this calc // Has user requested to end rinseback? if ( TRUE == endRinsebackRequested ) @@ -355,16 +398,16 @@ result = RINSEBACK_STOP_STATE; } // Has rinseback completed? - else if ( cumulativeRinsebackVolume_mL >= TARGET_RINSEBACK_VOLUME_ML ) + else if ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) { setRinsebackIsCompleted( TRUE ); setupForRinsebackStopOrPause(); result = RINSEBACK_STOP_STATE; #ifndef DISABLE_PUMP_FLOW_CHECKS // Check for under-delivery - if ( rinsebackVolumeDelivered_Safety < MIN_RINSEBACK_SAFETY_VOLUME_ML ) + if ( getRinsebackSafetyVolume() < MIN_RINSEBACK_SAFETY_VOLUME_ML ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_RINSEBACK_VOLUME_CHECK_FAILURE, TARGET_RINSEBACK_VOLUME_ML, rinsebackVolumeDelivered_Safety ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_RINSEBACK_VOLUME_CHECK_FAILURE, TARGET_RINSEBACK_VOLUME_ML, getRinsebackSafetyVolume() ); } #endif } @@ -383,11 +426,11 @@ } #ifndef DISABLE_PUMP_FLOW_CHECKS // Has independent safety volume exceeded safety limit? - else if ( rinsebackVolumeDelivered_Safety > MAX_RINSEBACK_SAFETY_VOLUME_ML ) + else if ( getRinsebackSafetyVolume() > MAX_RINSEBACK_SAFETY_VOLUME_ML ) { setRinsebackIsCompleted( TRUE ); setupForRinsebackStopOrPause(); - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_RINSEBACK_VOLUME_CHECK_FAILURE, TARGET_RINSEBACK_VOLUME_ML, rinsebackVolumeDelivered_Safety ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_RINSEBACK_VOLUME_CHECK_FAILURE, TARGET_RINSEBACK_VOLUME_ML, getRinsebackSafetyVolume() ); result = RINSEBACK_STOP_STATE; } #endif @@ -469,7 +512,7 @@ signalRinsebackToRecirc(); } // Has rinseback operation exceeded max time w/o delivering full volume? - if ( ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) && ( cumulativeRinsebackVolume_mL < TARGET_RINSEBACK_VOLUME_ML ) ) + if ( ( rinsebackTimerCtr > MAX_RINSEBACK_TIME ) && ( getRinsebackVolume() < TARGET_RINSEBACK_VOLUME_ML ) ) { signalGoToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); @@ -478,8 +521,8 @@ { additionalRinsebackRequested = FALSE; // deliver additional rinseback volume only if max volume not reached and max time not reached - if ( ( ( cumulativeRinsebackVolume_mL + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) && - ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( cumulativeRinsebackVolume_mL >= TARGET_RINSEBACK_VOLUME_ML ) ) ) + if ( ( ( getRinsebackVolume() + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) && + ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) ) { rinsebackAdditionalTimerCtr = 0; additionalRinsebackVolume_mL = 0.0; @@ -518,12 +561,12 @@ // update additional rinseback volume delivered so far additionalRinsebackVolume_mL += rinsebackVolumeSinceLast; - cumulativeRinsebackVolume_mL += rinsebackVolumeSinceLast; + cumulativeRinsebackVolume_mL.data += rinsebackVolumeSinceLast; rinsebackAdditionalTimerCtr++; // Has additional rinseback completed or timed out? if ( ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) || - ( cumulativeRinsebackVolume_mL >= MAX_TOTAL_RINSEBACK_VOLUME_ML ) || + ( getRinsebackVolume() >= MAX_TOTAL_RINSEBACK_VOLUME_ML ) || ( rinsebackAdditionalTimerCtr >= MAX_RINSEBACK_ADDITIONAL_TIME ) ) { setupForRinsebackStopOrPause(); @@ -811,7 +854,7 @@ if ( RINSEBACK_STOP_STATE == rinsebackState ) { - if ( ( cumulativeRinsebackVolume_mL + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) + if ( ( getRinsebackVolume() + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) { result = TRUE; additionalRinsebackRequested = TRUE; @@ -937,7 +980,7 @@ rinsebackPublishTimerCtr = 0; // If we have completed rinseback, timeout is no longer in force - indicate by zeroing timeout - if ( ( rinsebackState > RINSEBACK_PAUSED_STATE ) && ( cumulativeRinsebackVolume_mL >= TARGET_RINSEBACK_VOLUME_ML ) ) + if ( ( rinsebackState > RINSEBACK_PAUSED_STATE ) && ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) { timeout = 0; } @@ -946,7 +989,8 @@ { data.targetRinsebackVolumeMl = targetRinsebackVolumePlusAdditional_mL; } - data.deliveredRinsebackVolumeMl = cumulativeRinsebackVolume_mL; + data.deliveredRinsebackVolumeMl = getRinsebackVolume(); + data.safetyRinsebackVolumeMl = getRinsebackSafetyVolume(); data.rinsebackFlowRateMlMin = rinsebackRate_mL_min; if ( RINSEBACK_RUN_ADDITIONAL_STATE == rinsebackState ) { @@ -958,4 +1002,100 @@ } } + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetRinsebackVolumeOverride function overrides the calculated + * rinseback volume delivered. + * @details Inputs: none + * @details Outputs: cumulativeRinsebackVolume_mL + * @param vol override calculated rinseback volume (in mL) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetRinsebackVolumeOverride( F32 vol ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + cumulativeRinsebackVolume_mL.ovData = vol; + cumulativeRinsebackVolume_mL.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetRinsebackVolumeOverride function resets the override of the + * calculated rinseback volume. + * @details Inputs: none + * @details Outputs: cumulativeRinsebackVolume_mL + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetRinsebackVolumeOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + cumulativeRinsebackVolume_mL.override = OVERRIDE_RESET; + cumulativeRinsebackVolume_mL.ovData = cumulativeRinsebackVolume_mL.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetRinsebackSafetyVolumeOverride function overrides the calculated + * rinseback volume. + * @details Inputs: none + * @details Outputs: rinsebackVolumeDelivered_Safety + * @param vol override calculated rinseback safety volume (in mL) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetRinsebackSafetyVolumeOverride( F32 vol ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + rinsebackVolumeDelivered_Safety.ovData = vol; + rinsebackVolumeDelivered_Safety.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetRinsebackSafetyVolumeOverride function resets the override of the + * calculated rinseback safety volume. + * @details Inputs: none + * @details Outputs: rinsebackVolumeDelivered_Safety + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetRinsebackSafetyVolumeOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + rinsebackVolumeDelivered_Safety.override = OVERRIDE_RESET; + rinsebackVolumeDelivered_Safety.ovData = rinsebackVolumeDelivered_Safety.ovInitData; + } + + return result; +} + /**@}*/