Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -90,7 +90,7 @@ #define BP_MAX_CURR_WHEN_STOPPED_MA 150.0F ///< Motor controller current should not exceed this when pump should be stopped. #define BP_MAX_CURR_WHEN_RUNNING_MA 2000.0F ///< Motor controller current should not exceed this when pump should be running. -#define BP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. +#define BP_MAX_CURR_ERROR_DURATION_MS 5000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. #define BLOODPUMP_ADC_FULL_SCALE_V 3.0F ///< BP analog signals are 0-3V (while int. ADC ref may be different). #define BLOODPUMP_ADC_ZERO 1998 ///< Blood pump ADC channel zero offset. Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -90,7 +90,7 @@ #define DIP_MAX_CURR_WHEN_STOPPED_MA 150.0F ///< Motor controller current should not exceed this when pump should be stopped. #define DIP_MAX_CURR_WHEN_RUNNING_MA 2000.0F ///< Motor controller current should not exceed this when pump should be running. -#define DIP_MAX_CURR_ERROR_DURATION_MS 2000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. +#define DIP_MAX_CURR_ERROR_DURATION_MS 5000 ///< Motor controller current errors persisting beyond this duration will trigger an alarm. #define DIAL_IN_PUMP_ADC_FULL_SCALE_V 3.0F ///< BP analog signals are 0-3V (while int. ADC ref V may be different). #define DIAL_IN_PUMP_ADC_ZERO 1998 ///< Mid-point (zero) for ADC readings. @@ -1535,15 +1535,10 @@ **************************************************************************/ static BOOL setDialInPumpToFixedPWM( F32 pwm ) { - MOTOR_DIR_T dir = MOTOR_DIR_FORWARD; + MOTOR_DIR_T dir = ( pwm < 0.0F ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); BOOL result = FALSE; F32 pwmFabs = fabs(pwm); - if ( pwm < 0 ) - { - dir = MOTOR_DIR_REVERSE; - } - // Direction change while pump is running is not allowed unless we are turning off if ( ( FALSE == isDialInPumpOn ) && ( dir != dialInPumpDirectionSet ) ) { @@ -1927,14 +1922,12 @@ BOOL result = FALSE; F32 absolutePWM = fabs( pwmPct ); - if ( TRUE == isTestingActivated() ) + // check for max of pump pwm for acceptance. *** Function used in dialyzer re-prime, so no Dialin login required *** + if ( absolutePWM < MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ) { - // check for max of pump pwm for acceptance. - if ( absolutePWM < MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE ) - { - result = setDialInPumpToFixedPWM( pwmPct ); - } + result = setDialInPumpToFixedPWM( pwmPct ); } + return result; } Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -63,14 +63,13 @@ #define ARTERIAL_PRESSURE_SELF_TEST_MAX ( 100.0F ) ///< Maximum self-test value for arterial pressure sensor reading (in mmHg). #define ARTERIAL_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum arterial pressure reading (in mmHg) for range check. #define ARTERIAL_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum arterial pressure reading (in mmHg) for range check. -#define ARTERIAL_PRESSURE_ND_MIN_MMHG ( -250.0F ) ///< Minimum arterial pressure reading (in mmHg) when not dialyzing. #define VENOUS_PRESSURE_SELF_TEST_MIN ( -100.0F ) ///< Minimum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_SELF_TEST_MAX ( 100.0F ) ///< Maximum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_MAX_MMHG ( 2000.0F ) ///< Maximum venous pressure reading (in mmHg) for range check. #define VENOUS_PRESSURE_MIN_MMHG ( -1500.0F ) ///< Minimum venous pressure reading (in mmHg) for range check. -#define VENOUS_PRESSURE_ND_MAX_MMHG ( 300.0F ) ///< Maximum venous pressure reading (in mmHg) when not dialyzing. #define VENOUS_PRESSURE_OCCL_OFFSET_MMHG ( 50.0F ) ///< Venous pressure occlusion threshold offset from max alarm limit (in mmHg). +#define VENOUS_PRESSURE_LIMIT_DELAY_MS ( SEC_PER_MIN * MS_PER_SECOND ) ///< Venous pressure limit delay period following dialysis start/resume (use wider limits during this period). #define PSI_TO_MMHG ( 51.7149F ) ///< Conversion factor for converting PSI to mmHg. @@ -165,6 +164,7 @@ static U32 venPressureReadingsShortIdx = 0; ///< Index for next sample in rolling average array. static F32 venPressureReadingsShortTotal = 0.0; ///< Rolling total - used to calc average. static U32 venPressureReadingsShortCount = 0; ///< Number of samples in flow rolling average buffer. +static U32 venPressureLimitDelayStart; ///< Time stamp for last time dialysis started/resumed. static PRESSURE_SELF_TEST_STATE_T presOcclPostState; ///< Pressure self test post state. static HD_PRESSURE_SENSORS_CAL_RECORD_T pressureSensorsCalRecord; ///< Pressure sensors calibration record. static HD_OCCLUSION_SENSORS_CAL_RECORD_T occlusionSensorsCalRecord; ///< Occlusion sensors calibration record. @@ -208,13 +208,14 @@ initFPGAPersistentAlarm( FPGA_PERS_ERROR_VENOUS_PRESSURE_SESNOR, ALARM_ID_HD_VENOUS_SENSOR_FPGA_FAULT, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS, PRES_SENSORS_FPGA_ERROR_TIMEOUT_MS ); - longFilteredArterialPressure = 0.0F; - shortFilteredArterialPressure = 0.0F; - shortFilteredVenousPressure = 0.0F; - presOcclDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - presOcclState = PRESSURE_WAIT_FOR_POST_STATE; - presOcclPostState = PRESSURE_SELF_TEST_STATE_START; + longFilteredArterialPressure = 0.0F; + shortFilteredArterialPressure = 0.0F; + shortFilteredVenousPressure = 0.0F; + presOcclDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + presOcclState = PRESSURE_WAIT_FOR_POST_STATE; + presOcclPostState = PRESSURE_SELF_TEST_STATE_START; bloodPumpOcclusionAfterCartridgeInstall = 0; + venPressureLimitDelayStart = 0; } /*********************************************************************//** @@ -302,6 +303,20 @@ } } +/*********************************************************************//** + * @brief + * The signalStartDialysisStartOrResume function signals that dialysis has + * just been started or resumed which begins a brief time window where + * venous pressure limits are relaxed while treatment reaches stability. + * @details Inputs: none + * @details Outputs: venPressureLimitDelayStart + * @return none + *************************************************************************/ +void signalStartDialysisStartOrResume( void ) +{ + venPressureLimitDelayStart = getMSTimerCount(); +} + /*********************************************************************//** * @brief * The execPresOccl function executes the pressure and occlusion monitor. @@ -470,12 +485,12 @@ // Check arterial pressure during treatment mode against either user set limits or fixed max limits depending on treatment state if ( ( MODE_TREA == getCurrentOperationMode() ) && - ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) || - ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) || - ( TREATMENT_BLOOD_PRIME_STATE == txState ) ) ) + ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( DIALYSIS_UF_STATE == getDialysisState() ) ) || + ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) ) ) { F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); + BOOL artPresLow, artPresHigh; // If BP is ramping up, extend range to outer limits as pressure may not yet have reached expected range. if ( isBloodPumpRampComplete() != TRUE ) @@ -484,24 +499,36 @@ artHighLimit = (F32)getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); } + artPresLow = ( artPres < artLowLimit ? TRUE : FALSE ); + artPresHigh = ( artPres > artHighLimit ? TRUE : FALSE ); + // Check arterial pressure is within user set alarm limits - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < artLowLimit ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPresLow ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, artLowLimit ); } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres > artHighLimit ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPresHigh ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres, artHighLimit ); } } else if ( MODE_TREA == getCurrentOperationMode() ) // All treatment states not covered by the if above { - // Check arterial pressure is within non-treatment alarm limits - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < ARTERIAL_PRESSURE_ND_MIN_MMHG ) ) + F32 artLowLimit = (F32)getS32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); + F32 artHighLimit = (F32)getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); + BOOL artPresLow = ( artPres < artLowLimit ? TRUE : FALSE ); + BOOL artPresHigh = ( artPres > artHighLimit ? TRUE : FALSE ); + + // Check arterial pressure is within max selectable range + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPresLow ) ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, ARTERIAL_PRESSURE_ND_MIN_MMHG ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, artLowLimit ); } + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPresHigh ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_HIGH, artPres, artHighLimit ); + } } else { // Reset persistence if alarm is out of scope @@ -537,12 +564,12 @@ // Check venous pressure during treatment mode against either user set limits or fixed max limits depending on treatment state if ( ( MODE_TREA == getCurrentOperationMode() ) && - ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) || - ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) || - ( TREATMENT_BLOOD_PRIME_STATE == txState ) ) ) + ( ( ( TREATMENT_DIALYSIS_STATE == txState ) && ( DIALYSIS_UF_STATE == getDialysisState() ) && ( TRUE == didTimeout( venPressureLimitDelayStart, VENOUS_PRESSURE_LIMIT_DELAY_MS ) ) ) || + ( ( TREATMENT_STOP_STATE == txState ) && ( TRUE == isBloodPumpRunning() ) ) ) ) { F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); + BOOL venPresLow, venPresHigh; // If BP is ramping up, extend range to outer limits as pressure may not yet have reached expected range. if ( isBloodPumpRampComplete() != TRUE ) @@ -551,10 +578,13 @@ venHighLimit = (F32)getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); } + venPresLow = ( venPres < venLowLimit ? TRUE : FALSE ); + venPresHigh = ( venPres > venHighLimit ? TRUE : FALSE ); + // Cannot monitor for low venous pressure while venting air trap if ( getValveAirTrapStatus() != STATE_OPEN ) { - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPres < venLowLimit ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPresLow ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_LOW, venPres, venLowLimit ); } @@ -564,19 +594,27 @@ isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > venHighLimit ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPresHigh ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, venHighLimit ); } } else if ( MODE_TREA == getCurrentOperationMode() ) // All treatment states not covered by the if statement above { - // Check venous pressure is less than non-treatment alarm limit - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres > VENOUS_PRESSURE_ND_MAX_MMHG ) ) + F32 venLowLimit = (F32)getS32TreatmentParamLowerRangeLimit( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); + F32 venHighLimit = (F32)getS32TreatmentParamUpperRangeLimit( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); + BOOL venPresLow = ( venPres < venLowLimit ? TRUE : FALSE ); + BOOL venPresHigh = ( venPres > venHighLimit ? TRUE : FALSE ); + + // Check venous pressure is within max selectable range + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_HIGH, venPresHigh ) ) { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, VENOUS_PRESSURE_ND_MAX_MMHG ); + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_HIGH, venPres, venHighLimit ); } - isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, FALSE ); + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_VENOUS_PRESSURE_LOW, venPresLow ) ) + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_VENOUS_PRESSURE_LOW, venPres, venLowLimit ); + } } else { // Reset persistence if alarm is out of scope Index: firmware/App/Controllers/PresOccl.h =================================================================== diff -u -r0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision 0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa) +++ firmware/App/Controllers/PresOccl.h (.../PresOccl.h) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -76,6 +76,7 @@ BOOL isCartridgeLoaded( void ); BOOL isCartridgeUnloaded( void ); BOOL isSalineBagEmpty( void ); +void signalStartDialysisStartOrResume( void ); void setOcclusionInstallLevel( void ); Index: firmware/App/HDCommon.h =================================================================== diff -u -r6e584e378bc1bc41a17aa8cbd1a49e023ee8ac2d -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/HDCommon.h (.../HDCommon.h) (revision 6e584e378bc1bc41a17aa8cbd1a49e023ee8ac2d) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -35,6 +35,7 @@ // #define BOARD_WITH_NO_HARDWARE 1 // Target is a PCB w/ no hardware // #define SIMULATE_UI 1 // Build w/o requirement that UI be there // #define TASK_TIMING_OUTPUT_ENABLED 1 // Re-purposes alarm lamp pins for task timing +// #define DIALYZER_REPRIME_ENABLED 1 // Build with dialyzer reprime code #include #include Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r29150914d74e54bd6476d560a4253b0170c3ff33 -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 29150914d74e54bd6476d560a4253b0170c3ff33) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -26,6 +26,7 @@ #include "ModeTreatment.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" +#include "PresOccl.h" #include "Reservoirs.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" @@ -51,6 +52,20 @@ #define MAX_ACTIVE_LOAD_CELL_CHANGE_G 50.0F ///< Maximum delta between new and previous measured UF volume. +#ifdef DIALYZER_REPRIME_ENABLED +// Dialyzer reprime constants +static const U32 DIALYZER_REPRIME_INTERVAL = ((30 * SEC_PER_MIN * MS_PER_SECOND) / TASK_GENERAL_INTERVAL); +/// Dialyzer reprime interval count. Time between reprime attempts. +#define DIALYZER_REPRIME_REPRIME_DURATION_MS ( 21 * MS_PER_SECOND ) ///< Duration of dialyzer reprime reprime state. +#define DIALYZER_REPRIME_PURGE_PRIOR_1_DURATION_MS ( 10 * MS_PER_SECOND ) ///< Duration of dialyzer reprime purge prior 1 state. +#define DIALYZER_REPRIME_PURGE_PRIOR_2_DURATION_MS ( 6 * MS_PER_SECOND ) ///< Duration of dialyzer reprime purge prior 2 state. +#define DIALYZER_REPRIME_PURGE_LINES_DURATION_MS ( 10 * MS_PER_SECOND ) ///< Duration of dialyzer reprime purge prior 2 state. +#define DIALYZER_REPRIME_BEFORE_TREATEMENT_END_INTERVAL_SEC 300 ///< Time before end of treatment to perform final dialyzer reprime, sec. +#define DP_FAST_PURGE_FLOW_RATE_ML_MIN 500.0F ///< Dialysate pump speed for purging air in dialyzer reprime states, ml/min. +#define DPI_REPRIME_PWM_DC -0.23F ///< Inlet dialysate pump PWM duty cycle (-520 RPM = appx -100 mL/min). +#define DPO_REPRIME_PWM_DC -0.225F ///< Outlet dialysate pump PWM duty cycle (-500 RPM = appx -104 mL/min). +#endif + /// Defined states for the Load Cell cycles. typedef enum Reservoir_Steady_Cycle { @@ -61,9 +76,12 @@ // ********** private data ********** -static DIALYSIS_STATE_T currentDialysisState; ///< Current state of the dialysis sub-mode state machine. -static UF_STATE_T currentUFState; ///< Current state of the ultrafiltration state machine. -static SALINE_BOLUS_STATE_T currentSalineBolusState; ///< Current state of the saline bolus state machine. +static DIALYSIS_STATE_T currentDialysisState; ///< Current state of the dialysis sub-mode state machine. +static UF_STATE_T currentUFState; ///< Current state of the ultrafiltration state machine. +static SALINE_BOLUS_STATE_T currentSalineBolusState; ///< Current state of the saline bolus state machine. +#ifdef DIALYZER_REPRIME_ENABLED +static DIALYZER_REPRIME_STATE_T currentDialyzerReprimeState; ///< Current state of the dialyzer reprime state machine. +#endif static F32 refUFVolume; ///< Current reference volume for ultrafiltration (Where should we be w/r/t ultrafiltration). static F32 measUFVolume; ///< Current total measured volume for ultrafiltration (Where are we w/r/t ultrafiltration). @@ -86,26 +104,45 @@ static U32 salineBolusBroadcastTimerCtr; ///< Saline bolus data broadcast timer counter used to schedule when to transmit data. static BOOL salineBolusStartRequested; ///< Flag indicates a saline bolus start has been requested by user. -static BOOL salineBolusAbortRequested; ///< Flag indicates a saline bolus abort has been requested by user. -static BOOL salineBolusAutoResumeUF = FALSE; ///< Flag indicates UF should be auto-resumed after saline bolus completes. +static BOOL salineBolusAbortRequested; ///< Flag indicates a salien bolus abort has been requested by user. +static BOOL autoResumeUF; ///< Flag indicates UF should be auto-resumed after saline bolus completes. static F32 totalSalineVolumeDelivered_mL; ///< Volume (mL) in total of saline delivered so far (cumulative for all boluses including current one). static F32 bolusSalineVolumeDelivered_mL; ///< Volume (mL) of current bolus delivered so far (calculated from measured blood flow rate). static F32 expectedSalineBolusVolume_mL; ///< Volume (mL) of current bolus delivered so far (calculated from target blood flow rate). static U32 bolusSalineLastVolumeTimeStamp; ///< Time stamp for last saline volume update. +#ifdef DIALYZER_REPRIME_ENABLED +static U32 dialyzerReprimeIntervalTimerCtr; ///< Timer counter to determine when the dialyzer reprime should be done. +static BOOL dialyzerReprimeInProgress; ///< Flag indicates whether the dialyzer reprime has been interrupted. +static BOOL dialyzerReprimeFinalReprimeFinished; ///< Flag indicates whether the final dialyzer reprime has completed. +static U32 dialyzerReprimeStateTimer; ///< General state timer for tracking duration of dialyzer reprime states. +#endif + // ********** private function prototypes ********** static DIALYSIS_STATE_T handleDialysisUltrafiltrationState( void ); static DIALYSIS_STATE_T handleDialysisSalineBolusState( void ); +#ifdef DIALYZER_REPRIME_ENABLED +static DIALYSIS_STATE_T handleDialysisDialyzerReprimeState( void ); +#endif static UF_STATE_T handleUFPausedState( DIALYSIS_STATE_T *dialysisState ); static UF_STATE_T handleUFRunningState( DIALYSIS_STATE_T *dialysisState ); -static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( DIALYSIS_STATE_T *dialysisState ); -static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( DIALYSIS_STATE_T *dialysisState ); +static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( void ); +static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( void ); static SALINE_BOLUS_STATE_T handleSalineBolusInProgressState( DIALYSIS_STATE_T *dialysisState ); static SALINE_BOLUS_STATE_T handleSalineBolusMaxDeliveredState( DIALYSIS_STATE_T *dialysisState ); +#ifdef DIALYZER_REPRIME_ENABLED +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimeDialysatePumpsOffState( void ); +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimePurgePrior1State( void ); +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimePurgePrior2State( void ); +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimeRePrimeState( void ); +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimePurgeLinesState( DIALYSIS_STATE_T *dialysisState ); +static void initDialyzerReprime( void ); +#endif + static void checkUFControl( void ); static void updateUFVolumes( void ); @@ -147,7 +184,14 @@ salineBolusBroadcastTimerCtr = 0; totalSalineVolumeDelivered_mL = 0.0; + autoResumeUF = FALSE; +#ifdef DIALYZER_REPRIME_ENABLED + dialyzerReprimeIntervalTimerCtr = 0; + dialyzerReprimeInProgress = FALSE; + dialyzerReprimeFinalReprimeFinished = FALSE; +#endif + for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) { lcLastSteadyWeight[RESERVOIR_STEADY_CYCLE_START][i] = LOAD_CELL_ILLEGAL_WEIGHT_VALUE; @@ -185,9 +229,9 @@ { currentSalineBolusState = SALINE_BOLUS_STATE_IDLE; } - if ( TRUE == salineBolusAutoResumeUF ) + if ( TRUE == autoResumeUF ) { - salineBolusAutoResumeUF = FALSE; + autoResumeUF = FALSE; currentUFState = UF_RUNNING_STATE; } } @@ -216,6 +260,8 @@ resetReservoirsVariables(); + signalStartDialysisStartOrResume(); + // Set valves for dialysis setValvePosition( VDI, VALVE_POSITION_B_OPEN ); setValvePosition( VDO, VALVE_POSITION_B_OPEN ); @@ -368,7 +414,6 @@ U32 salineBolusVolume = getTreatmentParameterU32( TREATMENT_PARAM_SALINE_BOLUS_VOLUME ); HD_OP_MODE_T currOpMode = getCurrentOperationMode(); TREATMENT_STATE_T currTreatSubMode = getTreatmentState(); - SALINE_BOLUS_STATE_T currSalineBolusState = getSalineBolusState(); // Must be in treatment mode, dialysis sub-mode, saline bolus in idle state in order to start a saline bolus if ( currOpMode != MODE_TREA ) @@ -383,10 +428,16 @@ { rejReason = REQUEST_REJECT_REASON_SALINE_MAX_VOLUME_REACHED; } - else if ( currSalineBolusState != SALINE_BOLUS_STATE_IDLE ) + else if ( DIALYSIS_SALINE_BOLUS_STATE == currentDialysisState ) { rejReason = REQUEST_REJECT_REASON_SALINE_BOLUS_IN_PROGRESS; } +#ifdef DIALYZER_REPRIME_ENABLED + else if ( DIALYSIS_DIALYZER_REPRIME_STATE == currentDialysisState ) + { + rejReason = REQUEST_REJECT_REASON_DIALYZER_REPRIME_IN_PROGRESS; + } +#endif else { accept = TRUE; @@ -473,8 +524,22 @@ return currentSalineBolusState; } +#ifdef DIALYZER_REPRIME_ENABLED /*********************************************************************//** * @brief + * The getDialyzerRePrimeState function gets the current dialyzer re-prime state. + * @details Inputs: currentDialyzerReprimeState + * @details Outputs: none + * @return currentDialyzerReprimeState + *************************************************************************/ +DIALYZER_REPRIME_STATE_T getDialyzerRePrimeState( void ) +{ + return currentDialyzerReprimeState; +} +#endif + +/*********************************************************************//** + * @brief * The getUltrafiltrationVolumeCollected function gets the current ultrafiltration * volume collected so far for current treatment. * @details Inputs: measUFVolume @@ -638,7 +703,11 @@ case DIALYSIS_SALINE_BOLUS_STATE: currentDialysisState = handleDialysisSalineBolusState(); break; - +#ifdef DIALYZER_REPRIME_ENABLED + case DIALYSIS_DIALYZER_REPRIME_STATE: + currentDialysisState = handleDialysisDialyzerReprimeState(); + break; +#endif default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_STATE, currentDialysisState ) break; @@ -677,6 +746,27 @@ setHeparinCompleted(); } +#ifdef DIALYZER_REPRIME_ENABLED + // Check whether it is time for dialyzer reprime + // Either a fixed interval or some interval before treatment end. + if ( ( ++dialyzerReprimeIntervalTimerCtr >= DIALYZER_REPRIME_INTERVAL) || + ( ( FALSE == dialyzerReprimeFinalReprimeFinished ) && + ( getTreatmentTimeRemainingSecs() <= DIALYZER_REPRIME_BEFORE_TREATEMENT_END_INTERVAL_SEC ) + ) + ) + { + initDialyzerReprime(); + if ( UF_RUNNING_STATE == currentUFState ) + { + autoResumeUF = TRUE; + } + currentUFState = UF_PAUSED_STATE; + result = DIALYSIS_DIALYZER_REPRIME_STATE; + } + else + { +#endif + // Handle current ultrafiltration state switch ( currentUFState ) { @@ -694,6 +784,10 @@ break; } +#ifdef DIALYZER_REPRIME_ENABLED + } +#endif + if ( priorSubState != currentUFState ) { SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentUFState ); @@ -704,8 +798,8 @@ /*********************************************************************//** * @brief - * The handleDialysisSolutionInfusionState function handles the solution - * infustion state of the Dialysis state machine. + * The handleDialysisSalineBolusState function handles the saline bolus + * state of the Dialysis state machine. * @details Inputs: currentSalineBolusState * @details Outputs: currentSalineBolusState * @return next Dialysis state. @@ -719,11 +813,11 @@ switch ( currentSalineBolusState ) { case SALINE_BOLUS_STATE_IDLE: - currentSalineBolusState = handleSalineBolusIdleState( &result ); + currentSalineBolusState = handleSalineBolusIdleState(); break; case SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP: - currentSalineBolusState = handleSalineBolusWait4Pumps2Stop( &result ); + currentSalineBolusState = handleSalineBolusWait4Pumps2Stop(); break; case SALINE_BOLUS_STATE_IN_PROGRESS: @@ -748,8 +842,59 @@ return result; } +#ifdef DIALYZER_REPRIME_ENABLED /*********************************************************************//** * @brief + * The handleDialysisDialyzerReprimeState function handles the dialyzer reprime + * state of the Dialysis state machine. + * @details Inputs: prior currentDialyzerReprimeState + * @details Outputs: new currentDialyzerReprimeState + * @return next Dialysis state. + *************************************************************************/ +static DIALYSIS_STATE_T handleDialysisDialyzerReprimeState( void ) +{ + DIALYSIS_STATE_T result = DIALYSIS_DIALYZER_REPRIME_STATE; + DIALYZER_REPRIME_STATE_T priorSubState = currentDialyzerReprimeState; + + switch ( currentDialyzerReprimeState ) + { + case DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF: + currentDialyzerReprimeState = handleDialyzerReprimeDialysatePumpsOffState(); + break; + + case DIALYZER_REPRIME_STATE_PURGE_PRIOR_1: + currentDialyzerReprimeState = handleDialyzerReprimePurgePrior1State(); + break; + + case DIALYZER_REPRIME_STATE_PURGE_PRIOR_2: + currentDialyzerReprimeState = handleDialyzerReprimePurgePrior2State(); + break; + + case DIALYZER_REPRIME_STATE_REPRIME: + currentDialyzerReprimeState = handleDialyzerReprimeRePrimeState(); + break; + + case DIALYZER_REPRIME_STATE_PURGE_LINES: + currentDialyzerReprimeState = handleDialyzerReprimePurgeLinesState( &result ); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSIS_INVALID_DIALYZER_REPRIME_STATE, currentDialyzerReprimeState ) + currentDialyzerReprimeState = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + break; + } + + if ( priorSubState != currentDialyzerReprimeState ) + { + SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_SUB_STATE_CHANGE, priorSubState, currentDialyzerReprimeState ); + } + + return result; +} +#endif + +/*********************************************************************//** + * @brief * The handleUFPausedState function handles the Paused state of the * ultrafiltration state machine. * @details Inputs: salineBolusStartRequested @@ -764,7 +909,7 @@ // Handle saline bolus start request from user if ( TRUE == salineBolusStartRequested ) { - salineBolusAutoResumeUF = FALSE; + autoResumeUF = FALSE; // Go to saline bolus state if we can if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) { @@ -815,7 +960,7 @@ if ( SALINE_BOLUS_STATE_IDLE == currentSalineBolusState ) { // Since we were doing UF prior to saline bolus, we want to auto-resume when done - salineBolusAutoResumeUF = TRUE; + autoResumeUF = TRUE; // Go to UF paused state result = UF_PAUSED_STATE; // Go to saline bolus state @@ -836,10 +981,9 @@ * saline bolus state machine. * @details Inputs: none * @details Outputs: - * @param dialysisState next dialysis state * @return next saline bolus state *************************************************************************/ -static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( DIALYSIS_STATE_T *dialysisState ) +static SALINE_BOLUS_STATE_T handleSalineBolusIdleState( void ) { SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_IDLE; @@ -865,10 +1009,9 @@ * to stop state of the saline bolus state machine. * @details Inputs: none * @details Outputs: - * @param dialysisState next dialysis state * @return next saline bolus state *************************************************************************/ -static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( DIALYSIS_STATE_T *dialysisState ) +static SALINE_BOLUS_STATE_T handleSalineBolusWait4Pumps2Stop( void ) { SALINE_BOLUS_STATE_T result = SALINE_BOLUS_STATE_WAIT_FOR_PUMPS_STOP; @@ -978,9 +1121,9 @@ if ( FALSE == errorFound ) { // Resume UF if appropriate - if ( TRUE == salineBolusAutoResumeUF ) + if ( TRUE == autoResumeUF ) { - salineBolusAutoResumeUF = FALSE; + autoResumeUF = FALSE; currentUFState = UF_RUNNING_STATE; } // Resume dialysis @@ -1011,8 +1154,185 @@ return result; } +#ifdef DIALYZER_REPRIME_ENABLED /*********************************************************************//** * @brief + * The initDialyzerReprimeState function performs the steps to initiate + * the dialyzer reprime task. + * @details Inputs: + * @details Outputs: currentDialyzerReprimeState + * @return none. + *************************************************************************/ +static void initDialyzerReprime( void ) +{ + // Give commands to stop pumps + setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + currentDialyzerReprimeState = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; +} + +/*********************************************************************//** + * @brief + * The handleDialysatePumpsOffState function handles the dialysate pumps off state of the + * dialyzer reprime state machine. + * @details Inputs: isDialInPumpRunning(), isDialOutPumpRunning(), dialyzerReprimeInProgress flag + * @details Outputs: next dialyzer reprime state, dialyzerReprimeInProgress flag + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimeDialysatePumpsOffState( void ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + + if ( ( FALSE == isDialInPumpRunning() ) && ( FALSE == isDialOutPumpRunning() ) ) + { + // Decide which state to transition to + if ( TRUE == dialyzerReprimeInProgress ) + { // the reprime was interrupted, so it is necessary to purge any air that may have been left in the lines + setDialInPumpTargetFlowRate( DP_FAST_PURGE_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + result = DIALYZER_REPRIME_STATE_PURGE_PRIOR_1; + } + else + { + // Set valves to flow through dialyzer + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + testSetDialInPumpTargetDutyCycle( DPI_REPRIME_PWM_DC ); + testSetDialOutPumpTargetDutyCycle( DPO_REPRIME_PWM_DC ); + dialyzerReprimeInProgress = TRUE; + result = DIALYZER_REPRIME_STATE_REPRIME; + } + dialyzerReprimeStateTimer = getMSTimerCount(); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleState function handles the purge prior 1 state of the dialyzer reprime + * state machine. + * @details Inputs: dialyzerReprimeStateTimer + * @details Outputs: dialyzerReprimeStateTimer, next dialyzer reprime state + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimePurgePrior1State( void ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_PURGE_PRIOR_1; + + if ( ( TRUE == didTimeout( dialyzerReprimeStateTimer, DIALYZER_REPRIME_PURGE_PRIOR_1_DURATION_MS ) ) ) + { + // Stop the dialysate in pump before opening valves + signalDialInPumpHardStop(); + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + // Start the two dialysate pumps together. + setDialInPumpTargetFlowRate( DP_FAST_PURGE_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialOutPumpTargetRate( DP_FAST_PURGE_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + dialyzerReprimeStateTimer = getMSTimerCount(); + result = DIALYZER_REPRIME_STATE_PURGE_PRIOR_2; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handlePurgePrior2State function handles the purge prior 2 state of the dialyzer reprime + * state machine. + * @details Inputs: dialyzerReprimeStateTimer + * @details Outputs: next dialyzer reprime state + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimePurgePrior2State( void ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_PURGE_PRIOR_2; + + if ( ( TRUE == didTimeout( dialyzerReprimeStateTimer, DIALYZER_REPRIME_PURGE_PRIOR_2_DURATION_MS ) ) ) + { + // ramp down the pumps to zero before turning them on in reverse + setDialInPumpTargetFlowRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + setDialOutPumpTargetRate( 0, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_CLOSED_LOOP ); + dialyzerReprimeInProgress = FALSE; // This will cause a transition to reprime state after pumps stop + result = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleState function handles the reprime state of the dialyzer reprime + * state machine. + * @details Inputs: dialyzerReprimeStateTimer + * @details Outputs: dialyzerReprimeStateTimer, next dialyzer reprime state + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimeRePrimeState( void ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_REPRIME; + + if ( ( TRUE == didTimeout( dialyzerReprimeStateTimer, DIALYZER_REPRIME_REPRIME_DURATION_MS ) ) ) + { + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + setDialInPumpTargetFlowRate( DP_FAST_PURGE_FLOW_RATE_ML_MIN, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + dialyzerReprimeStateTimer = getMSTimerCount(); + result = DIALYZER_REPRIME_STATE_PURGE_LINES; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleState function handles the purge lines state of the dialyzer reprime + * state machine. + * @details Inputs: dialyzerReprimeStateTimer + * @details Outputs: dialyzerReprimeStateTimer, dialyzerReprimeInProgress, + * dialyzerReprimeIntervalTimerCtr, next dialyzer reprime state + * @param dialysis Dialysis state + * @return next dialyzer reprime state + *************************************************************************/ +static DIALYZER_REPRIME_STATE_T handleDialyzerReprimePurgeLinesState( DIALYSIS_STATE_T *dialysisState ) +{ + DIALYZER_REPRIME_STATE_T result = DIALYZER_REPRIME_STATE_PURGE_LINES; + + if ( ( TRUE == didTimeout( dialyzerReprimeStateTimer, DIALYZER_REPRIME_PURGE_LINES_DURATION_MS ) ) ) + { + signalDialInPumpHardStop(); + signalDialOutPumpHardStop(); + // Delay 1 more second before resuming treatment + if ( TRUE == didTimeout( dialyzerReprimeStateTimer, DIALYZER_REPRIME_PURGE_LINES_DURATION_MS + MS_PER_SECOND ) ) + { + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + // Reset the timer for reprime interval and the reprime in progress flag. + dialyzerReprimeIntervalTimerCtr = 0; + dialyzerReprimeInProgress = FALSE; + if ( getTreatmentTimeRemainingSecs() <= DIALYZER_REPRIME_BEFORE_TREATEMENT_END_INTERVAL_SEC) + { + dialyzerReprimeFinalReprimeFinished = TRUE; + } + // Dialysis back to UF state + *dialysisState = DIALYSIS_UF_STATE; + // This handles resuming UF if it was paused by re-prime + resetSalineBolus(); + // Resume dialysis + transitionToDialysis(); + result = DIALYZER_REPRIME_STATE_DIALYSATE_PUMPS_OFF; + } + } + + return result; +} +#endif + +/*********************************************************************//** + * @brief * The publishSalineBolusData function handles the max saline delivered * state of the saline bolus state machine. This is a terminal state. * @details Inputs: none Index: firmware/App/Modes/Dialysis.h =================================================================== diff -u -r99ec83eff4683ad69a249f935d74cb9226984d21 -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision 99ec83eff4683ad69a249f935d74cb9226984d21) +++ firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -65,6 +65,10 @@ DIALYSIS_STATE_T getDialysisState( void ); UF_STATE_T getUltrafiltrationState( void ); SALINE_BOLUS_STATE_T getSalineBolusState( void ); +#ifdef DIALYZER_REPRIME_ENABLED +DIALYZER_REPRIME_STATE_T getDialyzerRePrimeState( void ); +#endif + F32 getUltrafiltrationVolumeCollected( void ); F32 getUltrafiltrationReferenceVolume( void ); F32 getTotalSalineBolusVolumeDelivered( void ); Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r9d924ec76ce770eb2a94088bfe37bfb0e30981a8 -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 9d924ec76ce770eb2a94088bfe37bfb0e30981a8) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -740,11 +740,19 @@ 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 ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) + if ( dialysisState != DIALYSIS_SALINE_BOLUS_STATE ) { +#ifdef DIALYZER_REPRIME_ENABLED + if ( dialysisState != DIALYSIS_DIALYZER_REPRIME_STATE ) + { +#endif treatmentTimeMS += msSinceLast; +#ifdef DIALYZER_REPRIME_ENABLED + } +#endif } lastTreatmentTimeStamp = newTime; @@ -1423,6 +1431,11 @@ payload.txEndState = getCurrentTreatmentEndState(); payload.heparinState = getHeparinState(); payload.dialysisState = getDialysisState(); +#ifdef DIALYZER_REPRIME_ENABLED + payload.dlzReprimeState = getDialyzerRePrimeState(); +#else + payload.dlzReprimeState = 0; +#endif broadcastData( MSG_ID_TREATMENT_STATE_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&payload, sizeof( TREATMENT_STATE_DATA_T ) ); treatmentStateBroadcastTimerCtr = 0; Index: firmware/App/Modes/ModeTreatmentParams.c =================================================================== diff -u -r99ec83eff4683ad69a249f935d74cb9226984d21 -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 99ec83eff4683ad69a249f935d74cb9226984d21) +++ firmware/App/Modes/ModeTreatmentParams.c (.../ModeTreatmentParams.c) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -69,8 +69,8 @@ { CRITICAL_DATA_TYPE_U32, {.uInt=50}, {.uInt=150}, {.uInt=75} }, // TREATMENT_PARAM_RINSEBACK_FLOW_RATE { CRITICAL_DATA_TYPE_S32, {.sInt=-300}, {.sInt=70}, {.sInt=-300} }, // TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT { CRITICAL_DATA_TYPE_S32, {.sInt=-270}, {.sInt=100}, {.sInt=100} }, // TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT - { CRITICAL_DATA_TYPE_S32, {.sInt=20}, {.sInt=370}, {.sInt=20} }, // TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT - { CRITICAL_DATA_TYPE_S32, {.sInt=50}, {.sInt=400}, {.sInt=400} }, // TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=20}, {.sInt=270}, {.sInt=20} }, // TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT + { CRITICAL_DATA_TYPE_S32, {.sInt=50}, {.sInt=300}, {.sInt=300} }, // TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT { 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=35.0}, {.sFlt=37.0}, {.sFlt=37.0} }, // TREATMENT_PARAM_DIALYSATE_TEMPERATURE Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 0a61f7fa5ff6945ebc2e507d8ecb71a652c38eaa) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -182,6 +182,7 @@ SW_FAULT_ID_NVDATA_RTC_RAM_OPS_FAILURE, SW_FAULT_ID_HD_INVALID_ALARM_AUDIO_STATE, SW_FAULT_ID_INVALID_ALARM_ID_REFERENCED, + SW_FAULT_ID_DIALYSIS_INVALID_DIALYZER_REPRIME_STATE, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -rf93726ae564239c163661876813259174bca1767 -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision f93726ae564239c163661876813259174bca1767) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -7,8 +7,8 @@ * * @file Reservoirs.c * -* @author (last) Dara Navaei -* @date (last) 07-Mar-2023 +* @author (last) Sean Nash +* @date (last) 16-Mar-2023 * * @author (original) Dara Navaei * @date (original) 21-Nov-2021 @@ -75,7 +75,9 @@ static F32 dilutionLevelPct; ///< Reservoir dilution level. static DG_OP_MODE_T dgOpMode; ///< DG operation mode. static U32 dgSubMode; ///< DG operation submode. -static U32 timeReservoirInUse; ///< Reservoir time in use in milliseconds. +static U32 timeReservoirInUse; ///< Reservoir time in use in general task intervals. +static U32 timeReservoirInUF; ///< Reservoir time in ultrafiltration (in ms). +static U32 lastTimeReservoirInUF; ///< Reservoir time in ultrafiltration from prior reservoir (in ms). static F32 volSpentUFML; ///< Ultrafiltration volume in milliliters. static DG_RESERVOIR_ID_T activeReservoir; ///< Active reservoir. static F32 recirculationLevelPct; ///< Recirculation level in percent. @@ -129,6 +131,8 @@ dgOpMode = DG_MODE_INIT; dgSubMode = 0; timeReservoirInUse = 0; + timeReservoirInUF = 0; + lastTimeReservoirInUF = 0; volSpentUFML = 0.0F; activeReservoir = DG_RESERVOIR_1; recirculationLevelPct = 0.0F; @@ -244,6 +248,32 @@ calculateActiveReservoirCycleTime(); } +/*********************************************************************//** + * @brief + * The getLastReservoirUFTimeInMs function returns the reservoir ultrafiltration + * time (in ms) for the last reservoir used in treatment. + * @details Inputs: none + * @details Outputs: none + * @return lastTimeReservoirInUF + *************************************************************************/ +U32 getLastReservoirUFTimeInMs( void ) +{ + return lastTimeReservoirInUF; +} + +/*********************************************************************//** + * @brief + * The updateReservoirUFTime function updates the reservoir ultrafiltration + * time (in ms) for currently active reservoir used in treatment. + * @details Inputs: timeReservoirInUF + * @details Outputs: timeReservoirInUF + * @return lastTimeReservoirInUF + *************************************************************************/ +void updateReservoirUFTime( void ) +{ + timeReservoirInUF += TASK_GENERAL_INTERVAL; +} + // ********** private functions ********** /*********************************************************************//** @@ -661,6 +691,8 @@ setFinalReservoirVolume(); // Switched the active reservoir so reset the reservoir in use timer + lastTimeReservoirInUF = timeReservoirInUF; + timeReservoirInUF = 0; timeReservoirInUse = 0; // Reset to start state to restart drain, fill, switch process. Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rafe0d7c5e1ada7872125e04d62fe5602427ffa63 -r709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision afe0d7c5e1ada7872125e04d62fe5602427ffa63) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 709def41bcde8e2e59d83c5e9c5a06ab0ee74ec8) @@ -7068,7 +7068,7 @@ msg.hdr.payloadLen = sizeof(CURRENT_TREATMENT_PARAMS_DATA_PAYLOAD_T); memcpy(payloadPtr, ¤t_params, sizeof(CURRENT_TREATMENT_PARAMS_DATA_PAYLOAD_T)); - return serializeMessage(msg, COMM_BUFFER_OUT_CAN_PC, ACK_REQUIRED ); + return serializeMessage(msg, COMM_BUFFER_OUT_CAN_PC, ACK_NOT_REQUIRED ); } /*********************************************************************//**