/************************************************************************** * * Copyright (c) 2019-2024 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) Dara Navaei * @date (last) 24-Apr-2024 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 * ***************************************************************************/ #include "AirTrap.h" #include "AlarmLamp.h" #include "BloodFlow.h" #include "Buttons.h" #include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "Dialysis.h" #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "Reservoirs.h" #include "Rinseback.h" #include "RTC.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" #include "TreatmentEnd.h" #include "TreatmentRecirc.h" #include "TreatmentStop.h" #include "Utilities.h" #include "Valves.h" /** * @addtogroup HDTreatmentMode * @{ */ // ********** private definitions ********** #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_DIALYSATE_VOLUME_ML ( 150 * ML_PER_LITER ) ///< Maximum dialysate volume (in mL). #define USER_CONFIRM_CHANGE_TIMEOUT_MS ( 60 * MS_PER_SECOND ) ///< Require user to confirm UF volume change within this time. #define PREVENT_UF_VOL_CHANGE_IF_NEARLY_DONE_SEC ( 10 * SEC_PER_MIN ) ///< Prevent UF volume change if treatment within this much time from end of treatment (in seconds). /// 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 ) /// Interval (ms/task time) at which the treatment state data is published on the CAN bus. #define TREATMENT_STATE_DATA_PUB_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) /// Interval (ms/task time) at which updated, valid treatment setting ranges are published on the CAN bus. #define TREATMENT_SETTINGS_RANGES_PUB_INTERVAL ( ( 60 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) /// Interval (ms) at which the treatment periodic data is published on the CAN bus. static const U32 TREATMENT_PERIODIC_DATA_PUB_INTERVAL = ( 30 * SEC_PER_MIN * MS_PER_SECOND ); /// Interval (ms) at which the treatment periodic data is logged. static const U32 TREATMENT_PERIODIC_DATA_LOG_INTERVAL = ( MS_PER_SECOND ); #define CALC_ELAPSED_TREAT_TIME_IN_SECS() ( treatmentTimeMS / MS_PER_SECOND ) ///< Macro to calculate the elapsed treatment time in seconds. /// Macro to calculate the elapsed treatment time in minutes. #define CALC_ELAPSED_TREAT_TIME_IN_MIN() ( ( treatmentTimeMS / MS_PER_SECOND ) / SEC_PER_MIN ) /// Macro to calculate the remaining treatment time in seconds. #define CALC_TREAT_TIME_REMAINING_IN_SECS() ( (S32)presTreatmentTimeSecs - (S32)( treatmentTimeMS / MS_PER_SECOND ) ) // ********** private data ********** static TREATMENT_STATE_T currentTreatmentState; ///< Current state (sub-mode) of treatment mode. static BOOL bloodIsPrimed; ///< Flag indicates whether blood-side circuit has been primed with blood. Set FALSE at init and start of rinseback. Set TRUE at end of blood prime. static BOOL rinsebackDone; ///< Flag indicates whether a rinseback has been completed. Set FALSE at start of blood prime. Set TRUE at init and end of rinseback. static BOOL treatmentCompleted; ///< Flag indicates whether the treatment has completed. static U32 presTreatmentTimeSecs; ///< Prescribed treatment time (in seconds). static F32 presMaxUFVolumeML; ///< Prescribed ultrafiltration volume (in mL). static F32 presUFRate; ///< Prescribed ultrafiltration rate (in mL/min). static U32 treatmentTimeMS; ///< Elapsed treatment time (in ms). static U32 lastTreatmentTimeStamp; ///< Last time elapsed treatment time was recorded (a timestamp in ms). static U32 treatmentTimeBroadcastTimerCtr; ///< Treatment time data broadcast timer counter used to schedule when to transmit data. static U32 treatmentStateBroadcastTimerCtr; ///< Treatment state data broadcast timer counter used to schedule when to transmit data. static U32 treatmentParamsRangesBroadcastTimerCtr; ///< Treatment parameter ranges broadcast timer counter used to schedule when to transmit updated ranges. /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T treatmentTimePublishInterval = { TREATMENT_TIME_DATA_PUB_INTERVAL, TREATMENT_TIME_DATA_PUB_INTERVAL, TREATMENT_TIME_DATA_PUB_INTERVAL, 0 }; /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T treatmentStatePublishInterval = { TREATMENT_STATE_DATA_PUB_INTERVAL, TREATMENT_STATE_DATA_PUB_INTERVAL, TREATMENT_STATE_DATA_PUB_INTERVAL, 0 }; /// Interval (in task intervals) at which to publish alarm status to CAN bus. static OVERRIDE_U32_T treatmentParamRangesPublishInterval = { TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, TREATMENT_SETTINGS_RANGES_PUB_INTERVAL, 0 }; static BOOL resumeTreatmentAlarmResponseRequest; ///< Flag indicates user has requested treatment resume. static BOOL initiateRinsebackAlarmResponseRequest; ///< Flag indicates user has requested rinseback. static BOOL endTreatmentAlarmResponseRequest; ///< Flag indicates user has requested treatment end. static BOOL rinsebackToStoppedRequest; ///< Flag indicates user has requested return to treatment from rinseback workflow. static BOOL endTreatmentRequest; ///< Flag indicates user has requested end of treatment from rinseback workflow. static BOOL bloodPrimeToDialysisRequest; ///< Flag indicates blood prime has completed and time to start dialysis. static BOOL rinsebackToRecircRequest; ///< Flag indicates user has requested to proceed to re-circulate sub-mode. static BOOL treatmentEndToRinsebackRequest; ///< Flag indicates user has requested final rinseback. static BOOL resumeBlockedByAlarm; ///< Flag indicates an alarm has blocked resume of this treatment. static U32 pendingParamChangesTimer; ///< User required to confirm UF volume change within 1 minute. static F32 pendingUFVolumeChange; ///< An ultrafiltration volume change (mL) is pending user confirmation. static F32 pendingUFRateChange; ///< An ultrafiltration rate change (mL/min) is pending user confirmation. static U32 pendingTreatmentTimeChange; ///< A treatment time change (min) is pending user confirmation. static U32 lastTreatmentPeriodicDataPublishTimeStamp; ///< Last treatment 30 minutes periodic data publish time stamp. static U32 lastTreatmentPeriodicDataCollectTimeStamp; ///< Last treatment periodic data collect time stamp. static F32 lastUltraFiltrationVolume_mL; ///< Last 30 minutes ultra filtration volume in mL. static F32 bloodFlowRateSum_mL_min; ///< Blood flow rate sum logged every second. static F32 dialysateFlowRateSum_mL_min; ///< Dialysate flow rate sum logged every second. static F32 arterialPressureSum_mmHg; ///< Arterial pressure sum logged every second. static F32 venousPressureSum_mmHg; ///< Venous pressure sum logged every second. static F32 treatmentBloodFlowRateTotal_mL_min; ///< Blood flow rate total per treatment logged every second. static F32 treatmentDialysateFlowRateTotal_mL_min; ///< Dialysate flow rate total per treatment logged every second. static F32 treatmentDialysateTempTotal_degree_C; ///< Dialysate temperature total per treatment logged every second. static F32 treatmentArterialPressureTotal_mmHg; ///< Arterial pressure total per treatment logged every second. static F32 treatmentVenousPressureTotal_mmHg; ///< Venous pressure total per treatment logged every second. static BOOL sendLastTreatmentPeriodicData; ///< Flag determines if HD needs to send the last treatment periodic data. static U32 treatmentStartTimeStamp; ///< Treatment start timestampt for logging purpose. static U32 treatmentEndTimeStamp; ///< Treatment end timestampt for logging purpose. // ********** private function prototypes ********** static void broadcastTreatmentSettingsRanges( void ); static void broadcastTreatmentPeriodicData(); static U32 getMinTreatmentTimeInMinutes( void ); static TREATMENT_STATE_T handleTreatmentStartState( void ); static TREATMENT_STATE_T handleTreatmentBloodPrimeState( void ); static TREATMENT_STATE_T handleTreatmentDialysisState( void ); static TREATMENT_STATE_T handleTreatmentStopState( void ); static TREATMENT_STATE_T handleTreatmentRinsebackState( void ); static TREATMENT_STATE_T handleTreatmentRecircState( void ); static TREATMENT_STATE_T handleTreatmentEndState( void ); static void resetSignalFlags( void ); static void resetAlarmSignalFlags( void ); /*********************************************************************//** * @brief * The initTreatmentMode function initializes the Treatment Mode module. * @details Inputs: none * @details Outputs: Treatment Mode module initialized. * @return none *************************************************************************/ void initTreatmentMode( void ) { currentTreatmentState = TREATMENT_START_STATE; bloodIsPrimed = FALSE; treatmentCompleted = FALSE; rinsebackDone = FALSE; resumeBlockedByAlarm = FALSE; treatmentTimeMS = 0; lastTreatmentTimeStamp = 0; treatmentTimeBroadcastTimerCtr = TREATMENT_TIME_DATA_PUB_INTERVAL; // So we send time data immediately when we begin treatment mode treatmentStateBroadcastTimerCtr = TREATMENT_STATE_DATA_PUB_INTERVAL; // So we send state data immediately when we begin treatment mode treatmentParamsRangesBroadcastTimerCtr = TREATMENT_SETTINGS_RANGES_PUB_INTERVAL; // So we send ranges immediately when we begin treatment mode presTreatmentTimeSecs = 0; presMaxUFVolumeML = 0.0; presUFRate = 0.0; resetSignalFlags(); resetAlarmSignalFlags(); pendingParamChangesTimer = 0; pendingUFVolumeChange = 0.0; pendingUFRateChange = 0.0; pendingTreatmentTimeChange = 0; lastTreatmentPeriodicDataPublishTimeStamp = 0; lastTreatmentPeriodicDataCollectTimeStamp = 0; lastUltraFiltrationVolume_mL = 0.0; bloodFlowRateSum_mL_min = 0.0; dialysateFlowRateSum_mL_min = 0.0; arterialPressureSum_mmHg = 0.0; venousPressureSum_mmHg = 0.0; treatmentBloodFlowRateTotal_mL_min = 0.0; treatmentDialysateFlowRateTotal_mL_min = 0.0; treatmentDialysateTempTotal_degree_C = 0.0; treatmentArterialPressureTotal_mmHg = 0.0; treatmentVenousPressureTotal_mmHg = 0.0; sendLastTreatmentPeriodicData = FALSE; treatmentStartTimeStamp = getRTCTimestamp(); treatmentEndTimeStamp = 0; // reset dialysate temperature alarm persistences prior to starting a treatment. resetPersistentAlarmTimer( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_SAFETY_TEMP ); resetPersistentAlarmTimer( ALARM_ID_HD_DIALYSATE_TEMP_ABOVE_TARGET_TEMP ); resetPersistentAlarmTimer( ALARM_ID_HD_DIALYSATE_TEMP_BELOW_TARGET_TEMP ); } /*********************************************************************//** * @brief * The transitionToTreatmentMode function prepares for transition to treatment mode. * @details Inputs: none * @details Outputs: * @return initial state *************************************************************************/ U32 transitionToTreatmentMode( void ) { if ( ( getTestConfigStatus( TEST_CONFIG_RECOVER_TREATMENT ) != TRUE ) || ( getPreviousOperationMode() != DG_MODE_FAUL ) ) { // Initialize treatment mode each time we transition to it initTreatmentMode(); initReservoirs(); // Initialize treatment sub-modes each time we transition to treatment mode initBloodPrime(); initDialysis(); initTreatmentStop(); initRinseback(); initTreatmentRecirc(); initTreatmentEnd(); } // Started the treatment set the start time in epoch setTxLastStartTimeEpoch( getRTCTimestamp() ); setCurrentSubState( NO_SUB_STATE ); // Enable venous bubble detection in treatment mode setVenousBubbleDetectionEnabled( TRUE ); return currentTreatmentState; } /*********************************************************************//** * @brief * The getTreatmentState function gets the current treatment mode state. * @details Inputs: currentTreatmentState * @details Outputs: none * @return currentTreatmentState *************************************************************************/ TREATMENT_STATE_T getTreatmentState( void ) { return currentTreatmentState; } /*********************************************************************//** * @brief * The isTreatmentCompleted function determines whether the treatment has * completed (indicating treatment duration has elapsed). * @details Inputs: treatmentCompleted * @details Outputs: none * @return treatmentCompleted *************************************************************************/ BOOL isTreatmentCompleted( void ) { return treatmentCompleted; } /*********************************************************************//** * @brief * The isTreatmentResumeBlocked function determines whether the treatment has * seen an alarm that prevents resumption. * @details Inputs: resumeBlockedByAlarm * @details Outputs: none * @return resumeBlockedByAlarm *************************************************************************/ BOOL isTreatmentResumeBlocked( void ) { return resumeBlockedByAlarm; } /*********************************************************************//** * @brief * The getTreatmentTimeRemainingSecs function determines the number of seconds * remaining in the treatment. * @details Inputs: presTreatmentTimeSecs, treatmentTimeMS * @details Outputs: none * @return The number of seconds remaining in the treatment. *************************************************************************/ U32 getTreatmentTimeRemainingSecs( void ) { U32 result = CALC_TREAT_TIME_REMAINING_IN_SECS(); return result; } /*********************************************************************//** * @brief * The getActualTreatmentTimeSecs function determines the actual treatment * duration in seconds. * @details Inputs: treatmentTimeMS * @details Outputs: none * @return The actual treatment duration in seconds. *************************************************************************/ U32 getActualTreatmentTimeSecs( void ) { return ( treatmentTimeMS / MS_PER_SECOND ); } /*********************************************************************//** * @brief * The getRinsebackCompleted function determines whether a rinseback has been * completed (indicating blood-side circuit should be primarily saline). * @details Inputs: rinsebackDone * @details Outputs: none * @return rinsebackDone *************************************************************************/ BOOL getRinsebackCompleted( void ) { return rinsebackDone; } /*********************************************************************//** * @brief * The setRinsebackIsCompleted function sets that flag indicating whether a * rinseback has been completed. Call this function with TRUE when rinseback * operation is completed. Call this function with FALSE at start of blood * prime operation. * @details Inputs: none * @details Outputs: rinsebackDone * @param flag TRUE if rinseback has been completed, FALSE if not * @return none *************************************************************************/ void setRinsebackIsCompleted( BOOL flag ) { rinsebackDone = 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 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 getCurrentUFSetRate function returns the currently set target * ultrafiltration rate. * @details Inputs: presUFRate * @details Outputs: none * @return presUFRate *************************************************************************/ F32 getCurrentUFSetRate( void ) { return presUFRate; } /*********************************************************************//** * @brief * The getTreatmentAvgBloodFlowRate function returns the average blood flow * rate collected through out the treatment. * @details Inputs: treatmentTimeMS, treatmentBloodFlowRateTotal_mL_min * @details Outputs: none * @return the average blood flow rate *************************************************************************/ F32 getTreatmentAvgBloodFlowRate( void ) { U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); F32 result = 0.0; if ( numberOfDataPoint > 0 ) { result = ( treatmentBloodFlowRateTotal_mL_min / numberOfDataPoint ); } return result; } /*********************************************************************//** * @brief * The getTreatmentAvgDialysateFlowRate function returns the average dialysate * flow rate collected through out the treatment. * @details Inputs: treatmentTimeMS, treatmentDialysateFlowRateTotal_mL_min * @details Outputs: none * @return the average dialysate flow rate *************************************************************************/ F32 getTreatmentAvgDialysateFlowRate( void ) { U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); F32 result = 0.0; if ( numberOfDataPoint > 0 ) { result = ( treatmentDialysateFlowRateTotal_mL_min / numberOfDataPoint ); } return result; } /*********************************************************************//** * @brief * The getTreatmentAvgDialysateTemp function returns the average dialysate * temperature collected through out the treatment. * @details Inputs: treatmentTimeMS, treatmentDialysateTempTotal_degree_C * @details Outputs: none * @return the average dialysate temperature *************************************************************************/ F32 getTreatmentAvgDialysateTemp( void ) { U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); F32 result = 0.0; if ( numberOfDataPoint > 0 ) { result = ( treatmentDialysateTempTotal_degree_C / numberOfDataPoint ); } return result; } /*********************************************************************//** * @brief * The getTreatmentAvgArterialPressure function returns the average arterial * pressure collected through out the treatment. * @details Inputs: treatmentTimeMS, treatmentArterialPressureTotal_mmHg * @details Outputs: none * @return the average arterial pressure *************************************************************************/ F32 getTreatmentAvgArterialPressure( void ) { U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); F32 result = 0.0; if ( numberOfDataPoint > 0 ) { result = ( treatmentArterialPressureTotal_mmHg / numberOfDataPoint ); } return result; } /*********************************************************************//** * @brief * The getTreatmentAvgVenousPressure function returns the average venous * pressure collected through out the treatment. * @details Inputs: treatmentTimeMS, treatmentVenousPressureTotal_mmHg * @details Outputs: none * @return the average venous pressure *************************************************************************/ F32 getTreatmentAvgVenousPressure( void ) { U32 const numberOfDataPoint = ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ); F32 result = 0.0; if ( numberOfDataPoint > 0 ) { result = ( treatmentVenousPressureTotal_mmHg / numberOfDataPoint ); } return result; } /*********************************************************************//** * @brief * The getTreatmentStartTimeStamp function returns the treatment start * time stamp. * @details Inputs: treatmentStartTimeStamp * @details Outputs: none * @return the treatment start time stamp *************************************************************************/ U32 getTreatmentStartTimeStamp( void ) { return treatmentStartTimeStamp; } /*********************************************************************//** * @brief * The getTreatmentEndTimeStamp function returns the treatment end * time stamp. * @details Inputs: treatmentEndTimeStamp * @details Outputs: none * @return the treatment end time stamp *************************************************************************/ U32 getTreatmentEndTimeStamp( void ) { return treatmentEndTimeStamp; } /*********************************************************************//** * @brief * The signalAlarmActionToTreatmentMode function executes the given alarm action * as appropriate while in Treatment Mode. * @details Inputs: none * @details Outputs: given alarm action executed * @param action ID of alarm action to execute * @return none *************************************************************************/ void signalAlarmActionToTreatmentMode( ALARM_ACTION_T action ) { switch( action ) { case ALARM_ACTION_STOP: // Stop signal actively polled by mode/sub-mode/state break; case ALARM_ACTION_RESUME: resumeTreatmentAlarmResponseRequest = TRUE; break; case ALARM_ACTION_RINSEBACK: initiateRinsebackAlarmResponseRequest = TRUE; break; case ALARM_ACTION_END_TREATMENT: endTreatmentAlarmResponseRequest = TRUE; break; case ALARM_ACTION_ACK: // Nothing to be done here break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_INVALID_ALARM_ACTION, (U32)action ) break; } } /*********************************************************************//** * @brief * The signalRinsebackToTreatmentStopped function signals that user wants to return * to treatment from rinseback workflow. * @details Inputs: none * @details Outputs: rinsebackToStoppedRequest * @return none *************************************************************************/ void signalGoToTreatmentStopped( void ) { rinsebackToStoppedRequest = TRUE; } /*********************************************************************//** * @brief * The signalGoToRinseback function signals that user wants to perform * a rinseback operation. * @details Inputs: none * @details Outputs: rinsebackRequested * @return none *************************************************************************/ void signalGoToRinseback( void ) { treatmentEndToRinsebackRequest = TRUE; } /*********************************************************************//** * @brief * The signalRinsebackToTreatmentEnd function signals that user wants to end the * treatment from rinseback workflow. * @details Inputs: none * @details Outputs: rinsebackToEndTreatmentRequest * @return none *************************************************************************/ void signalEndTreatment( void ) { endTreatmentRequest = TRUE; } /*********************************************************************//** * @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 signalRinsebackToRecirc function signals that user wants to continue * on to re-circulate portion of rinseback workflow. * @details Inputs: none * @details Outputs: rinsebackToRecircRequest * @return none *************************************************************************/ void signalRinsebackToRecirc( void ) { rinsebackToRecircRequest = TRUE; } /*********************************************************************//** * @brief * The execTreatmentMode function executes the Treatment Mode state machine. * @details Inputs: currentTreatmentState * @details Outputs: currentTreatmentState * @return current state (sub-mode) *************************************************************************/ U32 execTreatmentMode( void ) { BOOL stop = isStopButtonPressed(); // Trigger user stop alarm at any time in treatment mode when user presses stop button if ( TRUE == stop ) { activateAlarmNoData( ALARM_ID_HD_TREATMENT_STOPPED_BY_USER ); } // Check if resume treatment blocked by alarm if ( TRUE == doesAlarmIndicateNoResume() ) { resumeBlockedByAlarm = TRUE; } // Check dialysate temperature during treatment mode (except end state where treatment is over, dialyzer is bypassed and temp is no longer an issue) if ( currentTreatmentState != TREATMENT_END_STATE ) { checkDialysateTemperature(); } // Treatment mode state machine switch ( currentTreatmentState ) { case TREATMENT_START_STATE: currentTreatmentState = handleTreatmentStartState(); break; case TREATMENT_BLOOD_PRIME_STATE: currentTreatmentState = handleTreatmentBloodPrimeState(); break; case TREATMENT_DIALYSIS_STATE: currentTreatmentState = handleTreatmentDialysisState(); break; case TREATMENT_STOP_STATE: currentTreatmentState = handleTreatmentStopState(); break; case TREATMENT_RINSEBACK_STATE: currentTreatmentState = handleTreatmentRinsebackState(); break; case TREATMENT_RECIRC_STATE: currentTreatmentState = handleTreatmentRecircState(); break; case TREATMENT_END_STATE: currentTreatmentState = handleTreatmentEndState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_TREATMENT_INVALID_STATE, currentTreatmentState ); break; } // Alarm response request flags should be handled at this point, reset in case not handled in current state resetAlarmSignalFlags(); // clear signal flags from sub-modes before calling sub-mode executives resetSignalFlags(); // Broadcast treatment data broadcastTreatmentTimeAndState(); broadcastTreatmentSettingsRanges(); broadcastTreatmentPeriodicData(); // Manage air trap control execAirTrapMonitorTreatment(); return currentTreatmentState; } /*********************************************************************//** * @brief * The handleTreatmentStartState function handles the Start state of * the Treatment Mode state machine. Should only pass through this state * once at very beginning of treatment. * @details Inputs: none * @details Outputs: treatmentTimeMS, lastTreatmentTimeStamp * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentStartState( void ) { TREATMENT_STATE_T result = TREATMENT_BLOOD_PRIME_STATE; // Initialize treatment time treatmentTimeMS = 0; lastTreatmentTimeStamp = getMSTimerCount(); presTreatmentTimeSecs = SEC_PER_MIN * getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); presMaxUFVolumeML = getTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME ) * (F32)ML_PER_LITER; presUFRate = presMaxUFVolumeML / (F32)getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); transitionToBloodPrime(); return result; } /*********************************************************************//** * @brief * The handleTreatmentBloodPrimeState function handles the blood prime state of * the Treatment Mode state machine. * @details Inputs: presUFRate * @details Outputs: none * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentBloodPrimeState( void ) { TREATMENT_STATE_T result = TREATMENT_BLOOD_PRIME_STATE; 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 ) { lastTreatmentTimeStamp = getMSTimerCount(); // Kick dialysis sub-mode off setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); if ( presUFRate > 0.0 ) { sendTreatmentLogEventData( UF_START_RESUME_EVENT, 0.0, presUFRate ); } transitionToDialysis(); result = TREATMENT_DIALYSIS_STATE; } } return result; } /*********************************************************************//** * @brief * The handleTreatmentDialysisState function handles the Dialysis state of * the Treatment Mode state machine. * @details Inputs: none * @details Outputs: treatmentTimeMS, lastTreatmentTimeStamp, dialysis sub-mode * executed. * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentDialysisState( void ) { TREATMENT_STATE_T result = TREATMENT_DIALYSIS_STATE; U32 newTime = getMSTimerCount(); U32 msSinceLast = calcTimeBetween( lastTreatmentTimeStamp, newTime ); DIALYSIS_STATE_T dialysisState = getDialysisState(); // Update treatment time (unless delivering a saline bolus) if ( dialysisState != DIALYSIS_SALINE_BOLUS_STATE ) { treatmentTimeMS += msSinceLast; } lastTreatmentTimeStamp = newTime; // End treatment if treatment duration has been reached if ( CALC_ELAPSED_TREAT_TIME_IN_SECS() >= presTreatmentTimeSecs ) { treatmentCompleted = TRUE; sendLastTreatmentPeriodicData = TRUE; treatmentEndTimeStamp = getRTCTimestamp(); stopDialysis(); transitionToTreatmentEnd(); SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_END_OF_TREATMENT_WARNING, presTreatmentTimeSecs ); result = TREATMENT_END_STATE; } // Otherwise, execute state machine for treatment dialysis sub-mode else { execReservoirs(); execDialysis(); // Handle alarm stoppage if ( TRUE == doesAlarmStatusIndicateStop() ) { transitionToTreatmentStop(); result = TREATMENT_STOP_STATE; } } return result; } /*********************************************************************//** * @brief * The handleTreatmentStopState function executes the Stop state of the * Treatment Mode state machine. * @details Inputs: none * @details Outputs: treatment stop sub-mode executed. * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentStopState( void ) { TREATMENT_STATE_T result = TREATMENT_STOP_STATE; BOOL leavingTreatmentStopState = TRUE; // If user requests resumption of treatment, resume treatment if ( TRUE == resumeTreatmentAlarmResponseRequest ) { resumeTreatmentAlarmResponseRequest = FALSE; // Hard stop the pumps so they will ramp up from zero together on resume signalDialInPumpHardStop(); signalDialOutPumpHardStop(); if ( TRUE == getBloodIsPrimed() ) { lastTreatmentTimeStamp = getMSTimerCount(); transitionToDialysis(); result = TREATMENT_DIALYSIS_STATE; } else { transitionToBloodPrime(); result = TREATMENT_BLOOD_PRIME_STATE; } signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); } // If user requests rinseback, go to rinseback else if ( TRUE == initiateRinsebackAlarmResponseRequest ) { // TODO - should we block rinseback request if no blood in line (i.e. already did a rinseback)? transitionToRinseback(); result = TREATMENT_RINSEBACK_STATE; } // If user requests treatment end, end treatment else if ( TRUE == endTreatmentAlarmResponseRequest ) { sendLastTreatmentPeriodicData = TRUE; requestNewOperationMode( MODE_POST ); } // Otherwise execute state machine for treatment stop sub-mode else { execReservoirs(); execTreatmentStop(); leavingTreatmentStopState = FALSE; } // If leaving treatment stop state, zero alarm countdown timer for UI if ( TRUE == leavingTreatmentStopState ) { TREATMENT_STOP_PAYLOAD_T data; data.timeout = 0; data.countdown = 0; broadcastData( MSG_ID_HD_TREATMENT_STOP_TIMER_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_STOP_PAYLOAD_T ) ); } return result; } /*********************************************************************//** * @brief * The handleTreatmentRinsebackState function executes the rinseback state of the * Treatment Mode state machine. * @details Inputs: endTreatmentAlarmResponseRequest, resumeTreatmentAlarmResponseRequest, * rinsebackToRecircRequest, rinsebackToStoppedRequest, endTreatmentRequest * @details Outputs: treatment rinseback sub-mode executed, sendLastTreatmentPeriodicData * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentRinsebackState( void ) { TREATMENT_STATE_T result = TREATMENT_RINSEBACK_STATE; // If user requests treatment end, end treatment if ( TRUE == endTreatmentAlarmResponseRequest ) { sendLastTreatmentPeriodicData = TRUE; requestNewOperationMode( MODE_POST ); } // Otherwise execute state machine for treatment rinseback sub-mode else { // If user requests resumption of treatment, resume rinseback if ( TRUE == resumeTreatmentAlarmResponseRequest ) { resumeTreatmentAlarmResponseRequest = FALSE; signalRinsebackAlarmResumeUserAction(); } // Execute treatment rinseback sub-mode execRinseback(); } // Handle signals from rinseback sub-mode if ( TRUE == rinsebackToRecircRequest ) { transitionToTreatmentRecirc(); result = TREATMENT_RECIRC_STATE; } else if ( TRUE == rinsebackToStoppedRequest ) { transitionToTreatmentStop(); result = TREATMENT_STOP_STATE; } else if ( TRUE == endTreatmentRequest ) { requestNewOperationMode( MODE_POST ); } return result; } /*********************************************************************//** * @brief * The handleTreatmentRecircState function executes the re-circulate state of the * Treatment Mode state machine. * @details Inputs: endTreatmentAlarmResponseRequest, rinsebackToStoppedRequest, * endTreatmentRequest * @details Outputs: sendLastTreatmentPeriodicData * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentRecircState( void ) { TREATMENT_STATE_T result = TREATMENT_RECIRC_STATE; // If user requests treatment end, end treatment if ( TRUE == endTreatmentAlarmResponseRequest ) { sendLastTreatmentPeriodicData = TRUE; requestNewOperationMode( MODE_POST ); } else { // Execute treatment re-circ sub-mode execTreatmentRecirc(); } // Handle signals from treatment re-circ sub-mode if ( TRUE == rinsebackToStoppedRequest ) { stopDialysis(); transitionToTreatmentStop(); result = TREATMENT_STOP_STATE; } else if ( TRUE == endTreatmentRequest ) { requestNewOperationMode( MODE_POST ); } return result; } /*********************************************************************//** * @brief * The handleTreatmentEndState function executes the end state of the * Treatment Mode state machine. * @details Inputs: none * @details Outputs: treatment end sub-mode executed. * @return next treatment mode state *************************************************************************/ static TREATMENT_STATE_T handleTreatmentEndState( void ) { TREATMENT_STATE_T result = TREATMENT_END_STATE; // Handle final rinseback alarm response from user if ( TRUE == initiateRinsebackAlarmResponseRequest ) { signalTreatmentEndAlarmRinsebackUserAction(); } // Handle alarm response from user to end treatment w/o rinseback else if ( TRUE == endTreatmentAlarmResponseRequest ) { signalTreatmentEndAlarmEndTxUserAction(); } // End treatment state does not allow resume // Execute treatment end sub-mode execTreatmentEnd(); // Handle signals from treatment end sub-mode if ( TRUE == treatmentEndToRinsebackRequest ) { transitionToRinseback(); result = TREATMENT_RINSEBACK_STATE; } else if ( TRUE == endTreatmentRequest ) { requestNewOperationMode( MODE_POST ); } return result; } /*********************************************************************//** * @brief * The verifyTreatmentDurationSettingChange function verifies and responds to * the user treatment duration setting change request. * @details Inputs: current operating mode, treatment states and parameters * @details Outputs: response message sent * @param treatmentTime Proposed new treatment duration (in min) * @return TRUE if new treatment duration setting valid, FALSE if not. *************************************************************************/ BOOL verifyTreatmentDurationSettingChange( U32 treatmentTime ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; HD_OP_MODE_T currMode = getCurrentOperationMode(); // Check if we are in an appropriate treatment state for settings adjustment if ( ( MODE_TREA == currMode ) && ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_END_STATE ) && ( CALC_ELAPSED_TREAT_TIME_IN_MIN() < treatmentTime ) && ( treatmentTime >= getMinTreatmentTimeInMinutes() ) ) { // Always adjust UF volume to accommodate treatment time change (not UF rate) F32 uFVolume = ( (F32)( treatmentTime - CALC_ELAPSED_TREAT_TIME_IN_MIN() ) * presUFRate ) + getUltrafiltrationReferenceVolume(); F32 uFVolumeL = uFVolume / ML_PER_LITER; U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * treatmentTime; // In mL // The minimum treatment time is either in the range of the institutional record or the 1-minute treatment config has been requested which is an exception BOOL isMinTxTimeValid = ( ( treatmentTime >= getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ) ) || ( TRUE == getTestConfigStatus( TEST_CONFIG_ENABLE_ONE_MINUTE_TREATMENT ) ) ? TRUE : FALSE ); BOOL isTxTimeValid = ( ( TRUE == isMinTxTimeValid ) && ( treatmentTime <= getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_TREATMENT_DURATION ) ) ? TRUE : FALSE ); BOOL isMinUFVolValid = ( ( uFVolumeL >= getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ) ) || ( uFVolumeL <= 0.0F ) ? TRUE : FALSE ); BOOL isUFVolValid = ( ( TRUE == isMinUFVolValid ) && ( uFVolumeL <= getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ) ) ? TRUE : FALSE ); if ( ( TRUE == isTxTimeValid ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) && ( TRUE == isUFVolValid ) ) { result = TRUE; sendTreatmentLogEventData( TREATMENT_DURATION_CHANGE_EVENT, ( presTreatmentTimeSecs / SEC_PER_MIN ), treatmentTime ); presMaxUFVolumeML = uFVolume; presTreatmentTimeSecs = treatmentTime * SEC_PER_MIN; setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, ( presMaxUFVolumeML / (F32)ML_PER_LITER ) ); setTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION, ( presTreatmentTimeSecs / SEC_PER_MIN ) ); setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); } else { if ( FALSE == isTxTimeValid ) { rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_OUT_OF_RANGE; } else if ( FALSE == isUFVolValid ) { rejectReason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; } else { rejectReason = REQUEST_REJECT_REASON_DIAL_VOLUME_OUT_OF_RANGE; } } } else { if ( MODE_TREA != currMode ) { rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } else if ( ( currentTreatmentState <= TREATMENT_START_STATE ) || ( currentTreatmentState >= TREATMENT_END_STATE ) ) { rejectReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; } else if ( treatmentTime < getMinTreatmentTimeInMinutes() ) { rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_MINIMUM; } else { rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; } } // Send response to request sendChangeTreatmentDurationResponse( result, rejectReason, presTreatmentTimeSecs / SEC_PER_MIN, presMaxUFVolumeML ); // Send new ranges for settings treatmentParamsRangesBroadcastTimerCtr = getU32OverrideValue( &treatmentParamRangesPublishInterval ); broadcastTreatmentSettingsRanges(); // Send time/state data immediately for UI update broadcastTreatmentTimeAndState(); return result; } /*********************************************************************//** * @brief * The verifyUFSettingsChange function verifies and responds to a new * ultrafiltration volume setting from the user. * @details Inputs: current operating mode, treatment states and parameters * @details Outputs: response message sent * @param uFVolume New ultrafiltration volume requested by the user * @return TRUE if new UF volume is valid, FALSE if not. *************************************************************************/ BOOL verifyUFSettingsChange( F32 uFVolume ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; S32 timeDiff = 0; F32 rateDiff = 0.0; HD_OP_MODE_T currMode = getCurrentOperationMode(); S32 txSecRem = CALC_TREAT_TIME_REMAINING_IN_SECS(); S32 txMinEla = CALC_ELAPSED_TREAT_TIME_IN_SECS() / SEC_PER_MIN; F32 txMinRem = (F32)txSecRem / (F32)SEC_PER_MIN; F32 colUFVol = getUltrafiltrationReferenceVolume(); // How much UF volume have we taken so far? // Reset pending UF/time settings changes to current values in case request is rejected pendingUFVolumeChange = presMaxUFVolumeML; pendingUFRateChange = presUFRate; pendingTreatmentTimeChange = presTreatmentTimeSecs / SEC_PER_MIN; // Check if we are in an appropriate treatment state for settings adjustment if ( ( MODE_TREA == currMode ) && ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_END_STATE ) && ( uFVolume >= ( getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER ) ) && ( uFVolume <= ( getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER ) ) && ( uFVolume > colUFVol ) && ( CALC_TREAT_TIME_REMAINING_IN_SECS() >= PREVENT_UF_VOL_CHANGE_IF_NEARLY_DONE_SEC ) ) { DIALYSIS_STATE_T currDialysisState = getDialysisState(); UF_STATE_T currUFState = getUltrafiltrationState(); F32 remUFVol = uFVolume - colUFVol; // What would remaining UF volume be after subtracting UF volume already taken F32 uFRate = remUFVol / txMinRem; // What UF rate would be if user selected to adjust it U32 trtTime = ( fabs( presUFRate ) < NEARLY_ZERO ? txMinEla + 1 : (S32)( remUFVol / presUFRate ) + txMinEla + 1 ); // What the treatment duration would be if user selected to adjust it U32 dialVolume = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) * trtTime; // What dialysate volume would be if user selected to adjust time // UF should already be paused but let's make sure. if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && ( DIALYSIS_UF_STATE == currDialysisState ) && ( UF_RUNNING_STATE == currUFState ) ) { pauseUF(); } // Start t/o timer - user must confirm UF changes within 1 minute from now pendingParamChangesTimer = getMSTimerCount(); // Verify UF rate change would be valid (leave zero if not valid - UI will disable option) if ( uFRate <= (F32)MAX_UF_RATE_ML_MIN ) { result = TRUE; pendingUFVolumeChange = uFVolume; pendingUFRateChange = uFRate; rateDiff = ( uFRate - presUFRate ); } else { pendingUFRateChange = 0.0; } // Treatment duration change is now never valid - leave zero - UI will disable option) pendingTreatmentTimeChange = 0; // If neither option works, reject for UF rate if ( FALSE == result ) { rejectReason = REQUEST_REJECT_REASON_UF_RATE_OUT_OF_RANGE; } } else { if ( MODE_TREA != currMode ) { rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } else if ( ( currentTreatmentState <= TREATMENT_START_STATE ) || ( currentTreatmentState >= TREATMENT_END_STATE ) ) { rejectReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; } // UF volume cannot be set lower than the UF volume that has already been collected else if ( ( uFVolume > ( getF32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER ) ) || ( uFVolume < ( getF32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_UF_VOLUME ) * ML_PER_LITER ) ) || ( uFVolume <= colUFVol ) ) { rejectReason = REQUEST_REJECT_REASON_UF_VOLUME_OUT_OF_RANGE; } else { rejectReason = REQUEST_REJECT_REASON_TREATMENT_TOO_CLOSE_TO_FINISHED; } } // Respond to UF settings change request sendChangeUFSettingsResponse( result, rejectReason, pendingUFVolumeChange, pendingTreatmentTimeChange, pendingUFRateChange, timeDiff, rateDiff, presUFRate ); return result; } /*********************************************************************//** * @brief * The verifyUFSettingsConfirmation function verifies the user confirmed * ultrafiltration settings change(s) and, if valid, accepts the new settings. * @details Inputs: current operating mode, treatment states and parameters, * pendingUFVolumeChange, pendingUFRateChange * @details Outputs: response message sent, presMaxUFVolumeML, * presTreatmentTimeSecs, presUFRate * @param uFVolume New ultrafiltration volume confirmed by the user * @param adjustment The adjustment selected by the user * @return TRUE if new UF settings accepted, FALSE if not. *************************************************************************/ BOOL verifyUFSettingsConfirmation( F32 uFVolume, U32 adjustment ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; HD_OP_MODE_T currMode = getCurrentOperationMode(); // User confirmed UF settings change(s)? if ( ( MODE_TREA == currMode ) && ( FALSE == didTimeout( pendingParamChangesTimer, USER_CONFIRM_CHANGE_TIMEOUT_MS ) ) ) { DIALYSIS_STATE_T currDialysisState = getDialysisState(); UF_STATE_T currUFState = getUltrafiltrationState(); sendTreatmentLogEventData( UF_VOLUME_CHANGE_EVENT, presMaxUFVolumeML, pendingUFVolumeChange ); presMaxUFVolumeML = pendingUFVolumeChange; result = setTreatmentParameterF32( TREATMENT_PARAM_UF_VOLUME, ( presMaxUFVolumeML / (F32)ML_PER_LITER ) ); // User should only allow UF rate adjustment to achieve UF volume change if ( UF_ADJ_UF_RATE == adjustment ) { sendTreatmentLogEventData( UF_RATE_CHANGE_EVENT, presUFRate, pendingUFRateChange ); presUFRate = pendingUFRateChange; signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); } setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); // If UF paused, resume with new settings if ( ( TREATMENT_DIALYSIS_STATE == currentTreatmentState ) && ( DIALYSIS_UF_STATE == currDialysisState ) && ( UF_PAUSED_STATE == currUFState ) ) { resumeUF(); } } else { if ( currMode != MODE_TREA ) { rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } else { rejectReason = REQUEST_REJECT_REASON_TIMEOUT_WAITING_FOR_USER_CONFIRM; } } // Respond to UF settings change confirmation sendChangeUFSettingsOptionResponse( result, rejectReason, presMaxUFVolumeML, presTreatmentTimeSecs / SEC_PER_MIN, presUFRate ); // Send new ranges for settings treatmentParamsRangesBroadcastTimerCtr = getU32OverrideValue( &treatmentParamRangesPublishInterval ); broadcastTreatmentSettingsRanges(); // Send time/state data immediately for UI update broadcastTreatmentTimeAndState(); return result; } /*********************************************************************//** * @brief * The verifyBloodAndDialysateRateSettingsChange function verifies the * user blood & dialysate flow rate settings change. * @details Inputs: current operating mode, treatment states and parameters * @details Outputs: response message sent * @param bloodRate Proposed new blood flow rate (in mL/min) * @param dialRate Proposed new dialysate flow rate (in mL/min) * @return TRUE if new blood & dialysate rate settings are valid, FALSE if not. *************************************************************************/ BOOL verifyBloodAndDialysateRateSettingsChange( U32 bloodRate, U32 dialRate ) { BOOL result = FALSE; REQUEST_REJECT_REASON_CODE_T rejectReason = REQUEST_REJECT_REASON_NONE; HD_OP_MODE_T currMode = getCurrentOperationMode(); // Check if we are in treatment mode for settings change if ( MODE_TREA == currMode ) { F32 dialVolumeSoFar = (F32)( getTreatmentAvgDialysateFlowRate() * ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ) ) / (F32)( SEC_PER_MIN ); F32 dialVolumeNowToEnd = (F32)( dialRate * CALC_TREAT_TIME_REMAINING_IN_SECS() ) / (F32)( SEC_PER_MIN ); F32 dialVolume = dialVolumeSoFar + dialVolumeNowToEnd; // mL // Validate new rates if ( ( bloodRate >= getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_BLOOD_FLOW ) ) && ( bloodRate <= getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_BLOOD_FLOW ) ) && ( dialRate >= getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_DIALYSATE_FLOW ) ) && ( dialRate <= getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_DIALYSATE_FLOW ) ) && ( dialVolume <= (F32)MAX_DIALYSATE_VOLUME_ML ) ) { result = TRUE; // handle blood pump flow rate change if ( bloodRate != (U32)getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ) { sendTreatmentLogEventData( BLOOD_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), bloodRate ); signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); // Set to new rate result &= setTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW, bloodRate ); setDialysisBloodPumpFlowRate( getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ) ); } // Handle dialysate flow rate changes if ( dialRate != (U32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ) { sendTreatmentLogEventData( DIALYSATE_FLOW_RATE_CHANGE_EVENT, getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), dialRate ); signalInitiatePressureStabilization( USE_NORMAL_STABILIZATION_PERIOD ); // Set to new rate result &= setTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW, dialRate ); setDialysisDialInFlowAndUFRate( getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ), presMaxUFVolumeML, presUFRate ); } } else { if ( ( bloodRate < getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_BLOOD_FLOW ) ) || ( bloodRate > getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_BLOOD_FLOW ) ) ) { rejectReason = REQUEST_REJECT_REASON_BLOOD_FLOW_OUT_OF_RANGE; } else if ( ( dialRate < getU32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_DIALYSATE_FLOW ) ) || ( dialRate > getU32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_DIALYSATE_FLOW ) ) ) { rejectReason = REQUEST_REJECT_REASON_DIAL_FLOW_OUT_OF_RANGE; } else { rejectReason = REQUEST_REJECT_REASON_DIAL_VOLUME_OUT_OF_RANGE; } } } else { rejectReason = REQUEST_REJECT_REASON_NOT_IN_TREATMENT_MODE; } sendChangeBloodDialysateRateChangeResponse( result, (U32)rejectReason, getTreatmentParameterU32( TREATMENT_PARAM_BLOOD_FLOW ), getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ); // Send new ranges for settings treatmentParamsRangesBroadcastTimerCtr = getU32OverrideValue( &treatmentParamRangesPublishInterval ); broadcastTreatmentSettingsRanges(); return result; } /*********************************************************************//** * @brief * The verifyPressureLimitsChange function verifies a user change request * for in-line pressure alarm limits. If valid, new limits are accepted * and set. * @details Inputs: none * @details Outputs: new pressure limits set, response sent * @param data payload record with new pressure limits * @return TRUE if new pressure limits accepted, FALSE if not. *************************************************************************/ BOOL verifyPressureLimitsChange( PRESSURE_LIMIT_CHANGE_REQUEST_T *data ) { BOOL result = TRUE; CRITICAL_DATAS_T proposedNewArtLimitWindow; CRITICAL_DATAS_T proposedNewVenLimitWindow; CRITICAL_DATAS_T proposedNewVenLimitAsymmetric; PRESSURE_LIMIT_CHANGE_RESPONSE_T respRecord = { FALSE, 0, 0, 0, 0 }; proposedNewArtLimitWindow.sInt = data->artPresLimitWindowmmHg; proposedNewVenLimitWindow.sInt = data->venPresLimitWindowmmHg; proposedNewVenLimitAsymmetric.sInt = data->venPresLimitAsymmetricmmHg; // Check ranges for changed limits if ( FALSE == isTreatmentParamInRange( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW, proposedNewArtLimitWindow ) ) { respRecord.rejReasonCode = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; result = FALSE; } if ( FALSE == isTreatmentParamInRange( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW, proposedNewVenLimitWindow ) ) { respRecord.rejReasonCode = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; result = FALSE; } if ( FALSE == isTreatmentParamInRange( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC, proposedNewVenLimitAsymmetric ) ) { respRecord.rejReasonCode = REQUEST_REJECT_REASON_PARAM_OUT_OF_RANGE; result = FALSE; } // Set overall result - are changes accepted? respRecord.accepted = result; // If changes accepted, set new pressure limits if ( TRUE == result ) { S32 artLimitWindow = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ); S32 venLimitWindow = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ); S32 venLimitAsymmetric = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ); setTreatmentParameterS32( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW, data->artPresLimitWindowmmHg ); setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW, data->venPresLimitWindowmmHg ); setTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC, data->venPresLimitAsymmetricmmHg ); if ( abs( artLimitWindow - data->artPresLimitWindowmmHg ) > 0 ) { sendTreatmentLogEventData( ARTERIAL_PRESSURE_LIMIT_WINDOW_CHANGE_EVENT, (F32)artLimitWindow, (F32)data->artPresLimitWindowmmHg ); } if ( abs( venLimitWindow - data->venPresLimitWindowmmHg ) > 0 ) { sendTreatmentLogEventData( VENOUS_PRESSURE_LIMIT_WINDOW_CHANGE_EVENT, (F32)venLimitWindow, (F32)data->venPresLimitWindowmmHg ); } if ( abs( venLimitAsymmetric - data->venPresLimitAsymmetricmmHg ) > 0 ) { sendTreatmentLogEventData( VENOUS_PRESSURE_LIMIT_ASYM_CHANGE_EVENT, (F32)venLimitAsymmetric, (F32)data->venPresLimitAsymmetricmmHg ); } } // Read back limits for transmit to UI. respRecord.artPresLimitWindowmmHg = getTreatmentParameterS32( TREATMENT_PARAM_ART_PRES_LIMIT_WINDOW ); respRecord.venPresLimitWindowmmHg = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_WINDOW ); respRecord.venPresLimitAsymmetricmmHg = getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRES_LIMIT_ASYMMETRIC ); // Send response sendPressureLimitsChangeResponse( &respRecord ); return result; } /*********************************************************************//** * @brief * The broadcastTreatmentTimeAndState function broadcasts treatment time and * state data during treatment. * @details Inputs: treatmentTimeBroadcastTimerCtr, elapsedTreatmentTimeInSecs, * presTreatmentTimeSecs, treatmentStateBroadcastTimerCtr * @details Outputs: treatmentTimeBroadcastTimerCtr, treatmentStateBroadcastTimerCtr * @return none *************************************************************************/ void broadcastTreatmentTimeAndState( void ) { U32 elapsedTreatmentTimeInSecs; // Update treatment time stats and broadcast - end treatment if time elapsedTreatmentTimeInSecs = CALC_ELAPSED_TREAT_TIME_IN_SECS(); // Broadcast treatment time data at interval if ( ++treatmentTimeBroadcastTimerCtr >= getU32OverrideValue( &treatmentTimePublishInterval ) ) { TREATMENT_TIME_DATA_T data = { 0, 0, 0 }; if ( isTreatmentCompleted() != TRUE ) { data.treatmentTimeElapsedinSec = elapsedTreatmentTimeInSecs; // if alarm preventing treatment resumption, treatment is essentially over and we want to indicate that with published treatment time data if ( isTreatmentResumeBlocked() != TRUE ) { data.treatmentTimePrescribedinSec = presTreatmentTimeSecs; data.treatmentTimeRemaininginSec = presTreatmentTimeSecs - elapsedTreatmentTimeInSecs; } else { data.treatmentTimePrescribedinSec = 0; data.treatmentTimeRemaininginSec = 0; } } broadcastData( MSG_ID_TREATMENT_TIME_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( TREATMENT_TIME_DATA_T ) ); treatmentTimeBroadcastTimerCtr = 0; } // Broadcast treatment state data at interval if ( ++treatmentStateBroadcastTimerCtr >= getU32OverrideValue( &treatmentStatePublishInterval ) ) { TREATMENT_STATE_DATA_T payload; payload.treatmentSubMode = (U32)currentTreatmentState; payload.uFState = getUltrafiltrationState(); payload.salineBolusState = getSalineBolusState(); payload.txStopState = getCurrentTreatmentStopState(); payload.bldPrimeState = getCurrentBloodPrimeState(); payload.rinsebackState = getCurrentRinsebackState(); payload.txRecircState = getCurrentTreatmentRecircState(); payload.txEndState = getCurrentTreatmentEndState(); payload.heparinState = getHeparinState(); payload.dialysisState = getDialysisState(); broadcastData( MSG_ID_TREATMENT_STATE_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&payload, sizeof( TREATMENT_STATE_DATA_T ) ); treatmentStateBroadcastTimerCtr = 0; } } /*********************************************************************//** * @brief * The broadcastTreatmentSettingsRanges function computes and broadcasts * updated treatment parameter ranges that the user may change during treatment. * It is assumed that prescription settings have already been set prior to calling * this function. * @details Inputs: current operating mode, treatment states and parameters * @details Outputs: valid ranges message sent on interval * @return none *************************************************************************/ static void broadcastTreatmentSettingsRanges( void ) { if ( ++treatmentParamsRangesBroadcastTimerCtr >= getU32OverrideValue( &treatmentParamRangesPublishInterval ) ) { // Compute values need to assess max dialysate rate with respect to 150L limit. F32 dialVolumeSoFar = (F32)( getTreatmentAvgDialysateFlowRate() * ( treatmentTimeMS / TREATMENT_PERIODIC_DATA_LOG_INTERVAL ) ) / (F32)( SEC_PER_MIN ); F32 maxQd = ( (F32)MAX_DIALYSATE_VOLUME_ML - dialVolumeSoFar ) / ( (F32)CALC_TREAT_TIME_REMAINING_IN_SECS() / (F32)SEC_PER_MIN ); // Compute minimum treatment duration U32 presTime = ( presTreatmentTimeSecs / SEC_PER_MIN ); U32 elapseTime = CALC_ELAPSED_TREAT_TIME_IN_MIN(); U32 minTime = MAX( (elapseTime + 2), getMinTreatmentTimeInMinutes() ); // Treatment duration cannot be < 1 hour. add two minutes to cover rounding and ensure it is valid for next minute // Compute maximum treatment duration (from both UF and dialysate volume perspectives) U32 maxTimeRem = ( MAX_UF_VOLUME_ML - (U32)getUltrafiltrationReferenceVolume() ) / ( presUFRate > 0.0F ? (U32)presUFRate : 1 ); U32 maxTime1 = minTime + maxTimeRem; U32 maxTime2 = MAX_DIALYSATE_VOLUME_ML / getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); U32 maxTime = MAX( maxTime1, maxTime2 ); // Compute minimum UF volume F32 minUFVol = getUltrafiltrationReferenceVolume() + presUFRate; // Compute maximum UF volume (considering from adjustment of UF rate and time perspectives) F32 maxUFVol1 = minUFVol + ( (F32)( presTime - elapseTime ) * MAX_UF_RATE_ML_MIN ); F32 maxUFVol2 = ( presUFRate > 0.0F ? minUFVol + ( (F32)( MAX_TREATMENT_TIME_MINUTES - elapseTime - 1 ) * presUFRate ) : minUFVol ); F32 maxUFVol = MAX( maxUFVol1, maxUFVol2 ); // Compute minimum dialysate flow rate U32 minDialRate = MIN_DIAL_IN_FLOW_RATE; // Compute maximum dialysate flow rate from max dialysate volume perspective U32 maxDialRate = ( maxQd > (F32)MIN_DIAL_IN_FLOW_RATE ? (U32)((S32)maxQd) : minDialRate ); // Now ensure maximums do not exceed the literal maximums maxTime = MIN( maxTime, MAX_TREATMENT_TIME_MINUTES ); maxUFVol = MIN( maxUFVol, (F32)MAX_UF_VOLUME_ML ); maxDialRate = MIN( maxDialRate, MAX_DIAL_IN_FLOW_RATE ); // Send updated treatment parameter ranges to UI sendTreatmentParamsRangesToUI( minTime, maxTime, minUFVol, maxUFVol, minDialRate, maxDialRate ); treatmentParamsRangesBroadcastTimerCtr = 0; } } /*********************************************************************//** * @brief * The broadcastTreatmentPeriodicData function computes and broadcasts * periodic treatment data during treatment. * @details Inputs: treatmentPeriodDataBroadcastTimerCtr * @details Outputs: collected and sent average treatment data over 30 minutes * @return none *************************************************************************/ static void broadcastTreatmentPeriodicData( void ) { U32 const timeElapsedSinceLastCollect_ms = calcTimeBetween( lastTreatmentPeriodicDataCollectTimeStamp, treatmentTimeMS ); U32 const timeElapsedSinceLastPublish_ms = calcTimeBetween( lastTreatmentPeriodicDataPublishTimeStamp, treatmentTimeMS ); if ( timeElapsedSinceLastCollect_ms >= TREATMENT_PERIODIC_DATA_LOG_INTERVAL ) { F32 const arterialPres = getFilteredArterialPressure(); F32 const venousPres = getFilteredVenousPressure(); if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) { treatmentBloodFlowRateTotal_mL_min += getMeasuredBloodFlowRate(); treatmentDialysateFlowRateTotal_mL_min += getMeasuredDialInFlowRate(); treatmentDialysateTempTotal_degree_C += getDialysateTemperature(); treatmentArterialPressureTotal_mmHg += arterialPres; treatmentVenousPressureTotal_mmHg += venousPres; } lastTreatmentPeriodicDataCollectTimeStamp = treatmentTimeMS; bloodFlowRateSum_mL_min += getMeasuredBloodFlowRate(); dialysateFlowRateSum_mL_min += getMeasuredDialInFlowRate(); arterialPressureSum_mmHg += arterialPres; venousPressureSum_mmHg += venousPres; } if ( ( timeElapsedSinceLastPublish_ms >= TREATMENT_PERIODIC_DATA_PUB_INTERVAL ) || ( TRUE == sendLastTreatmentPeriodicData ) ) { TREATMENT_LOG_DATA_PERIODIC_T periodTreatmentData; F32 const uFVolumeCollected = getUltrafiltrationVolumeCollected(); U32 const numberOfDataPoint = timeElapsedSinceLastPublish_ms / TREATMENT_PERIODIC_DATA_LOG_INTERVAL; if ( numberOfDataPoint > 0 ) { // don't send data if no data since last publish periodTreatmentData.avgUFRate = ( uFVolumeCollected - lastUltraFiltrationVolume_mL ) / ( numberOfDataPoint / SEC_PER_MIN ); periodTreatmentData.avgBloodFlowRate = bloodFlowRateSum_mL_min / numberOfDataPoint; periodTreatmentData.avgDialysateFlowRate = dialysateFlowRateSum_mL_min / numberOfDataPoint; periodTreatmentData.avgArterialPressure = arterialPressureSum_mmHg / numberOfDataPoint; periodTreatmentData.avgVenousPressure = venousPressureSum_mmHg / numberOfDataPoint; sendTreatmentPeriodicDataToUI( &periodTreatmentData ); } // reset for next round to publish sendLastTreatmentPeriodicData = FALSE; lastTreatmentPeriodicDataPublishTimeStamp = treatmentTimeMS; lastUltraFiltrationVolume_mL = uFVolumeCollected; bloodFlowRateSum_mL_min = 0.0; dialysateFlowRateSum_mL_min = 0.0; arterialPressureSum_mmHg = 0.0; venousPressureSum_mmHg = 0.0; } } /*********************************************************************//** * @brief * The getMinTreatmentTimeInMinutes function returns the minimum treatment * time (in minutes) that the user could set treatment duration to. * @details Inputs: MIN_TREATMENT_TIME_MINUTES * @details Outputs: none * @return minimum treatment time in minutes *************************************************************************/ static U32 getMinTreatmentTimeInMinutes( void ) { U32 treatmentTime = MIN_TREATMENT_TIME_MINUTES; if ( TRUE == getTestConfigStatus( TEST_CONFIG_ENABLE_ONE_MINUTE_TREATMENT ) ) { treatmentTime = 1; } return treatmentTime; } /*********************************************************************//** * @brief * The resetSignalFlags function resets all non-alarm signal flags. * @details Inputs: none * @details Outputs: non-alarm signal flags set to FALSE * @return none *************************************************************************/ static void resetSignalFlags( void ) { rinsebackToStoppedRequest = FALSE; endTreatmentRequest = FALSE; rinsebackToRecircRequest = FALSE; bloodPrimeToDialysisRequest = FALSE; treatmentEndToRinsebackRequest = FALSE; } /*********************************************************************//** * @brief * The resetAlarmSignalFlags function resets all alarm signal flags. * @details Inputs: none * @details Outputs: alarm signal flags set to FALSE * @return none *************************************************************************/ static void resetAlarmSignalFlags( void ) { resumeTreatmentAlarmResponseRequest = FALSE; initiateRinsebackAlarmResponseRequest = FALSE; endTreatmentAlarmResponseRequest = FALSE; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetTreatmentTimeRemainingOverride function overrides the * treatment time remaining. * @details Inputs: presTreatmentTimeSecs, currentTreatmentState * @details Outputs: treatmentTimeMS * @param value override treatment time remaining overridden to this (in sec) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetTreatmentTimeRemainingOverride( U32 value ) { BOOL result = FALSE; if ( ( TRUE == isTestingActivated() ) && ( value < presTreatmentTimeSecs ) ) { if ( ( MODE_TREA == getCurrentOperationMode() ) && ( currentTreatmentState < TREATMENT_END_STATE ) ) { result = TRUE; treatmentTimeMS = ( presTreatmentTimeSecs - value ) * MS_PER_SECOND; } } return result; } /*********************************************************************//** * @brief * The testSetTreatmentTimePublishIntervalOverride function sets the override of the * treatment time data publication interval. * @details Inputs: none * @details Outputs: treatmentTimePublishInterval * @param ms milliseconds between treatment time broadcasts * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetTreatmentTimePublishIntervalOverride( U32 ms ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = ms / TASK_GENERAL_INTERVAL; result = TRUE; treatmentTimePublishInterval.ovData = intvl; treatmentTimePublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetTreatmentTimePublishIntervalOverride function resets the override of the * treatment time data publication interval. * @details Inputs: none * @details Outputs: treatmentTimePublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetTreatmentTimePublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; treatmentTimePublishInterval.override = OVERRIDE_RESET; treatmentTimePublishInterval.ovData = treatmentTimePublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetTreatmentStatePublishIntervalOverride function sets the override of the * treatment state data publication interval. * @details Inputs: none * @details Outputs: treatmentStatePublishInterval * @param ms milliseconds between treatment state broadcasts * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetTreatmentStatePublishIntervalOverride( U32 ms ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = ms / TASK_GENERAL_INTERVAL; result = TRUE; treatmentStatePublishInterval.ovData = intvl; treatmentStatePublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetTreatmentStatePublishIntervalOverride function resets the override of the * treatment state data publication interval. * @details Inputs: none * @details Outputs: treatmentStatePublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetTreatmentStatePublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; treatmentStatePublishInterval.override = OVERRIDE_RESET; treatmentStatePublishInterval.ovData = treatmentStatePublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetTreatmentParamRangesPublishIntervalOverride function sets the override of the * treatment param ranges data publication interval. * @details Inputs: none * @details Outputs: treatmentParamRangesPublishInterval * @param ms milliseconds between treatment param range broadcasts * @return TRUE if override set successful, FALSE if not *************************************************************************/ BOOL testSetTreatmentParamRangesPublishIntervalOverride( U32 ms ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = ms / TASK_GENERAL_INTERVAL; result = TRUE; treatmentParamRangesPublishInterval.ovData = intvl; treatmentParamRangesPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetTreatmentParamRangesPublishIntervalOverride function resets the override of the * treatment param ranges data publication interval. * @details Inputs: none * @details Outputs: treatmentParamRangesPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetTreatmentParamRangesPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; treatmentParamRangesPublishInterval.override = OVERRIDE_RESET; treatmentParamRangesPublishInterval.ovData = treatmentParamRangesPublishInterval.ovInitData; } return result; } /**@}*/