Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -reef41b7363d82763095a1317f1757f360f0d9ec1 -rf0ea13c1a9908920793be07a946dc366d2ab5019 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision eef41b7363d82763095a1317f1757f360f0d9ec1) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision f0ea13c1a9908920793be07a946dc366d2ab5019) @@ -22,6 +22,7 @@ #include "DDInterface.h" #include "ModeService.h" #include "ModeTreatment.h" +#include "Messaging.h" //#include "NVDataMgmt.h" #include "OperationModes.h" #include "Pressures.h" @@ -43,6 +44,8 @@ #define MAX_TREATMENT_TIME_MINUTES ( 8 * MIN_PER_HOUR ) ///< Maximum treatment time (in minutes). #define MIN_TREATMENT_TIME_MINUTES ( 1 * MIN_PER_HOUR ) ///< Minimum treatment time (in minutes). +#define MAX_BOLUS_VOLUME_ML ( 300 ) ///< Minimum fluid bolus volume (in mL). +#define MIN_BOLUS_VOLUME_ML ( 100 ) ///< Maximum fluid bolus volume (in mL). /// Interval (ms/task time) at which the treatment time data is published on the CAN bus. #define TREATMENT_TIME_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) @@ -819,6 +822,229 @@ /*********************************************************************//** * @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, duration, UF volume goal, and UF rate. + * @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 elapsedTreatmentTimeMin = 0.0F; + F32 measuredUFVolumeL = 0.0F; + F32 remainingUFVolumeL = 0.0F; + F32 remainingTreatmentTimeHr = 0.0F; + F32 newUfRateLHr = 0.0F; + + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.duration = 0; + response.ufVolumeGoal = 0.0F; + response.ufRate = 0.0F; + + if ( message->hdr.payloadLen == sizeof( DURATION_VALIDATE_REQUEST_PAYLOAD_T ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( request ) ); + + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + response.duration = request.duration; + + if ( ( request.duration >= MIN_TREATMENT_TIME_MINUTES ) && + ( request.duration <= MAX_TREATMENT_TIME_MINUTES ) ) + { + elapsedTreatmentTimeMin = (F32)treatmentTimeMS / (F32)MS_PER_SECOND / (F32)SEC_PER_MIN; + + if ( (F32)request.duration <= elapsedTreatmentTimeMin ) + { + response.accepted = FALSE; + 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; + + response.ufVolumeGoal = presUFVolumeL; + response.ufRate = newUfRateLHr; + + if ( newUfRateLHr <= 2.0F ) + { + response.accepted = TRUE; + } + else + { + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; + } + } + else + { + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; + } + } + } + else + { + response.accepted = FALSE; + 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 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. + * @return TRUE if response message is sent successfully, FALSE otherwise. + *************************************************************************/ +BOOL signalUserConfirmationOfTreatmentDuration( MESSAGE_T *message ) +{ + BOOL result = FALSE; + DURATION_CONFIRM_REQUEST_PAYLOAD_T request; + TREATMENT_TIME_CHANGE_RESPONSE_PAYLOAD_T response; + F32 elapsedTreatmentTimeMin = 0.0F; + F32 measuredUFVolumeL = 0.0F; + F32 remainingUFVolumeL = 0.0F; + F32 remainingTreatmentTimeHr = 0.0F; + + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.duration = 0; + response.volume = 0.0F; + + if ( message->hdr.payloadLen == sizeof( DURATION_CONFIRM_REQUEST_PAYLOAD_T ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( request ) ); + + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + response.duration = request.duration; + response.volume = presUFVolumeL; + + if ( ( request.duration >= MIN_TREATMENT_TIME_MINUTES ) && + ( request.duration <= MAX_TREATMENT_TIME_MINUTES ) ) + { + elapsedTreatmentTimeMin = (F32)treatmentTimeMS / (F32)MS_PER_SECOND / (F32)SEC_PER_MIN; + + if ( (F32)request.duration <= elapsedTreatmentTimeMin ) + { + response.accepted = FALSE; + 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 ) + { + presTreatmentTimeSecs = request.duration * SEC_PER_MIN; + presUFRateLHr = remainingUFVolumeL / remainingTreatmentTimeHr; + + setTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION, request.duration ); + + setDialysisDDParams( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), + presUFVolumeL, + presUFRateLHr ); + + response.accepted = TRUE; + } + else + { + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; + } + } + } + else + { + response.accepted = FALSE; + response.rejectionReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; + } + } + + result = sendMessage( MSG_ID_TD_DURATION_CONFIRM_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; + + 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; + + if ( ( request.bolusVolume >= MIN_BOLUS_VOLUME_ML ) && + ( request.bolusVolume <= MAX_BOLUS_VOLUME_ML ) ) + { + response.accepted = TRUE; + response.rejectionReason = REQUEST_REJECT_REASON_NONE; + + // TODO: Add state validation and apply bolus volume when saline bolus feature is integrated. + } + 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 broadcastTreatmentTimeAndState function broadcasts treatment time and * state data during treatment. * @details \b Inputs: treatmentTimeBroadcastTimerCtr, elapsedTreatmentTimeInSecs, Index: firmware/App/Modes/ModeTreatment.h =================================================================== diff -u -r395522dffef1348e176564925656012f529c1910 -rf0ea13c1a9908920793be07a946dc366d2ab5019 --- firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision 395522dffef1348e176564925656012f529c1910) +++ firmware/App/Modes/ModeTreatment.h (.../ModeTreatment.h) (revision f0ea13c1a9908920793be07a946dc366d2ab5019) @@ -94,26 +94,29 @@ // ********** public function prototypes ********** -void initTreatmentMode( void ); // Initialize this unit -U32 transitionToTreatmentMode( void ); // Prepares for transition to treatment mode -U32 execTreatmentMode( void ); // Execute the treatment mode state machine (call from OperationModes) +void initTreatmentMode( void ); // Initialize this unit +U32 transitionToTreatmentMode( void ); // Prepares for transition to treatment mode +U32 execTreatmentMode( void ); // Execute the treatment mode state machine (call from OperationModes) -void signalAlarmActionToTreatmentMode( ALARM_ACTION_T action ); // Execute alarm action as appropriate for treatment mode -void signalEndTreatment( void ); // Requesting transition to post-treatment mode -void signalBloodPrimeToDialysis( void ); // Blood prime sub-mode is signaling to move on to dialysis sub-mode +void signalAlarmActionToTreatmentMode( ALARM_ACTION_T action ); // Execute alarm action as appropriate for treatment mode +void signalEndTreatment( void ); // Requesting transition to post-treatment mode +void signalBloodPrimeToDialysis( void ); // Blood prime sub-mode is signaling to move on to dialysis sub-mode +BOOL validateAndSetTreatmentDuration( MESSAGE_T *message ); // Validate duration request and compute UF rate +BOOL signalUserConfirmationOfTreatmentDuration( MESSAGE_T *message );// Apply confirmed duration and update runtime settings +BOOL validateAndSetBolusVolume( MESSAGE_T *message ); // Validate bolus volume request and update parameter -void broadcastTreatmentTimeAndState( void ); // Broadcast the times and states of this treatment +void broadcastTreatmentTimeAndState( void ); // Broadcast the times and states of this treatment -TREATMENT_STATE_T getTreatmentState( void ); // Determine the current treatment sub-mode (state) -BOOL isTreatmentCompleted( void ); // Determine whether the treatment has completed -BOOL isTreatmentResumeBlocked( void ); // Determine whether the treatment is not allowed to be resumed. -U32 getTreatmentTimeRemainingSecs( void ); // Determine number of seconds remaining in the treatment -U32 getActualTreatmentTimeSecs( void ); // Determine the actual treatment duration in seconds -void setBloodIsPrimed( BOOL flag ); // Set whether the blood-side circuit of the dialyzer has been primed with blood (F causes Tx start/resume to do blood prime first) -BOOL getBloodIsPrimed( void ); // Determine whether the blood-side circuit of the dialyzer has been primed with blood +TREATMENT_STATE_T getTreatmentState( void ); // Determine the current treatment sub-mode (state) +BOOL isTreatmentCompleted( void ); // Determine whether the treatment has completed +BOOL isTreatmentResumeBlocked( void ); // Determine whether the treatment is not allowed to be resumed. +U32 getTreatmentTimeRemainingSecs( void ); // Determine number of seconds remaining in the treatment +U32 getActualTreatmentTimeSecs( void ); // Determine the actual treatment duration in seconds +void setBloodIsPrimed( BOOL flag ); // Set whether the blood-side circuit of the dialyzer has been primed with blood (F causes Tx start/resume to do blood prime first) +BOOL getBloodIsPrimed( void ); // Determine whether the blood-side circuit of the dialyzer has been primed with blood -U32 getTreatmentStartTimeStamp( void ); // Get the treatment start time stamp -U32 getTreatmentEndTimeStamp( void ); // Get the treatment end time stamp +U32 getTreatmentStartTimeStamp( void ); // Get the treatment start time stamp +U32 getTreatmentEndTimeStamp( void ); // Get the treatment end time stamp /**@}*/ Index: firmware/App/Modes/StateTxDialysis.c =================================================================== diff -u -r6f02ff4686ec9dfc60247e9ed3fc9c5cc7771543 -rf0ea13c1a9908920793be07a946dc366d2ab5019 --- firmware/App/Modes/StateTxDialysis.c (.../StateTxDialysis.c) (revision 6f02ff4686ec9dfc60247e9ed3fc9c5cc7771543) +++ firmware/App/Modes/StateTxDialysis.c (.../StateTxDialysis.c) (revision f0ea13c1a9908920793be07a946dc366d2ab5019) @@ -252,14 +252,14 @@ response.rejectionReason = REQUEST_REJECT_REASON_NONE; // Verify payload length is valid - if ( sizeof( BOOL ) == message->hdr.payloadLen ) + if ( sizeof( U32 ) == message->hdr.payloadLen ) { - BOOL payload; + U32 requestedState = 0U; - memcpy( &payload, message->payload, sizeof( BOOL ) ); + memcpy( &requestedState, message->payload, sizeof( U32 ) ); // Handle request to resume ultrafiltration - if ( TRUE == payload ) + if ( requestedState == 0U ) { if ( ( MODE_TREA == currMode ) && ( TREATMENT_DIALYSIS_STATE == trtState ) && ( DIALYSIS_UF_PAUSED_STATE == currentDialysisState ) ) { @@ -287,13 +287,13 @@ } } // Handle request to pause ultrafiltration - else + else if ( requestedState == 1U ) { if ( ( MODE_TREA == currMode ) && ( TREATMENT_DIALYSIS_STATE == trtState ) && ( DIALYSIS_UF_STATE == currentDialysisState ) ) { ufPauseRequested = TRUE; response.accepted = TRUE; - if ( setUFRateLHr > 0.0 ) + if ( setUFRateLHr > 0.0F ) { //sendTreatmentLogEventData( UF_PAUSE_EVENT, setUFRateLHr, 0.0 ); } @@ -314,11 +314,15 @@ } } } + else + { + response.rejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + } } else - { + { response.rejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; - } + } // 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 ) ); Index: firmware/App/Monitors/Pressures.c =================================================================== diff -u -r44bae490e03e2b458b4795673a1b108a27bcce54 -rf0ea13c1a9908920793be07a946dc366d2ab5019 --- firmware/App/Monitors/Pressures.c (.../Pressures.c) (revision 44bae490e03e2b458b4795673a1b108a27bcce54) +++ firmware/App/Monitors/Pressures.c (.../Pressures.c) (revision f0ea13c1a9908920793be07a946dc366d2ab5019) @@ -47,6 +47,23 @@ #define PRES_LIMIT_SHORT_STABILIZE_TIME_MS ( 10 * MS_PER_SECOND ) ///< Duration of pressure limit short stabilization period (in ms). #define PRES_LIMIT_RESTABILIZE_TIME_MS ( 15 * SEC_PER_MIN * MS_PER_SECOND ) ///< Duration of pressure limit re-stabilize period (in ms). +// Pressure limit window validation ranges (UI-editable values as per PRS) +#define ART_PRESSURE_LIMIT_WINDOW_MIN_MMHG ( 120 ) ///< Minimum arterial pressure window limit (mmHg) +#define ART_PRESSURE_LIMIT_WINDOW_MAX_MMHG ( 200 ) ///< Maximum arterial pressure window limit (mmHg) +#define ART_PRESSURE_LIMIT_WINDOW_STEP_MMHG ( 40 ) ///< Arterial pressure window increment (mmHg) + +#define VEN_PRESSURE_LIMIT_WINDOW_MIN_MMHG ( 100 ) ///< Minimum venous pressure window limit (mmHg) +#define VEN_PRESSURE_LIMIT_WINDOW_MAX_MMHG ( 200 ) ///< Maximum venous pressure window limit (mmHg) +#define VEN_PRESSURE_LIMIT_WINDOW_STEP_MMHG ( 20 ) ///< Venous pressure window increment (mmHg) + +#define VEN_ASYM_PRESSURE_LIMIT_WINDOW_MIN_MMHG ( 20 ) ///< Minimum venous asymmetric pressure limit (mmHg) +#define VEN_ASYM_PRESSURE_LIMIT_WINDOW_MAX_MMHG ( 35 ) ///< Maximum venous asymmetric pressure limit (mmHg) +#define VEN_ASYM_PRESSURE_LIMIT_WINDOW_STEP_MMHG ( 5 ) ///< Venous asymmetric pressure increment (mmHg) + +#define TMP_PRESSURE_LIMIT_WINDOW_MIN_MMHG ( 40 ) ///< Minimum TMP pressure window limit (mmHg) +#define TMP_PRESSURE_LIMIT_WINDOW_MAX_MMHG ( 100 ) ///< Maximum TMP pressure window limit (mmHg) +#define TMP_PRESSURE_LIMIT_WINDOW_STEP_MMHG ( 20 ) ///< TMP pressure window increment (mmHg) + /// Pressure Limit minimum stabilization time before short stabilization time activation static const U32 PRES_LIMIT_MIN_STABILIZATION_TIME_IN_MS = ( PRES_LIMIT_STABILIZATION_TIME_MS - PRES_LIMIT_SHORT_STABILIZE_TIME_MS ); @@ -214,6 +231,10 @@ static void determineArtVenPressureLimits( void ); static void filterInlinePressureReadings( F32 artPres, F32 venPres, F32 tmpPres ); static void filterBaroPressureReadings( F32 baroPresPSI ); +static BOOL isArterialPressureLimitWindowValid( S32 value ); +static BOOL isVenousPressureLimitWindowValid( S32 value ); +static BOOL isVenousAsymmetricPressureLimitWindowValid( S32 value ); +static BOOL isTmpPressureLimitWindowValid( S32 value ); /*********************************************************************//** * @brief @@ -1249,7 +1270,154 @@ return result; } +/*********************************************************************//** +* @brief +* The pressureLimitHandleChangeRequest function validates pressure limit +* change request received from the UI. +* @details \b Message \b Received: MSG_ID_UI_PRESSURE_LIMITS_CHANGE_REQUEST +* @details \b Message \b Sent: MSG_ID_TD_PRESSURE_LIMITS_CHANGE_RESPONSE +* @details \b Inputs: arterial, venous, venous asymmetric, and TMP +* pressure limit window values +* @details \b Outputs: pressure limits updated when valid +* @param message set message from UI +* @return TRUE if request is valid, FALSE if not +*************************************************************************/ +BOOL pressureLimitHandleChangeRequest ( MESSAGE_T *message ) +{ + BOOL result = FALSE; + REQUEST_REJECT_REASON_CODE_T rejReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + PRESSURE_LIMIT_CHANGE_REQUEST_T request = { 0 }; + PRESSURE_LIMIT_CHANGE_RESPONSE_T response = { 0 }; + if ( message->hdr.payloadLen == sizeof( request ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( request ) ); + + if ( isArterialPressureLimitWindowValid( request.arterialPressureLimitWindowMMHG ) && + isVenousPressureLimitWindowValid( request.venousPressureLimitWindowMMHG ) && + isVenousAsymmetricPressureLimitWindowValid( request.venousAsymmetricPressureLimitWindowMMHG ) && + isTmpPressureLimitWindowValid( request.tmpPressureLimitWindowMMHG ) ) + { + setTreatmentParameterS32( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW, + request.arterialPressureLimitWindowMMHG ); + + setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW, + request.venousPressureLimitWindowMMHG ); + + setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC, + request.venousAsymmetricPressureLimitWindowMMHG ); + + setTreatmentParameterS32( TREATMENT_PARAM_TMP_PRES_LIMIT_WINDOW, + request.tmpPressureLimitWindowMMHG ); + + updatePressureLimitWindows(); + + result = TRUE; + rejReason = REQUEST_REJECT_REASON_NONE; + } + else + { + result = FALSE; + rejReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + } + } + + response.accepted = result; + response.rejectionReason = rejReason; + response.arterialPressureLimitWindowMMHG = request.arterialPressureLimitWindowMMHG; + response.venousPressureLimitWindowMMHG = request.venousPressureLimitWindowMMHG; + response.venousAsymmetricPressureLimitWindowMMHG = request.venousAsymmetricPressureLimitWindowMMHG; + response.tmpPressureLimitWindowMMHG = request.tmpPressureLimitWindowMMHG; + + sendMessage( MSG_ID_TD_PRESSURE_LIMITS_CHANGE_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, + sizeof( response ) ); + + return result; +} + +/*********************************************************************//** + * @brief + * The isPressureLimitValueValid function checks whether a pressure limit + * value is within the specified range and aligns with the defined step. + * @details \b Inputs: value, minValue, maxValue, stepValue + * @details \b Outputs: none + * @return TRUE if value is valid, FALSE otherwise + *************************************************************************/ +static BOOL isPressureLimitValueValid( S32 value, S32 minValue, S32 maxValue, S32 stepValue ) +{ + BOOL result = FALSE; + + if ( ( value >= minValue ) && ( value <= maxValue ) ) + { + result = ( ( ( value - minValue ) % stepValue ) == 0 ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isArterialPressureLimitWindowValid function checks whether the + * arterial pressure limit window value is within valid range. + * @details \b Inputs: value + * @details \b Outputs: none + * @return TRUE if value is valid, FALSE otherwise + *************************************************************************/ +static BOOL isArterialPressureLimitWindowValid( S32 value ) +{ + return isPressureLimitValueValid( value, + ART_PRESSURE_LIMIT_WINDOW_MIN_MMHG, + ART_PRESSURE_LIMIT_WINDOW_MAX_MMHG, + ART_PRESSURE_LIMIT_WINDOW_STEP_MMHG ); +} + +/*********************************************************************//** + * @brief + * The isVenousPressureLimitWindowValid function checks whether the + * venous pressure limit window value is within valid range. + * @details \b Inputs: value + * @details \b Outputs: none + * @return TRUE if value is valid, FALSE otherwise + *************************************************************************/ +static BOOL isVenousPressureLimitWindowValid( S32 value ) +{ + return isPressureLimitValueValid( value, + VEN_PRESSURE_LIMIT_WINDOW_MIN_MMHG, + VEN_PRESSURE_LIMIT_WINDOW_MAX_MMHG, + VEN_PRESSURE_LIMIT_WINDOW_STEP_MMHG ); +} + +/*********************************************************************//** + * @brief + * The isVenousAsymmetricPressureLimitWindowValid function checks whether + * the venous asymmetric pressure limit window value is within valid range. + * @details \b Inputs: value + * @details \b Outputs: none + * @return TRUE if value is valid, FALSE otherwise + *************************************************************************/ +static BOOL isVenousAsymmetricPressureLimitWindowValid( S32 value ) +{ + return isPressureLimitValueValid( value, + VEN_ASYM_PRESSURE_LIMIT_WINDOW_MIN_MMHG, + VEN_ASYM_PRESSURE_LIMIT_WINDOW_MAX_MMHG, + VEN_ASYM_PRESSURE_LIMIT_WINDOW_STEP_MMHG ); +} + +/*********************************************************************//** + * @brief + * The isTmpPressureLimitWindowValid function checks whether the TMP + * pressure limit window value is within valid range. + * @details \b Inputs: value + * @details \b Outputs: none + * @return TRUE if value is valid, FALSE otherwise + *************************************************************************/ +static BOOL isTmpPressureLimitWindowValid( S32 value ) +{ + return isPressureLimitValueValid( value, + TMP_PRESSURE_LIMIT_WINDOW_MIN_MMHG, + TMP_PRESSURE_LIMIT_WINDOW_MAX_MMHG, + TMP_PRESSURE_LIMIT_WINDOW_STEP_MMHG ); +} /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Monitors/Pressures.h =================================================================== diff -u -rb017f10001f67282ab6622e34d629ae2f884cdc9 -rf0ea13c1a9908920793be07a946dc366d2ab5019 --- firmware/App/Monitors/Pressures.h (.../Pressures.h) (revision b017f10001f67282ab6622e34d629ae2f884cdc9) +++ firmware/App/Monitors/Pressures.h (.../Pressures.h) (revision f0ea13c1a9908920793be07a946dc366d2ab5019) @@ -99,6 +99,7 @@ F32 getBaroPressurePSI( void ); BOOL pressureLimitHandleWidenRequest( MESSAGE_T *message ); +BOOL pressureLimitHandleChangeRequest ( MESSAGE_T *message ); BOOL testPressuresDataPublishIntervalOverride( MESSAGE_T *message ); BOOL testTMPOverride( MESSAGE_T *message ); Index: firmware/App/Services/Messaging.c =================================================================== diff -u -r72bc0d5f33dbb07afc8a7cd9015e4861c6c371a1 -rf0ea13c1a9908920793be07a946dc366d2ab5019 --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision 72bc0d5f33dbb07afc8a7cd9015e4861c6c371a1) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision f0ea13c1a9908920793be07a946dc366d2ab5019) @@ -31,6 +31,7 @@ #include "LevelSensors.h" #include "Messaging.h" #include "ModeStandby.h" +#include "ModeTreatment.h" #include "OperationModes.h" #include "PAL.h" #include "Pressures.h" @@ -110,10 +111,14 @@ { MSG_ID_UI_TREATMENT_PARAMS_TO_VALIDATE, &validateAndSetTreatmentParameters }, { MSG_ID_UI_ULTRAFILTRATION_VOLUME_TO_VALIDATE, &validateAndSetUFVolume }, { MSG_ID_UI_TREATMENT_PARAMS_CONFIRMED, &signalUserConfirmationOfTreatmentParameters }, + { MSG_ID_UI_DURATION_VALIDATE_REQUEST, &validateAndSetTreatmentDuration }, + { MSG_ID_UI_DURATION_CONFIRM_REQUEST, &signalUserConfirmationOfTreatmentDuration }, + { MSG_ID_UI_BOLUS_VOLUME_CHANGE_REQUEST, &validateAndSetBolusVolume }, { MSG_ID_UI_INITIATE_TREATMENT_WORKFLOW, &signalUserInitiateTreatment }, { MSG_ID_UI_UF_PAUSE_RESUME_REQUEST, &signalPauseResumeUF }, { MSG_ID_TESTER_LOGIN_REQUEST, &handleTesterLogInRequest }, { MSG_ID_UI_PRESSURE_LIMIT_WIDEN_REQUEST, &pressureLimitHandleWidenRequest }, + { MSG_ID_UI_PRESSURE_LIMITS_CHANGE_REQUEST, &pressureLimitHandleChangeRequest }, { MSG_ID_UI_BLOOD_PRIME_CMD_REQUEST, &bloodPrimeHandleCmdRequest }, { MSG_ID_UI_TREATMENT_SET_POINT_BLOOD_FLOW_CHANGE_REQUEST, &bloodPrimeHandleBloodFlowChangeRequest }, { MSG_ID_TD_SOFTWARE_RESET_REQUEST, &testTDSoftwareResetRequest }, @@ -490,7 +495,6 @@ return result; } - // *********************************************************************** // ***************** Message Sending Helper Functions ******************** // *********************************************************************** Index: firmware/App/Services/Messaging.h =================================================================== diff -u -r395522dffef1348e176564925656012f529c1910 -rf0ea13c1a9908920793be07a946dc366d2ab5019 --- firmware/App/Services/Messaging.h (.../Messaging.h) (revision 395522dffef1348e176564925656012f529c1910) +++ firmware/App/Services/Messaging.h (.../Messaging.h) (revision f0ea13c1a9908920793be07a946dc366d2ab5019) @@ -81,6 +81,18 @@ F32 ufRate; ///< UF rate in mL. } UF_SETTINGS_CONFIRMATION_RESPONSE_PAYLOAD_T; +/// Payload record structure for treatment duration validate request. +typedef struct +{ + U32 duration; ///< Requested treatment duration in minutes. +} DURATION_VALIDATE_REQUEST_PAYLOAD_T; + +/// Payload record structure for treatment duration confirm request. +typedef struct +{ + U32 duration; ///< Confirmed treatment duration in minutes. +} DURATION_CONFIRM_REQUEST_PAYLOAD_T; + /// Payload record structure for treatment duration change response. typedef struct { @@ -90,6 +102,50 @@ F32 volume; ///< UF Volume in mL. } TREATMENT_TIME_CHANGE_RESPONSE_PAYLOAD_T; +/// Payload record structure for treatment duration validate response. +typedef struct +{ + BOOL accepted; ///< Accepted/Rejected + U32 rejectionReason; ///< Rejection reason if not accepted. + U32 duration; ///< Treatment duration in minutes. + F32 ufVolumeGoal; ///< UF volume goal in mL. + F32 ufRate; ///< UF rate in mL/min. +} DURATION_VALIDATE_RESPONSE_PAYLOAD_T; + +/// Payload record structure for bolus volume change request. +typedef struct +{ + U32 bolusVolume; ///< Requested bolus volume (in mL) +} BOLUS_VOLUME_CHANGE_REQUEST_PAYLOAD_T; + +/// Payload record structure for bolus volume change response. +typedef struct +{ + 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. +typedef struct +{ + S32 arterialPressureLimitWindowMMHG; ///< Arterial pressure limit window in mmHg. + S32 venousPressureLimitWindowMMHG; ///< Venous pressure limit window in mmHg. + S32 venousAsymmetricPressureLimitWindowMMHG; ///< Venous asymmetric pressure limit window in mmHg. + S32 tmpPressureLimitWindowMMHG; ///< TMP pressure limit window in mmHg. +} PRESSURE_LIMIT_CHANGE_REQUEST_T; + +/// Payload record structure for pressure limit change response. +typedef struct +{ + BOOL accepted; ///< Accepted/Rejected + U32 rejectionReason; ///< Rejection reason if not accepted. + S32 arterialPressureLimitWindowMMHG; ///< Arterial pressure limit window in mmHg. + S32 venousPressureLimitWindowMMHG; ///< Venous pressure limit window in mmHg. + S32 venousAsymmetricPressureLimitWindowMMHG; ///< Venous asymmetric pressure limit window in mmHg. + S32 tmpPressureLimitWindowMMHG; ///< TMP pressure limit window in mmHg. +} PRESSURE_LIMIT_CHANGE_RESPONSE_T; + /// Payload record structure for blood / dialysate rate change response. typedef struct {