/**********************************************************************//** * * Copyright (c) 2019-2020 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 PresOccl.c * * @date 15-Jan-2020 * @author S. Nash * * @brief Monitor for pressure and occlusion sensors. * **************************************************************************/ #include "PresOccl.h" #include "AlarmMgmt.h" #include "FPGA.h" #include "OperationModes.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "Timers.h" /** * @addtogroup PressureOcclusion * @{ */ // ********** private definitions ********** /// Default publication interval for pressure and occlusion data. #define PRES_OCCL_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the pressure/occlusion data is published on the CAN bus. /// Defined states for the pressure and occlusion monitor state machine. typedef enum PresOccl_States { PRESSURE_INIT_STATE = 0, ///< Initialization state. PRESSURE_CONTINUOUS_READ_STATE, ///< Continuous read sensors state. NUM_OF_PRESSURE_STATES ///< Number of pressure/occlusion monitor states. } PRESSURE_STATE_T; /// Defined states for the pressure and occlusion self test state machine. typedef enum PresOccl_Self_Test_States { PRESSURE_SELF_TEST_STATE_START = 0, ///< Self test start state. PRESSURE_TEST_STATE_IN_PROGRESS, ///< Self test in progress state. PRESSURE_TEST_STATE_COMPLETE, ///< Self test completed state. NUM_OF_PRESSURE_SELF_TEST_STATES ///< Number of pressure/occlusion self test states. } PRESSURE_SELF_TEST_STATE_T; // ********** private data ********** static PRESSURE_STATE_T presOcclState = PRESSURE_INIT_STATE; ///< current state of pressure monitor state machine. static U32 presOcclDataPublicationTimerCounter = 0; ///< used to schedule pressure data publication to CAN bus. DATA_DECL( U32, PresOcclDataPub, presOcclDataPublishInterval, PRES_OCCL_DATA_PUB_INTERVAL, PRES_OCCL_DATA_PUB_INTERVAL ); ///< interval (in ms) at which to publish pressure/occlusion data to CAN bus. DATA_DECL( F32, ArterialPressure, arterialPressure, 0, 0 ); ///< measured arterial pressure. DATA_DECL( F32, VenousPressure, venousPressure, 0.0, 0.0 ); ///< measured venous pressure. DATA_DECL( F32, BloodPumpOcclusion, bloodPumpOcclusion, 0.0, 0.0 ); ///< measured blood pump occlusion pressure. DATA_DECL( F32, DialInPumpOcclusion, dialInPumpOcclusion, 0.0, 0.0 ); ///< measured dialysate inlet pump occlusion pressure. DATA_DECL( F32, DialOutPumpOcclusion, dialOutPumpOcclusion, 0.0, 0.0 ); ///< measured dialysate outlet pump occlusion pressure. static PRESSURE_SELF_TEST_STATE_T presOcclSelfTestState = PRESSURE_SELF_TEST_STATE_START; ///< current pressure self test state. static U32 bloodPumpSelfTestTimerCount = 0; ///< timer counter for pressure self test. static F32 arterialPressureLowLimitmmHG = 0.0; ///< lower alarm limit for arterial pressure. static F32 arterialPressureHighLimitmmHG = 0.0; ///< upper alarm limit for arterial pressure. static F32 venousPressureLowLimitmmHG = 0.0; ///< lower alarm limit for venous pressure. static F32 venousPressureHighLimitmmHG = 0.0; ///< upper alarm limit for venous pressure. // TODO - set thresholds for occlusions static F32 bloodPumpOcclusionPressureThresholdmmHG = 50.0; ///< pressure threshold for blood pump occlusion. static F32 dialInPumpOcclusionPressureThresholdmmHG = 50.0; ///< pressure threshold for dialysate inlet pump occlusion. static F32 dialOutPumpOcclusionPressureThresholdmmHG = 50.0; ///< pressure threshold for dialysate outlet pump occlusion. // ********** private function prototypes ********** static PRESSURE_STATE_T handlePresOcclInitState( void ); static PRESSURE_STATE_T handlePresOcclContReadState( void ); static void checkOcclusions( void ); static void publishPresOcclData( void ); static DATA_GET_PROTOTYPE( U32, getPublishPresOcclDataInterval ); /*********************************************************************//** * @brief * The initPresOccl function initializes the initPresOccl module. * @details * Inputs : none * Outputs : initPresOccl module initialized. * @return none *************************************************************************/ void initPresOccl( void ) { // TODO - anything to initialize? } /*********************************************************************//** * @brief * The setPressureLimits function sets the lower and upper alarm limits \n * for a given pressure sensor. * @details * Inputs : none * Outputs : pressure limits * @param sensor : pressure sensor we are setting limits for * @param low : lower alarm limit (mmHg) * @param high : upper alarm limit (mmHg) * @return none *************************************************************************/ void setPressureLimits( PRESSURE_SENSORS_T sensor, F32 low, F32 high ) { switch ( sensor ) // TODO - will low/high limits be range checked by caller or should we do it here? what are valid ranges? { case PRESSURE_SENSOR_ARTERIAL: arterialPressureLowLimitmmHG = low; arterialPressureHighLimitmmHG = high; break; case PRESSURE_SENSOR_VENOUS: venousPressureLowLimitmmHG = low; venousPressureHighLimitmmHG = high; break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_PRES_OCCL_INVALID_PRES_SENSOR, sensor ) break; } } /*********************************************************************//** * @brief * The setOcclusionThreshold function sets the occlusion pressure threshold \n * for a given occlusion sensor. * @details * Inputs : none * Outputs : pressure threshold * @param sensor : occlusion sensor we are setting threshold for * @param threshold : pressure threshold above which indicates an occlusion (mmHg) * @return none *************************************************************************/ void setOcclusionThreshold( OCCLUSION_SENSORS_T sensor, F32 threshold ) { switch ( sensor ) // TODO - will threshold be range checked by caller or should we do it here? what is valid range? { case OCCLUSION_SENSOR_BLOOD_PUMP: bloodPumpOcclusionPressureThresholdmmHG = threshold; break; case OCCLUSION_SENSOR_DIAL_IN_PUMP: dialInPumpOcclusionPressureThresholdmmHG = threshold; break; case OCCLUSION_SENSOR_DIAL_OUT_PUMP: dialOutPumpOcclusionPressureThresholdmmHG = threshold; break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_PRES_OCCL_INVALID_OCCL_SENSOR, sensor ) break; } } /*********************************************************************//** * @brief * The execPresOccl function executes the pressure and occlusion monitor. * @details * Inputs : presOcclState * Outputs : presOcclState * @return none *************************************************************************/ void execPresOccl( void ) { // state machine switch ( presOcclState ) { case PRESSURE_INIT_STATE: presOcclState = handlePresOcclInitState(); break; case PRESSURE_CONTINUOUS_READ_STATE: presOcclState = handlePresOcclContReadState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_PRES_OCCL_INVALID_STATE, presOcclState ) break; } // publish pressure/occlusion data on interval publishPresOcclData(); } /*********************************************************************//** * @brief * The handlePresOcclInitState function handles the pres/occl initialize state \n * of the pressure/occlusion monitor state machine. * @details * Inputs : TBD * Outputs : TBD * @return next state *************************************************************************/ static PRESSURE_STATE_T handlePresOcclInitState( void ) { PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; return result; } /*********************************************************************//** * @brief * The handlePresOcclContReadState function handles the continuous read state \n * of the pressure/occlusion monitor state machine. * @details * Inputs : TBD * Outputs : pressure sensor values updated * @return next state *************************************************************************/ static PRESSURE_STATE_T handlePresOcclContReadState( void ) { PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; U16 artPres = getFPGAArterialPressure(); U16 venPres = getFPGAVenousPressure(); U16 bldOccl = getFPGABloodPumpOcclusion(); U16 dliOccl = getFPGADialInPumpOcclusion(); U16 dloOccl = getFPGADialOutPumpOcclusion(); // TODO - convert ADC counts to mmHg for each sensor arterialPressure.data = (F32)artPres; venousPressure.data = (F32)venPres; bloodPumpOcclusion.data = (F32)bldOccl; dialInPumpOcclusion.data = (F32)dliOccl; dialOutPumpOcclusion.data = (F32)dloOccl; // TODO - any filtering required??? // check for occlusions checkOcclusions(); // TODO - any other checks return result; } /*********************************************************************//** * @brief * The checkPressureLimits function gets the pressure/occlusion data \n * publication interval. * @details * Inputs : occlusion pressures for the pumps * Outputs : * @return none *************************************************************************/ static void checkOcclusions( void ) { F32 bpOccl = getMeasuredBloodPumpOcclusion(); F32 diOccl = getMeasuredDialInPumpOcclusion(); F32 doOccl = getMeasuredDialOutPumpOcclusion(); if ( bpOccl > bloodPumpOcclusionPressureThresholdmmHG ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_OCCLUSION_BLOOD_PUMP, bpOccl ) // TODO - stop blood pump immediately, ... } if ( diOccl > dialInPumpOcclusionPressureThresholdmmHG ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_OCCLUSION_DIAL_IN_PUMP, diOccl ) // TODO - stop dialysate inlet pump immediately, ... } if ( doOccl > dialOutPumpOcclusionPressureThresholdmmHG ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_OCCLUSION_DIAL_OUT_PUMP, doOccl ) // TODO - stop dialysate outlet pump immediately, ... } } /*********************************************************************//** * @brief * The getPublishPresOcclDataInterval function gets the pressure/occlusion data \n * publication interval. * @details * Inputs : presOcclDataPublishInterval * Outputs : none * @return the current pressure/occlusion data publication interval (in task intervals). *************************************************************************/ DATA_GET( U32, getPublishPresOcclDataInterval, presOcclDataPublishInterval ) /*********************************************************************//** * @brief * The getMeasuredArterialPressure function gets the current arterial pressure. * @details * Inputs : arterialPressure * Outputs : none * @return the current arterial pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredArterialPressure, arterialPressure ) /*********************************************************************//** * @brief * The getMeasuredVenousPressure function gets the measured venous pressure. * @details * Inputs : venousPressure * Outputs : none * @return the current venous pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredVenousPressure, venousPressure ) /*********************************************************************//** * @brief * The getMeasuredBloodPumpOcclusion function gets the measured blood pump \n * occlusion pressure. * @details * Inputs : bloodPumpOcclusion * Outputs : none * @return the current blood pump occlusion pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredBloodPumpOcclusion, bloodPumpOcclusion ) /*********************************************************************//** * @brief * The getMeasuredDialInPumpOcclusion function gets the measured dialysate \n * inlet pump occlusion pressure. * @details * Inputs : dialInPumpOcclusion * Outputs : none * @return the current dialysis inlet pump occlusion pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredDialInPumpOcclusion, dialInPumpOcclusion ) /*********************************************************************//** * @brief * The getMeasuredDialOutPumpOcclusion function gets the measured dialysate \n * outlet pump occlusion pressure. * @details * Inputs : dialOutPumpOcclusion * Outputs : none * @return the current dialysis outlet pump occlusion pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpOcclusion, dialOutPumpOcclusion ) /*********************************************************************//** * @brief * The publishPresOcclData function publishes pressure/occlusion data at the \n * set interval. * @details * Inputs : TBD * Outputs : Pressure/occlusion data are published to CAN bus. * @return none *************************************************************************/ static void publishPresOcclData( void ) { // publish pressure/occlusion data on interval if ( ++presOcclDataPublicationTimerCounter >= getPublishPresOcclDataInterval() ) { F32 artPres = getMeasuredArterialPressure(); F32 venPres = getMeasuredVenousPressure(); F32 bpOccl = getMeasuredBloodPumpOcclusion(); F32 diOccl = getMeasuredDialInPumpOcclusion(); F32 doOccl = getMeasuredDialOutPumpOcclusion(); broadcastPresOcclData( artPres, venPres, bpOccl, diOccl, doOccl ); presOcclDataPublicationTimerCounter = 0; } } /*********************************************************************//** * @brief * The execPresOcclTest function executes the state machine for the \n * PresOccl self test. * @details * Inputs : none * Outputs : none * @return the current state of the PresOccl self test. *************************************************************************/ SELF_TEST_STATUS_T execPresOcclTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_FAILED; // TODO - implement self test(s) return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetPresOcclDataPublishIntervalOverride function overrides the \n * pressure and occlusion data publish interval. * @details * Inputs : none * Outputs : presOcclDataPublishInterval * @param value : override pressure and occlusion data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetPresOcclDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_GENERAL_INTERVAL; result = TRUE; presOcclDataPublishInterval.ovData = intvl; presOcclDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetPresOcclDataPublishIntervalOverride function resets the override \n * of the pressure and occlusion data publish interval. * @details * Inputs : none * Outputs : presOcclDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetPresOcclDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; presOcclDataPublishInterval.override = OVERRIDE_RESET; presOcclDataPublishInterval.ovData = presOcclDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetArterialPressureOverride function overrides the measured arterial \n * pressure. * @details * Inputs : none * Outputs : arterialPressure * @param value : override arterial pressure (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetArterialPressureOverride( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; arterialPressure.ovData = value; arterialPressure.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetArterialPressureOverride function resets the override of the \n * arterial pressure. * @details * Inputs : none * Outputs : arterialPressure * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetArterialPressureOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; arterialPressure.override = OVERRIDE_RESET; arterialPressure.ovData = arterialPressure.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetVenousPressureOverride function overrides the measured venous \n * pressure. * @details * Inputs : none * Outputs : venousPressure * @param value : override measured venous pressure with (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetVenousPressureOverride( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; venousPressure.ovData = value; venousPressure.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetVenousPressureOverride function resets the override of the \n * venous pressure. * @details * Inputs : none * Outputs : venousPressure * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetVenousPressureOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; venousPressure.override = OVERRIDE_RESET; venousPressure.ovData = venousPressure.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetBloodPumpOcclusionOverride function overrides the measured \n * blood pump occlusion pressure.n * @details * Inputs : none * Outputs : bloodPumpOcclusion * @param value : override measured blood pump occlusion pressure with (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBloodPumpOcclusionOverride( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodPumpOcclusion.ovData = value; bloodPumpOcclusion.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBloodPumpOcclusionOverride function resets the override of the \n * measured blood pump occlusion pressure. * @details * Inputs : none * Outputs : bloodPumpOcclusion * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetBloodPumpOcclusionOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodPumpOcclusion.override = OVERRIDE_RESET; bloodPumpOcclusion.ovData = bloodPumpOcclusion.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetDialInPumpOcclusionOverride function overrides the measured \n * dialysate inlet pump occlusion pressure.n * @details * Inputs : none * Outputs : dialInPumpOcclusion * @param value : override measured dialysate inlet pump occlusion pressure (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetDialInPumpOcclusionOverride( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; dialInPumpOcclusion.ovData = value; dialInPumpOcclusion.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetDialInPumpOcclusionOverride function resets the override of the \n * measured dialysate inlet pump occlusion pressure. * @details * Inputs : none * Outputs : dialInPumpOcclusion * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetDialInPumpOcclusionOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; dialInPumpOcclusion.override = OVERRIDE_RESET; dialInPumpOcclusion.ovData = dialInPumpOcclusion.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetDialOutPumpOcclusionOverride function overrides the measured \n * dialysate outlet pump occlusion pressure. * @details * Inputs : none * Outputs : dialOutPumpOcclusion * @param value : override measured dialysate outlet pump occlusion pressure (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetDialOutPumpOcclusionOverride( F32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; dialOutPumpOcclusion.ovData = value; dialOutPumpOcclusion.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetDialOutPumpOcclusionOverride function resets the override of the \n * measured dialysate outlet pump occlusion pressure. * @details * Inputs : none * Outputs : dialOutPumpOcclusion * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetDialOutPumpOcclusionOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; dialOutPumpOcclusion.override = OVERRIDE_RESET; dialOutPumpOcclusion.ovData = dialOutPumpOcclusion.ovInitData; } return result; } /**@}*/