/**********************************************************************//** * * Copyright (c) 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 BloodFlow.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 } 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 } 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 initPresOccl * The initPresOccl function initializes the initPresOccl module. * @details * Inputs : none * Outputs : initPresOccl module initialized. * @param none * @return none *************************************************************************/ void initPresOccl( void ) { // TODO - anything to initialize? } /*********************************************************************//** * @brief setPressureLimits * 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 setOcclusionThreshold * 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 execPresOccl * The execPresOccl function executes the pressure and occlusion monitor. * @details * Inputs : presOcclState * Outputs : presOcclState * @param none * @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 handlePresOcclInitState * The handlePresOcclInitState function handles the pres/occl initialize state \n * of the pressure/occlusion monitor state machine. * @details * Inputs : TBD * Outputs : TBD * @param none * @return next state *************************************************************************/ static PRESSURE_STATE_T handlePresOcclInitState( void ) { PRESSURE_STATE_T result = PRESSURE_CONTINUOUS_READ_STATE; return result; } /*********************************************************************//** * @brief handlePresOcclContReadState * The handlePresOcclContReadState function handles the continuous read state \n * of the pressure/occlusion monitor state machine. * @details * Inputs : TBD * Outputs : pressure sensor values updated * @param none * @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 checkPressureLimits * The checkPressureLimits function gets the pressure/occlusion data \n * publication interval. * @details * Inputs : occlusion pressures for the pumps * Outputs : * @param none * @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 getPublishPresOcclDataInterval * The getPublishPresOcclDataInterval function gets the pressure/occlusion data \n * publication interval. * @details * Inputs : presOcclDataPublishInterval * Outputs : none * @param none * @return the current pressure/occlusion data publication interval (in ms). *************************************************************************/ DATA_GET( U32, getPublishPresOcclDataInterval, presOcclDataPublishInterval ) /*********************************************************************//** * @brief getMeasuredArterialPressure * The getMeasuredArterialPressure function gets the current arterial pressure. * @details * Inputs : arterialPressure * Outputs : none * @param none * @return the current arterial pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredArterialPressure, arterialPressure ) /*********************************************************************//** * @brief getMeasuredVenousPressure * The getMeasuredVenousPressure function gets the measured venous pressure. * @details * Inputs : venousPressure * Outputs : none * @param none * @return the current venous pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredVenousPressure, venousPressure ) /*********************************************************************//** * @brief getMeasuredBloodPumpOcclusion * The getMeasuredBloodPumpOcclusion function gets the measured blood pump \n * occlusion pressure. * @details * Inputs : bloodPumpOcclusion * Outputs : none * @param none * @return the current blood pump occlusion pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredBloodPumpOcclusion, bloodPumpOcclusion ) /*********************************************************************//** * @brief getMeasuredDialInPumpOcclusion * The getMeasuredDialInPumpOcclusion function gets the measured dialysate \n * inlet pump occlusion pressure. * @details * Inputs : dialInPumpOcclusion * Outputs : none * @param none * @return the current dialysis inlet pump occlusion pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredDialInPumpOcclusion, dialInPumpOcclusion ) /*********************************************************************//** * @brief getMeasuredDialOutPumpOcclusion * The getMeasuredDialOutPumpOcclusion function gets the measured dialysate \n * outlet pump occlusion pressure. * @details * Inputs : dialOutPumpOcclusion * Outputs : none * @param none * @return the current dialysis outlet pump occlusion pressure (in mmHg). *************************************************************************/ DATA_GET( F32, getMeasuredDialOutPumpOcclusion, dialOutPumpOcclusion ) /*********************************************************************//** * @brief publishPresOcclData * The publishPresOcclData function publishes pressure/occlusion data at the \n * set interval. * @details * Inputs : TBD * Outputs : Pressure/occlusion data are published to CAN bus. * @param none * @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 execPresOcclTest * The execPresOcclTest function executes the state machine for the \n * PresOccl self test. * @details * Inputs : none * Outputs : none * @param 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 testSetPresOcclDataPublishIntervalOverride * 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 testResetPresOcclDataPublishIntervalOverride * 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 testSetArterialPressureOverride and testResetArterialPressureOverride * The testSetArterialPressureOverride function overrides the measured arterial \n * pressure. * The testResetArterialPressureOverride function resets the override of the \n * arterial pressure. * @details * Inputs : none * Outputs : arterialPressure * @param value : override arterial pressure (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetArterialPressureOverride, testResetArterialPressureOverride, arterialPressure ) /*********************************************************************//** * @brief testSetVenousPressureOverride and testResetVenousPressureOverride * The testSetVenousPressureOverride function overrides the measured venous \n * pressure. * The testResetVenousPressureOverride function resets the override of the \n * venous pressure. * @details * Inputs : none * Outputs : venousPressure * @param value : override measured vensous pressure with (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetVenousPressureOverride, testResetVenousPressureOverride, venousPressure ) /*********************************************************************//** * @brief testSetBloodPumpOcclusionOverride and testResetBloodPumpOcclusionOverride * The testSetBloodPumpOcclusionOverride function overrides the measured \n * blood pump occlusion pressure. \n * The testResetBloodPumpOcclusionOverride function resets the override of the \n * measured blood pump occlusion pressure. * @details * Inputs : none * Outputs : bloodPumpOcclusion * @param value : override measured blood pump occlusion pressure with (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetBloodPumpOcclusionOverride, testResetBloodPumpOcclusionOverride, bloodPumpOcclusion ) /*********************************************************************//** * @brief testSetDialInPumpOcclusionOverride and testResetDialInPumpOcclusionOverride * The testSetDialInPumpOcclusionOverride function overrides the measured \n * dialysate inlet pump occlusion pressure. \n * The testResetDialInPumpOcclusionOverride function resets the override of the \n * measured dialysate inlet pump occlusion pressure. * @details * Inputs : none * Outputs : dialInPumpOcclusion * @param value : override measured dialysate inlet pump occlusion pressure (in mmHg) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetDialInPumpOcclusionOverride, testResetDialInPumpOcclusionOverride, dialInPumpOcclusion ) /*********************************************************************//** * @brief testSetDialOutPumpOcclusionOverride and testResetDialOutPumpOcclusionOverride * The testSetDialOutPumpOcclusionOverride function overrides the measured \n * dialysate outlet pump occlusion pressure. \n * The testResetDialOutPumpOcclusionOverride function resets the override of the \n * measured 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 *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetDialOutPumpOcclusionOverride, testResetDialOutPumpOcclusionOverride, dialOutPumpOcclusion )