Index: firmware/App/Services/TxParams.c =================================================================== diff -u -rd387dc3cd21e6f1fb7e161032f30eb49a9c1b48e -r96604b790636c66ef21980a4f13ee9f987f12fee --- firmware/App/Services/TxParams.c (.../TxParams.c) (revision d387dc3cd21e6f1fb7e161032f30eb49a9c1b48e) +++ firmware/App/Services/TxParams.c (.../TxParams.c) (revision 96604b790636c66ef21980a4f13ee9f987f12fee) @@ -195,6 +195,7 @@ static BOOL checkTreatmentParamsDependencies( U32 *reasons ); static BOOL checkUFDependencies( U32 *reasons ); static REQUEST_REJECT_REASON_CODE_T validateIsolatedUFSettings( U32 durationMin, F32 volumeGoalMl ); +static REQUEST_REJECT_REASON_CODE_T validateIsolatedUFDuration( U32 durationMin ); static U32 calculateIsolatedUFMaxVolumeMl( U32 durationMin ); static BOOL isPostTreatmentIsolatedUFRequest( void ); static void extractTreatmentParamsFromPayload( TREATMENT_PARAMS_DATA_RESPONSE_PAYLOAD_T payload ); @@ -261,9 +262,9 @@ *************************************************************************/ static void resetIsolatedUFSettingsPending( void ) { - isolatedUFSettingsPending = FALSE; + isolatedUFSettingsPending = FALSE; isolatedUFDurationPendingMin = 0; - isolatedUFVolumePendingMl = 0.0F; + isolatedUFVolumePendingMl = 0.0F; } /*********************************************************************//** @@ -561,27 +562,27 @@ result = ( ( ( param == TREATMENT_PARAM_HDF_DILUTION ) || ( param == TREATMENT_PARAM_SUBST_FLUID_VOLUME ) ) ? TRUE : FALSE ); break; - case TREATMENT_MODALITY_ISOLATED_UF: - switch ( param ) - { - case TREATMENT_PARAM_HDF_DILUTION: - case TREATMENT_PARAM_SUBST_FLUID_VOLUME: - case TREATMENT_PARAM_DIALYSATE_FLOW: - case TREATMENT_PARAM_DIALYSATE_TEMPERATURE: - case TREATMENT_PARAM_ACID_CONCENTRATE: - case TREATMENT_PARAM_ACID_CONCENTRATE_CONV_FACTOR: - case TREATMENT_PARAM_SODIUM: - case TREATMENT_PARAM_BICARBONATE: - case TREATMENT_PARAM_DRY_BICARB_CART_SIZE: - result = TRUE; - break; +// case TREATMENT_MODALITY_ISOLATED_UF: // TODO uncomment in phase 3 when ISO UF is a standalone modality +// switch ( param ) +// { +// case TREATMENT_PARAM_HDF_DILUTION: +// case TREATMENT_PARAM_SUBST_FLUID_VOLUME: +// case TREATMENT_PARAM_DIALYSATE_FLOW: +// case TREATMENT_PARAM_DIALYSATE_TEMPERATURE: +// case TREATMENT_PARAM_ACID_CONCENTRATE: +// case TREATMENT_PARAM_ACID_CONCENTRATE_CONV_FACTOR: +// case TREATMENT_PARAM_SODIUM: +// case TREATMENT_PARAM_BICARBONATE: +// case TREATMENT_PARAM_DRY_BICARB_CART_SIZE: +// result = TRUE; +// break; +// +// default: +// result = FALSE; +// break; +// } +// break; - default: - result = FALSE; - break; - } - break; - default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_TREATMENT_MODALITY, (U32)txType ) break; @@ -863,77 +864,87 @@ * @brief * The isPostTreatmentIsolatedUFRequest function determines whether isolated UF * is being requested after prescribed HD/HDF treatment time has elapsed. - * @details \b Inputs: getTreatmentState, isTreatmentCompleted + * @details \b Inputs: getTreatmentState * @details \b Outputs: none * @return TRUE if post-treatment isolated UF entry applies, FALSE otherwise. *************************************************************************/ static BOOL isPostTreatmentIsolatedUFRequest( void ) { - BOOL result = FALSE; - - if ( ( TREATMENT_END_STATE == getTreatmentState() ) && - ( TRUE == isTreatmentCompleted() ) && - ( TREATMENT_MODALITY_ISOLATED_UF != getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_MODALITY ) ) ) - { - result = TRUE; - } - - return result; + return ( TREATMENT_END_STATE == getTreatmentState() ); } /*********************************************************************//** * @brief - * The validateIsolatedUFSettings function validates isolated UF duration, - * volume goal, and derived rate before UI confirmation. - * @details \b Inputs: durationMin, volumeGoalMl + * The validateIsolatedUFDuration function validates isolated UF duration + * before UI confirmation. + * @details \b Inputs: durationMin * @details \b Outputs: none * @param durationMin Isolated UF duration in minutes. - * @param volumeGoalMl Isolated UF volume goal in mL. * @return Rejection reason code, or REQUEST_REJECT_REASON_NONE if valid. *************************************************************************/ -static REQUEST_REJECT_REASON_CODE_T validateIsolatedUFSettings( U32 durationMin, F32 volumeGoalMl ) +static REQUEST_REJECT_REASON_CODE_T validateIsolatedUFDuration( U32 durationMin ) { REQUEST_REJECT_REASON_CODE_T reason = REQUEST_REJECT_REASON_NONE; - F32 volumeGoalL = volumeGoalMl / (F32)ML_PER_LITER; - F32 ufRateMlMin = calculateIsolatedUFRateMlMin( durationMin, volumeGoalMl ); - U32 elapsedTreatmentMin = getActualTreatmentTimeSecs() / SEC_PER_MIN; - BOOL postTreatmentRequest = isPostTreatmentIsolatedUFRequest(); - BOOL validTreatmentState = FALSE; + U32 prescribedDurationMin = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); + U32 maxTreatmentDurationMin = getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ); + U32 cumulativeIsoUFTimeMin = getCumulativeIsolatedUFTimeMin(); + U32 totalDurationMin = prescribedDurationMin + cumulativeIsoUFTimeMin + durationMin; - if ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) - { - validTreatmentState = TRUE; - } - else if ( TRUE == postTreatmentRequest ) - { - validTreatmentState = TRUE; - } - if ( MODE_TREA != getCurrentOperationMode() ) { reason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } - else if ( FALSE == validTreatmentState ) + else if ( ( TREATMENT_DIALYSIS_STATE != getTreatmentState() ) && + ( FALSE == isPostTreatmentIsolatedUFRequest() ) ) { reason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; } - else if ( ( durationMin < getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ) ) || - ( durationMin > getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ) ) ) + else if ( durationMin < MIN_ISOLATED_UF_DURATION_MIN ) { reason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; } - else if ( ( FALSE == postTreatmentRequest ) && ( durationMin <= elapsedTreatmentMin ) ) + else if ( durationMin > maxTreatmentDurationMin ) { - reason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; + reason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; } - else if ( ( volumeGoalL < getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ) ) || - ( volumeGoalL > getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ) ) ) + else if ( totalDurationMin > maxTreatmentDurationMin ) { - reason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; + reason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; } - else if ( ( ufRateMlMin < MIN_UF_RATE_ML_MIN ) || ( ufRateMlMin > MAX_UF_RATE_ML_MIN ) ) + + return reason; +} + +/*********************************************************************//** + * @brief + * The validateIsolatedUFSettings function validates isolated UF duration, + * volume goal, and derived rate before UI confirmation. + * @details \b Inputs: durationMin, volumeGoalMl + * @details \b Outputs: none + * @param durationMin Isolated UF duration in minutes. + * @param volumeGoalMl Isolated UF volume goal in mL. + * @return Rejection reason code, or REQUEST_REJECT_REASON_NONE if valid. + *************************************************************************/ +static REQUEST_REJECT_REASON_CODE_T validateIsolatedUFSettings( U32 durationMin, F32 volumeGoalMl ) +{ + REQUEST_REJECT_REASON_CODE_T reason = validateIsolatedUFDuration( durationMin ); + F32 ufRateMlMin = calculateIsolatedUFRateMlMin( durationMin, volumeGoalMl ); + F32 maxVolumeMl = (F32)calculateIsolatedUFMaxVolumeMl( durationMin ); + + if ( REQUEST_REJECT_REASON_NONE == reason ) { - reason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; + if ( volumeGoalMl < MIN_ISOLATED_UF_VOLUME_ML ) + { + reason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; + } + else if ( volumeGoalMl > maxVolumeMl ) + { + reason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; + } + else if ( ( ufRateMlMin < MIN_UF_RATE_ML_MIN ) || ( ufRateMlMin > MAX_UF_RATE_ML_MIN ) ) + { + reason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; + } } return reason; @@ -950,8 +961,17 @@ *************************************************************************/ static U32 calculateIsolatedUFMaxVolumeMl( U32 durationMin ) { - F32 maxVolumeMl = MIN( (F32)durationMin * MAX_UF_RATE_ML_MIN, (F32)MAX_UF_VOLUME_ML ); + F32 maxRateVolumeMl = (F32)durationMin * MAX_UF_RATE_ML_MIN; + F32 cumulativeIsoUFVolumeMl = getCumulativeIsolatedUFVolumeMl(); + F32 prescriptionUFVolumeMl = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; + F32 maxSessionVolumeMl = (F32)MAX_UF_VOLUME_ML - cumulativeIsoUFVolumeMl - prescriptionUFVolumeMl; + F32 maxVolumeMl = MIN( maxRateVolumeMl, maxSessionVolumeMl ); + if ( maxVolumeMl < 0.0F ) + { + maxVolumeMl = 0.0F; + } + return (U32)maxVolumeMl; } @@ -961,38 +981,37 @@ * duration change request. * @details \b Message \b Sent: MSG_ID_TD_ISOLATED_UF_DURATION_CHANGE_RESPONSE * @details \b Inputs: message - * @details \b Outputs: isolatedUFDurationPendingMin + * @details \b Outputs: none * @param message Duration change request message from UI. - * @return TRUE if the request is valid and staged, FALSE otherwise. + * @return TRUE if the duration is valid, FALSE otherwise. *************************************************************************/ BOOL handleIsolatedUFDurationChangeRequest( MESSAGE_T *message ) { BOOL accepted = FALSE; REQUEST_REJECT_REASON_CODE_T reason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; ISOLATED_UF_DURATION_CHANGE_RESPONSE_PAYLOAD_T response; - U32 durationMin = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); - F32 volumeGoalMl = ( TRUE == isolatedUFSettingsPending ? isolatedUFVolumePendingMl : - getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER ); + U32 durationMin = 0U; if ( sizeof( ISOLATED_UF_DURATION_CHANGE_REQUEST_PAYLOAD_T ) == message->hdr.payloadLen ) { ISOLATED_UF_DURATION_CHANGE_REQUEST_PAYLOAD_T request; memcpy( &request, message->payload, sizeof( ISOLATED_UF_DURATION_CHANGE_REQUEST_PAYLOAD_T ) ); durationMin = request.mDuration; - reason = validateIsolatedUFSettings( durationMin, volumeGoalMl ); + reason = validateIsolatedUFDuration( durationMin ); if ( REQUEST_REJECT_REASON_NONE == reason ) { - isolatedUFSettingsPending = TRUE; - isolatedUFDurationPendingMin = durationMin; - isolatedUFVolumePendingMl = volumeGoalMl; accepted = TRUE; } } + else + { + reason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + } - response.mAccepted = (U32)accepted; - response.mReason = (U32)reason; + response.mAccepted = (U32)accepted; + response.mReason = (U32)reason; response.mVolumeMax = calculateIsolatedUFMaxVolumeMl( durationMin ); sendMessage( MSG_ID_TD_ISOLATED_UF_DURATION_CHANGE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&response), sizeof( ISOLATED_UF_DURATION_CHANGE_RESPONSE_PAYLOAD_T ) ); @@ -1002,7 +1021,7 @@ /*********************************************************************//** * @brief * The handleIsolatedUFVolumeGoalChangeRequest function handles a UI isolated - * UF volume goal change request. + * UF settings change request containing both duration and volume goal. * @details \b Message \b Sent: MSG_ID_TD_ISOLATED_UF_VOLUME_GOAL_CHANGE_RESPONSE * @details \b Inputs: message * @details \b Outputs: isolatedUFVolumePendingMl @@ -1014,9 +1033,8 @@ BOOL accepted = FALSE; REQUEST_REJECT_REASON_CODE_T reason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; ISOLATED_UF_VOLUME_GOAL_CHANGE_RESPONSE_PAYLOAD_T response; - U32 durationMin = ( TRUE == isolatedUFSettingsPending ? isolatedUFDurationPendingMin : - getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ) ); - F32 volumeGoalMl = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; + U32 durationMin = 0U; + F32 volumeGoalMl = 0.0F; if ( sizeof( ISOLATED_UF_VOLUME_GOAL_CHANGE_REQUEST_PAYLOAD_T ) == message->hdr.payloadLen ) { @@ -1029,18 +1047,22 @@ if ( REQUEST_REJECT_REASON_NONE == reason ) { - isolatedUFSettingsPending = TRUE; + isolatedUFSettingsPending = TRUE; isolatedUFDurationPendingMin = durationMin; - isolatedUFVolumePendingMl = volumeGoalMl; + isolatedUFVolumePendingMl = volumeGoalMl; accepted = TRUE; } } + else + { + reason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + } response.mAccepted = (U32)accepted; - response.mReason = (U32)reason; - response.mVolume = (U32)volumeGoalMl; + response.mReason = (U32)reason; + response.mVolume = (U32)volumeGoalMl; response.mDuration = durationMin; - response.mRate = (U32)calculateIsolatedUFRateMlMin( durationMin, volumeGoalMl ); + response.mRate = (U32)calculateIsolatedUFRateMlMin( durationMin, volumeGoalMl ); sendMessage( MSG_ID_TD_ISOLATED_UF_VOLUME_GOAL_CHANGE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&response), sizeof( ISOLATED_UF_VOLUME_GOAL_CHANGE_RESPONSE_PAYLOAD_T ) ); return accepted; @@ -1109,6 +1131,10 @@ } } } + else + { + reason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + } response.mAccepted = (U32)accepted; response.mReason = (U32)reason;