Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -rd3ae2d91603ae6d2d25b9abdb220cc144cf90692 -r054fa08b67ed2a31f7848b179fbcd1b4da501b0f --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision d3ae2d91603ae6d2d25b9abdb220cc144cf90692) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 054fa08b67ed2a31f7848b179fbcd1b4da501b0f) @@ -43,8 +43,13 @@ #define MAX_UF_RATE_ML_MIN ( (F32)2500 / (F32)MIN_PER_HOUR ) ///< Maximum ultrafiltration rate (in mL/min). #define MAX_DIALYSATE_VOLUME_ML ( 180 * ML_PER_LITER ) ///< Maximum dialysate volume (in mL). +#define PREVENT_UF_VOL_CHANGE_IF_NEARLY_DONE_SEC ( 10 * SEC_PER_MIN ) ///< Prevent UF volume change if treatment within this much time from end of treatment (in seconds). + #define TREATMENT_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the treatment time & state data is published on the CAN bus +#define CALC_ELAPSED_TREAT_TIME_IN_SECS() ( treatmentTimeMS / MS_PER_SECOND ) ///< Macro to calculate the elapsed treatment time in seconds. +#define CALC_TREAT_TIME_REMAINING_IN_SECS() ( (S32)presTreatmentTimeSecs - (S32)( treatmentTimeMS / MS_PER_SECOND ) ) ///< Macro to calculate the remaining treatment time in seconds. + // ********** private data ********** static TREATMENT_STATE_T currentTreatmentState; ///< Current state (sub-mode) of treatment mode. @@ -356,6 +361,7 @@ BOOL verifyTreatmentDurationSettingChange( U32 treatmentTime ) { BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; S32 timeDiff = 0; F32 rateDiff = 0.0; OP_MODE currMode = getCurrentOperationMode(); @@ -376,8 +382,30 @@ pendingTreatmentTimeChange = treatmentTime; // min timeDiff = treatmentTime - ( (U32)( (F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN ) + 1 ); } + else + { + if ( treatmentTime > MAX_TREATMENT_TIME_MINUTES ) + { + rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; + } + else + { + rejectReason = REQUEST_REJECT_REASON_DIAL_VOLUME_OUT_OF_RANGE; + } + } } - sendChangeUFSettingsResponse( result, pendingUFVolumeChange, pendingTreatmentTimeChange, pendingUFRateChange, timeDiff, rateDiff ); + else + { + if ( MODE_TREA == currMode ) + { + rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; + } + else + { + rejectReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; + } + } + sendChangeUFSettingsResponse( result, rejectReason, pendingUFVolumeChange, pendingTreatmentTimeChange, pendingUFRateChange, timeDiff, rateDiff ); return result; } @@ -396,12 +424,16 @@ BOOL verifyUFSettingsChange( F32 uFVolume, UF_ADJ_T adjustment ) { BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; S32 timeDiff = 0; F32 rateDiff = 0.0; OP_MODE currMode = getCurrentOperationMode(); - // check if we are in an appropriate treatment state for settings adjustment - if ( ( MODE_TREA == currMode ) && ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_DIALYSIS_END_STATE ) ) + // check if we are in an appropriate treatment state for settings adjustment // TODO - we cannot be within TBD min from end of treatment in order to allow UF volume change + if ( ( MODE_TREA == currMode ) && + ( currentTreatmentState > TREATMENT_START_STATE ) && + ( currentTreatmentState < TREATMENT_DIALYSIS_END_STATE ) && + ( CALC_TREAT_TIME_REMAINING_IN_SECS() < PREVENT_UF_VOL_CHANGE_IF_NEARLY_DONE_SEC ) ) { // TODO - verify not too close to end of treatment for settings change DIALYSIS_STATE_T currDialysisState = getDialysisState(); @@ -438,6 +470,18 @@ pendingTreatmentTimeChange = trtTime; timeDiff = trtTime - ( (U32)( (F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN ) + 1 ); } + else + { + if ( trtTime > MAX_TREATMENT_TIME_MINUTES ) + { + rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; + } + else + { + rejectReason = REQUEST_REJECT_REASON_DIAL_VOLUME_OUT_OF_RANGE; + } + + } } else { // UF Rate is adjusted then @@ -451,10 +495,30 @@ pendingTreatmentTimeChange = trtTime; rateDiff = ( uFRate - presUFRate ); } + else + { + rejectReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; + } } } + else + { + if ( MODE_TREA == currMode ) + { + rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; + } + else if ( ( currentTreatmentState <= TREATMENT_START_STATE ) || + ( currentTreatmentState >= TREATMENT_DIALYSIS_END_STATE ) ) + { + rejectReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; + } + else + { + rejectReason = REQUEST_REJECT_REASON_TREATMENT_TOO_CLOSE_TO_FINISHED; + } + } // respond to UF settings change request - sendChangeUFSettingsResponse( result, pendingUFVolumeChange, pendingTreatmentTimeChange, pendingUFRateChange, timeDiff, rateDiff ); + sendChangeUFSettingsResponse( result, rejectReason, pendingUFVolumeChange, pendingTreatmentTimeChange, pendingUFRateChange, timeDiff, rateDiff ); return result; } @@ -506,3 +570,57 @@ return result; } + +/*********************************************************************//** + * @brief + * The verifyBloodAndDialysateRateSettingsChange function verifies the \n + * user blood & dialysate flow rate settings change. + * @details + * Inputs : none + * Outputs : none + * @param bloodRate : Proposed new blood flow rate (in mL/min). + * @param dialRate : Proposed new dialysate flow rate (in mL/min). + * @return TRUE if new blood & dialysate rate settings are valid, FALSE if not. + *************************************************************************/ +BOOL verifyBloodAndDialysateRateSettingsChange( U32 bloodRate, U32 dialRate ) +{ + BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; + OP_MODE currMode = getCurrentOperationMode(); + + // check if we are in treatment mode for settings change + if ( MODE_TREA == currMode ) + { + U32 dialVolume = dialRate * ( (U32)( (F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN ) + 1 ); // in mL + + // validate new rates + if ( ( bloodRate >= MIN_BLOOD_FLOW_RATE ) && ( bloodRate <= MAX_BLOOD_FLOW_RATE ) && + ( dialRate >= MIN_DIAL_IN_FLOW_RATE ) && ( dialRate <= MAX_DIAL_IN_FLOW_RATE ) && + ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) + { + result = TRUE; + // set to new rates + presBloodFlowRate = bloodRate; + presDialysateFlowRate = dialRate; + setDialysisParams( presBloodFlowRate, presDialysateFlowRate, presMaxUFVolumeML, presUFRate ); + } + else + { + if ( ( bloodRate < MIN_BLOOD_FLOW_RATE ) || ( bloodRate > MAX_BLOOD_FLOW_RATE ) ) + { + rejectReason = REQUEST_REJECT_REASON_BLOOD_FLOW_OUT_OF_RANGE; + } + else if ( ( dialRate < MIN_DIAL_IN_FLOW_RATE ) || ( dialRate > MAX_DIAL_IN_FLOW_RATE ) ) + { + rejectReason = REQUEST_REJECT_REASON_DIAL_FLOW_OUT_OF_RANGE; + } + else + { + rejectReason = REQUEST_REJECT_REASON_DIAL_VOLUME_OUT_OF_RANGE; + } + } + } + sendChangeBloodDialysateRateChangeResponse( result, (U32)rejectReason, bloodRate, dialRate ); + + return result; +}