Index: firmware/App/Services/TxParams.c =================================================================== diff -u -ra12f3ce494cd2a18aee31659c17d8a619fc70f7d -rd6775171de59386445ffdf70d6b32bcdfc1db07e --- firmware/App/Services/TxParams.c (.../TxParams.c) (revision a12f3ce494cd2a18aee31659c17d8a619fc70f7d) +++ firmware/App/Services/TxParams.c (.../TxParams.c) (revision d6775171de59386445ffdf70d6b32bcdfc1db07e) @@ -8,7 +8,7 @@ * @file TxParams.c * * @author (last) Vijay Pamula -* @date (last) 29-May-2026 +* @date (last) 11-Jun-2026 * * @author (original) Varshini Nagabooshanam * @date (original) 02-Dec-2025 @@ -21,6 +21,7 @@ #include "BloodFlow.h" #include "Buttons.h" #include "Messaging.h" +#include "ModeStandby.h" #include "ModeTreatment.h" #include "ModePreTreat.h" #include "OperationModes.h" @@ -139,11 +140,11 @@ static const TREATMENT_PARAMS_PROPERTIES_T SYS_CONFIG_TREAT_PARAMS_PROPERTIES[ NUM_OF_SYS_CONFIG_TREATMENT_PARAMS ] = { // type min max default - { CRITICAL_DATA_TYPE_U32, {.uInt=120}, {.uInt=200}, {.uInt=120} }, // TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW - { CRITICAL_DATA_TYPE_U32, {.uInt=100}, {.uInt=200}, {.uInt=100} }, // TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW - { CRITICAL_DATA_TYPE_U32, {.uInt=20}, {.uInt=35}, {.uInt=20} }, // TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC - { CRITICAL_DATA_TYPE_U32, {.uInt=40}, {.uInt=100}, {.uInt=40} }, // TREATMENT_PARAM_TMP_PRES_LIMIT_WINDOW - { CRITICAL_DATA_TYPE_U32, {.uInt=100}, {.uInt=500}, {.uInt=200} }, // TREATMENT_PARAM_RINSEBACK_FLOW_RATE + { CRITICAL_DATA_TYPE_U32, {.uInt=50}, {.uInt=100}, {.uInt=50} }, // TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW + { CRITICAL_DATA_TYPE_U32, {.uInt=50}, {.uInt=100}, {.uInt=50} }, // TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW + { CRITICAL_DATA_TYPE_U32, {.uInt=20}, {.uInt=35}, {.uInt=35} }, // TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC + { CRITICAL_DATA_TYPE_U32, {.uInt=20}, {.uInt=50}, {.uInt=20} }, // TREATMENT_PARAM_TMP_PRES_LIMIT_WINDOW + { CRITICAL_DATA_TYPE_U32, {.uInt=100}, {.uInt=500}, {.uInt=200} }, // TREATMENT_PARAM_RINSEBACK_FLOW_RATEs { CRITICAL_DATA_TYPE_U32, {.uInt=300}, {.uInt=1000}, {.uInt=300} }, // TREATMENT_PARAM_PRIME_DISCARD_VOLUME { CRITICAL_DATA_TYPE_U32, {.uInt=70}, {.uInt=140}, {.uInt=90} }, // TREATMENT_PARAM_SYSTOLIC_BP_LOW_ALARM_LIMIT { CRITICAL_DATA_TYPE_U32, {.uInt=100}, {.uInt=260}, {.uInt=200} }, // TREATMENT_PARAM_SYSTOLIC_BP_HIGH_ALARM_LIMIT @@ -207,6 +208,8 @@ static BOOL isVenousPressureLimitWindowValid( U32 value ); static BOOL isVenousAsymmetricPressureLimitWindowValid( U32 value ); static BOOL isTmpPressureLimitWindowValid( U32 value ); +static BOOL isVitalsAlarmLimitValueValid(U32 value, SYS_CONFIG_TREATMENT_PARAM_T param ); +static BOOL isVitalsMeasurementIntervalValid( U32 value, TREATMENT_PARAM_T param ); //static void getInstitutionalRecordEdgeValue( TREATMENT_PARAM_T param, CRITICAL_DATAS_T* value, BOOL isMin ); @@ -573,11 +576,11 @@ switch ( txType ) { - case TREATMENT_MODALITY_HDF: + case TREATMENT_MODALITY_HDF_ONLINE_FLUID: result = FALSE; break; - case TREATMENT_MODALITY_HD: + case TREATMENT_MODALITY_HD_SALINE_FLUID: result = ( ( ( param == TREATMENT_PARAM_HDF_DILUTION ) || ( param == TREATMENT_PARAM_SUBST_FLUID_VOLUME ) ) ? TRUE : FALSE ); break; @@ -736,6 +739,7 @@ F32 hepDR = stagedParams[ TREATMENT_PARAM_HEPARIN_DELIVERY_RATE ].sFlt; F32 hepBV = stagedParams[ TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ].sFlt; F32 txVol = hepBV + ( hepDR * ( hepST / (F32)SEC_PER_MIN ) ) + SYRINGE_PUMP_PRIME_VOLUME_ML + SYRINGE_PUMP_FILL_VOLUME_OFFSET_ML; + TREATMENT_TYPE_T modality = (TREATMENT_TYPE_T)stagedParams[ TREATMENT_PARAM_TREATMENT_MODALITY ].uInt; // Variable to validate acid conversion factor consistency U32 acidType = stagedParams[ TREATMENT_PARAM_ACID_CONCENTRATE ].uInt; @@ -766,6 +770,13 @@ result = FALSE; } + // Verify Rx entered modality with the treatment initiation modality + if ( modality != getModality() ) + { + reasons[ TREATMENT_PARAM_TREATMENT_MODALITY ] = REQUEST_REJECT_REASON_MODALITY_MISMATCH; + result = FALSE; + } + return result; } @@ -1637,6 +1648,136 @@ /*********************************************************************//** * @brief + * The vitalsAdjustmentHandleChangeRequest function handles the UI vitals + * settings change request during Treatment mode. + * @details \b Message \b Sent: MSG_ID_TD_VITALS_ADJUSTMENT_RESPONSE + * including acceptance status and per-parameter rejection reasons. + * @details \b Inputs: none. + * @details \b Outputs: none. + * @param message set message from UI which includes the requested vitals + * alarm limits and measurement interval. + * @return TRUE if response message is sent successfully, FALSE otherwise. + *************************************************************************/ +BOOL vitalsAdjustmentHandleChangeRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + BOOL accepted = FALSE; + VITALS_ADJUSTMENT_REQUEST_PAYLOAD_T request; + VITALS_ADJUSTMENT_RESPONSE_PAYLOAD_T response; + + if ( message->hdr.payloadLen == sizeof( VITALS_ADJUSTMENT_REQUEST_PAYLOAD_T ) ) + { + memcpy( &request, &message->payload[ 0 ], sizeof( VITALS_ADJUSTMENT_REQUEST_PAYLOAD_T ) ); + + response.systolicBpLowAlarmLimitRejectionReason = REQUEST_REJECT_REASON_NONE; + response.systolicBpHighAlarmLimitRejectionReason = REQUEST_REJECT_REASON_NONE; + response.heartRateLowAlarmLimitRejectionReason = REQUEST_REJECT_REASON_NONE; + response.heartRateHighAlarmLimitRejectionReason = REQUEST_REJECT_REASON_NONE; + response.vitalsMeasurementIntervalRejectionReason = REQUEST_REJECT_REASON_NONE; + + if ( FALSE == isVitalsAlarmLimitValueValid( request.systolicBpLowAlarmLimit, + TREATMENT_PARAM_SYSTOLIC_BP_LOW_ALARM_LIMIT ) ) + { + response.systolicBpLowAlarmLimitRejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + } + + if ( FALSE == isVitalsAlarmLimitValueValid( request.systolicBpHighAlarmLimit, + TREATMENT_PARAM_SYSTOLIC_BP_HIGH_ALARM_LIMIT ) ) + { + response.systolicBpHighAlarmLimitRejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + } + + if ( FALSE == isVitalsAlarmLimitValueValid( request.heartRateLowAlarmLimit, + TREATMENT_PARAM_HEART_RATE_LOW_ALARM_LIMIT ) ) + { + response.heartRateLowAlarmLimitRejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + } + + if ( FALSE == isVitalsAlarmLimitValueValid( request.heartRateHighAlarmLimit, + TREATMENT_PARAM_HEART_RATE_HIGH_ALARM_LIMIT ) ) + { + response.heartRateHighAlarmLimitRejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + } + + if ( FALSE == isVitalsMeasurementIntervalValid( request.vitalsMeasurementInterval_min, + TREATMENT_PARAM_BP_MEAS_INTERVAL ) ) + { + response.vitalsMeasurementIntervalRejectionReason = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + } + + accepted = ( REQUEST_REJECT_REASON_NONE == response.systolicBpLowAlarmLimitRejectionReason ) && + ( REQUEST_REJECT_REASON_NONE == response.systolicBpHighAlarmLimitRejectionReason ) && + ( REQUEST_REJECT_REASON_NONE == response.heartRateLowAlarmLimitRejectionReason ) && + ( REQUEST_REJECT_REASON_NONE == response.heartRateHighAlarmLimitRejectionReason ) && + ( REQUEST_REJECT_REASON_NONE == response.vitalsMeasurementIntervalRejectionReason ); + + if ( TRUE == accepted ) + { + setSysConfigTreatmentParameterU32( TREATMENT_PARAM_SYSTOLIC_BP_LOW_ALARM_LIMIT, request.systolicBpLowAlarmLimit ); + setSysConfigTreatmentParameterU32( TREATMENT_PARAM_SYSTOLIC_BP_HIGH_ALARM_LIMIT, request.systolicBpHighAlarmLimit ); + setSysConfigTreatmentParameterU32( TREATMENT_PARAM_HEART_RATE_LOW_ALARM_LIMIT, request.heartRateLowAlarmLimit ); + setSysConfigTreatmentParameterU32( TREATMENT_PARAM_HEART_RATE_HIGH_ALARM_LIMIT, request.heartRateHighAlarmLimit ); + setTreatmentParameterU32( TREATMENT_PARAM_BP_MEAS_INTERVAL, request.vitalsMeasurementInterval_min ); + } + } + else + { + response.systolicBpLowAlarmLimitRejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.systolicBpHighAlarmLimitRejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.heartRateLowAlarmLimitRejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.heartRateHighAlarmLimitRejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + response.vitalsMeasurementIntervalRejectionReason = REQUEST_REJECT_REASON_INVALID_REQUEST_FORMAT; + } + + response.accepted = accepted; + + result = sendMessage( MSG_ID_TD_VITALS_ADJUSTMENT_RESPONSE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08 *)&response, sizeof( VITALS_ADJUSTMENT_RESPONSE_PAYLOAD_T ) ); + + return result; +} + +/*********************************************************************//** + * @brief + * The isVitalsAlarmLimitValueValid function validates a vitals alarm + * limit value against the configured range for the specified parameter. + * @details \b Inputs: none. + * @details \b Outputs: none. + * @param value vitals alarm limit value to validate. + * @param param vitals alarm limit treatment parameter. + * @return TRUE if value is valid, FALSE otherwise. + *************************************************************************/ +static BOOL isVitalsAlarmLimitValueValid( U32 value, SYS_CONFIG_TREATMENT_PARAM_T param ) +{ + BOOL limitValid; + + limitValid = ( ( value >= getU32SysConfigTreatmentParamLowerRangeLimit( param ) ) && + ( value <= getU32SysConfigTreatmentParamUpperRangeLimit( param ) ) ) ? TRUE : FALSE; + + return limitValid; +} + +/*********************************************************************//** + * @brief + * The isVitalsMeasurementIntervalValid function validates the vitals + * measurement interval value against the configured range. + * @details \b Inputs: none. + * @details \b Outputs: none. + * @param value vitals measurement interval value (minutes). + * @param param treatment parameter associated with the interval. + * @return TRUE if value is valid, FALSE otherwise. + *************************************************************************/ +static BOOL isVitalsMeasurementIntervalValid( U32 value, TREATMENT_PARAM_T param ) +{ + BOOL intervalValid; + + intervalValid = ( ( value >= getU32TreatmentParamLowerRangeLimit( param ) ) && + ( value <= getU32TreatmentParamUpperRangeLimit( param ) ) ) ? TRUE : FALSE; + + return intervalValid; +} + +/*********************************************************************//** + * @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 including acceptance status