Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -r1240b612f790f931825aba86ec37f37eccce9336 -r844f98879b7425c207b58562e623ab960adbc357 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 1240b612f790f931825aba86ec37f37eccce9336) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 844f98879b7425c207b58562e623ab960adbc357) @@ -22,7 +22,8 @@ #include "OperationModes.h" #include "PersistentAlarm.h" #include "SystemCommMessages.h" -#include "TaskGeneral.h" +#include "TaskGeneral.h" +#include "Temperatures.h" #include "Timers.h" /** @@ -41,34 +42,39 @@ #define VENOUS_PRESSURE_OFFSET ( 1638 ) ///< Offset for 14-bit venous pressure sensor reading. #define VENOUS_PRESSURE_SCALE ( 14745 - VENOUS_PRESSURE_OFFSET ) ///< Scale for venous pressure sensor. -#define VENOUS_PRESSURE_MIN ( -30.0 ) ///< Minimum of scale for venous pressure sensor reading (in PSI). -#define VENOUS_PRESSURE_MAX ( 30.0 ) ///< Maximum of scale for venous pressure sensor reading (in PSI). +#define VENOUS_PRESSURE_MIN_PSI ( -30.0 ) ///< Minimum of scale for venous pressure sensor reading (in PSI). +#define VENOUS_PRESSURE_MAX_PSI ( 30.0 ) ///< Maximum of scale for venous pressure sensor reading (in PSI). #define ARTERIAL_PRESSURE_SELF_TEST_MIN ( -300.0 ) ///< Minimum self-test value for arterial pressure sensor reading (in mmHg). #define ARTERIAL_PRESSURE_SELF_TEST_MAX ( 100.0 ) ///< Maximum self-test value for arterial pressure sensor reading (in mmHg). +#define ARTERIAL_PRESSURE_MAX_MMHG ( 2000.0 ) ///< Maximum arterial pressure reading (in mmHg) for range check. +#define ARTERIAL_PRESSURE_MIN_MMHG ( -1500.0 ) ///< Minimum arterial pressure reading (in mmHg) for range check. #define VENOUS_PRESSURE_SELF_TEST_MIN ( -100.0 ) ///< Minimum self-test value for venous pressure sensor reading (in mmHg). #define VENOUS_PRESSURE_SELF_TEST_MAX ( 600.0 ) ///< Maximum self-test value for venous pressure sensor reading (in mmHg). +#define VENOUS_PRESSURE_MAX_MMHG ( 2000.0 ) ///< Maximum venous pressure reading (in mmHg) for range check. +#define VENOUS_PRESSURE_MIN_MMHG ( -1500.0 ) ///< Minimum venous pressure reading (in mmHg) for range check. -#define VENOUS_PRESSURE_MIN_TEMP ( 0.0 ) ///< Minimum venous pressure sensor temperature. TODO - get from Systems -#define VENOUS_PRESSURE_MAX_TEMP ( 50.0 ) ///< Maximum venous pressure sensor temperature. TODO - get from Systems +#define VENOUS_PRESSURE_MIN_TEMP ( 0.0 ) ///< Minimum venous pressure sensor temperature. +#define VENOUS_PRESSURE_MAX_TEMP ( 80.0 ) ///< Maximum venous pressure sensor temperature. +#define MIN_OCCLUSION_COUNTS ( 2000 ) ///< Minimum occlusion sensor reading for range check. + #define PSI_TO_MMHG ( 51.7149 ) ///< Conversion factor for converting PSI to mmHg. #define VENOUS_PRESSURE_NORMAL_OP 0 ///< Venous pressure status bits indicate normal operation. #define VENOUS_PRESSURE_CMD_MODE 1 ///< Venous pressure status bits indicate sensor in command mode. #define VENOUS_PRESSURE_STALE_DATA 2 ///< Venous pressure status bits indicate data is stale (no new data since last fpga read). #define VENOUS_PRESSURE_DIAG_CONDITION 3 ///< Venous pressure status bits diagnostic condition (alarm). -#define OCCLUSION_THRESHOLD 25000 ///< Threshold above which an occlusion is detected. +#define OCCLUSION_THRESHOLD_OFFSET 10000 ///< Threshold offset. Combined with initial reading after cartridge install, a threshold is derived above which an occlusion is detected. +#define OCCLUSION_CLEAR_THRESHOLD_OFFSET 6000 ///< Threshold offset. Combined with initial reading after cartridge install, a threshold is derived below which an occlusion is cleared. #define CARTRIDGE_LOADED_THRESHOLD 5000 ///< Threshold above which a cartridge is considered loaded. +/// Occlusion sensors maximum pressure reading limit when cartridge is considered loaded. +#define OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX 20000 #define EMPTY_SALINE_BAG_THRESHOLD_MMHG -300.0 ///< Threshold below which the saline bag is considered empty (in mmHg). TODO - get real threshold from Systems static const U32 EMPTY_SALINE_BAG_PERSISTENCE = ( 250 / TASK_GENERAL_INTERVAL ); ///< Time that saline bag looks empty before saying it is empty. -/// Occlusion sensors minimum pressure reading limit when no cartridge is loaded. -#define OCCLUSION_NO_CARTRIDGE_PRESSURE_READING_MIN 2000 -/// Occlusion sensors maximum pressure reading limit when cartridge is considered loaded. -#define OCCLUSION_CARTRIDGE_LOADED_PRESSURE_READING_MAX 20000 #define PRES_ALARM_PERSISTENCE ( 1 * MS_PER_SECOND ) ///< Alarm persistence period for pressure alarms. @@ -100,14 +106,19 @@ static OVERRIDE_F32_T venousPressure = {0.0, 0.0, 0.0, 0 }; ///< Measured venous pressure. static OVERRIDE_U32_T bloodPumpOcclusion = {0, 0, 0, 0 }; ///< Measured blood pump occlusion pressure. static OVERRIDE_U32_T dialInPumpOcclusion = {0, 0, 0, 0 }; ///< Measured dialysate inlet pump occlusion pressure. -static OVERRIDE_U32_T dialOutPumpOcclusion = {0, 0, 0, 0 }; ///< Measured dialysate outlet pump occlusion pressure. - +static OVERRIDE_U32_T dialOutPumpOcclusion = {0, 0, 0, 0 }; ///< Measured dialysate outlet pump occlusion pressure. + +static U32 bloodPumpOcclusionAfterCartridgeInstall; ///< Measured blood pump occlusion reading taken after cartridge install. +static U32 dialInPumpOcclusionAfterCartridgeInstall; ///< Measured dialysate inlet pump occlusion reading taken after cartridge install. +static U32 dialOutPumpOcclusionAfterCartridgeInstall; ///< Measured dialysate outlet pump occlusion reading taken after cartridge install. + static U32 emptySalineBagCtr = 0; ///< Timer counter for empty bag detection. -static U08 lastVenousPressureReadCtr; ///< Previous venous pressure read count. -static U08 lastBPOcclReadCtr; ///< Previous BP occlusion read count. -static U08 lastDPiOcclReadCtr; ///< Previous DPi occlusion read count. -static U08 lastDPoOcclReadCtr; ///< Previous DPo occlusion read count. +static U08 lastArterialPressureReadCtr; ///< Previous arterial pressure sensor read count. +static U08 lastVenousPressureReadCtr; ///< Previous venous pressure sensor read count. +static U08 lastBPOcclReadCtr; ///< Previous BP occlusion sensor read count. +static U08 lastDPiOcclReadCtr; ///< Previous DPi occlusion sensor read count. +static U08 lastDPoOcclReadCtr; ///< Previous DPo occlusion sensor read count. static U08 lastBPErrorCtr; ///< Previous BP error count. static U08 lastDPIErrorCtr; ///< Previous DPi error count. static U08 lastDPOErrorCtr; ///< Previous DPo error count. @@ -121,7 +132,6 @@ static void checkVenousPressureInRange( void ); static void checkOcclusions( void ); static void publishPresOcclData( void ); -static U32 getPublishPresOcclDataInterval( void ); /*********************************************************************//** * @brief @@ -137,6 +147,7 @@ initPersistentAlarm( ALARM_ID_ARTERIAL_PRESSURE_HIGH, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_LOW, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_VENOUS_PRESSURE_HIGH, PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_SENSOR_TEMP_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_BP_OCCLUSION_READ_TIMEOUT_ERROR, 0, PRES_ALARM_PERSISTENCE ); @@ -145,14 +156,24 @@ initPersistentAlarm( ALARM_ID_HD_BP_OCCLUSION_SENSOR_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_DPI_OCCLUSION_SENSOR_ERROR, 0, PRES_ALARM_PERSISTENCE ); initPersistentAlarm( ALARM_ID_HD_DPO_OCCLUSION_SENSOR_ERROR, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_DPI_OCCLUSION_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_DPO_OCCLUSION_OUT_OF_RANGE, 0, PRES_ALARM_PERSISTENCE ); + lastArterialPressureReadCtr = 0; lastVenousPressureReadCtr = 0; lastBPOcclReadCtr = 0; lastDPiOcclReadCtr = 0; lastDPoOcclReadCtr = 0; lastBPErrorCtr = 0; lastDPIErrorCtr = 0; lastDPOErrorCtr = 0; + + bloodPumpOcclusionAfterCartridgeInstall = 0; + dialInPumpOcclusionAfterCartridgeInstall = 0; + dialOutPumpOcclusionAfterCartridgeInstall = 0; } /*********************************************************************//** @@ -225,6 +246,22 @@ return result; } +/*********************************************************************//** + * @brief + * The setOcclusionInstallLevels function sets the occlusion sensor levels + * for an installed cartridge. This function should be called after a new + * cartridge is installed. + * @details Inputs: bloodPumpOcclusion, dialInPumpOcclusion, dialOutPumpOcclusion + * @details Outputs: bloodPumpOcclusionAfterCartridgeInstall, dialInPumpOcclusionAfterCartridgeInstall, dialOutPumpOcclusionAfterCartridgeInstall + * @return none + *************************************************************************/ +void setOcclusionInstallLevels( void ) +{ + bloodPumpOcclusionAfterCartridgeInstall = getMeasuredBloodPumpOcclusion(); + dialInPumpOcclusionAfterCartridgeInstall = getMeasuredDialInPumpOcclusion(); + dialOutPumpOcclusionAfterCartridgeInstall = getMeasuredDialOutPumpOcclusion(); +} + /*********************************************************************//** * @brief * The execPresOccl function executes the pressure and occlusion monitor. @@ -299,15 +336,28 @@ U16 venPres = fpgaVenPres & 0x3FFF; // 14-bit data U08 venPresStatus = (U08)( fpgaVenPres >> 14 ); // High 2 bits is status code for venous pressure F32 venPresPSI; - F32 venTemp = getFPGAVenousPressureTemperature(); + F32 venTemp = getTemperatureValue( TEMPSENSOR_VENOUS_PRESSURE_SENSOR ); U08 venReadCtr = getFPGAVenousPressureReadCounter(); // TODO - any filtering required??? // Convert arterial pressure to mmHg if no fault if ( 0 == artPresAlarm ) { - arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ); + U08 artReadCtr = getFPGAArterialPressureReadCounter(); + U08 artErrorCtr = getFPGAArterialPressureErrorCounter(); + + // Check for stale arterial pressure reading + if ( FALSE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_READ_TIMEOUT_ERROR, ( lastArterialPressureReadCtr == artReadCtr || artErrorCtr > 0 ) ) ) + { + arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ); + } + else + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_READ_TIMEOUT_ERROR, (U32)artErrorCtr ); + } + // Record arterial pressure sensor read counter for next time around + lastArterialPressureReadCtr = artReadCtr; } else { @@ -321,10 +371,10 @@ { activateAlarmNoData( ALARM_ID_HD_VENOUS_PRESSURE_READ_TIMEOUT_ERROR ); } - // Record venous read counter for next time around + // Record venous pressure sensor read counter for next time around lastVenousPressureReadCtr = venReadCtr; // Convert venous pressure to PSI and then mmHg - venPresPSI = ( (F32)(venPres - VENOUS_PRESSURE_OFFSET) * (VENOUS_PRESSURE_MAX - VENOUS_PRESSURE_MIN) / (F32)VENOUS_PRESSURE_SCALE ) + VENOUS_PRESSURE_MIN; + venPresPSI = ( (F32)(venPres - VENOUS_PRESSURE_OFFSET) * (VENOUS_PRESSURE_MAX_PSI - VENOUS_PRESSURE_MIN_PSI) / (F32)VENOUS_PRESSURE_SCALE ) + VENOUS_PRESSURE_MIN_PSI; // Convert venous pressure from PSI to mmHg if sensor status is normal if ( VENOUS_PRESSURE_NORMAL_OP == venPresStatus ) { @@ -362,6 +412,7 @@ U08 dpiErrorCtr = getFPGADialInPumpOcclusionErrorCounter(); U08 dpoErrorCtr = getFPGADialOutPumpOcclusionErrorCounter(); +#ifndef DISABLE_PRESSURE_CHECKS // Check for sensor errors if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_SENSOR_ERROR, ( bpErrorCtr != lastBPErrorCtr ) ) ) { @@ -389,6 +440,7 @@ { activateAlarmNoData( ALARM_ID_HD_DPO_OCCLUSION_READ_TIMEOUT_ERROR ); } +#endif // Record occlusion sensor readings bloodPumpOcclusion.data = (U32)getFPGABloodPumpOcclusion(); @@ -416,13 +468,23 @@ { F32 artPres = getMeasuredArterialPressure(); +#ifndef DISABLE_PRESSURE_CHECKS + // Check arterial pressure is in range + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, + ( artPres > ARTERIAL_PRESSURE_MAX_MMHG || artPres < ARTERIAL_PRESSURE_MIN_MMHG ) ) ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_ARTERIAL_PRESSURE_OUT_OF_RANGE, artPres ); + } +#endif + // Check arterial pressure during treatment mode if ( MODE_TREA == getCurrentOperationMode() ) { F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); #ifndef DISABLE_PRESSURE_CHECKS + // Check arterial pressure is within user set alarm limits if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres < artLowLimit ) ) { SET_ALARM_WITH_2_F32_DATA( ALARM_ID_ARTERIAL_PRESSURE_LOW, artPres, artLowLimit ); @@ -458,6 +520,15 @@ { F32 venPres = getMeasuredVenousPressure(); +#ifndef DISABLE_PRESSURE_CHECKS + // Check arterial pressure is in range + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres > VENOUS_PRESSURE_MAX_MMHG ) || + TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres < VENOUS_PRESSURE_MIN_MMHG ) ) + { + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_VENOUS_PRESSURE_OUT_OF_RANGE, venPres ); + } +#endif + // Check arterial pressure during treatment mode if ( MODE_TREA == getCurrentOperationMode() ) { @@ -500,46 +571,53 @@ { U32 bpOccl = getMeasuredBloodPumpOcclusion(); U32 diOccl = getMeasuredDialInPumpOcclusion(); - U32 doOccl = getMeasuredDialOutPumpOcclusion(); + U32 doOccl = getMeasuredDialOutPumpOcclusion(); -#ifndef DISABLE_PRESSURE_CHECKS - if ( bpOccl > OCCLUSION_THRESHOLD ) - { +#ifndef DISABLE_PRESSURE_CHECKS + // Range check occlusion sensors + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, bpOccl < MIN_OCCLUSION_COUNTS ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_OUT_OF_RANGE, bpOccl ); + } + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPI_OCCLUSION_OUT_OF_RANGE, diOccl < MIN_OCCLUSION_COUNTS ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPI_OCCLUSION_OUT_OF_RANGE, diOccl ); + } + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_DPO_OCCLUSION_OUT_OF_RANGE, doOccl < MIN_OCCLUSION_COUNTS ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DPO_OCCLUSION_OUT_OF_RANGE, doOccl ); + } + + // Check for occlusions + if ( bpOccl > ( OCCLUSION_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) + { + signalBloodPumpHardStop(); // Stop pump immediately SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) - // TODO - stop blood pump immediately, ... + } + else if ( bpOccl < ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + bloodPumpOcclusionAfterCartridgeInstall ) ) + { + clearAlarmCondition( ALARM_ID_OCCLUSION_BLOOD_PUMP ); } - if ( diOccl > OCCLUSION_THRESHOLD ) + if ( diOccl > ( OCCLUSION_THRESHOLD_OFFSET + dialInPumpOcclusionAfterCartridgeInstall ) ) { + signalDialInPumpHardStop(); // Stop pump immediately SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_DIAL_IN_PUMP, diOccl ) - // TODO - stop dialysate inlet pump immediately, ... } - if ( doOccl > OCCLUSION_THRESHOLD ) + else if ( diOccl < ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + dialInPumpOcclusionAfterCartridgeInstall ) ) + { + clearAlarmCondition( ALARM_ID_OCCLUSION_DIAL_IN_PUMP ); + } + if ( doOccl > ( OCCLUSION_THRESHOLD_OFFSET + dialOutPumpOcclusionAfterCartridgeInstall ) ) { + signalDialOutPumpHardStop(); // Stop pump immediately SET_ALARM_WITH_1_U32_DATA( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP, doOccl ) - // TODO - stop dialysate outlet pump immediately, ... - } -#endif -} - -/*********************************************************************//** - * @brief - * The getPublishPresOcclDataInterval function gets the pressure/occlusion data - * publication interval. - * @details Inputs: presOcclDataPublishInterval - * @details Outputs: none - * @return the current pressure/occlusion data publication interval (in task intervals). - *************************************************************************/ -static U32 getPublishPresOcclDataInterval( void ) -{ - U32 result = presOcclDataPublishInterval.data; - - if ( OVERRIDE_KEY == presOcclDataPublishInterval.override ) + } + else if ( doOccl < ( OCCLUSION_CLEAR_THRESHOLD_OFFSET + dialOutPumpOcclusionAfterCartridgeInstall ) ) { - result = presOcclDataPublishInterval.ovData; + clearAlarmCondition( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP ); } - - return result; -} +#endif +} /*********************************************************************//** * @brief @@ -650,7 +728,7 @@ static void publishPresOcclData( void ) { // Publish pressure/occlusion data on interval - if ( ++presOcclDataPublicationTimerCounter >= getPublishPresOcclDataInterval() ) + if ( ++presOcclDataPublicationTimerCounter >= getU32OverrideValue( &presOcclDataPublishInterval ) ) { PRESSURE_OCCLUSION_DATA_T data; @@ -681,17 +759,17 @@ F32 const arterialPressure = getMeasuredArterialPressure(); F32 const venousPressure = getMeasuredVenousPressure(); - if ( ( bpPressure <= OCCLUSION_NO_CARTRIDGE_PRESSURE_READING_MIN ) || ( bpPressure >= OCCLUSION_THRESHOLD ) ) + if ( bpPressure > CARTRIDGE_LOADED_THRESHOLD ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_BP_OCCLUSION_SELF_TEST_FAILURE, bpPressure ); } - if ( ( dialysateInPressure <= OCCLUSION_NO_CARTRIDGE_PRESSURE_READING_MIN ) || ( dialysateInPressure >= OCCLUSION_THRESHOLD ) ) + if ( dialysateInPressure > CARTRIDGE_LOADED_THRESHOLD ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DIP_OCCLUSION_SELF_TEST_FAILURE, dialysateInPressure ); } - if ( ( dialysateOutPressure <= OCCLUSION_NO_CARTRIDGE_PRESSURE_READING_MIN ) || ( dialysateOutPressure >= OCCLUSION_THRESHOLD ) ) + if ( dialysateOutPressure > CARTRIDGE_LOADED_THRESHOLD ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_DOP_OCCLUSION_SELF_TEST_FAILURE, dialysateOutPressure ); }