Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r289696b3b5e15120cfecbe447ff45ef093959056 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 289696b3b5e15120cfecbe447ff45ef093959056) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file BloodFlow.c * -* @author (last) Sean -* @date (last) 25-Oct-2024 +* @author (last) Dara Navaei +* @date (last) 26-Oct-2025 * -* @author (original) Sean -* @date (original) 25-Oct-2024 +* @author (original) Sean Nash +* @date (original) 24-Oct-2024 * ***************************************************************************/ Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r78fe8ab743ad4c64144421662960757a29b9b0b0 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 78fe8ab743ad4c64144421662960757a29b9b0b0) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,6 +1,6 @@ /************************************************************************** * -* Copyright (c) 2025-2025 Diality Inc. - All Rights Reserved. +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. @@ -15,6 +15,7 @@ * ***************************************************************************/ +#include "Buttons.h" #include "ModePreTreat.h" #include "OperationModes.h" #include "Timers.h" Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -rf90801d4a4f5cd1276b4a54175d101710b4096f2 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision f90801d4a4f5cd1276b4a54175d101710b4096f2) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModeStandby.c * -* @author (last) Sean -* @date (last) 30-Jul-2024 +* @author (last) Dara Navaei +* @date (last) 25-Sep-2025 * -* @author (original) Sean -* @date (original) 30-Jul-2024 +* @author (original) Sean Nash +* @date (original) 01-Aug-2024 * ***************************************************************************/ Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r289696b3b5e15120cfecbe447ff45ef093959056 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 289696b3b5e15120cfecbe447ff45ef093959056) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,20 +1,21 @@ /************************************************************************** * -* Copyright (c) 2025-2025 Diality Inc. - All Rights Reserved. +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file ModeTreatment.c * -* @author (last) Sean -* @date (last) 25-Mar-2025 +* @author (last) Varshini Nagabooshanam +* @date (last) 19-Jan-2026 * -* @author (original) Sean -* @date (original) 25-Mar-2025 +* @author (original) Sean Nash +* @date (original) 21-Apr-2025 * ***************************************************************************/ +#include #include "AirTrap.h" //#include "BloodFlow.h" #include "Bubbles.h" @@ -24,6 +25,7 @@ #include "ModeTreatment.h" //#include "NVDataMgmt.h" #include "OperationModes.h" +#include "Pressures.h" #include "StateTxDialysis.h" #include "StateTxPaused.h" //#include "Switches.h" @@ -183,7 +185,7 @@ // Initialize treatment mode each time we transition to it initTreatmentMode(); // Initialize treatment sub-modes each time we transition to treatment mode -// initBloodPrime(); + initBloodPrime(); initDialysis(); initTreatmentPaused(); // initRinseback(); @@ -316,6 +318,35 @@ /*********************************************************************//** * @brief + * The setBloodIsPrimed function sets that flag indicating whether the + * blood-side circuit has been primed with blood. Call this function with + * TRUE when blood prime operation is completed. Call this function with + * FALSE at start of treatment or start of rinseback operation. + * @details Inputs: none + * @details Outputs: bloodIsPrimed + * @param flag TRUE if blood side circuit is primed with blood, FALSE if not + * @return none + *************************************************************************/ +void setBloodIsPrimed( BOOL flag ) +{ + bloodIsPrimed = flag; +} + +/*********************************************************************//** + * @brief + * The getBloodIsPrimed function determines whether the blood-side circuit + * has been primed with blood (indicating blood-side circuit should be primarily blood). + * @details Inputs: bloodIsPrimed + * @details Outputs: none + * @return bloodIsPrimed + *************************************************************************/ +BOOL getBloodIsPrimed( void ) +{ + return bloodIsPrimed; +} + +/*********************************************************************//** + * @brief * The signalAlarmActionToTreatmentMode function executes the given alarm action * as appropriate while in Treatment Mode. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if invalid alarm action given. @@ -329,7 +360,7 @@ switch( action ) { case ALARM_ACTION_STOP: - // Stop signal actively polled by mode/sub-mode/state + // signal actively polled by mode/sub-mode/state break; case ALARM_ACTION_RESUME: @@ -369,9 +400,22 @@ /*********************************************************************//** * @brief + * The signalBloodPrimeToDialysis function signals that blood prime has + * completed and it is time to move on to dialysis. + * @details Inputs: none + * @details Outputs: bloodPrimeToDialysisRequest + * @return none + *************************************************************************/ +void signalBloodPrimeToDialysis( void ) +{ + bloodPrimeToDialysisRequest = TRUE; +} + +/*********************************************************************//** + * @brief * The execTreatmentMode function executes the Treatment Mode state machine. - * @details \b Alarm: ALARM_ID_TD_TREATMENT_STOPPED_BY_USER if user presses - * the stop button + * @details \b Alarm: ALARM_ID_TD_TREATMENT_PED_BY_USER if user presses + * the button * @details \b Inputs: currentTreatmentState * @details \b Outputs: currentTreatmentState, resumeBlockedByAlarm * @return current state (sub-mode) @@ -380,7 +424,7 @@ { BOOL stop = isStopButtonPressed(); - // Trigger user stop alarm at any time in treatment mode when user presses stop button + // Trigger user alarm at any time in treatment mode when user presses button if ( TRUE == stop ) { activateAlarmNoData( ALARM_ID_TD_TREATMENT_STOPPED_BY_USER ); @@ -480,7 +524,7 @@ TREATMENT_STATE_T result = TREATMENT_BLOOD_PRIME_STATE; lastTreatmentTimeStamp = getMSTimerCount(); - //transitionToBloodPrime(); // TODO + transitionToBloodPrime(); setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); // TODO - remove later return result; @@ -500,19 +544,19 @@ // setRinsebackIsCompleted( FALSE ); -// // Handle alarm stoppage -// if ( TRUE == doesAlarmStatusIndicateStop() ) -// { -// transitionToTreatmentStop(); -// result = TREATMENT_STOP_STATE; -// } -// else -// { -// execBloodPrime(); -// -// // Handle signals from blood prime sub-mode -// if ( TRUE == bloodPrimeToDialysisRequest ) -// { + // Handle alarm page + if ( TRUE == doesAlarmStatusIndicateStop() ) + { + transitionToTreatmentPaused(); + result = TREATMENT_PAUSED_STATE; + } + else + { + execBloodPrime(); + + // Handle signals from blood prime sub-mode + if ( TRUE == bloodPrimeToDialysisRequest ) + { lastTreatmentTimeStamp = getMSTimerCount(); // Kick dialysis sub-mode off setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); @@ -526,8 +570,8 @@ // // To update partial blood pump occlusion baseline - start of treatment // signalBloodPumpPressureOcclBaseline(); result = TREATMENT_DIALYSIS_STATE; -// } -// } + } + } return result; } @@ -567,7 +611,7 @@ else { execDialysis(); - // Handle alarm stoppage + // Handle alarm page if ( TRUE == doesAlarmStatusIndicateStop() ) { transitionToTreatmentPaused(); @@ -596,18 +640,18 @@ { resumeTreatmentAlarmResponseRequest = FALSE; -// if ( TRUE == getBloodIsPrimed() ) + if ( TRUE == getBloodIsPrimed() ) { lastTreatmentTimeStamp = getMSTimerCount(); transitionToDialysis(); result = TREATMENT_DIALYSIS_STATE; } -// else -// { -// transitionToBloodPrime(); -// result = TREATMENT_BLOOD_PRIME_STATE; -// } -// signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); + else + { + transitionToBloodPrime(); + result = TREATMENT_BLOOD_PRIME_STATE; + } + signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); } // If user requests rinseback, go to rinseback // else if ( TRUE == initiateRinsebackAlarmResponseRequest ) @@ -631,7 +675,7 @@ // If leaving treatment paused state, zero alarm countdown timer for UI // if ( TRUE == leavingTreatmentPausedState ) // { -// TREATMENT_STOP_PAYLOAD_T data; +// TREATMENT_PAUSED_PAYLOAD_T data; // // data.timeout = 0; // data.countdown = 0; @@ -646,7 +690,7 @@ * The handleTreatmentRinsebackState function executes the rinseback state of the * Treatment Mode state machine. * @details \b Inputs: endTreatmentAlarmResponseRequest, resumeTreatmentAlarmResponseRequest, - * rinsebackToRecircRequest, rinsebackToStoppedRequest, endTreatmentRequest + * rinsebackToRecircRequest, rinsebackTopedRequest, endTreatmentRequest * @details \b Outputs: treatment rinseback sub-mode executed, sendLastTreatmentPeriodicData * @return next treatment mode state *************************************************************************/ @@ -679,10 +723,10 @@ // transitionToTreatmentRecirc(); // result = TREATMENT_RECIRC_STATE; // } -// else if ( TRUE == rinsebackToStoppedRequest ) +// else if ( TRUE == rinsebackTopedRequest ) // { -// transitionToTreatmentStop(); -// result = TREATMENT_STOP_STATE; +// transitionToTreatment(); +// result = TREATMENT_PAUSED_STATE; // } // else if ( TRUE == endTreatmentRequest ) // { @@ -696,7 +740,7 @@ * @brief * The handleTreatmentRecircState function executes the re-circulate state of the * Treatment Mode state machine. - * @details \b Inputs: endTreatmentAlarmResponseRequest, rinsebackToStoppedRequest, + * @details \b Inputs: endTreatmentAlarmResponseRequest, rinsebackTopedRequest, * endTreatmentRequest * @details \b Outputs: sendLastTreatmentPeriodicData * @return next treatment mode state @@ -718,11 +762,11 @@ // } // // // Handle signals from treatment re-circ sub-mode -// if ( TRUE == rinsebackToStoppedRequest ) +// if ( TRUE == rinsebackTopedRequest ) // { -// stopDialysis(); -// transitionToTreatmentStop(); -// result = TREATMENT_STOP_STATE; +// Dialysis(); +// transitionToTreatment(); +// result = TREATMENT__STATE; // } // else if ( TRUE == endTreatmentRequest ) // { @@ -829,10 +873,10 @@ treatmentStateBroadcastTimerCtr = 0; payload.treatmentSubMode = (U32)currentTreatmentState; - payload.bldPrimeState = 0; // getCurrentBloodPrimeState(); + payload.bldPrimeState = getCurrentBloodPrimeState(); payload.dialysisState = getDialysisState(); payload.isoUFState = 0; - payload.txStopState = getCurrentTreatmentPausedState(); + payload.txPausedState = getCurrentTreatmentPausedState(); payload.rinsebackState = 0; // getCurrentRinsebackState(); payload.txRecircState = 0; // getCurrentTreatmentRecircState(); payload.txEndState = 0; // getCurrentTreatmentEndState(); @@ -1000,7 +1044,7 @@ *************************************************************************/ static void resetSignalFlags( void ) { -// rinsebackToStoppedRequest = FALSE; +// rinsebackTopedRequest = FALSE; endTreatmentRequest = FALSE; // rinsebackToRecircRequest = FALSE; bloodPrimeToDialysisRequest = FALSE; Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -rf90801d4a4f5cd1276b4a54175d101710b4096f2 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision f90801d4a4f5cd1276b4a54175d101710b4096f2) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file OperationModes.c * -* @author (last) Sean -* @date (last) 30-Jul-2024 +* @author (last) Dara Navaei +* @date (last) 13-Oct-2025 * -* @author (original) Sean -* @date (original) 30-Jul-2024 +* @author (original) Sean Nash +* @date (original) 01-Aug-2024 * ***************************************************************************/ Index: firmware/App/Modes/StateTxBloodPrime.c =================================================================== diff -u -r395522dffef1348e176564925656012f529c1910 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Modes/StateTxBloodPrime.c (.../StateTxBloodPrime.c) (revision 395522dffef1348e176564925656012f529c1910) +++ firmware/App/Modes/StateTxBloodPrime.c (.../StateTxBloodPrime.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -19,7 +19,7 @@ #include "AirTrap.h" #include "BloodFlow.h" #include "ModeTreatment.h" -#include "ModeTxParams.h" +#include "TxParams.h" #include "OperationModes.h" #include "Switches.h" #include "TaskGeneral.h" Index: firmware/App/Modes/StateTxDialysis.c =================================================================== diff -u -r289696b3b5e15120cfecbe447ff45ef093959056 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Modes/StateTxDialysis.c (.../StateTxDialysis.c) (revision 289696b3b5e15120cfecbe447ff45ef093959056) +++ firmware/App/Modes/StateTxDialysis.c (.../StateTxDialysis.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2025-2025 Diality Inc. - All Rights Reserved. +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file StateTxDialysis.c * -* @author (last) Sean -* @date (last) 15-Apr-2025 +* @author (last) Sean Nash +* @date (last) 03-Jun-2025 * -* @author (original) Sean -* @date (original) 15-Apr-2025 +* @author (original) Sean Nash +* @date (original) 21-Apr-2025 * ***************************************************************************/ Index: firmware/App/Modes/StateTxPaused.c =================================================================== diff -u -r289696b3b5e15120cfecbe447ff45ef093959056 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Modes/StateTxPaused.c (.../StateTxPaused.c) (revision 289696b3b5e15120cfecbe447ff45ef093959056) +++ firmware/App/Modes/StateTxPaused.c (.../StateTxPaused.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2025-2025 Diality Inc. - All Rights Reserved. +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file StateTxPaused.c * -* @author (last) Sean -* @date (last) 18-Apr-2025 +* @author (last) Sean Nash +* @date (last) 16-Sep-2025 * -* @author (original) Sean -* @date (original) 18-Apr-2025 +* @author (original) Sean Nash +* @date (original) 21-Apr-2025 * ***************************************************************************/ Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r679d535b77aa6722671084774ad5d96e9789e12e -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 679d535b77aa6722671084774ad5d96e9789e12e) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file AlarmMgmtSWFaults.h * -* @author (last) Sean -* @date (last) 30-Jul-2024 +* @author (last) Varshini Nagabooshanam +* @date (last) 19-Jan-2026 * -* @author (original) Sean -* @date (original) 30-Jul-2024 +* @author (original) Sean Nash +* @date (original) 01-Aug-2024 * ***************************************************************************/ @@ -176,6 +176,12 @@ SW_FAULT_ID_VALVES_INVALID_VALVE_ENCODER_REQ = 145, SW_FAULT_ID_TD_VALVES_INVALID_IDLE = 146, SW_FAULT_ID_TD_VALVES_INVALID_IN_TRANSITION = 147, + SW_FAULT_ID_TD_EJECTOR_OPTICAL_SENSOR_INVALID_REQ = 148, + SW_FAULT_ID_VALVES_INVALID_VALVE_HOMING_SET = 149, + SW_FAULT_ID_VALVES_INVALID_VALVE_MAX_ENC_POS_REQ = 150, + SW_FAULT_ID_VALVES_INVALID_VALVE_FINDING_EDGE = 151, + SW_FAULT_ID_TD_VALVES_INVALID_FIND_DEENERGIZED_EDGE = 152, + SW_FAULT_ID_BLOOD_PRIME_INVALID_STATE = 153, SW_FAULT_ID_MODE_PRE_TREATMENT_INVALID_STATE = 148, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/DDInterface.c =================================================================== diff -u -r679d535b77aa6722671084774ad5d96e9789e12e -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Services/DDInterface.c (.../DDInterface.c) (revision 679d535b77aa6722671084774ad5d96e9789e12e) +++ firmware/App/Services/DDInterface.c (.../DDInterface.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file DDInterface.c * -* @author (last) Sean -* @date (last) 30-Jul-2024 +* @author (last) Dara Navaei +* @date (last) 16-Oct-2025 * -* @author (original) Sean -* @date (original) 30-Jul-2024 +* @author (original) Sean Nash +* @date (original) 01-Aug-2024 * ***************************************************************************/ Index: firmware/App/Services/Messaging.c =================================================================== diff -u -r289696b3b5e15120cfecbe447ff45ef093959056 -r4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision 289696b3b5e15120cfecbe447ff45ef093959056) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -1,17 +1,17 @@ /************************************************************************** * -* Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. +* Copyright (c) 2024-2026 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file Messaging.c * -* @author (last) Sean -* @date (last) 30-Jul-2024 +* @author (last) Varshini Nagabooshanam +* @date (last) 19-Jan-2026 * -* @author (original) Sean -* @date (original) 30-Jul-2024 +* @author (original) Sean Nash +* @date (original) 01-Aug-2024 * ***************************************************************************/ @@ -35,6 +35,7 @@ #include "PAL.h" #include "Pressures.h" #include "RotaryValve.h" +#include "StateTxBloodPrime.h" #include "StateTxDialysis.h" #include "StateTxPaused.h" #include "Switches.h" @@ -161,6 +162,7 @@ { MSG_ID_TD_OP_MODE_OVERRIDE_REQUEST, &testSetOperationMode }, { MSG_ID_TD_EJECTOR_MOTOR_SET_SPEED_REQUEST, &testSetEjectorMotorSpeed }, { MSG_ID_TD_EJECTOR_COMMAND, &testEjectorCommand }, + { MSG_ID_TD_EJECTOR_PUBLISH_INTERVAL_OVERRIDE_REQUEST, &testEjectorDataPublishIntervalOverride }, { MSG_ID_TD_SET_AIR_TRAP_CONTROL, &testSetAirTrapControl }, { MSG_ID_TD_HOME_BLOOD_PUMP, &testHomeBloodPump }, { MSG_ID_TD_BLOOD_FLOW_ALPHA_Y_INTERCEPT_OVERRIDE_REQUEST, &testBPFlowAlphaYInterceptOverride }, @@ -176,6 +178,9 @@ { MSG_ID_TD_BARO_PRESSURE_OVERRIDE, &testBaroPressureOverride }, { MSG_ID_TD_TEMPERATURE_OVERRIDE, &testTemperatureOverride }, { MSG_ID_TD_TEMPERATURE_PUBLISH_INTERVAL_OVERRIDE_REQUEST, &testTemperatureDataPublishIntervalOverride }, + { MSG_ID_TD_EJECTOR_OPT_SENSOR_OVERRIDE_REQUEST, &testEjectorOpticalSensorOverride }, + { MSG_ID_TD_BLOOD_PRIME_VOLUME_OVERRIDE, &testBloodPrimeVolumeOverride }, + { MSG_ID_TD_BLOOD_PRIME_PUBLISH_INTERVAL_OVERRIDE_REQUEST, &testBloodPrimePublishIntervalOverride }, }; #define NUM_OF_FUNCTION_HANDLERS (sizeof(MSG_FUNCTION_HANDLER_LOOKUP) / sizeof(MSG_HANDLER_LOOKUP_T)) Index: firmware/App/Services/TxParams.c =================================================================== diff -u --- firmware/App/Services/TxParams.c (revision 0) +++ firmware/App/Services/TxParams.c (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -0,0 +1,1239 @@ +/************************************************************************** +* +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file TxParams.c +* +* @author (last) Sean +* @date (last) 26-Nov-2025 +* +* @author (original) Sean +* @date (original) 17-Nov-2025 +* +***************************************************************************/ + +#include "AirPump.h" +#include "AirTrap.h" +#include "BloodFlow.h" +#include "Buttons.h" +#include "Messaging.h" +#include "ModeTreatment.h" +#include "ModePreTreat.h" +#include "OperationModes.h" +#include "Pressures.h" +#include "StateTxDialysis.h" +#include "Switches.h" +#include "TDCommon.h" +#include "TxParams.h" +#include "Utilities.h" +#include "Valve3Way.h" +#include "Valves.h" + +/** + * @addtogroup TxParams + * @{ + */ + +// ********** private definitions ********** + +#define MAX_HEPARIN_VOLUME_ML 10.0F ///< Maximum heparin volume ( in mL ) +#define NO_HEPARIN_PRE_STOP_TIME_SET 0 ///< Zero value indicates no Heparin pre-stop time was set by user +#define NO_HEPARIN_TYPE_SET 0xFFFFFFFF ///< UI will send this value for Heparin type if Heparin not used + +#define INSTIT_CHEM_DISINFECT_ENABLE_RANGE 1 ///< Institutional record chemical disinfect enable/disable allowable range + +#define SYRINGE_PUMP_PRIME_VOLUME_ML 0.353F ///< Target syringe prime volume (in mL). TODO- move these to syringe pump controller when implemented +#define SYRINGE_PUMP_FILL_VOLUME_OFFSET_ML 0.8F ///< Advised fill volume offset due to HW variance. + +/// Record for range and default of treatment parameters. +typedef struct +{ + CRITICAL_DATA_TYPES_T dataType; ///< Data type for the treatment parameter + CRITICAL_DATAS_T min; ///< Minimum of range + CRITICAL_DATAS_T max; ///< Maximum of range + CRITICAL_DATAS_T def; ///< Default value +} TREATMENT_PARAMS_PROPERTIES_T; + +/// Dialyzer volume data record structure. +typedef struct +{ + U32 bloodVolume; ///< Blood volume of the dialyzer in mL. + U32 dialysateVolume; ///< Dialysate volume of the dialyzer in mL. +} DIALYZER_VOLUME_DATA_T; + +/// Record structure for adjustable treatment parameters +typedef struct +{ + U32 bloodFlowRate_mL_min; ///< Original blood flow rate (in mL/min) set by user before treatment start + U32 dialysateFlowRate_mL_min; ///< Original dialysate flow rate (in mL/min) set by user before treatment start + U32 treatmentDuration_min; ///< Original treatment duration (in min) set by user before treatment start + S32 arterialPressureLimitWindow_mmHg; ///< Original alarm limit window for arterial pressure (in mmHg) set by user before treatment start + S32 venousPressureLimitWindow_mmHg; ///< Original alarm limit window for venous pressure (in mmHg) set by user before treatment start + S32 venousPressureLimitAsymmetric_mmHg; ///< Original alarm limit asymmetric for venous pressure (in mmHg) set by user before treatment start + S32 tmpLimitWindow_mmHg; ///< Original alarm limit window for trans-membrane pressure (in mmHg) set by user before treatment start + F32 uFVolume_L; ///< Original ultrafiltration volume (in L) set by user before treatment start +} ADJ_TREATMENT_PARAMS_T; + +#pragma pack(push, 1) +/// Record structure for response to validate Tx params +typedef struct +{ + BOOL accepted; ///< Command accepted. + U32 reason[ NUM_OF_TREATMENT_PARAMS - 1 ]; ///< Rejection reason codes; 1 for each parameter. +} TREATMENT_PARAMS_VAL_RESP_DATA_PAYLOAD_T; + +/// Record structure for response to validate ultrafiltration volume +typedef struct +{ + BOOL accepted; ///< Command accepted. + U32 rejReason; ///< Rejection reason code (if rejected). + F32 ufVolumeMl; ///< Validated ultrafiltration volume (in mL). +} UF_VOLUME_VAL_RESP_DATA_PAYLOAD_T; + +/// Record structure for set treatment parameter Dialin message. +typedef struct +{ + U32 paramID; ///< Treatment parameter ID. + CRITICAL_DATAS_T value; ///< Set value. +} DIALIN_SET_TX_PARAM_PAYLOAD_T; +#pragma pack(pop) + +// ********** private data ********** + +static const TREATMENT_PARAMS_PROPERTIES_T TREAT_PARAMS_PROPERTIES[ NUM_OF_TREATMENT_PARAMS ] = +{ // type min max default + { CRITICAL_DATA_TYPE_U32, {.uInt=50}, {.uInt=500}, {.uInt=50} }, // TREATMENT_PARAM_BLOOD_FLOW + { CRITICAL_DATA_TYPE_U32, {.uInt=50}, {.uInt=600}, {.uInt=50} }, // TREATMENT_PARAM_DIALYSATE_FLOW + { CRITICAL_DATA_TYPE_U32, {.uInt=60}, {.uInt=480}, {.uInt=60} }, // TREATMENT_PARAM_TREATMENT_DURATION + { CRITICAL_DATA_TYPE_U32, {.uInt=100}, {.uInt=300}, {.uInt=100} }, // TREATMENT_PARAM_SALINE_BOLUS_VOLUME + { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=480}, {.uInt=0} }, // TREATMENT_PARAM_HEPARIN_STOP_TIME + { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=0}, {.uInt=0} }, // TREATMENT_PARAM_HEPARIN_TYPE + { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=2}, {.uInt=0} }, // TREATMENT_PARAM_ACID_CONCENTRATE + { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=0}, {.uInt=0} }, // TREATMENT_PARAM_BICARB_CONCENTRATE + { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=6}, {.uInt=0} }, // TREATMENT_PARAM_DIALYZER_TYPE + { CRITICAL_DATA_TYPE_U32, {.uInt=0}, {.uInt=60}, {.uInt=0} }, // TREATMENT_PARAM_BP_MEAS_INTERVAL + { CRITICAL_DATA_TYPE_U32, {.uInt=100}, {.uInt=300}, {.uInt=200} }, // TREATMENT_PARAM_RINSEBACK_FLOW_RATE + { CRITICAL_DATA_TYPE_U32, {.uInt=200}, {.uInt=400}, {.uInt=300} }, // TREATMENT_PARAM_RINSEBACK_VOLUME + { CRITICAL_DATA_TYPE_S32, {.sInt=120}, {.sInt=200}, {.sInt=120} }, // TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW + { CRITICAL_DATA_TYPE_S32, {.sInt=100}, {.sInt=200}, {.sInt=100} }, // TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW + { CRITICAL_DATA_TYPE_S32, {.sInt=20}, {.sInt=35}, {.sInt=20} }, // TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC + { CRITICAL_DATA_TYPE_S32, {.sInt=40}, {.sInt=100}, {.sInt=40} }, // TREATMENT_PARAM_TMP_PRES_LIMIT_WINDOW + { CRITICAL_DATA_TYPE_F32, {.sFlt=35.0}, {.sFlt=38.0}, {.sFlt=37.0} }, // TREATMENT_PARAM_DIALYSATE_TEMPERATURE + { CRITICAL_DATA_TYPE_F32, {.sFlt=0.0}, {.sFlt=1.0}, {.sFlt=0.0} }, // TREATMENT_PARAM_HEPARIN_DISPENSE_RATE + { CRITICAL_DATA_TYPE_F32, {.sFlt=0.0}, {.sFlt=2.0}, {.sFlt=0.0} }, // TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME + { CRITICAL_DATA_TYPE_F32, {.sFlt=0.0}, {.sFlt=8.0}, {.sFlt=0.0} }, // TREATMENT_PARAM_UF_VOLUME +}; + +/// Dialyzer volumes (blood and dialysate) table in mL for each type of dialyzer. +const DIALYZER_VOLUME_DATA_T dialyzerVolumeTable[ NUM_OF_DIALYZER_TYPES ] = + { { 82, 170 }, // DIALYZER_TYPE_BBRAUN_PRO_13H + { 100, 200 }, // DIALYZER_TYPE_BBRAUN_PRO_16H + { 120, 257 }, // DIALYZER_TYPE_BBRAUN_PRO_19H + { 87, 233 }, // DIALYZER_TYPE_FRESENIUS_OPTIFLUX_F160NRE + { 102, 280 }, // DIALYZER_TYPE_FRESENIUS_OPTIFLUX_F180NRE + { 113, 348 }, // DIALYZER_TYPE_FRESENIUS_OPTIFLUX_F200NRE + { 142, 304 } }; // DIALYZER_TYPE_FRESENIUS_OPTIFLUX_F250NRE + +// Current treatment parameter values +static CRITICAL_DATA_T treatmentParameters[ NUM_OF_TREATMENT_PARAMS ]; ///< Treatment parameters. +static CRITICAL_DATAS_T stagedParams[ NUM_OF_TREATMENT_PARAMS ]; ///< Temporary staged treatment parameters for validation and awaiting user confirmation. + +// Original treatment parameter values (for those that can be changed during treatment) +static ADJ_TREATMENT_PARAMS_T origTreatmentParams; ///< Originally set (before treatment) treatment parameters. + +static BOOL validTreatParamsReceived = FALSE; ///< Flag indicates user has provided treatment parameters. +static BOOL treatParamsConfirmed = FALSE; ///< Flag indicates user has confirmed the treatment parameters. + +// ********** private function prototypes ********** + +static void resetAllTreatmentParameters( void ); +static BOOL checkTreatmentParamsInRange( U32 *reasons ); +static BOOL checkTreatmentParamsDependencies( U32 *reasons ); +static void extractTreatmentParamsFromPayload( TREATMENT_PARAMS_DATA_PAYLOAD_T payload ); +//static void checkPressureParamsRange( TREATMENT_PARAMS_DATA_PAYLOAD_T* txParams ); +static void sendTreatmentParamsResponse( BOOL rejected, U32 *reasons ); +//static void getInstitutionalRecordEdgeValue( TREATMENT_PARAM_T param, CRITICAL_DATAS_T* value, BOOL isMin ); + +/*********************************************************************//** + * @brief + * The resetAllTreatmentParameters function resets treatment parameters + * to default values. + * @details \b Inputs: none + * @details \b Outputs: All treatment parameters reset to default values and + * original and staged treatment parameters reset to zero. + * @return none + *************************************************************************/ +static void resetAllTreatmentParameters( void ) +{ + TREATMENT_PARAM_T param; + + for ( param = TREATMENT_PARAM_FIRST_UINT; param < NUM_OF_TREATMENT_PARAMS; param++ ) + { + // Set type, range, and default value for each treatment parameter + treatmentParameters[ param ].typ = TREAT_PARAMS_PROPERTIES[ param ].dataType; + treatmentParameters[ param ].minimum = TREAT_PARAMS_PROPERTIES[ param ].min; + treatmentParameters[ param ].maximum = TREAT_PARAMS_PROPERTIES[ param ].max; + treatmentParameters[ param ].defValue = TREAT_PARAMS_PROPERTIES[ param ].def; + resetCriticalData( &treatmentParameters[ param ] ); + // Set staged parameter values to zero + stagedParams[ param ].uInt = 0; + } + + // Zero original parameter values + origTreatmentParams.bloodFlowRate_mL_min = 0; + origTreatmentParams.dialysateFlowRate_mL_min = 0; + origTreatmentParams.treatmentDuration_min = 0; + origTreatmentParams.arterialPressureLimitWindow_mmHg = 0; + origTreatmentParams.venousPressureLimitWindow_mmHg = 0; + origTreatmentParams.venousPressureLimitAsymmetric_mmHg = 0; + origTreatmentParams.tmpLimitWindow_mmHg = 0; + origTreatmentParams.uFVolume_L = 0.0F; +} + +/*********************************************************************//** + * @brief + * The setTreatmentParameterU32 function sets a given unsigned integer + * treatment parameter to a given value. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: treatmentParameters[] + * @param param ID of treatment parameter to set unsigned integer value for + * @param value unsigned integer value to assign to given treatment parameter + * @return TRUE if set was successful, FALSE if not + *************************************************************************/ +BOOL setTreatmentParameterU32( TREATMENT_PARAM_T param, U32 value ) +{ + CRITICAL_DATAS_T integerData; + BOOL result = FALSE; + + integerData.uInt = value; + result = isTreatmentParamInRange( param, integerData ); + + // Validate parameter + if ( param <= TREATMENT_PARAM_LAST_UINT ) + { + if ( TRUE == result ) + { + CRITICAL_DATAS_T data = treatmentParameters[ param ].data; + + data.uInt = value; + result = setCriticalData( &treatmentParameters[ param ], data ); + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_SET_U32_PARAM, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The setTreatmentParameterS32 function sets a given signed integer treatment + * parameter to a given value. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: treatmentParameters[] + * @param param ID of treatment parameter to set signed integer value for + * @param value signed integer value to assign to given treatment parameter + * @return TRUE if set was successful, FALSE if not + *************************************************************************/ +BOOL setTreatmentParameterS32( TREATMENT_PARAM_T param, S32 value ) +{ + CRITICAL_DATAS_T unsignedIntData; + BOOL result = FALSE; + + unsignedIntData.sInt = value; + result = isTreatmentParamInRange( param, unsignedIntData ); + + // Validate parameter + if ( ( param >= TREATMENT_PARAM_FIRST_INT ) && ( param <= TREATMENT_PARAM_LAST_INT ) ) + { + if ( TRUE == result ) + { + CRITICAL_DATAS_T data = treatmentParameters[ param ].data; + + data.sInt = value; + result = setCriticalData( &treatmentParameters[ param ], data ); + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_SET_S32_PARAM, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The setTreatmentParameterF32 sets a given floating point treatment parameter + * to a given value. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: treatmentParameters[] + * @param param ID of treatment parameter to set floating point value for + * @param value floating point value to assign to given treatment parameter + * @return TRUE if set was successful, FALSE if not + *************************************************************************/ +BOOL setTreatmentParameterF32( TREATMENT_PARAM_T param, F32 value ) +{ + CRITICAL_DATAS_T floatData; + BOOL result = FALSE; + + floatData.sFlt = value; + result = isTreatmentParamInRange( param, floatData ); + + // Validate parameter + if ( ( param >= TREATMENT_PARAM_FIRST_F32 ) && ( param < NUM_OF_TREATMENT_PARAMS ) ) + { + if ( TRUE == result ) + { + CRITICAL_DATAS_T data = treatmentParameters[ param ].data; + + data.sFlt = value; + result = setCriticalData( &treatmentParameters[ param ], data ); + } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_SET_F32_PARAM, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentParameterU32 function gets the value of a given unsigned + * integer treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of treatment parameter to get unsigned integer value for + * @return value of given unsigned integer treatment parameter + *************************************************************************/ +U32 getTreatmentParameterU32( TREATMENT_PARAM_T param ) +{ + U32 result = 1; + + // Validate parameter + if ( param <= TREATMENT_PARAM_LAST_UINT ) + { + CRITICAL_DATAS_T data = getCriticalData( &treatmentParameters[ param ] ); + + result = data.uInt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_U32_PARAM, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentParameterS32 function gets the value of a given signed + * integer treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of treatment parameter to get signed integer value for + * @return value of given signed integer treatment parameter + *************************************************************************/ +S32 getTreatmentParameterS32( TREATMENT_PARAM_T param ) +{ + S32 result = 1; + + // Validate parameter + if ( ( param >= TREATMENT_PARAM_FIRST_INT ) && ( param <= TREATMENT_PARAM_LAST_INT ) ) + { + CRITICAL_DATAS_T data = getCriticalData( &treatmentParameters[ param ] ); + + result = data.sInt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_S32_PARAM, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentParameterF32 function gets the value of a given floating point + * treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of treatment parameter to get floating point value for + * @return value of given floating point treatment parameter + *************************************************************************/ +F32 getTreatmentParameterF32( TREATMENT_PARAM_T param ) +{ + F32 result = 1.0; + + // Validate parameter + if ( ( param >= TREATMENT_PARAM_FIRST_F32 ) && ( param < NUM_OF_TREATMENT_PARAMS ) ) + { + CRITICAL_DATAS_T data = getCriticalData( &treatmentParameters[ param ] ); + + result = data.sFlt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getTreatmentParameterS32DefaultValue function gets the defaultvalue + * of a given signed integer treatment parameter. + * @details \b Inputs: TREAT_PARAMS_PROPERTIES[] + * @details \b Outputs: none + * @param param ID of treatment parameter to get signed integer default value for + * @return default value of given signed integer treatment parameter + *************************************************************************/ +S32 getTreatmentParameterS32DefaultValue( TREATMENT_PARAM_T param ) +{ + return TREAT_PARAMS_PROPERTIES[ param ].def.sInt; +} + +/*********************************************************************//** + * @brief + * The validateAndSetTreatmentParameters function validates received + * treatment parameters. + * @details \b Message \b Sent: MSG_ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE + * @details \b Message \b Sent: MSG_ID_TD_TREATMENT_PARAM_RANGES if params are valid + * @details \b Inputs: none + * @details \b Outputs: stagedParams[], validTreatParamsReceived + * @param message set message from UI which includes the user set treatment + * parameters record. + * @return TRUE if received treatment parameters are valid, FALSE if not + *************************************************************************/ +BOOL validateAndSetTreatmentParameters( MESSAGE_T *message ) +{ + BOOL paramsAreInvalid = TRUE; + BOOL paramsAreInRange, paramsAreConsistent; + BOOL result = FALSE; + TREATMENT_PARAMS_DATA_PAYLOAD_T params; + U32 rejReasons[ NUM_OF_TREATMENT_PARAMS ]; + + // Initialize reject reasons to zeroes + memset( (U08*)&rejReasons[0], 0, sizeof( U32 ) * NUM_OF_TREATMENT_PARAMS ); + + // Verify message payload length is valid + if ( sizeof( TREATMENT_PARAMS_DATA_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( ¶ms, message->payload, sizeof( TREATMENT_PARAMS_DATA_PAYLOAD_T ) ); + + // Check the received arterial and venous pressure values from the UI to be checked and capped against the min and max + // values in the institutional record + // checkPressureParamsRange( ¶ms ); // TODO + + // Extract treatment parameters from given payload to staging array so we can more easily work with them + extractTreatmentParamsFromPayload( params ); + + // Range check each treatment parameter + paramsAreInRange = checkTreatmentParamsInRange( &rejReasons[0] ); + + // Validate dependencies + paramsAreConsistent = checkTreatmentParamsDependencies( &rejReasons[0] ); + + // Determine overall validity of received treatment parameters + if ( ( TRUE == paramsAreInRange ) && ( TRUE == paramsAreConsistent ) ) + { + paramsAreInvalid = FALSE; + validTreatParamsReceived = TRUE; + } + + // Respond to set treatment parameters request message + sendTreatmentParamsResponse( paramsAreInvalid, &rejReasons[0] ); + // Send initial adjustable ranges to UI so UF volume range will be known when UF volume prompted for later + if ( TRUE == validTreatParamsReceived ) + { + U32 setTxDuration = stagedParams[ TREATMENT_PARAM_TREATMENT_DURATION ].uInt; + TREATMENT_PARAM_RANGE_BROADCAST_PAYLOAD_T payload; + + 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.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 ) ); + } + + result = ( TRUE == paramsAreInvalid ? FALSE : TRUE ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The checkTreatmentParamsInRange function checks whether received + * treatment parameters are in range. + * @details \b Inputs: stagedParams[] + * @details \b Outputs: reasons[] + * @param reasons Pointer to array of reject reason codes for each parameter + * @return TRUE if treatment parameters are in range, FALSE if not + *************************************************************************/ +static BOOL checkTreatmentParamsInRange( U32 *reasons ) +{ + BOOL result = TRUE; + TREATMENT_PARAM_T param; + + // Range check treatment parameters up to (but not including) UF volume + for ( param = TREATMENT_PARAM_FIRST_UINT; param < TREATMENT_PARAM_UF_VOLUME; param++ ) + { + reasons[ param ] = REQUEST_REJECT_REASON_NONE; + +#if 0 +// if ( FALSE == isTreatmentParamInRange( param, stagedParams[ param ] ) ) // TODO - restore when institutional settings implemented (and remove range checks below) +// { +// reasons[ param ] = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; +// result = FALSE; +// } +#else + if ( param <= TREATMENT_PARAM_LAST_UINT ) + { + if ( ( stagedParams[ param ].uInt < TREAT_PARAMS_PROPERTIES[ param ].min.uInt ) || + ( stagedParams[ param ].uInt > TREAT_PARAMS_PROPERTIES[ param ].max.uInt ) ) + { + reasons[ param ] = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + result = FALSE; + } + } + else if ( param <= TREATMENT_PARAM_LAST_INT ) + { + if ( ( stagedParams[ param ].sInt < TREAT_PARAMS_PROPERTIES[ param ].min.sInt ) || + ( stagedParams[ param ].sInt > TREAT_PARAMS_PROPERTIES[ param ].max.sInt ) ) + { + reasons[ param ] = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + result = FALSE; + } + } + else + { + if ( ( stagedParams[ param ].sFlt < TREAT_PARAMS_PROPERTIES[ param ].min.sFlt ) || + ( stagedParams[ param ].sFlt > TREAT_PARAMS_PROPERTIES[ param ].max.sFlt ) ) + { + reasons[ param ] = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; + result = FALSE; + } + } + } +#endif + + return result; +} + +/*********************************************************************//** + * @brief + * The checkTreatmentParamsDependencies function checks dependencies between + * received treatment parameters. + * @details \b Inputs: stagedParams[] + * @details \b Outputs: reasons[] + * @param reasons Pointer to array of reject reason codes for each parameter + * @return TRUE if treatment parameter dependencies are ok, FALSE if not + *************************************************************************/ +static BOOL checkTreatmentParamsDependencies( U32 *reasons ) +{ + BOOL result = TRUE; + U32 txDur = stagedParams[ TREATMENT_PARAM_TREATMENT_DURATION ].uInt; + U32 hepST = stagedParams[ TREATMENT_PARAM_HEPARIN_STOP_TIME ].uInt; + F32 hepDR = stagedParams[ TREATMENT_PARAM_HEPARIN_DISPENSE_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; + + // Verify Heparin stop time is only set if Heparin dispense rate is set + if ( ( hepST > 0 ) && ( hepDR < NEARLY_ZERO ) ) + { + reasons[ TREATMENT_PARAM_HEPARIN_STOP_TIME ] = REQUEST_REJECT_REASON_HEPARIN_STOP_TIME_WITH_NO_DISPENSE; + result = FALSE; + } + // Verify Heparin stop time does not exceed Tx duration + else if ( hepST > txDur ) + { + reasons[ TREATMENT_PARAM_HEPARIN_STOP_TIME ] = REQUEST_REJECT_REASON_HEPARIN_STOP_TIME_EXCEEDS_DURATION; + result = FALSE; + } + // Verify Heparin stop time does not exceed max 10 mL Heparin volume + else if ( txVol > MAX_HEPARIN_VOLUME_ML ) + { + reasons[ TREATMENT_PARAM_HEPARIN_STOP_TIME ] = REQUEST_REJECT_REASON_HEPARIN_VOLUME_EXCEEDS_10_ML; + result = FALSE; + } + + return result; +} + +/*********************************************************************//** + * @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 resetTreatmentParameters function resets the Treatment Parameters + * session flags and parameter values. + * @details Inputs: none + * @details Outputs: validTreatParamsReceived, treatParamsConfirmed, + * treatParamsRejected cleared and parameters reset. + * @return none + *************************************************************************/ +void resetTreatmentParameters( void ) +{ + validTreatParamsReceived = FALSE; + treatParamsConfirmed = FALSE; + + resetAllTreatmentParameters(); +} + +/*********************************************************************//** +* @brief +* The getValidTreatParamsReceived function reports whether a valid set +* of Treatment Parameters has been staged. +* @details Inputs: validTreatParamsReceived +* @details Outputs: none +* @return TRUE if valid parameters are available, FALSE otherwise. +**************************************************************************/ +BOOL getValidTreatParamsReceived( void ) +{ + return validTreatParamsReceived; +} + +/*********************************************************************//** + * @brief + * The getTreatParamsConfirmed function reports whether the current + * Treatment Parameters have been confirmed by the user. + * @details Inputs: treatParamsConfirmed + * @details Outputs: none + * @return TRUE if the current Treatment Parameters are confirmed, + * FALSE otherwise. + *************************************************************************/ +BOOL getTreatParamsConfirmed( void ) +{ + return treatParamsConfirmed; +} + +/*********************************************************************//** + * @brief + * The signalUserConfirmationOfTreatmentParameters function sets the user + * confirmation flag signaling user has confirmed or rejected treatment + * parameters. + * @details \b Inputs: none + * @details \b Outputs: treatParamsConfirmed + * @param message confirmation message from UI which includes the user + * confirmation or restTreamentParameters. + * @return TRUE if confirmation/rejection accepted, FALSE if not + *************************************************************************/ +BOOL signalUserConfirmationOfTreatmentParameters( MESSAGE_T *message ) +{ + BOOL confirmed = FALSE; + BOOL result = FALSE; + + if ( sizeof( BOOL ) == message->hdr.payloadLen ) + { + memcpy( &confirmed, message->payload, sizeof( BOOL ) ); + if ( TRUE == confirmed ) + { + // ModePreTreat uses this via getTreatParamsConfirmed() + treatParamsConfirmed = TRUE; + } + else + { + // Rejected – clear session + resetTreatmentParameters(); + } + result = TRUE; + } + else + { + result = FALSE; + } + + 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. + * @details \b Inputs: none + * @details \b Outputs: stagedParams[] + * @param payload message payload record containing received treatment parameters + * @return none + *************************************************************************/ +static void extractTreatmentParamsFromPayload( TREATMENT_PARAMS_DATA_PAYLOAD_T payload ) +{ + // Pull treatment parameters into data array so we can more easily work with them + memcpy( &stagedParams[0], &payload, sizeof(TREATMENT_PARAMS_DATA_PAYLOAD_T) ); +} + +/*********************************************************************//** + * @brief + * The sendTreatmentParamsResponse function responds to the treatment parameters + * received from the UI. An over-all ok/rejected flag as well as individual reject + * reason codes for each parameter are provided back to the UI. + * @details \b Message \b Sent: MSG_ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE + * @details \b Inputs : none + * @details \b Outputs : Response to treatment parameters message constructed and sent. + * @param rejected 1 if rejected, 0 if parameters ok + * @param reasons array of reject reason codes for each parameter (0=not rejected) + * @return none + *************************************************************************/ +static void sendTreatmentParamsResponse( BOOL rejected, U32 *reasons ) +{ + TREATMENT_PARAMS_VAL_RESP_DATA_PAYLOAD_T payload; + + payload.accepted = ( TRUE == rejected ? FALSE : TRUE ); + memcpy( &payload.reason[0], &reasons[0], sizeof( TREATMENT_PARAMS_DATA_PAYLOAD_T ) ); + sendMessage( MSG_ID_TD_RESP_TREATMENT_PARAMS_TO_VALIDATE, COMM_BUFFER_OUT_CAN_TD_2_UI, (U08*)(&payload), sizeof( TREATMENT_PARAMS_VAL_RESP_DATA_PAYLOAD_T ) ); +} + +/*********************************************************************//** + * @brief + * The getDialyzerBloodVolume function gets the blood side volume (in mL) + * for a given dialyzer type. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given dialyzer type is invalid + * @details \b Inputs : dialyzerVolumeTable[] + * @details \b Outputs : none + * @param dialyzer The type of dialyzer to get the blood side volume for + * @return The blood side volume for the given dialyzer type + *************************************************************************/ +U32 getDialyzerBloodVolume( DIALYZER_TYPE_T dialyzer ) +{ + U32 result = 0; + + if ( dialyzer < NUM_OF_DIALYZER_TYPES ) + { + result = dialyzerVolumeTable[ dialyzer ].bloodVolume; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYZER_TYPE_INVALID1, (U32)dialyzer ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getDialyzerDialysateVolume function gets the dialysate side volume (in mL) + * for a given dialyzer type. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given dialyzer type is invalid + * @details \b Inputs : dialyzerVolumeTable[] + * @details \b Outputs : none + * @param dialyzer The type of dialyzer to get the dialysate side volume for + * @return The dialysate side volume for the given dialyzer type + *************************************************************************/ +U32 getDialyzerDialysateVolume( DIALYZER_TYPE_T dialyzer ) +{ + U32 result = 0; + + if ( dialyzer < NUM_OF_DIALYZER_TYPES ) + { + result = dialyzerVolumeTable[ dialyzer ].dialysateVolume; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYZER_TYPE_INVALID2, (U32)dialyzer ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The isTreatmentParamInRange function determines whether a given treatment + * parameter is in range. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid + * @details \b Inputs: treatParamsRanges[], hdInstitutionalRecord + * @details \b Outputs: none + * @param param ID of parameter to check range for + * @param value value of parameter to check range for + * @return TRUE if given treatment parameter is in range, FALSE if not + *************************************************************************/ +BOOL isTreatmentParamInRange( TREATMENT_PARAM_T param, CRITICAL_DATAS_T value ) +{ + BOOL result = TRUE; // TODO FALSE; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { +// switch( param ) +// { +// case TREATMENT_PARAM_BLOOD_FLOW: +// result = ( ( value.uInt >= hdInstitutionalRecord.minBloodFlowMLPM ) && +// ( value.uInt <= hdInstitutionalRecord.maxBloodFlowMLPM ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_DIALYSATE_FLOW: +// result = ( ( value.uInt >= hdInstitutionalRecord.minDialysateFlowMLPM ) && +// ( value.uInt <= hdInstitutionalRecord.maxDialysateFlowMLPM ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_TREATMENT_DURATION: +// result = ( ( value.uInt >= hdInstitutionalRecord.minTxDurationMIN ) && +// ( value.uInt <= hdInstitutionalRecord.maxTxDurationMIN ) ? TRUE : FALSE ); +// // If the 1-minute treatment is selected, it is ok to accept the time. This test configuration specifically checks for a 1-minute run +// result |= ( TRUE == getTestConfigStatus( TEST_CONFIG_ENABLE_ONE_MINUTE_TREATMENT ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_SALINE_BOLUS_VOLUME: +// result = ( ( value.uInt >= hdInstitutionalRecord.minSalineBolusVolumeML ) && +// ( value.uInt <= hdInstitutionalRecord.maxSalineBolusVolumeML ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_DIALYSATE_TEMPERATURE: +// result = ( ( value.sFlt >= hdInstitutionalRecord.minDialysateTempC ) && +// ( value.sFlt <= hdInstitutionalRecord.maxDialysateTempC ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW: +// result = ( ( value.sInt >= hdInstitutionalRecord.minArtPressLimitWindowMMHG ) && +// ( value.sInt <= hdInstitutionalRecord.maxArtPressLimitWindowMMHG ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW: +// result = ( ( value.sInt >= hdInstitutionalRecord.minVenPressLimitWindowMMHG ) && +// ( value.sInt <= hdInstitutionalRecord.maxVenPressLimitWindowMMHG ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC: +// result = ( ( value.sInt >= hdInstitutionalRecord.minVenAsymPressLimitMMHG ) && +// ( value.sInt <= hdInstitutionalRecord.maxVenAsymPressLimitMMHG ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_TMP_PRES_LIMIT_WINDOW: +// result = ( ( value.sInt >= hdInstitutionalRecord.minTmpPressLimitWindowMMHG ) && +// ( value.sInt <= hdInstitutionalRecord.maxTmpPressLimitWindowMMHG ) ? TRUE : FALSE ); +// break; +// +// case TREATMENT_PARAM_UF_VOLUME: +// result = ( ( value.sFlt >= hdInstitutionalRecord.minUFVolumeL ) && ( value.sFlt <= hdInstitutionalRecord.maxUFVolumeL ) ? TRUE : FALSE ); +// result |= ( fabs( value.sFlt ) <= NEARLY_ZERO ? TRUE : FALSE ); // There might be a minimum UF volume set in the institutional record but a treatment with 0 vol should be allowed +// break; +// +// default: +//#ifndef _VECTORCAST_ +// // The treatment parameters that do not have any institutional record. +// // Right now, all the F32 and S32 data types are covered in the institutional record and therefore, there is no test case that is either F32 or S32 +// // and gets here so it is removed from VectorCAST to be able to achieve 100% coverage of the function +// // The treatment parameters that do not have any institutional record. +// if ( CRITICAL_DATA_TYPE_U32 == TREAT_PARAMS_PROPERTIES[ param ].dataType ) +//#endif +// { +// result = ( ( value.uInt >= TREAT_PARAMS_PROPERTIES[ param ].min.uInt ) && +// ( value.uInt <= TREAT_PARAMS_PROPERTIES[ param ].max.uInt ) ? TRUE : FALSE ); +// } +//#ifndef _VECTORCAST_ +// // Right now, all the F32 and S32 data types are covered in the institutional record and therefore, there is no test case that is either F32 or S32 +// // and gets here so it is removed from VectorCAST to be able to achieve 100% coverage of the function +// else if ( CRITICAL_DATA_TYPE_S32 == TREAT_PARAMS_PROPERTIES[ param ].dataType ) +// { +// result = ( ( value.sInt >= TREAT_PARAMS_PROPERTIES[ param ].min.sInt ) && +// ( value.sInt <= TREAT_PARAMS_PROPERTIES[ param ].max.sInt ) ? TRUE : FALSE ); +// } +// else +// { +// result = ( ( value.sFlt >= TREAT_PARAMS_PROPERTIES[ param ].min.sFlt ) && +// ( value.sFlt <= TREAT_PARAMS_PROPERTIES[ param ].max.sFlt ) ? TRUE : FALSE ); +// } +//#endif +// } + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_PARAM, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getS32TreatmentParamLowerRangeLimit function returns the lower range + * limit for a given signed integer treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of parameter to get lower range limit for + * @return lower range limit for given signed integer treatment parameter + *************************************************************************/ +S32 getS32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_T param ) +{ + S32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; + // getInstitutionalRecordEdgeValue( param, &value, TRUE ); TODO + value = treatmentParameters[ param ].minimum; + result = value.sInt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_S32_PARAM_MIN_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getS32TreatmentParamUpperRangeLimit function returns the upper range + * limit for a given signed integer treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid. + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of parameter to get upper range limit for + * @return upper range limit for given signed integer treatment parameter + *************************************************************************/ +S32 getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_T param ) +{ + S32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; +// getInstitutionalRecordEdgeValue( param, &value, FALSE ); // TODO + value = treatmentParameters[ param ].maximum; + result = value.sInt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_S32_PARAM_MAX_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getU32TreatmentParamLowerRangeLimit function returns the lower range + * limit for a given unsigned integer treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid. + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of parameter to get lower range limit for + * @return lower range limit for given unsigned integer treatment parameter + *************************************************************************/ +U32 getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_T param ) +{ + U32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; +// getInstitutionalRecordEdgeValue( param, &value, TRUE ); // TODO + value = treatmentParameters[ param ].minimum; + result = value.uInt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_U32_PARAM_MIN_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getU32TreatmentParamUpperRangeLimit function returns the upper range + * limit for a given unsigned integer treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid. + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of parameter to get upper range limit for + * @return upper range limit for given unsigned integer treatment parameter + *************************************************************************/ +U32 getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_T param ) +{ + U32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; +// getInstitutionalRecordEdgeValue( param, &value, FALSE ); // TODO + value = treatmentParameters[ param ].maximum; + result = value.uInt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_U32_PARAM_MAX_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getF32TreatmentParamLowerRangeLimit function returns the lower range + * limit for a given float treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid. + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of parameter to get lower range limit for + * @return lower range limit for given float treatment parameter + *************************************************************************/ +F32 getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_T param ) +{ + F32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; +// getInstitutionalRecordEdgeValue( param, &value, TRUE ); // TODO + value = treatmentParameters[ param ].minimum; + result = value.sFlt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM_MIN_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getF32TreatmentParamUpperRangeLimit function returns the upper range + * limit for a given float treatment parameter. + * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given param is invalid. + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param param ID of parameter to get lower range limit for + * @return upper range limit for given float treatment parameter + *************************************************************************/ +F32 getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_T param ) +{ + F32 result = 0; + + if ( param < NUM_OF_TREATMENT_PARAMS ) + { + CRITICAL_DATAS_T value; +// getInstitutionalRecordEdgeValue( param, &value, FALSE ); // TODO + value = treatmentParameters[ param ].maximum; + result = value.sFlt; + } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_PARAMS_INVALID_GET_F32_PARAM_MAX_LIMIT, (U32)param ) + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getS32DefaultTreatmentParamEdge function returns the min or max of + * the default treatment parameters + * @details \b Inputs: TREAT_PARAMS_PROPERTIES[] + * @details \b Outputs: none + * @param param ID of parameter + * @param isMin to indicate whether minimum is needed for maximum + * @return the requested min or max value + *************************************************************************/ +S32 getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ) +{ + S32 value = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.sInt : TREAT_PARAMS_PROPERTIES[ param ].max.sInt ); + + return value; +} + +/*********************************************************************//** + * @brief + * The getU32DefaultTreatmentParamEdge function returns the min or max of + * the default treatment parameters + * @details \b Inputs: TREAT_PARAMS_PROPERTIES[] + * @details \b Outputs: none + * @param param ID of parameter + * @param isMin to indicate whether minimum is needed for maximum + * @return the requested min or max value + *************************************************************************/ +U32 getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ) +{ + U32 value = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.uInt : TREAT_PARAMS_PROPERTIES[ param ].max.uInt ); + + return value; +} + +/*********************************************************************//** + * @brief + * The getF32DefaultTreatmentParamEdge function returns the min or max of + * the default treatment parameters + * @details \b Inputs: TREAT_PARAMS_PROPERTIES[] + * @details \b Outputs: none + * @param param ID of parameter + * @param isMin to indicate whether minimum is needed for maximum + * @return the requested min or max value + *************************************************************************/ +F32 getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ) +{ + F32 value = ( TRUE == isMin ? TREAT_PARAMS_PROPERTIES[ param ].min.sFlt : TREAT_PARAMS_PROPERTIES[ param ].max.sFlt ); + + return value; +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetTreatmentParameter function sets a given treatment parameter + * to a given value. + * @details \b Inputs: none + * @details \b Outputs: treatmentParameters[] + * @param message Set treatment parameter message from Dialin which includes + * the ID of the treatment parameter to be set and the value to set it to. + * @return TRUE if set request is successful, FALSE if not + *************************************************************************/ +BOOL testSetTreatmentParameter( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // Verify payload length is valid + if ( message->hdr.payloadLen == sizeof( DIALIN_SET_TX_PARAM_PAYLOAD_T ) ) + { + DIALIN_SET_TX_PARAM_PAYLOAD_T payload; + + memcpy( (U08*)&payload, &message->payload[0], sizeof( DIALIN_SET_TX_PARAM_PAYLOAD_T ) ); + + // Verify treatment parameter ID is valid + if ( (TREATMENT_PARAM_T)payload.paramID < NUM_OF_TREATMENT_PARAMS ) + { + // Set the given Tx param to the given value + if ( (TREATMENT_PARAM_T)payload.paramID <= TREATMENT_PARAM_LAST_UINT ) + { + result = setTreatmentParameterU32( (TREATMENT_PARAM_T)payload.paramID, payload.value.uInt ); + } + else if ( (TREATMENT_PARAM_T)payload.paramID >= TREATMENT_PARAM_FIRST_F32 ) + { + result = setTreatmentParameterF32( (TREATMENT_PARAM_T)payload.paramID, payload.value.sFlt ); + } + else + { + result = setTreatmentParameterS32( (TREATMENT_PARAM_T)payload.paramID, payload.value.sInt ); + } + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testTxParamsRequest function publishes the complete set of treatment + * parameters. + * @details \b Message \b Sent: MSG_ID_TD_RSP_CURRENT_TREATMENT_PARAMETERS + * @details \b Inputs: treatmentParameters[] + * @details \b Outputs: none + * @param message The message from Dialin requesting that treatment parameters + * be published. + * @return TRUE if publish treatment parameters request is successful, FALSE if not + *************************************************************************/ +BOOL testTxParamsRequest( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // Verify payload length + if ( 0 == message->hdr.payloadLen ) + { + CURRENT_TREATMENT_PARAMS_DATA_PAYLOAD_T payload; + TREATMENT_PARAM_T param; + + // Build and publish current treatment parameters record + for ( param = (TREATMENT_PARAM_T)0; param < NUM_OF_TREATMENT_PARAMS; param++ ) + { + stagedParams[ param ] = treatmentParameters[ param ].data; + } + memcpy( (U08*)&payload, (U08*)&stagedParams[0], sizeof( CURRENT_TREATMENT_PARAMS_DATA_PAYLOAD_T ) ); + sendMessage( MSG_ID_TD_RSP_CURRENT_TREATMENT_PARAMETERS, COMM_BUFFER_OUT_CAN_PC, (U08*)&payload, sizeof( CURRENT_TREATMENT_PARAMS_DATA_PAYLOAD_T ) ); + + result = TRUE; + } + + return result; +} + +/**@}*/ Index: firmware/App/Services/TxParams.h =================================================================== diff -u --- firmware/App/Services/TxParams.h (revision 0) +++ firmware/App/Services/TxParams.h (revision 4bbd5980e71fec58ab5ee2f1c9a50bdc76a5a38c) @@ -0,0 +1,121 @@ +/************************************************************************** +* +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file TxParams.h +* +* @author (last) Sean +* @date (last) 26-Nov-2025 +* +* @author (original) Sean +* @date (original) 17-Nov-2025 +* +***************************************************************************/ + +#ifndef __TX_PARAMS_H__ +#define __TX_PARAMS_H__ + +#include "TDCommon.h" +#include "TDDefs.h" +#include "Utilities.h" + +/** + * @defgroup TxParams TxParams + * @brief Treatment parameters unit provides validation + * and confirmation handling for treatment parameters from the UI. + * + * @addtogroup TxParams + * @{ + */ + +// ********** 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_VOLUME_ML ( 8 * ML_PER_LITER ) ///< Maximum ultrafiltration volume (in mL). + +/// Record structure for a treatment parameters payload from UI. +typedef struct +{ + U32 bloodFlowRate_mL_min; ///< User set blood flow rate (in mL/min) + U32 dialysateFlowRate_mL_min; ///< User set dialysate flow rate (in mL/min) + U32 treatmentDuration_min; ///< User set treatment duration (in min) + U32 salineBolusVolume_mL; ///< User set saline bolus volume (in mL) + U32 hepStopTime_min; ///< User set Heparin stop time (in min) + U32 hepType; ///< User set Heparin type option + U32 acidConcentrate; ///< User set acid concentrate option + U32 bicarbConcentrate; ///< User set bicarbonate concentrate option + U32 dialyzerType; ///< User set dialyzer type option + U32 bpInterval_min; ///< User set blood pressure measurement interval (in min) + U32 rinsebackFlowRate_mL_min; ///< User set rinseback flow rate (in mL/min) + U32 rinsebackVolume_mL; ///< User set rinseback volume (in mL) + S32 arterialPressureLimitWindow_mmHg; ///< User set alarm limit window for arterial pressure (in mmHg) + S32 venousPressureLimitWindow_mmHg; ///< User set alarm limit window for venous pressure (in mmHg) + S32 venousPressureLimitAsymmetric_mmHg; ///< User set alarm limit asymmetric for venous pressure (in mmHg) + S32 tmpLimitWindow_mmHg; ///< User set alarm limit window for trans-membrane pressure (in mmHg) + F32 dialysateTemperature_degC; ///< User set dialysate temperature (in deg C) + F32 hepDispenseRate_mL_hr; ///< User set Heparin dispense rate (in mL/hr) + F32 hepBolusVolume_mL; ///< User set Heparin bolus volume (in mL) +} TREATMENT_PARAMS_DATA_PAYLOAD_T; + +/// Record structure for reporting all current treatment parameters to Dialin +typedef struct +{ + TREATMENT_PARAMS_DATA_PAYLOAD_T treatment_parameters; ///< Record structure of treatment parameters + F32 uFVolume_L; ///< Current ultrafiltration volume (in L). +} CURRENT_TREATMENT_PARAMS_DATA_PAYLOAD_T; + +/// Payload record structure for treatment parameter range broadcast messages. +typedef struct +{ + U32 minTreatmentTime; ///< Minimum treatment duration (in minutes) + U32 maxTreatmentTime; ///< Maximum treatment duration (in minutes) + F32 minUFVolume; ///< Minimum ultrafiltration volume (in mL) + F32 maxUFVolume; ///< Maximum ultrafiltration volume (in mL) + U32 minDialRate; ///< Minimum dialysate flow rate (in mL/min) + U32 maxDialRate; ///< Maximum dialysate flow rate (in mL/min) +} TREATMENT_PARAM_RANGE_BROADCAST_PAYLOAD_T; + +// ********** public function prototypes **************** + +BOOL setTreatmentParameterU32( TREATMENT_PARAM_T param, U32 value ); // Set a specified unsigned integer treatment parameter value +BOOL setTreatmentParameterS32( TREATMENT_PARAM_T param, S32 value ); // Set a specified signed integer treatment parameter value +BOOL setTreatmentParameterF32( TREATMENT_PARAM_T param, F32 value ); // Set a specified floating point treatment parameter value +U32 getTreatmentParameterU32( TREATMENT_PARAM_T param ); // Get a specified unsigned integer treatment parameter +S32 getTreatmentParameterS32( TREATMENT_PARAM_T param ); // Get a specified signed integer treatment parameter +F32 getTreatmentParameterF32( TREATMENT_PARAM_T param ); // Get a specified floating point treatment parameter +S32 getTreatmentParameterS32DefaultValue( TREATMENT_PARAM_T param ); // Get the default value for a specified signed integer treatment parameter + +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 + +void resetTreatmentParameters( void ); // Reset all parameters to defaults +BOOL signalUserConfirmationOfTreatmentParameters( MESSAGE_T *message ); // Process UI confirm/reject Treatment parameters + +BOOL getValidTreatParamsReceived( void ); // Determine whether valid Treatment Parameters exist +BOOL getTreatParamsConfirmed( void ); // Determine whether user confirmed the parameters + +BOOL isTreatmentParamInRange( TREATMENT_PARAM_T param, CRITICAL_DATAS_T value ); // Check range for a proposed treatment parameter value +S32 getS32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_T param ); // Get lower range limit for signed integer treatment parameter +S32 getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_T param ); // Get upper range limit for signed integer treatment parameter +U32 getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_T param ); // Get lower range limit for unsigned integer treatment parameter +U32 getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_T param ); // Get upper range limit for unsigned integer treatment parameter +F32 getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_T param ); // Get lower range limit for floating point treatment parameter +F32 getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_T param ); // Get upper range limit for floating point treatment parameter +S32 getS32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ); // Get default min/max edge for signed integer treatment parameter +U32 getU32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ); // Get default min/max edge for unsigned integer treatment parameter +F32 getF32DefaultTreatmentParamEdge( TREATMENT_PARAM_T param, BOOL isMin ); // Get default min/max edge for floating point treatment parameter + +U32 getDialyzerBloodVolume( DIALYZER_TYPE_T dialyzer ); // Get the blood side volume for a given dialyzer type +U32 getDialyzerDialysateVolume( DIALYZER_TYPE_T dialyzer ); // Get the dialysate side volume for a given dialyzer type + +BOOL testSetTreatmentParameter( MESSAGE_T *message ); // Set a specific treatment parameter value +BOOL testTxParamsRequest( MESSAGE_T *message ); // Request to publish current treatment parameters + +/**@}*/ + +#endif