Index: firmware/App/Services/TxParams.c =================================================================== diff -u -r8cceda439faa23a1e927721c6a9ef8e4ee30c5be -re23b34695d4b67bbce65248f97fc346d3acb7aa6 --- firmware/App/Services/TxParams.c (.../TxParams.c) (revision 8cceda439faa23a1e927721c6a9ef8e4ee30c5be) +++ firmware/App/Services/TxParams.c (.../TxParams.c) (revision e23b34695d4b67bbce65248f97fc346d3acb7aa6) @@ -148,8 +148,9 @@ 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. +static F32 validatedUFVolumeGoalMl = 0.0F; ///< Last validated UF volume goal in mL. +static F32 validatedUFRateMlMin = 0.0F; ///< Last validated UF rate in mL/min. +static BOOL validUFVolumeReceived = FALSE; ///< Flag indicates valid UF volume was validated. // ********** private function prototypes ********** @@ -590,78 +591,6 @@ /*********************************************************************//** * @brief - * The validateAndSetUFVolume function validates received ultrafiltration - * volume treatment parameter. - * @details \b Message \b Sent: MSG_ID_TD_RESP_ULTRAFILTRATION_VOLUME_TO_VALIDATE - * @details \b Inputs: none - * @details \b Outputs: none - * @param message set message from UI which includes the user set ultrafiltration - * volume (in mL). - * @return TRUE if received UF volume parameter is valid, FALSE if not - *************************************************************************/ -BOOL validateAndSetUFVolume( MESSAGE_T *message ) -{ - BOOL accepted = FALSE; - REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_NONE; - F32 uFVolumeMl; - F32 uFVolumeL; - - // Verify message payload length is valid - if ( sizeof( F32 ) == message->hdr.payloadLen ) - { - UF_VOLUME_VAL_RESP_DATA_PAYLOAD_T respPayload; - - memcpy( &uFVolumeMl, message->payload, sizeof( F32 ) ); - uFVolumeL = uFVolumeMl / (F32)ML_PER_LITER; - - // Validate given UF volume - accepted = setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, uFVolumeL ); - - if ( TRUE == accepted ) - { - U32 treatmentDuration = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); - - // store the user set ultrafiltration volume in pre-treatment parameters setup, if it is validated, otherwise keep the initial 0.0 - origTreatmentParams.uFVolume_L = uFVolumeL; - - if ( treatmentDuration > 0 ) - { - F32 uFRate = uFVolumeMl / (F32)treatmentDuration; - - if ( ( uFRate > MAX_UF_RATE_ML_MIN ) || ( uFRate < MIN_UF_RATE_ML_MIN ) ) - { - accepted = FALSE; - rejReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; - } - } - else - { - accepted = FALSE; - rejReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_MINIMUM; - } - } - else - { - rejReason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; - } - - // Respond to set UF volume request message - uFVolumeL = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); - uFVolumeMl = uFVolumeL * (F32)ML_PER_LITER; - respPayload.accepted = accepted; - respPayload.rejReason = rejReason; - respPayload.ufVolumeMl = uFVolumeMl; - sendMessage( MSG_ID_TD_RESP_ULTRAFILTRATION_VOLUME_TO_VALIDATE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&respPayload), sizeof( UF_VOLUME_VAL_RESP_DATA_PAYLOAD_T ) ); - // setUserSetUFVolumeStatus( accepted ); // TODO - tell pre-tx whether UF volume has been set and accepted - } - - return accepted; -} - - - -/*********************************************************************//** - * @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 @@ -888,66 +817,8 @@ return result; } - /*********************************************************************//** * @brief - * The signalUserConfirmationOfUFVolume function handles the UI - * confirmation request for ultrafiltration (UF) volume change. - * @details \b Message \b Sent: MSG_ID_TD_ULTRAFILTRATION_CHANGE_VALIDATE_RESPONSE - * @details \b Inputs: message containing requested UF volume (mL). - * @details \b Outputs: response updated with acceptance status and - * rejection reason. - * @param message set message from UI which includes the user set - * ultrafiltration volume. - * @return TRUE if response message is sent successfully, FALSE otherwise. - *************************************************************************/ -BOOL signalUserConfirmationOfUFVolume( MESSAGE_T *message ) -{ - BOOL result = FALSE; - UI_RESPONSE_PAYLOAD_T response; - F32 requestedUFVolumeMl = 0.0F; - F32 requestedUFVolumeL = 0.0F; - F32 storedUFVolumeL = 0.0F; - F32 treatmentDurationMin = 0.0F; - F32 newUFRateLHr = 0.0F; - - response.accepted = FALSE; - response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; - - if ( sizeof( F32 ) == message->hdr.payloadLen ) - { - memcpy( &requestedUFVolumeMl, message->payload, sizeof( requestedUFVolumeMl ) ); - - requestedUFVolumeL = requestedUFVolumeMl / (F32)ML_PER_LITER; - storedUFVolumeL = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); - - if ( requestedUFVolumeL == storedUFVolumeL ) - { - treatmentDurationMin = (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); - - if ( treatmentDurationMin > 0.0F ) - { - newUFRateLHr = storedUFVolumeL / ( treatmentDurationMin / (F32)MIN_PER_HOUR ); - - setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), storedUFVolumeL, newUFRateLHr ); - - response.accepted = TRUE; - response.rejectionReason = REQUEST_REJECT_REASON_NONE; - } - else - { - response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_MINIMUM; - } - } - } - - result = sendMessage( MSG_ID_TD_ULTRAFILTRATION_CHANGE_VALIDATE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)&response, sizeof( response ) ); - - return result; -} - -/*********************************************************************//** - * @brief * The extractTreatmentParamsFromPayload function extracts the individual * treatment parameters received from the UI into a staging array where * they will be validated and stay until user confirms them. @@ -1381,8 +1252,8 @@ * 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 + * requested duration, prescribed UF volume goal (mL), + * and calculated UF rate (mL/min). When accepted, validated * values are stored for use during confirmation. * @return TRUE if response message is sent successfully, FALSE otherwise. *************************************************************************/ @@ -1392,10 +1263,10 @@ DURATION_VALIDATE_REQUEST_PAYLOAD_T request; DURATION_VALIDATE_RESPONSE_PAYLOAD_T response; - F32 presUFVolumeL = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ); + F32 presUFVolumeMl = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; F32 elapsedTreatmentTimeMin = (F32)getActualTreatmentTimeSecs() / (F32)SEC_PER_MIN; - F32 measuredUFVolumeL = getUltrafiltrationVolumeDrawn(); - F32 remainingUFVolumeL = presUFVolumeL - measuredUFVolumeL; + F32 measuredUFVolumeMl = getUltrafiltrationVolumeDrawn() * (F32)ML_PER_LITER; + F32 remainingUFVolumeMl = presUFVolumeMl - measuredUFVolumeMl; U32 minDuration = getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ); U32 maxDuration = getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ); @@ -1409,31 +1280,31 @@ // Clear previously validated values. validTreatmentDurationReceived = FALSE; validatedTreatmentDuration_min = 0U; - validatedUFRateLHr = 0.0F; - validatedUFVolumeGoalL = 0.0F; + validatedUFRateMlMin = 0.0F; + validatedUFVolumeGoalMl = 0.0F; if ( message->hdr.payloadLen == sizeof( DURATION_VALIDATE_REQUEST_PAYLOAD_T ) ) { memcpy( &request, &message->payload[ 0 ], sizeof( DURATION_VALIDATE_REQUEST_PAYLOAD_T ) ); + response.duration = request.duration; + if ( ( request.duration >= minDuration ) && ( request.duration <= maxDuration ) ) { if ( (F32)request.duration > elapsedTreatmentTimeMin ) { - if ( remainingUFVolumeL < 0.0F ) + if ( remainingUFVolumeMl < 0.0F ) { - remainingUFVolumeL = 0.0F; + remainingUFVolumeMl = 0.0F; } - // Calculate remaining treatment time (hours) - F32 remainingTreatmentTimeHr = ( (F32)request.duration - elapsedTreatmentTimeMin ) / (F32)MIN_PER_HOUR; + F32 remainingTreatmentTimeMin = (F32)request.duration - elapsedTreatmentTimeMin; - // Calculate new UF rate (L/hr) - F32 newUfRateLHr = remainingUFVolumeL / remainingTreatmentTimeHr; - F32 newUfRateMlMin = newUfRateLHr * (F32)ML_PER_LITER / (F32)MIN_PER_HOUR; + // Calculate new UF rate (mL/min). + F32 newUfRateMlMin = remainingUFVolumeMl / remainingTreatmentTimeMin; - response.ufVolumeGoal = presUFVolumeL; - response.ufRate = newUfRateLHr; + response.ufVolumeGoal = presUFVolumeMl; + response.ufRate = newUfRateMlMin; if ( newUfRateMlMin <= MAX_UF_RATE_ML_MIN ) { @@ -1444,26 +1315,23 @@ // Store validated values for confirmation step validTreatmentDurationReceived = TRUE; validatedTreatmentDuration_min = request.duration; - validatedUFVolumeGoalL = presUFVolumeL; - validatedUFRateLHr = newUfRateLHr; + validatedUFVolumeGoalMl = presUFVolumeMl; + validatedUFRateMlMin = newUfRateMlMin; } 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; } } @@ -1518,6 +1386,107 @@ /*********************************************************************//** * @brief + * The validateAndSetUFVolume function validates the received ultrafiltration + * volume treatment parameter. + * @details \b Message \b Sent: MSG_ID_TD_RESP_ULTRAFILTRATION_VOLUME_TO_VALIDATE + * @details \b Inputs: message containing requested UF volume in mL. + * @details \b Outputs: response with acceptance status, rejection reason, + * UF volume goal, duration, and UF rate. + * @param message Set message from UI which includes the requested UF volume + * in mL. + * @return TRUE if response message is sent successfully, FALSE otherwise. + *************************************************************************/ +BOOL validateAndSetUFVolume( MESSAGE_T *message ) +{ + BOOL result = FALSE; + UF_VOLUME_VALIDATE_REQUEST_PAYLOAD_T request; + UF_VOLUME_RESPONSE_PAYLOAD_T response; + + F32 elapsedTreatmentTimeMin = (F32)getActualTreatmentTimeSecs() / (F32)SEC_PER_MIN; + F32 measuredUFVolumeMl = getUltrafiltrationVolumeDrawn() * (F32)ML_PER_LITER; + F32 treatmentDurationMin = (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); + F32 requestedUFVolumeMl = 0.0F; + F32 requestedUFVolumeL = 0.0F; + F32 remainingUFVolumeMl = 0.0F; + F32 remainingTreatmentTimeMin = 0.0F; + F32 newUfRateMlMin = 0.0F; + F32 minUFVolumeL = getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ); + F32 maxUFVolumeL = getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ); + + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.ufVolumeGoal = 0.0F; + response.duration = 0U; + response.ufRate = 0.0F; + + // Clear previously validated values. + validUFVolumeReceived = FALSE; + validatedUFVolumeGoalMl = 0.0F; + validatedUFRateMlMin = 0.0F; + + if ( message->hdr.payloadLen == sizeof( UF_VOLUME_VALIDATE_REQUEST_PAYLOAD_T ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( UF_VOLUME_VALIDATE_REQUEST_PAYLOAD_T ) ); + + requestedUFVolumeMl = request.ufVolume; + requestedUFVolumeL = requestedUFVolumeMl / (F32)ML_PER_LITER; + + response.ufVolumeGoal = requestedUFVolumeMl; + response.duration = (U32)treatmentDurationMin; + + if ( ( requestedUFVolumeL >= minUFVolumeL ) && + ( requestedUFVolumeL <= maxUFVolumeL ) ) + { + if ( requestedUFVolumeMl >= measuredUFVolumeMl ) + { + if ( treatmentDurationMin > elapsedTreatmentTimeMin ) + { + remainingUFVolumeMl = requestedUFVolumeMl - measuredUFVolumeMl; + remainingTreatmentTimeMin = treatmentDurationMin - elapsedTreatmentTimeMin; + + // Calculate new UF rate in mL/min. + newUfRateMlMin = remainingUFVolumeMl / remainingTreatmentTimeMin; + + response.ufRate = newUfRateMlMin; + + if ( newUfRateMlMin <= MAX_UF_RATE_ML_MIN ) + { + response.accepted = TRUE; + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + + // Store validated values for confirmation step. + validUFVolumeReceived = TRUE; + validatedUFVolumeGoalMl = requestedUFVolumeMl; + validatedUFRateMlMin = newUfRateMlMin; + } + 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_UF_VOLUME_OUT_OF_RANGE; + } + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; + } + } + + result = sendMessage( MSG_ID_TD_RESP_ULTRAFILTRATION_VOLUME_TO_VALIDATE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( UF_VOLUME_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 @@ -1545,24 +1514,24 @@ // Echo values for confirmation screen response.duration = request.duration; - response.ufVolumeGoal = validatedUFVolumeGoalL; - response.ufRate = validatedUFRateLHr; + response.ufVolumeGoal = validatedUFVolumeGoalMl; + response.ufRate = validatedUFRateMlMin; if ( ( TRUE == validTreatmentDurationReceived ) && ( request.duration == validatedTreatmentDuration_min ) ) { setTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION, validatedTreatmentDuration_min ); - setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), validatedUFVolumeGoalL, validatedUFRateLHr ); + setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), validatedUFVolumeGoalMl, validatedUFRateMlMin ); response.accepted = TRUE; response.rejectionReason = REQUEST_REJECT_REASON_NONE; // Clear stored validated values validTreatmentDurationReceived = FALSE; validatedTreatmentDuration_min = 0U; - validatedUFVolumeGoalL = 0.0F; - validatedUFRateLHr = 0.0F; + validatedUFVolumeGoalMl = 0.0F; + validatedUFRateMlMin = 0.0F; } else if ( FALSE == validTreatmentDurationReceived ) @@ -1577,11 +1546,74 @@ } } - result = sendMessage( MSG_ID_TD_DURATION_CONFIRM_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( response ) ); + result = sendMessage( MSG_ID_TD_DURATION_CONFIRM_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( DURATION_VALIDATE_RESPONSE_PAYLOAD_T ) ); return result; } +/*********************************************************************//** + * @brief + * The signalUserConfirmationOfUFVolume function handles the UI + * confirmation request for ultrafiltration (UF) volume change. + * @details \b Message \b Sent: MSG_ID_TD_ULTRAFILTRATION_CHANGE_VALIDATE_RESPONSE + * @details \b Inputs: message containing requested UF volume (mL). + * @details \b Outputs: response updated with acceptance status and + * rejection reason. + * @param message set message from UI which includes the user set + * ultrafiltration volume. + * @return TRUE if response message is sent successfully, FALSE otherwise. + *************************************************************************/ +BOOL signalUserConfirmationOfUFVolume( MESSAGE_T *message ) +{ + BOOL result = FALSE; + UF_VOLUME_CONFIRM_REQUEST_PAYLOAD_T request; + UF_VOLUME_RESPONSE_PAYLOAD_T response; + + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.ufVolumeGoal = 0.0F; + response.duration = 0U; + response.ufRate = 0.0F; + + if ( message->hdr.payloadLen == sizeof( UF_VOLUME_CONFIRM_REQUEST_PAYLOAD_T ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( UF_VOLUME_CONFIRM_REQUEST_PAYLOAD_T ) ); + + // Echo values for confirmation screen + response.ufVolumeGoal = request.ufVolume; + response.duration = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); + response.ufRate = validatedUFRateMlMin; + + if ( ( TRUE == validUFVolumeReceived ) && + ( request.ufVolume == validatedUFVolumeGoalMl ) ) + { + setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, validatedUFVolumeGoalMl / (F32)ML_PER_LITER ); + + setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), validatedUFVolumeGoalMl, validatedUFRateMlMin ); + + response.accepted = TRUE; + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + + // Clear stored validated values + validUFVolumeReceived = FALSE; + validatedUFVolumeGoalMl = 0.0F; + validatedUFRateMlMin = 0.0F; + } + else if ( FALSE == validUFVolumeReceived ) + { + response.rejectionReason = REQUEST_REJECT_REASON_CONFIRMATION_NOT_EXPECTED; + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_CONFIRMATION_MISMATCH; + } + } + + result = sendMessage( MSG_ID_TD_ULTRAFILTRATION_CHANGE_VALIDATE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( UF_VOLUME_RESPONSE_PAYLOAD_T ) ); + + return result; +} + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/