Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r421336466eff4ba9fef0ca5416043e5d83c63841 -r1a3a2f806bb81b05f67f80efb94f1d82ce174c09 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 421336466eff4ba9fef0ca5416043e5d83c63841) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 1a3a2f806bb81b05f67f80efb94f1d82ce174c09) @@ -22,7 +22,6 @@ #include "DDInterface.h" #include "ModeService.h" #include "ModeTreatment.h" -#include "Messaging.h" //#include "NVDataMgmt.h" #include "OperationModes.h" #include "Pressures.h" @@ -914,7 +913,7 @@ // Compute minimum UF volume F32 minUFVol = 0.0F; // TODO getUltrafiltrationReferenceVolume() + presUFRate; // current UF volume + 1 min at current rate // Compute maximum UF volume (considering from adjustment of UF rate and time perspectives) - F32 maxUFVol1 = minUFVol + ( (F32)( presTime - elapseTime ) * MAX_UF_RATE_ML_MIN ); + F32 maxUFVol1 = minUFVol + ( (F32)( presTime - elapseTime ) * MAX_UF_RATE_L_HR ); F32 maxUFVol2 = ( presUFRateLHr > 0.0F ? minUFVol + ( (F32)( MAX_TREATMENT_TIME_MINUTES - elapseTime - 1 ) * presUFRateLHr ) : minUFVol ); F32 maxUFVol = MAX( maxUFVol1, maxUFVol2 ); // Set minimum dialysate flow rate Index: firmware/App/Modes/StateTxDialysis.c =================================================================== diff -u -r176f16b02f39ff31985a03b3546fc57e690f3306 -r1a3a2f806bb81b05f67f80efb94f1d82ce174c09 --- firmware/App/Modes/StateTxDialysis.c (.../StateTxDialysis.c) (revision 176f16b02f39ff31985a03b3546fc57e690f3306) +++ firmware/App/Modes/StateTxDialysis.c (.../StateTxDialysis.c) (revision 1a3a2f806bb81b05f67f80efb94f1d82ce174c09) @@ -231,17 +231,17 @@ } /*********************************************************************//** - * @brief - * The signalPauseResumeUF function handles a request to pause or resume - * ultrafiltration. - * @details \b Message \b Sent: MSG_ID_TD_UF_PAUSE_RESUME_RESPONSE - * @details \b Message \b Sent: UF_START_PAUSE_EVENT / UF_START_RESUME_EVENT - * @details \b Inputs: currentDialysisState, setUFRateLHr - * @details \b Outputs: ufPauseRequested, ufResumeRequested - * @param message Message from UI which includes a flag indicating whether - * to pause or resume ultrafiltration. - * @return TRUE if pause - *************************************************************************/ +* @brief +* The signalPauseResumeUF function handles a request to pause or resume +* ultrafiltration. +* @details \b Message \b Sent: MSG_ID_TD_UF_PAUSE_RESUME_RESPONSE +* @details \b Message \b Sent: UF_START_PAUSE_EVENT / UF_START_RESUME_EVENT +* @details \b Inputs: currentDialysisState, setUFRateLHr +* @details \b Outputs: ufPauseRequested, ufResumeRequested +* @param message Message from UI which includes a flag indicating whether +* to pause or resume ultrafiltration. +* @return TRUE if pause +*************************************************************************/ BOOL signalPauseResumeUF( MESSAGE_T *message ) { TREATMENT_STATE_T trtState = getTreatmentState(); @@ -254,73 +254,73 @@ // Verify payload length is valid if ( sizeof( BOOL ) == message->hdr.payloadLen ) { - BOOL requestedState = FALSE; + BOOL payload; - memcpy( &requestedState, message->payload, sizeof( requestedState ) ); + memcpy( &payload, message->payload, sizeof( BOOL ) ); // Handle request to resume ultrafiltration - if ( requestedState == FALSE ) + if ( TRUE == payload ) { if ( ( MODE_TREA == currMode ) && ( TREATMENT_DIALYSIS_STATE == trtState ) && ( DIALYSIS_UF_PAUSED_STATE == currentDialysisState ) ) { ufResumeRequested = TRUE; response.accepted = TRUE; - - if ( setUFRateLHr > 0.0F ) + if ( setUFRateLHr > 0.0 ) { - // sendTreatmentLogEventData( UF_START_RESUME_EVENT, 0.0F, setUFRateLHr ); + //sendTreatmentLogEventData( UF_START_RESUME_EVENT, 0.0, setUFRateLHr ); } } - else if ( MODE_TREA != currMode ) - { - response.rejectionReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; - } - else if ( TREATMENT_DIALYSIS_STATE != trtState ) - { - response.rejectionReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; - } else { - response.rejectionReason = REQUEST_REJECT_REASON_UF_NOT_PAUSED; + if ( MODE_TREA != currMode ) + { + response.rejectionReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; + } + else if ( TREATMENT_DIALYSIS_STATE != trtState ) + { + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_UF_NOT_PAUSED; + } } } // Handle request to pause ultrafiltration - else if ( requestedState == TRUE ) + else { if ( ( MODE_TREA == currMode ) && ( TREATMENT_DIALYSIS_STATE == trtState ) && ( DIALYSIS_UF_STATE == currentDialysisState ) ) { ufPauseRequested = TRUE; response.accepted = TRUE; - - if ( setUFRateLHr > 0.0F ) + if ( setUFRateLHr > 0.0 ) { - // sendTreatmentLogEventData( UF_PAUSE_EVENT, setUFRateLHr, 0.0F ); + //sendTreatmentLogEventData( UF_PAUSE_EVENT, setUFRateLHr, 0.0 ); } } - else if ( MODE_TREA != currMode ) - { - response.rejectionReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; - } - else if ( TREATMENT_DIALYSIS_STATE != trtState ) - { - response.rejectionReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; - } else { - response.rejectionReason = REQUEST_REJECT_REASON_UF_NOT_IN_PROGESS; + if ( MODE_TREA != currMode ) + { + response.rejectionReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; + } + else if ( TREATMENT_DIALYSIS_STATE != trtState ) + { + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; + } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_UF_NOT_IN_PROGESS; + } } } - else - { - response.rejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; - } } else { - response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.rejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; } - // Send response + // Send response w/ reason code if rejected sendMessage( MSG_ID_TD_UF_PAUSE_RESUME_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&response), sizeof( UI_RESPONSE_PAYLOAD_T ) ); return response.accepted; Index: firmware/App/Services/Messaging.c =================================================================== diff -u -r421336466eff4ba9fef0ca5416043e5d83c63841 -r1a3a2f806bb81b05f67f80efb94f1d82ce174c09 --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision 421336466eff4ba9fef0ca5416043e5d83c63841) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision 1a3a2f806bb81b05f67f80efb94f1d82ce174c09) @@ -496,6 +496,7 @@ return result; } + // *********************************************************************** // ***************** Message Sending Helper Functions ******************** // *********************************************************************** Index: firmware/App/Services/Messaging.h =================================================================== diff -u -r421336466eff4ba9fef0ca5416043e5d83c63841 -r1a3a2f806bb81b05f67f80efb94f1d82ce174c09 --- firmware/App/Services/Messaging.h (.../Messaging.h) (revision 421336466eff4ba9fef0ca5416043e5d83c63841) +++ firmware/App/Services/Messaging.h (.../Messaging.h) (revision 1a3a2f806bb81b05f67f80efb94f1d82ce174c09) @@ -14,15 +14,15 @@ * @date (original) 01-Aug-2024 * ***************************************************************************/ - -#ifndef __MESSAGING_H__ -#define __MESSAGING_H__ +#ifndef __MESSAGING_H__ +#define __MESSAGING_H__ + #include "TDCommon.h" #include "TDDefs.h" #include "MessageSupport.h" #include "MsgQueues.h" - + /** * @defgroup Messaging Messaging * @brief The system communication messages unit provides helper functions @@ -35,7 +35,7 @@ // ********** public definitions ********** #define ACK_REQUIRED TRUE ///< Macro for functions that want to know if an outgoing message requires acknowledgement from receiver. -#define ACK_NOT_REQUIRED FALSE ///< Macro for functions that want to know if an outgoing message requires acknowledgement from receiver. +#define ACK_NOT_REQUIRED FALSE ///< Macro for functions that want to know if an outgoing message requires acknowledgement from receiver. #pragma pack(push, 1) /// Payload record structure for ACK response. @@ -129,13 +129,13 @@ F32 maxHeparinBolusVolumeML; ///< Max heparin bolus volume in mL. U32 enableChemicalDisinfect; ///< Enable/disable chemical disinfect. } HD_INSTITUTIONAL_LOCAL_RECORD_T; - -// ********** public function prototypes ********** -// Serialize message +// ********** public function prototypes ********** + +// Serialize message U32 serializeMessage( MESSAGE_T msg, COMM_BUFFER_T buffer, BOOL ackReq ); -// ACK MSG +// ACK MSG BOOL sendACKMsg( MESSAGE_T *message ); // Handle version request message @@ -162,4 +162,4 @@ /**@}*/ -#endif +#endif 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 *************************************************************************/ Index: firmware/App/Services/TxParams.h =================================================================== diff -u -r421336466eff4ba9fef0ca5416043e5d83c63841 -r1a3a2f806bb81b05f67f80efb94f1d82ce174c09 --- firmware/App/Services/TxParams.h (.../TxParams.h) (revision 421336466eff4ba9fef0ca5416043e5d83c63841) +++ firmware/App/Services/TxParams.h (.../TxParams.h) (revision 1a3a2f806bb81b05f67f80efb94f1d82ce174c09) @@ -34,8 +34,8 @@ // ********** public definitions ********** #define MIN_PRESSURE_ALARM_LIMIT_DELTA_MMHG ( 30 ) ///< Minimum pressure alarm limit delta (in mmHg) -#define MAX_UF_RATE_ML_MIN ( 2000.01F / (F32)MIN_PER_HOUR ) ///< Maximum ultrafiltration rate (in mL/min). Added small decimal to prevent float round off issues. -#define MIN_UF_RATE_ML_MIN ( 0.0F ) ///< Minimum ultrafiltration rate (in mL/min). +#define MAX_UF_RATE_L_HR ( 2.0F ) ///< Maximum ultrafiltration rate (in L/hr) +#define MIN_UF_RATE_L_HR ( 0.0F ) ///< Minimum ultrafiltration rate (in L/hr) #define MAX_UF_VOLUME_ML ( 8 * ML_PER_LITER ) ///< Maximum ultrafiltration volume (in mL). /// Record structure for a treatment parameters payload from UI. @@ -113,7 +113,6 @@ { BOOL accepted; ///< Accepted/Rejected U32 rejectionReason; ///< Rejection reason if not accepted - U32 bolusVolume; ///< Bolus volume (in mL) } BOLUS_VOLUME_CHANGE_RESPONSE_PAYLOAD_T; /// Payload record structure for pressure limit change request. @@ -149,6 +148,7 @@ BOOL validateAndSetTreatmentParameters( MESSAGE_T *message ); // User provided treatment params to be set and validated BOOL validateAndSetUFVolume( MESSAGE_T *message ); // User provided ultrafiltration volume to be set and validated +// Edit Treatment parameter handlers BOOL validateAndSetTreatmentDuration( MESSAGE_T *message ); // User provided treatment duration to be set and validated BOOL validateAndSetBolusVolume( MESSAGE_T *message ); // User provided bolus volume to be set and validated BOOL pressureLimitHandleChangeRequest( MESSAGE_T *message ); // User provided pressure limit window values to be validated and applied