Index: firmware/App/Controllers/PresOccl.c =================================================================== diff -u -rf1e2d5b035e2ba41a5e4f9d8861a265aaef02622 -r34e43586567b8b43f713d28f1ce36fe781710649 --- firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision f1e2d5b035e2ba41a5e4f9d8861a265aaef02622) +++ firmware/App/Controllers/PresOccl.c (.../PresOccl.c) (revision 34e43586567b8b43f713d28f1ce36fe781710649) @@ -17,8 +17,10 @@ #include "PresOccl.h" #include "AlarmMgmt.h" -#include "FPGA.h" -#include "OperationModes.h" +#include "FPGA.h" +#include "ModeTreatmentParams.h" +#include "OperationModes.h" +#include "PersistentAlarm.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" @@ -52,7 +54,9 @@ #define MAX_TIME_BETWEEN_VENOUS_READINGS ( 500 / TASK_GENERAL_INTERVAL ) ///< Maximum time without fresh inline venous pressure reading. #define OCCLUSION_THRESHOLD 25000 ///< Threshold above which an occlusion is detected. -#define CARTRIDGE_LOADED_THRESHOLD 5000 ///< Threshold above which a cartridge is considered loaded. +#define CARTRIDGE_LOADED_THRESHOLD 5000 ///< Threshold above which a cartridge is considered loaded. + +#define PRES_ALARM_PERSISTENCE ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Alarm persistence period for pressure alarms. /// Defined states for the pressure and occlusion monitor state machine. typedef enum PresOccl_States @@ -93,7 +97,11 @@ // ********** private function prototypes ********** static PRESSURE_STATE_T handlePresOcclInitState( void ); -static PRESSURE_STATE_T handlePresOcclContReadState( void ); +static PRESSURE_STATE_T handlePresOcclContReadState( void ); +static void convertInlinePressures( void ); +static void convertOcclusionPressures( void ); +static void checkArterialPressureInRange( void ); +static void checkVenousPressureInRange( void ); static void checkOcclusions( void ); static void publishPresOcclData( void ); static DATA_GET_PROTOTYPE( U32, getPublishPresOcclDataInterval ); @@ -107,9 +115,42 @@ *************************************************************************/ void initPresOccl( void ) { - // TODO - anything to initialize? + // initialize persistent pressure alarms + initPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_LOW, ALARM_ID_ARTERIAL_PRESSURE_LOW, + isAlarmRecoverable( ALARM_ID_ARTERIAL_PRESSURE_LOW ), PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_HIGH, ALARM_ID_ARTERIAL_PRESSURE_HIGH, + isAlarmRecoverable( ALARM_ID_ARTERIAL_PRESSURE_HIGH ), PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_LOW, ALARM_ID_VENOUS_PRESSURE_LOW, + isAlarmRecoverable( ALARM_ID_VENOUS_PRESSURE_LOW ), PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); + initPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_HIGH, ALARM_ID_VENOUS_PRESSURE_HIGH, + isAlarmRecoverable( ALARM_ID_VENOUS_PRESSURE_HIGH ), PRES_ALARM_PERSISTENCE, PRES_ALARM_PERSISTENCE ); } +/*********************************************************************//** + * @brief + * The isCartridgeLoaded function determines whether a cartridge has been + * properly loaded by looking at the 3 occlusion pressure sensors. + * @details Inputs: occlusion pressures for the pumps + * @details Outputs: none + * @return TRUE if all 3 occlusion sensors read above loaded threshold, FALSE if not. + *************************************************************************/ +BOOL isCartridgeLoaded( void ) +{ + BOOL result = FALSE; + U32 bpOccl = getMeasuredBloodPumpOcclusion(); + U32 diOccl = getMeasuredDialInPumpOcclusion(); + U32 doOccl = getMeasuredDialOutPumpOcclusion(); + + if ( ( bpOccl >= CARTRIDGE_LOADED_THRESHOLD ) && + ( diOccl >= CARTRIDGE_LOADED_THRESHOLD ) && + ( doOccl >= CARTRIDGE_LOADED_THRESHOLD ) ) + { + result = TRUE; + } + + return result; +} + /*********************************************************************//** * @brief * The execPresOccl function executes the pressure and occlusion monitor. @@ -164,29 +205,56 @@ *************************************************************************/ static PRESSURE_STATE_T handlePresOcclContReadState( void ) { - PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; - + PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; + + // read latest in-line (arterial and venous) pressures + convertInlinePressures(); + + // read latest occlusion pressures + convertOcclusionPressures(); + + // check in-line pressures are in range + checkArterialPressureInRange(); + checkVenousPressureInRange(); + + // check for occlusions + checkOcclusions(); + + return result; +} + +/*********************************************************************//** + * @brief + * The convertInlinePressures function reads inline pressure sensor readings + * and converts to mmHg. Sensor status/alarm is checked. + * @details Inputs: FPGA + * @details Outputs: arterialPressure, venousPressure + * @return none + *************************************************************************/ +static void convertInlinePressures( void ) +{ U32 fpgaArtPres = getFPGAArterialPressure(); S32 artPres = (S32)( fpgaArtPres & MASK_OFF_U32_MSB ) - 0x800000; // subtract 2^23 from low 24 bits to get signed reading U08 artPresAlarm = (U08)( fpgaArtPres >> 24 ); // high byte is alarm code for arterial pressure - U16 fpgaVenPres = getFPGAVenousPressure(); + U16 fpgaVenPres = getFPGAVenousPressure(); U16 venPres = fpgaVenPres & 0x3FFF; // 14-bit data - U08 venPresStatus = (U08)( fpgaVenPres >> 14 ); // high 2 bits is status code for venous pressure - F32 venPresPSI = ( (F32)(venPres - VENOUS_PRESSURE_OFFSET) * (VENOUS_PRESSURE_MAX - VENOUS_PRESSURE_MIN) / (F32)VENOUS_PRESSURE_SCALE ) + VENOUS_PRESSURE_MIN; - U16 bldOccl = getFPGABloodPumpOcclusion(); - U16 dliOccl = getFPGADialInPumpOcclusion(); - U16 dloOccl = getFPGADialOutPumpOcclusion(); + U08 venPresStatus = (U08)( fpgaVenPres >> 14 ); // high 2 bits is status code for venous pressure + F32 venPresPSI; // TODO - any filtering required??? - // convert arterial pressure to mmHg + // convert arterial pressure to mmHg arterialPressure.data = ARTERIAL_PRESSURE_V_PER_BIT * ( (F32)(artPres) / ( ARTERIAL_PRESSURE_SENSITIVITY * ARTERIAL_PRESSURE_V_BIAS ) ); - // convert venous pressure from PSI to mmHg + + // convert venous pressure to PSI + venPresPSI = ( (F32)(venPres - VENOUS_PRESSURE_OFFSET) * (VENOUS_PRESSURE_MAX - VENOUS_PRESSURE_MIN) / (F32)VENOUS_PRESSURE_SCALE ) + VENOUS_PRESSURE_MIN; + // convert venous pressure from PSI to mmHg if sensor status is normal if ( VENOUS_PRESSURE_NORMAL_OP == venPresStatus ) - { + { venousPressure.data = venPresPSI * PSI_TO_MMHG; staleVenousPressureCtr = 0; } + // if venous pressure sensor status is not normal or reading is stale for too long, fault else { if ( ++staleVenousPressureCtr > MAX_TIME_BETWEEN_VENOUS_READINGS ) @@ -197,72 +265,127 @@ } } - // occlusion sensor values have no unit - take as is - bloodPumpOcclusion.data = (U32)bldOccl; - dialInPumpOcclusion.data = (U32)dliOccl; - dialOutPumpOcclusion.data = (U32)dloOccl; - - // check for occlusions - checkOcclusions(); - - // check for arterial pressure alarm + // check for arterial pressure sensor alarm if ( artPresAlarm != 0 ) { #ifndef DISABLE_PRESSURE_CHECKS SET_ALARM_WITH_1_U32_DATA( ALARM_ID_ARTERIAL_PRESSURE_SENSOR_FAULT, (U32)artPresAlarm ) #endif } - // check for venous pressure alarm + // check for venous pressure sensor alarm if ( ( VENOUS_PRESSURE_DIAG_CONDITION == venPresStatus ) || ( VENOUS_PRESSURE_CMD_MODE == venPresStatus ) ) { #ifndef DISABLE_PRESSURE_CHECKS SET_ALARM_WITH_1_U32_DATA( ALARM_ID_VENOUS_PRESSURE_SENSOR_FAULT, (U32)venPresStatus ) #endif } +} - return result; -} +/*********************************************************************//** + * @brief + * The convertOcclusionPressures function reads occlusion sensor readings. + * @details Inputs: FPGA + * @details Outputs: bloodPumpOcclusion, dialInPumpOcclusion, dialOutPumpOcclusion + * @return none + *************************************************************************/ +static void convertOcclusionPressures( void ) +{ + // TODO - any filtering required??? + // occlusion sensor values have no unit - take as is + bloodPumpOcclusion.data = (U32)getFPGABloodPumpOcclusion(); + dialInPumpOcclusion.data = (U32)getFPGADialInPumpOcclusion(); + dialOutPumpOcclusion.data = (U32)getFPGADialOutPumpOcclusion(); +} + /*********************************************************************//** * @brief - * The isCartridgeLoaded function determines whether a cartridge has been - * properly loaded by looking at the 3 occlusion pressure sensors. - * @details Inputs: occlusion pressures for the pumps - * @details Outputs: none - * @return TRUE if all 3 occlusion sensors read above loaded threshold, FALSE if not. + * The checkArterialPressureInRange function checks that artieral pressure is + * within the set alarm limits. Alarm is triggered if not. + * @details Inputs: arterialPressure + * @details Outputs: Alarm if out of range + * @return none *************************************************************************/ -BOOL isCartridgeLoaded( void ) +static void checkArterialPressureInRange( void ) { - BOOL result = FALSE; - U32 bpOccl = getMeasuredBloodPumpOcclusion(); - U32 diOccl = getMeasuredDialInPumpOcclusion(); - U32 doOccl = getMeasuredDialOutPumpOcclusion(); + F32 artLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_LOW_LIMIT ); + F32 artHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_ART_PRESSURE_HIGH_LIMIT ); + F32 artPres = getMeasuredArterialPressure(); - if ( ( bpOccl >= CARTRIDGE_LOADED_THRESHOLD ) && - ( diOccl >= CARTRIDGE_LOADED_THRESHOLD ) && - ( doOccl >= CARTRIDGE_LOADED_THRESHOLD ) ) + if ( artPres < artLowLimit ) // TODO - add persistence (code & requirement) { - result = TRUE; +#ifndef DISABLE_PRESSURE_CHECKS + checkPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_LOW, TRUE, artPres, artLowLimit ); +#endif } + else + { + checkPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_LOW, FALSE, artPres, artLowLimit ); + } + if ( artPres > artHighLimit ) + { +#ifndef DISABLE_PRESSURE_CHECKS + checkPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_HIGH, TRUE, artPres, artHighLimit ); +#endif + } + else + { + checkPersistentAlarm( PERSISTENT_ALARM_ARTERIAL_PRESSURE_HIGH, FALSE, artPres, artHighLimit ); + } +} - return result; +/*********************************************************************//** + * @brief + * The checkVenousPressureInRange function checks that venous pressure is + * within the set alarm limits. Alarm is triggered if not. + * @details Inputs: venousPressure + * @details Outputs: Alarm if out of range + * @return none + *************************************************************************/ +static void checkVenousPressureInRange( void ) +{ + F32 venLowLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_LOW_LIMIT ); + F32 venHighLimit = (F32)getTreatmentParameterS32( TREATMENT_PARAM_VEN_PRESSURE_HIGH_LIMIT ); + F32 venPres = getMeasuredVenousPressure(); + + if ( venPres < venLowLimit ) // TODO - add persistence (code & requirement) + { +#ifndef DISABLE_PRESSURE_CHECKS + checkPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_LOW, TRUE, venPres, venLowLimit ); +#endif + } + else + { + checkPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_LOW, FALSE, venPres, venLowLimit ); + } + if ( venPres > venHighLimit ) + { +#ifndef DISABLE_PRESSURE_CHECKS + checkPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_HIGH, TRUE, venPres, venHighLimit ); +#endif + } + else + { + checkPersistentAlarm( PERSISTENT_ALARM_VENOUS_PRESSURE_HIGH, FALSE, venPres, venHighLimit ); + } } - + /*********************************************************************//** * @brief * The checkPressureLimits function gets the pressure/occlusion data * publication interval. * @details Inputs: occlusion pressures for the pumps - * @details Outputs: + * @details Outputs: Alarm if occlusion limit exceeded * @return none *************************************************************************/ static void checkOcclusions( void ) { U32 bpOccl = getMeasuredBloodPumpOcclusion(); U32 diOccl = getMeasuredDialInPumpOcclusion(); U32 doOccl = getMeasuredDialOutPumpOcclusion(); - + + // TODO - add persistence #ifndef DISABLE_PRESSURE_CHECKS if ( bpOccl > OCCLUSION_THRESHOLD ) {