Index: firmware/App/Services/TxParams.c =================================================================== diff -u -r421336466eff4ba9fef0ca5416043e5d83c63841 -r1a3a2f806bb81b05f67f80efb94f1d82ce174c09 --- firmware/App/Services/TxParams.c (.../TxParams.c) (revision 421336466eff4ba9fef0ca5416043e5d83c63841) +++ firmware/App/Services/TxParams.c (.../TxParams.c) (revision 1a3a2f806bb81b05f67f80efb94f1d82ce174c09) @@ -148,6 +148,7 @@ static BOOL treatParamsConfirmed = FALSE; ///< Flag indicates user has confirmed the treatment parameters. static BOOL validTreatmentDurationReceived = FALSE; ///< Flag indicates valid treatment duration was validated. static U32 validatedTreatmentDuration_min = 0U; ///< Last validated treatment duration in minutes. +static F32 validatedUFVolumeGoalL = 0.0F; ///< Last validated UF volume goal in L. static F32 validatedUFRateLHr = 0.0F; ///< Last validated UF rate in L/hr. // ********** private function prototypes ********** @@ -476,7 +477,7 @@ payload.minTreatmentTime = treatmentParameters[ TREATMENT_PARAM_TREATMENT_DURATION ].minimum.uInt; payload.maxTreatmentTime = treatmentParameters[ TREATMENT_PARAM_TREATMENT_DURATION ].maximum.uInt; payload.minUFVolume = 0.0F; - payload.maxUFVolume = MIN( (F32)setTxDuration * MAX_UF_RATE_ML_MIN, (F32)MAX_UF_VOLUME_ML ); + payload.maxUFVolume = MIN( (F32)setTxDuration * MAX_UF_RATE_L_HR, (F32)MAX_UF_VOLUME_ML ); payload.minDialRate = treatmentParameters[ TREATMENT_PARAM_DIALYSATE_FLOW ].minimum.uInt; payload.maxDialRate = treatmentParameters[ TREATMENT_PARAM_DIALYSATE_FLOW ].maximum.uInt; sendMessage( MSG_ID_TD_TREATMENT_PARAM_RANGES, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&payload), sizeof( TREATMENT_PARAM_RANGE_BROADCAST_PAYLOAD_T ) ); @@ -627,7 +628,7 @@ { F32 uFRate = uFVolumeMl / (F32)treatmentDuration; - if ( ( uFRate > MAX_UF_RATE_ML_MIN ) || ( uFRate < MIN_UF_RATE_ML_MIN ) ) + if ( ( uFRate > MAX_UF_RATE_L_HR ) || ( uFRate < MIN_UF_RATE_L_HR ) ) { accepted = FALSE; rejReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; @@ -657,168 +658,10 @@ return accepted; } -/*********************************************************************//** - * @brief - * The validateAndSetTreatmentDuration function handles the UI treatment - * duration validation request during Treatment mode. - * @details \b Message \b Sent: MSG_ID_TD_DURATION_VALIDATE_RESPONSE - * @details \b Inputs: message containing requested treatment duration. - * @details \b Outputs: response updated with acceptance status, rejection - * reason, requested duration, proposed UF volume goal, and - * proposed UF rate. When accepted, validated values are stored - * for use during confirmation. - * @return TRUE if response message is sent successfully, FALSE otherwise. - *************************************************************************/ -BOOL validateAndSetTreatmentDuration( MESSAGE_T *message ) -{ - BOOL result = FALSE; - DURATION_VALIDATE_REQUEST_PAYLOAD_T request; - DURATION_VALIDATE_RESPONSE_PAYLOAD_T response; - F32 presUFVolumeL = 0.0F; - F32 elapsedTreatmentTimeMin = 0.0F; - F32 measuredUFVolumeL = 0.0F; - F32 remainingUFVolumeL = 0.0F; - F32 remainingTreatmentTimeHr = 0.0F; - F32 newUfRateLHr = 0.0F; - F32 newUfRateMlMin = 0.0F; - U32 minDuration = 0U; - U32 maxDuration = 0U; - response.accepted = FALSE; - response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; - response.duration = 0U; - response.ufVolumeGoal = 0.0F; - response.ufRate = 0.0F; - // Clear previously validated values. - validTreatmentDurationReceived = FALSE; - validatedTreatmentDuration_min = 0U; - validatedUFRateLHr = 0.0F; - - if ( message->hdr.payloadLen == sizeof( request ) ) - { - memcpy( &request, &message->payload[ 0 ], sizeof( request ) ); - - response.rejectionReason = REQUEST_REJECT_REASON_NONE; - response.duration = request.duration; - - presUFVolumeL = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); - - minDuration = getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ); - maxDuration = getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ); - - if ( ( request.duration >= minDuration ) && - ( request.duration <= maxDuration ) ) - { - elapsedTreatmentTimeMin = (F32)getActualTreatmentTimeSecs() / (F32)SEC_PER_MIN; - - if ( (F32)request.duration <= elapsedTreatmentTimeMin ) - { - response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; - } - else - { - measuredUFVolumeL = getUltrafiltrationVolumeDrawn(); - remainingUFVolumeL = presUFVolumeL - measuredUFVolumeL; - - if ( remainingUFVolumeL < 0.0F ) - { - remainingUFVolumeL = 0.0F; - } - - remainingTreatmentTimeHr = ( (F32)request.duration - elapsedTreatmentTimeMin ) / (F32)MIN_PER_HOUR; - - if ( remainingTreatmentTimeHr > 0.0F ) - { - newUfRateLHr = remainingUFVolumeL / remainingTreatmentTimeHr; - newUfRateMlMin = newUfRateLHr * (F32)ML_PER_LITER / (F32)MIN_PER_HOUR; - - response.ufVolumeGoal = presUFVolumeL; - response.ufRate = newUfRateLHr; - - if ( newUfRateMlMin <= MAX_UF_RATE_ML_MIN ) - { - response.accepted = TRUE; - - // Store validated values for confirmation. - validTreatmentDurationReceived = TRUE; - validatedTreatmentDuration_min = request.duration; - validatedUFRateLHr = newUfRateLHr; - } - else - { - response.rejectionReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; - } - } - else - { - response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; - } - } - } - else - { - response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; - } - } - - result = sendMessage( MSG_ID_TD_DURATION_VALIDATE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( response ) ); - - return result; -} - /*********************************************************************//** * @brief - * The validateAndSetBolusVolume function handles the UI fluid bolus - * volume change request during Treatment mode. - * @details \b Message \b Sent: MSG_ID_TD_BOLUS_VOLUME_CHANGE_RESPONSE - * @details \b Inputs: message containing requested bolus volume. - * @details \b Outputs: response updated with acceptance status, - * rejection reason, and bolus volume. - * @return TRUE if response message is sent successfully, FALSE otherwise. - *************************************************************************/ -BOOL validateAndSetBolusVolume( MESSAGE_T *message ) -{ - BOOL result = FALSE; - BOLUS_VOLUME_CHANGE_REQUEST_PAYLOAD_T request; - BOLUS_VOLUME_CHANGE_RESPONSE_PAYLOAD_T response; - U32 minBolusVolume_mL = 0U; - U32 maxBolusVolume_mL = 0U; - - response.accepted = FALSE; - response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; - response.bolusVolume = 0U; - - if ( message->hdr.payloadLen == sizeof( BOLUS_VOLUME_CHANGE_REQUEST_PAYLOAD_T ) ) - { - memcpy( &request, &message->payload[ 0 ], sizeof( request ) ); - - response.bolusVolume = request.bolusVolume; - - minBolusVolume_mL = getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - maxBolusVolume_mL = getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); - - if ( ( request.bolusVolume >= minBolusVolume_mL ) && - ( request.bolusVolume <= maxBolusVolume_mL ) ) - { - response.accepted = TRUE; - response.rejectionReason = REQUEST_REJECT_REASON_NONE; - - setTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME, request.bolusVolume ); - } - else - { - response.rejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; - } - } - - result = sendMessage( MSG_ID_TD_BOLUS_VOLUME_CHANGE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( response ) ); - - return result; -} - -/*********************************************************************//** - * @brief * The pressureLimitHandleChangeRequest function handles the UI pressure * limit change request during Treatment mode. * @details \b Message \b Sent: MSG_ID_TD_PRESSURE_LIMITS_CHANGE_RESPONSE @@ -1045,63 +888,7 @@ return result; } -/*********************************************************************//** - * @brief - * The signalUserConfirmationOfTreatmentDuration function handles the UI - * treatment duration confirmation request during Treatment mode. - * @details \b Message \b Sent: MSG_ID_TD_DURATION_CONFIRM_RESPONSE - * @details \b Inputs: message containing confirmed treatment duration. - * @details \b Outputs: response updated with acceptance status, rejection - * reason, duration, and UF volume. The confirmed duration is applied - * only when it matches the previously validated duration. - * @return TRUE if response message is sent successfully, FALSE otherwise. - *************************************************************************/ -BOOL signalUserConfirmationOfTreatmentDuration( MESSAGE_T *message ) -{ - BOOL result = FALSE; - DURATION_CONFIRM_REQUEST_PAYLOAD_T request; - DURATION_VALIDATE_RESPONSE_PAYLOAD_T response; - F32 presUFVolumeL = 0.0F; - response.accepted = FALSE; - response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; - response.duration = 0U; - response.ufRate = 0.0F; - - if ( message->hdr.payloadLen == sizeof( request ) ) - { - memcpy( &request, &message->payload[ 0 ], sizeof( request ) ); - - response.duration = request.duration; - response.ufVolumeGoal = presUFVolumeL; - response.ufRate = validatedUFRateLHr; - - if ( ( TRUE == validTreatmentDurationReceived ) && - ( request.duration == validatedTreatmentDuration_min ) ) - { - - setTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION, validatedTreatmentDuration_min ); - setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presUFVolumeL , validatedUFRateLHr ); - - response.accepted = TRUE; - response.rejectionReason = REQUEST_REJECT_REASON_NONE; - - // Clear validated values after successful apply. - validTreatmentDurationReceived = FALSE; - validatedTreatmentDuration_min = 0U; - validatedUFRateLHr = 0.0F; - } - else - { - response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; - } - } - - result = sendMessage( MSG_ID_TD_DURATION_CONFIRM_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( response ) ); - - return result; -} - /*********************************************************************//** * @brief * The signalUserConfirmationOfUFVolume function handles the UI @@ -1580,7 +1367,220 @@ return value; } +/************************************************************************* + * In-treatment treatment parameter edit function + *************************************************************************/ +/*********************************************************************//** + * @brief + * The validateAndSetTreatmentDuration function handles the UI treatment + * duration validation request during Treatment mode. + * @details \b Message \b Sent: + * MSG_ID_TD_DURATION_VALIDATE_RESPONSE + * @details \b Inputs: + * message containing requested treatment duration (minutes). + * @details \b Outputs: + * response updated with acceptance status, rejection reason, + * requested duration, prescribed UF volume goal (L), + * and calculated UF rate (L/hr). When accepted, validated + * values are stored for use during confirmation. + * @return TRUE if response message is sent successfully, FALSE otherwise. + *************************************************************************/ +BOOL validateAndSetTreatmentDuration( MESSAGE_T *message ) +{ + BOOL result = FALSE; + DURATION_VALIDATE_REQUEST_PAYLOAD_T request; + DURATION_VALIDATE_RESPONSE_PAYLOAD_T response; + + F32 presUFVolumeL = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); + F32 elapsedTreatmentTimeMin = (F32)getActualTreatmentTimeSecs() / (F32)SEC_PER_MIN; + F32 measuredUFVolumeL = getUltrafiltrationVolumeDrawn(); + F32 remainingUFVolumeL = presUFVolumeL - measuredUFVolumeL; + + U32 minDuration = getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ); + U32 maxDuration = getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ); + + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.duration = 0U; + response.ufVolumeGoal = 0.0F; + response.ufRate = 0.0F; + + // Clear previously validated values, + validTreatmentDurationReceived = FALSE; + validatedTreatmentDuration_min = 0U; + validatedUFRateLHr = 0.0F; + validatedUFVolumeGoalL = 0.0F; + + if ( message->hdr.payloadLen == sizeof( DURATION_VALIDATE_REQUEST_PAYLOAD_T ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( DURATION_VALIDATE_REQUEST_PAYLOAD_T ) ); + + if ( ( request.duration >= minDuration ) && ( request.duration <= maxDuration ) ) + { + if ( (F32)request.duration > elapsedTreatmentTimeMin ) + { + if ( remainingUFVolumeL < 0.0F ) + { + remainingUFVolumeL = 0.0F; + } + + // Calculate remaining treatment time (hours) + F32 remainingTreatmentTimeHr = ( (F32)request.duration - elapsedTreatmentTimeMin ) / (F32)MIN_PER_HOUR; + + // Calculate new UF rate (L/hr) + F32 newUfRateLHr = remainingUFVolumeL / remainingTreatmentTimeHr; + + response.ufVolumeGoal = presUFVolumeL; + response.ufRate = newUfRateLHr; + + if ( newUfRateLHr <= MAX_UF_RATE_L_HR ) + { + response.accepted = TRUE; + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + response.duration = request.duration; + + // Store validated values for confirmation step + validTreatmentDurationReceived = TRUE; + validatedTreatmentDuration_min = request.duration; + validatedUFVolumeGoalL = presUFVolumeL; + validatedUFRateLHr = newUfRateLHr; + + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; + response.duration = request.duration; + } + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; + response.duration = request.duration; + } + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; + response.duration = request.duration; + } + } + + result = sendMessage( MSG_ID_TD_DURATION_VALIDATE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( DURATION_VALIDATE_RESPONSE_PAYLOAD_T ) ); + + return result; +} + +/*********************************************************************//** + * @brief + * The validateAndSetBolusVolume function handles the UI fluid bolus + * volume change request during Treatment mode. + * @details \b Message \b Sent: MSG_ID_TD_BOLUS_VOLUME_CHANGE_RESPONSE + * @details \b Inputs: message containing requested bolus volume. + * @details \b Outputs: response updated with acceptance status, + * rejection reason. + * @return TRUE if response message is sent successfully, FALSE otherwise. + *************************************************************************/ +BOOL validateAndSetBolusVolume( MESSAGE_T *message ) +{ + BOOL result = FALSE; + BOLUS_VOLUME_CHANGE_REQUEST_PAYLOAD_T request; + BOLUS_VOLUME_CHANGE_RESPONSE_PAYLOAD_T response; + U32 minBolusVolume_mL = getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); + U32 maxBolusVolume_mL = getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); + + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + + if ( message->hdr.payloadLen == sizeof( BOLUS_VOLUME_CHANGE_REQUEST_PAYLOAD_T ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( BOLUS_VOLUME_CHANGE_REQUEST_PAYLOAD_T ) ); + + if ( ( request.bolusVolume >= minBolusVolume_mL ) && + ( request.bolusVolume <= maxBolusVolume_mL ) ) + { + response.accepted = TRUE; + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + + setTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME, request.bolusVolume ); + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + } + } + + result = sendMessage( MSG_ID_TD_BOLUS_VOLUME_CHANGE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( BOLUS_VOLUME_CHANGE_RESPONSE_PAYLOAD_T ) ); + + return result; +} + +/*********************************************************************//** + * @brief + * The signalUserConfirmationOfTreatmentDuration function handles the UI + * treatment duration confirmation request during Treatment mode. + * @details \b Message \b Sent: MSG_ID_TD_DURATION_CONFIRM_RESPONSE + * @details \b Inputs: message containing confirmed treatment duration. + * @details \b Outputs: response updated with acceptance status, rejection + * reason, duration, and UF volume. The confirmed duration is applied + * only when it matches the previously validated duration. + * @return TRUE if response message is sent successfully, FALSE otherwise. + *************************************************************************/ +BOOL signalUserConfirmationOfTreatmentDuration( MESSAGE_T *message ) +{ + BOOL result = FALSE; + DURATION_CONFIRM_REQUEST_PAYLOAD_T request; + DURATION_VALIDATE_RESPONSE_PAYLOAD_T response; + + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.duration = 0U; + response.ufVolumeGoal = 0.0F; + response.ufRate = 0.0F; + + if ( message->hdr.payloadLen == sizeof( DURATION_CONFIRM_REQUEST_PAYLOAD_T ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( DURATION_CONFIRM_REQUEST_PAYLOAD_T ) ); + + // Echo values for confirmation screen + response.duration = request.duration; + response.ufVolumeGoal = validatedUFVolumeGoalL; + response.ufRate = validatedUFRateLHr; + + if ( ( TRUE == validTreatmentDurationReceived ) && + ( request.duration == validatedTreatmentDuration_min ) ) + { + + setTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION, validatedTreatmentDuration_min ); + setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), validatedUFVolumeGoalL, validatedUFRateLHr ); + + response.accepted = TRUE; + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + + // Clear stored validated values + validTreatmentDurationReceived = FALSE; + validatedTreatmentDuration_min = 0U; + validatedUFVolumeGoalL = 0.0F; + validatedUFRateLHr = 0.0F; + + } + else if ( FALSE == validTreatmentDurationReceived ) + { + + response.rejectionReason = REQUEST_REJECT_REASON_CONFIRMATION_NOT_EXPECTED; + } + else + { + + response.rejectionReason = REQUEST_REJECT_REASON_CONFIRMATION_MISMATCH; + } + } + + result = sendMessage( MSG_ID_TD_DURATION_CONFIRM_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( response ) ); + + return result; +} + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/