Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r8466e63f95f65a3ffb18c3af85ac99328e41167b -r028345aae95254cd8ff027d0da533b345da06b4f --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 8466e63f95f65a3ffb18c3af85ac99328e41167b) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 028345aae95254cd8ff027d0da533b345da06b4f) @@ -289,12 +289,12 @@ { rejReason = REQUEST_REJECT_REASON_DG_NOT_IN_STANDBY_IDLE_STATE; } - +#ifndef DISABLE_BATT_COMM if ( FALSE == isBatteryCharged() ) { rejReason = REQUEST_REJECT_REASON_BATTERY_IS_NOT_CHARGED; } - +#endif if ( REQUEST_REJECT_REASON_NONE == rejReason ) { result = TRUE; Index: firmware/App/Modes/Rinseback.c =================================================================== diff -u -r1c628bfd5d6414b74b8cbd083f66839888a8236b -r028345aae95254cd8ff027d0da533b345da06b4f --- firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 1c628bfd5d6414b74b8cbd083f66839888a8236b) +++ firmware/App/Modes/Rinseback.c (.../Rinseback.c) (revision 028345aae95254cd8ff027d0da533b345da06b4f) @@ -37,12 +37,12 @@ // ********** private definitions ********** -#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 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_ADDITIONAL_RINSEBACK_VOLUME_ML 300.0 ///< Maximum total additional rinseback volume allowed : all additionals (in mL). +#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). #ifndef DISABLE_PUMP_FLOW_CHECKS /// Maximum rinseback volume measured by independent means (as % of target). @@ -57,6 +57,8 @@ static const U32 MAX_RINSEBACK_TIME = ( 5 * SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); /// Maximum time allowed after rinseback operation completed. Timer is reset whenever BP is running (additional). static const U32 MAX_RINSEBACK_DONE_TIME = ( 15 * SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); +/// Warning time after rinseback operation completed. Timer is reset whenever BP is running (additional). +static const U32 RINSEBACK_DONE_WARNING_TIME = ( 14 * SEC_PER_MIN * ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); /// Maximum time allowed for each additional rinseback volume delivery. static const U32 MAX_RINSEBACK_ADDITIONAL_TIME = ( 20 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ); /// Multiplier to convert flow (mL/min) into volume (mL) for period of general task interval. @@ -72,6 +74,7 @@ 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 F32 totalAdditionalRinsebackVolume_mL; ///< Total accumulated volume (in mL) delivered so far for all additional volumes combined. 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 U32 rinsebackAdditionalTimerCtr; ///< Timer counter for duration of an additional rinseback delivery. @@ -136,6 +139,7 @@ cumulativeRinsebackVolume_mL.data = 0.0; rinsebackVolumeDelivered_Safety.data = 0.0; additionalRinsebackVolume_mL = 0.0; + totalAdditionalRinsebackVolume_mL = 0.0; rinsebackMotorCount = 0; rinsebackLastMotorCount = getBloodPumpMotorCount(); rinsebackAdditionalTimerCtr = 0; @@ -526,7 +530,13 @@ { signalGoToTreatmentStopped(); activateAlarmNoData( ALARM_ID_TREATMENT_RINSEBACK_TIMEOUT_ALARM ); + clearAlarm( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING ); } + // Have we been in this stopped state for too long despite having delivered full blood volume back to patient? + else if ( ( rinsebackTimerCtr > RINSEBACK_DONE_WARNING_TIME ) && ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) + { + activateAlarmNoData( ALARM_ID_HD_TREATMENT_RINSEBACK_TIMEOUT_WARNING ); + } else if ( TRUE == recircRequested ) { signalRinsebackToRecirc(); @@ -535,8 +545,7 @@ { additionalRinsebackRequested = FALSE; // deliver additional rinseback volume only if max volume not reached and max time not reached - if ( ( ( getRinsebackVolume() + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) && - ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) ) + if ( ( rinsebackTimerCtr < MAX_RINSEBACK_TIME ) || ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ) ) { rinsebackAdditionalTimerCtr = 0; additionalRinsebackVolume_mL = 0.0; @@ -575,12 +584,12 @@ // update additional rinseback volume delivered so far additionalRinsebackVolume_mL += rinsebackVolumeSinceLast; + totalAdditionalRinsebackVolume_mL += rinsebackVolumeSinceLast; cumulativeRinsebackVolume_mL.data += rinsebackVolumeSinceLast; rinsebackAdditionalTimerCtr++; // Has additional rinseback completed or timed out? if ( ( additionalRinsebackVolume_mL >= TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) || - ( getRinsebackVolume() >= MAX_TOTAL_RINSEBACK_VOLUME_ML ) || ( rinsebackAdditionalTimerCtr >= MAX_RINSEBACK_ADDITIONAL_TIME ) ) { setupForRinsebackStopOrPause(); @@ -870,14 +879,14 @@ if ( RINSEBACK_STOP_STATE == rinsebackState ) { - if ( ( getRinsebackVolume() + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_RINSEBACK_VOLUME_ML ) + if ( ( totalAdditionalRinsebackVolume_mL + TARGET_ADDITIONAL_RINSEBACK_VOLUME_ML ) <= MAX_TOTAL_ADDITIONAL_RINSEBACK_VOLUME_ML ) { result = TRUE; additionalRinsebackRequested = TRUE; } else { - *rejReason = REQUEST_REJECT_REASON_RINSEBACK_MAX_VOLUME_REACHED; + *rejReason = REQUEST_REJECT_REASON_ADDL_RINSEBACK_MAX_VOLUME_REACHED; } } else @@ -910,6 +919,10 @@ { *rejReason = REQUEST_REJECT_REASON_ACTION_DISABLED_IN_CURRENT_STATE; } + else if ( getRinsebackVolume() < TARGET_RINSEBACK_VOLUME_ML ) + { + *rejReason = REQUEST_REJECT_REASON_RINSEBACK_NOT_COMPLETED; + } else { result = TRUE; @@ -992,8 +1005,16 @@ { RINSEBACK_DATA_PAYLOAD_T data; U32 timeout = MAX_RINSEBACK_TIME / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); - U32 countdown = ( rinsebackTimerCtr >= MAX_RINSEBACK_TIME ? 0 : ( MAX_RINSEBACK_TIME - rinsebackTimerCtr ) / ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ); + U32 countdown = ( getRinsebackVolume() >= TARGET_RINSEBACK_VOLUME_ML ? MAX_RINSEBACK_TIME : MAX_RINSEBACK_DONE_TIME ); + // Handle countdown past zero + if ( countdown > MAX_RINSEBACK_DONE_TIME ) + { + countdown = 0; + } + // Scale to seconds + countdown /= ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ); + data.targetRinsebackVolumeMl = TARGET_RINSEBACK_VOLUME_ML; rinsebackPublishTimerCtr = 0; // If we have completed rinseback, timeout is no longer in force - indicate by zeroing timeout. Also include any additionals to target.