Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r13b6bb9e3bbd6b07d5b51d46552a9f282b4f97e4 -rf9570a9717805d0759622da836a33ee04f3fa40f --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 13b6bb9e3bbd6b07d5b51d46552a9f282b4f97e4) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision f9570a9717805d0759622da836a33ee04f3fa40f) @@ -7,8 +7,8 @@ * * @file PresOccl.c * -* @author (last) Dara Navaei -* @date (last) 13-Jul-2022 +* @author (last) Michael Garthwaite +* @date (last) 26-Aug-2022 * * @author (original) Sean * @date (original) 15-Jan-2020 @@ -22,7 +22,8 @@ #include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" -#include "SystemCommMessages.h" +#include "SystemCommMessages.h" +#include "SelfTests.h" #include "TaskGeneral.h" #include "Temperatures.h" #include "Timers.h" @@ -660,7 +661,7 @@ static void checkOcclusions( void ) { U32 bpOccl = getMeasuredBloodPumpOcclusion(); - BOOL outOfRange = ( bpOccl < MIN_OCCLUSION_COUNTS || bpOccl > MAX_OCCLUSION_COUNTS ? TRUE : FALSE ); + BOOL outOfRange = ( bpOccl < MIN_OCCLUSION_COUNTS || bpOccl > MAX_OCCLUSION_COUNTS ? TRUE : FALSE ); #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_PRESSURE_CHECKS ) != SW_CONFIG_ENABLE_VALUE ) @@ -681,11 +682,34 @@ // Check for BP occlusion if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) { - signalBloodPumpHardStop(); // Stop pump immediately - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) + if ( getPreTreatmentSubState() > HD_PRE_TREATMENT_CART_INSTALL_STATE && getDrySelfTestsState() > DRY_SELF_TESTS_START_STATE ) + { + // Check for occlusion + if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) + { + signalBloodPumpHardStop(); // Stop pump immediately + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) + } + } } - else + + // Check for occlusion in Treatment modes where pumps are moving + else if ( MODE_TREA == getCurrentOperationMode() ) { + if ( TREATMENT_STOP_STATE != getTreatmentState() ) + { + // Check for occlusion + if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) + { + signalBloodPumpHardStop(); // Stop pump immediately + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) + } + } + } + + // Clear alarm regardless of op mode once conditions are met. + if ( bpOccl <= ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) + { clearAlarmCondition( ALARM_ID_OCCLUSION_BLOOD_PUMP ); } Index: firmware/App/HDCommon.h =================================================================== diff -u -rc1fb1a78a5e2373c5813a70f6a66fa8ca8945ff1 -rf9570a9717805d0759622da836a33ee04f3fa40f --- firmware/App/HDCommon.h (.../HDCommon.h) (revision c1fb1a78a5e2373c5813a70f6a66fa8ca8945ff1) +++ firmware/App/HDCommon.h (.../HDCommon.h) (revision f9570a9717805d0759622da836a33ee04f3fa40f) @@ -38,13 +38,12 @@ // #define RUN_WITHOUT_DG 1 // Run HD w/o DG // #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 DISABLE_BATT_COMM 1 // Disable battery communication + #define DISABLE_BATT_COMM 1 // Disable battery communication // TODO soft switch // #define READ_FPGA_ASYNC_DATA 1 // Test build reads non-priority register page every other time // #define DISABLE_FPGA_COUNTER_CHECKS 1 // Disable alarms associated with FPGA read/error counters // #define EMC_TEST_BUILD 1 // EMC test build - HD/DG run separately but connected, HD pumps toggle on/off w/ stop button #define DISABLE_WD_AND_SFTY_POST_TESTS 1 // Disable watchdog and safety shutdown POST tests - #define DISABLE_UI_POST_TEST 1 // Disable the UI POST -// #define PBA_ESTIMATION 1 // Estimate arterial pressure rather than look at PBA sensor // Part of DVT build switch +// #define DISABLE_UI_POST_TEST 1 // Disable the UI POST // TODO stays as a build switch until the calibration structure is updated with the build #define SKIP_CAL_CHECK 1 // Implement software configuration Index: firmware/App/Modes/Prime.c =================================================================== diff -u -r173e4fbf9bd750bccb2e758eb1c7ef36ed8db5a0 -rf9570a9717805d0759622da836a33ee04f3fa40f --- firmware/App/Modes/Prime.c (.../Prime.c) (revision 173e4fbf9bd750bccb2e758eb1c7ef36ed8db5a0) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision f9570a9717805d0759622da836a33ee04f3fa40f) @@ -7,8 +7,8 @@ * * @file Prime.c * -* @author (last) Bill Bracken -* @date (last) 24-Aug-2022 +* @author (last) Michael Garthwaite +* @date (last) 26-Aug-2022 * * @author (original) Quang Nguyen * @date (original) 08-Dec-2020 @@ -52,7 +52,7 @@ #define DIALYZER_VOLUME_SCALE_FACTOR 0.5F ///< Half of the dialyzer total volume. #define NO_AIR_DETECTED_COUNT ( 20 * MS_PER_SECOND ) ///< No air detected time period count. -#define PURGE_AIR_TIME_OUT_COUNT ( 60 * MS_PER_SECOND ) ///< Time period count for purge air time out. +#define PURGE_AIR_TIME_OUT_COUNT ( 120 * MS_PER_SECOND ) ///< Time period count for purge air time out. #define LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ( 1 * MS_PER_SECOND ) ///< Time load cell reading steady state detection sampling time in seconds. #define PRIME_DIALYSATE_BYPASS_TIME_LIMIT ( 15 * MS_PER_SECOND ) ///< Time limit for priming dialysate bypass circuit. #define STEADY_VOLUME_COUNT_SEC ( 10000 / LOAD_CELL_STEADY_VOLUME_SAMPLING_TIME ) ///< Counter must be greater than 10 seconds before steady volume is true. Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r7c73db9d00db93c5374fc0fbbe61117e589e95a2 -rf9570a9717805d0759622da836a33ee04f3fa40f --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 7c73db9d00db93c5374fc0fbbe61117e589e95a2) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision f9570a9717805d0759622da836a33ee04f3fa40f) @@ -40,6 +40,8 @@ #define DIA_FLOW_TO_FILL_FLOW_FIRST_ORDER_COEFF 7.5F ///< Dialysate flow rate to fill flow rate first order coefficient. #define DIA_FLOW_TO_FILL_FLOW_CONSTANT 2.0F ///< Dialysate flow rate to fill flow rate constant. +#define MAX_RESERVOIR_VOL_BEFORE_SWITCH_ML 1900.0F ///< Maximum reservoir volume before we switch reservoirs (in mL). + // ********** private data ********** /// States of the treatment reservoir management state machine. @@ -169,10 +171,8 @@ checkReservoirMaxVolume(); calculateActiveReservoirCycleTime(); - // TODO do we need this? Should we not call the reservoir management exec function in saline bolus? - - // Calculate volume used from active reservoir - do not accumulate if saline bolus is in progress - if ( getSalineBolusState() != SALINE_BOLUS_STATE_IN_PROGRESS ) + // Calculate volume used from active reservoir - do not accumulate if not performing dialysis or saline bolus is in progress + if ( ( TREATMENT_DIALYSIS_STATE == getTreatmentState() ) && ( getDialysisState() != DIALYSIS_SALINE_BOLUS_STATE ) ) { volSpentML += ( flowRateMLPerMS * msSinceLastVolumeCalc ); @@ -523,9 +523,7 @@ timeWaitToFillMS = timeDepleteMS - ( getFillTimeMS() + RESERVOIR_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS ); // If the wait time has elapsed, trigger a fill command - // TODO uncomment - //if ( timeWaitToFillMS <= 0 ) - // TODO uncomment + if ( timeWaitToFillMS <= 0 ) { cmdStartDGFill( FILL_RESERVOIR_TO_VOLUME_ML, targetFillFlowRateLPM ); } @@ -597,10 +595,16 @@ static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtWaitForFillSettleState( void ) { TREATMENT_RESERVOIR_MGMT_STATE_T state = TREATMENT_RESERVOIR_MGMT_WAIT_FOR_FILL_SETTLE_STATE; + DG_RESERVOIR_ID_T active = getDGActiveReservoir(); + // Get the ultra-filtration volume milliliters + // Get the dilution level in percent = spent ultra-filtration volume / target fill volume in milliliters + volSpentUFML = getReservoirUltrafiltrationVol( activeReservoir ); + dilutionLevelPct = volSpentUFML / (F32)FILL_RESERVOIR_TO_VOLUME_ML; + // Wait for the reservoir to settle and then send the commands to switch the active reservoir TODO - restore #define below if ( ( TRUE == didTimeout( reservoirSwitchStartTimeMS, 15000 /*RESERVOIR_SETTLE_TIME_MS*/ ) ) && - ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) ) ) + ( ( dilutionLevelPct >= MAX_RESERVOIR_DILUTION ) || ( volSpentML >= (F32)FILL_RESERVOIR_TO_VOLUME_ML ) || ( getReservoirWeight( active ) > MAX_RESERVOIR_VOL_BEFORE_SWITCH_ML ) ) ) { DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir();