/************************************************************************** * * Copyright (c) 2019-2019 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 05-Nov-2019 * @author S. Nash * * @brief Monitor/Controller for blood pump and flow sensor. * **************************************************************************/ #include #include "can.h" #include "etpwm.h" #include "Common.h" #include "FPGA.h" #include "InternalADC.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" #include "BloodFlow.h" // ********** private definitions ********** #define BLOOD_FLOW_DATA_PUB_INTERVAL (1000 / TASK_PRIORITY_INTERVAL) // interval (ms/task time) at which the blood flow data is published on the CAN bus #define MAX_BLOOD_FLOW_RATE 600 // mL/min #define MAX_BLOOD_PUMP_PWM_STEP_CHANGE 0.02 // duty cycle TODO - fixed or parameterized or set in motor controller? #define MAX_BLOOD_PUMP_PWM_DUTY_CYCLE 0.88 // controller will error if PWM duty cycle > 90%, so set max to 88% #define MIN_BLOOD_PUMP_PWM_DUTY_CYCLE 0.12 // controller will error if PWM duty cycle < 10%, so set min to 12% #define BP_CONTROL_INTERVAL (500 / TASK_GENERAL_INTERVAL) // interval (ms/task time) at which the blood pump is controlled #define BP_P_COEFFICIENT 0.0002 // P term for blood pump control #define BP_I_COEFFICIENT 0.00002 // I term for blood pump control #define BP_MAX_ERROR_SUM 10.0 // for anti-wind-up in I term #define BP_MIN_ERROR_SUM -10.0 #define BP_MAX_PWM_DC_DELTA 0.01 // prevents large steps in PWM duty cycle #define BP_MIN_PWM_DC_DELTA -0.01 #define BP_MAX_CURR_WHEN_STOPPED_MA 150.0 // motor controller current should not exceed this when pump should be stopped #define BP_MIN_CURR_WHEN_RUNNING_MA 150.0 // motor controller current should always exceed this when pump should be running #define BP_MAX_CURR_WHEN_RUNNING_MA 1000.0 // motor controller current should not exceed this when pump should be running #define BP_MAX_CURR_ERROR_DURATION_MS 500 // motor controller current errors persisting beyond this duration will trigger an alarm #define BP_SPEED_ADC_TO_RPM_FACTOR 1.375 // conversion factor from ADC counts to RPM for blood pump motor #define BP_CURRENT_ADC_TO_MA_FACTOR 2.65 // conversion factor from ADC counts to mA for blood pump motor #define BP_ML_PER_MIN_TO_PUMP_RPM_FACTOR (124.0 / ML_PER_LITER)// 124 pump revolutions = 1 liter or 1,000 mL #define BP_GEAR_RATIO 32.0 // blood pump motor to blood pump gear ratio #define BP_MOTOR_RPM_TO_PWM_DC_FACTOR 0.0003125 // ~32 BP motor RPM = 1% PWM duty cycle #define BP_PWM_ZERO_OFFSET 0.1 // 10% PWM duty cycle = zero speed #define BP_PWM_FROM_ML_PER_MIN(rate) ((rate) * BP_ML_PER_MIN_TO_PUMP_RPM_FACTOR * BP_GEAR_RATIO * BP_MOTOR_RPM_TO_PWM_DC_FACTOR + BP_PWM_ZERO_OFFSET) #define BLOODPUMP_ADC_FULL_SCALE_V 3.0 // BP analog signals are 0-3V (while int. ADC ref V is 3.3V) #define BLOODPUMP_ADC_MID_PT_BITS ((F32)(INT_ADC_FULL_SCALE_BITS >> 1) * (BLOODPUMP_ADC_FULL_SCALE_V / INT_ADC_REF_V)) #define SIGN_FROM_12_BIT_VALUE(v) ((S16)(v) - (S16)BLOODPUMP_ADC_MID_PT_BITS) #define SIZE_OF_ROLLING_AVG 100 // flow samples in rolling average calculations typedef enum BloodPump_States { BLOOD_PUMP_OFF_STATE = 0, BLOOD_PUMP_RAMPING_UP_STATE, BLOOD_PUMP_RAMPING_DOWN_STATE, BLOOD_PUMP_CONTROL_TO_TARGET_STATE, NUM_OF_BLOOD_PUMP_STATES } BLOOD_PUMP_STATE_T; typedef enum BloodFlow_Self_Test_States { BLOOD_FLOW_SELF_TEST_STATE_START = 0, BLOOD_FLOW_TEST_STATE_IN_PROGRESS, BLOOD_FLOW_TEST_STATE_COMPLETE, NUM_OF_BLOOD_FLOW_SELF_TEST_STATES } BLOOD_FLOW_SELF_TEST_STATE_T; // CAN3 port pin assignments for pump stop and direction outputs #define STOP_CAN3_PORT_MASK 0x00000002 // (Tx - re-purposed as output GPIO for blood pump stop signal) #define DIR_CAN3_PORT_MASK 0x00000002 // (Rx - re-purposed as output GPIO for blood pump direction signal) // blood pump stop and direction macros #define SET_BP_DIR() {canREG3->RIOC |= DIR_CAN3_PORT_MASK;} #define SET_BP_STOP() {canREG3->TIOC |= STOP_CAN3_PORT_MASK;} #define CLR_BP_DIR() {canREG3->RIOC &= ~DIR_CAN3_PORT_MASK;} #define CLR_BP_STOP() {canREG3->TIOC &= ~STOP_CAN3_PORT_MASK;} // ********** private data ********** static BLOOD_PUMP_STATE_T bloodPumpState = BLOOD_PUMP_OFF_STATE; // current state of blood flow controller state machine static U32 bloodFlowDataPublicationTimerCounter = 0; // used to schedule blood flow data publication to CAN bus static BOOL isBloodPumpOn = FALSE; // blood pump is currently running static F32 bloodPumpPWMDutyCyclePct = 0.0; // initial blood pump PWM duty cycle static F32 bloodPumpPWMDutyCyclePctSet = 0.0; // currently set blood pump PWM duty cycle static MOTOR_DIR_T bloodPumpDirection = MOTOR_DIR_FORWARD; // requested blood flow direction static MOTOR_DIR_T bloodPumpDirectionSet = MOTOR_DIR_FORWARD; // currently set blood flow direction DATA_DECL( U32, BloodFlowDataPub, bloodFlowDataPublishInterval, BLOOD_FLOW_DATA_PUB_INTERVAL, BLOOD_FLOW_DATA_PUB_INTERVAL ); // interval (in ms) at which to publish blood flow data to CAN bus DATA_DECL( S32, TargetBloodFlowRate, targetBloodFlowRate, 0, 0 ); // requested blood flow rate DATA_DECL( F32, MeasuredBloodFlowRate, measuredBloodFlowRate, 0.0, 0.0 ); // measured blood flow rate DATA_DECL( F32, MeasuredBloodPumpSpeed, adcBloodPumpSpeedRPM, 0.0, 0.0 ); // measured blood pump speed DATA_DECL( F32, MeasuredBloodPumpCurrent, adcBloodPumpCurrentmA, 0.0, 0.0 ); // measured blood pump motor current static F32 bpFlowError = 0.0; // blood flow error static F32 bpFlowErrorSum = 0.0; // blood flow error sum static U32 bpControlTimerCounter = 0; // determines when to perform control on blood flow static F32 flowReadings[SIZE_OF_ROLLING_AVG]; // holds flow samples for a rolling average static U32 flowReadingsIdx = 0; // index for next sample in rolling average array static F32 flowReadingsTotal = 0.0; // rolling total - used to calc average static U32 bpCurrErrorDurationCtr = 0; // used for tracking persistence of bp current errors static BLOOD_FLOW_SELF_TEST_STATE_T bloodPumpSelfTestState = BLOOD_FLOW_SELF_TEST_STATE_START; // current blood pump self test state static U32 bloodPumpSelfTestTimerCount = 0; // timer counter for blood pump self test // ********** private function prototypes ********** static BLOOD_PUMP_STATE_T handleBloodPumpOffState( void ); static BLOOD_PUMP_STATE_T handleBloodPumpRampingUpState( void ); static BLOOD_PUMP_STATE_T handleBloodPumpRampingDownState( void ); static BLOOD_PUMP_STATE_T handleBloodPumpControlToTargetState( void ); static void stopBloodPump( void ); static void releaseBloodPumpStop( void ); static void setBloodPumpDirection( MOTOR_DIR_T dir ); static DATA_GET_PROTOTYPE( U32, getPublishBloodFlowDataInterval ); /************************************************************************* * @brief initBloodFlow * The initBloodFlow function initializes the BloodFlow module. * @details * Inputs : none * Outputs : BloodFlow module initialized. * @param none * @return none *************************************************************************/ void initBloodFlow( void ) { U32 i; stopBloodPump(); setBloodPumpDirection( MOTOR_DIR_FORWARD ); // zero rolling flow average buffer for ( i = 0; i < SIZE_OF_ROLLING_AVG; i++ ) { flowReadings[i] = 0.0; } } /************************************************************************* * @brief setBloodPumpTargetFlowRate * The setBloodPumpTargetFlowRate function sets a new target flow rate and * pump direction. * @details * Inputs : isBloodPumpOn, bloodPumpDirectionSet * Outputs : targetBloodFlowRate, bloodPumpdirection, bloodPumpPWMDutyCyclePct * @param flowRate : new target blood flow rate * @param dir : new blood flow direction * @return TRUE if new flow rate & dir are set, FALSE if not *************************************************************************/ BOOL setBloodPumpTargetFlowRate( U32 flowRate, MOTOR_DIR_T dir ) { BOOL result = FALSE; // direction change while pump is running is not allowed if ( ( FALSE == isBloodPumpOn ) || ( 0 == flowRate ) || ( dir == bloodPumpDirectionSet ) ) { // verify flow rate if ( flowRate <= MAX_BLOOD_FLOW_RATE ) { targetBloodFlowRate.data = ( dir == MOTOR_DIR_FORWARD ? (S32)flowRate : (S32)flowRate * -1 ); bloodPumpDirection = dir; // set PWM duty cycle target to an estimated initial target to ramp to based on target flow rate - then we'll control to flow when ramp completed bloodPumpPWMDutyCyclePct = BP_PWM_FROM_ML_PER_MIN((F32)flowRate); // ~ 8% per 100 mL/min with a 10% zero offset added in (e.g. 100 mL/min = 8+10 = 18%) bloodPumpPWMDutyCyclePct = MIN(bloodPumpPWMDutyCyclePct,MAX_BLOOD_PUMP_PWM_DUTY_CYCLE); // limit pwm duty cycle to controller maximum // reset flow control stats bpFlowError = 0.0; bpFlowErrorSum = 0.0; bpControlTimerCounter = 0; switch ( bloodPumpState ) { case BLOOD_PUMP_RAMPING_UP_STATE: // see if we need to reverse direction of ramp if ( bloodPumpPWMDutyCyclePct < bloodPumpPWMDutyCyclePctSet ) { bloodPumpState = BLOOD_PUMP_RAMPING_DOWN_STATE; } break; case BLOOD_PUMP_RAMPING_DOWN_STATE: // see if we need to reverse direction of ramp if ( bloodPumpPWMDutyCyclePct > bloodPumpPWMDutyCyclePctSet ) { bloodPumpState = BLOOD_PUMP_RAMPING_UP_STATE; } break; case BLOOD_PUMP_CONTROL_TO_TARGET_STATE: // start ramp to new target in appropriate direction if ( bloodPumpPWMDutyCyclePctSet > bloodPumpPWMDutyCyclePct ) { bloodPumpState = BLOOD_PUMP_RAMPING_DOWN_STATE; } else { bloodPumpState = BLOOD_PUMP_RAMPING_UP_STATE; } break; default: // ok - not all states need to be handled here break; } result = TRUE; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_FLOW_SET_TOO_HIGH, bloodPumpState ) } } return result; } /************************************************************************* * @brief execBloodFlowMonitor * The execBloodFlowMonitor function executes the blood flow monitor. * @details * Inputs : none * Outputs : none * @param none * @return none *************************************************************************/ void execBloodFlowMonitor( void ) { U16 bpRPM = getIntADCReading( INT_ADC_BLOOD_PUMP_SPEED ); U16 bpmA = getIntADCReading( INT_ADC_BLOOD_PUMP_MOTOR_CURRENT ); F32 bpFlow = getFPGABloodFlow(); // TODO - change to avg. blood flow when available from FPGA MOTOR_DIR_T bpMCDir; adcBloodPumpSpeedRPM.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpRPM)) * BP_SPEED_ADC_TO_RPM_FACTOR; adcBloodPumpCurrentmA.data = (F32)(SIGN_FROM_12_BIT_VALUE(bpmA)) * BP_CURRENT_ADC_TO_MA_FACTOR; flowReadingsTotal -= flowReadings[flowReadingsIdx]; flowReadings[flowReadingsIdx] = bpFlow; flowReadingsTotal += bpFlow; flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG-1 ); measuredBloodFlowRate.data = flowReadingsTotal / (F32)SIZE_OF_ROLLING_AVG; if ( BLOOD_PUMP_CONTROL_TO_TARGET_STATE == bloodPumpState ) { // check set direction vs. direction from sign of motor controller speed bpMCDir = ( getMeasuredBloodPumpSpeed() >= 0.0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); if ( bloodPumpDirectionSet != bpMCDir ) { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_BLOOD_PUMP_MC_DIRECTION_CHECK, (U32)bloodPumpDirectionSet, (U32)bpMCDir ) } } // check motor controller current thresholds as appropriate if ( BLOOD_PUMP_OFF_STATE == bloodPumpState ) { if ( getMeasuredBloodPumpCurrent() > BP_MAX_CURR_WHEN_STOPPED_MA ) { bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpCurrent() ); } } else { bpCurrErrorDurationCtr = 0; } } else // pump s/b running { F32 bpCurr = getMeasuredBloodPumpCurrent(); if ( ( bpCurr < BP_MIN_CURR_WHEN_RUNNING_MA ) || ( bpCurr > BP_MAX_CURR_WHEN_RUNNING_MA ) ) { bpCurrErrorDurationCtr += TASK_PRIORITY_INTERVAL; if ( bpCurrErrorDurationCtr > BP_MAX_CURR_ERROR_DURATION_MS ) { SET_ALARM_WITH_1_F32_DATA( ALARM_ID_BLOOD_PUMP_MC_CURRENT_CHECK, getMeasuredBloodPumpCurrent() ); } } else { bpCurrErrorDurationCtr = 0; } } // publish blood flow data on interval if ( ++bloodFlowDataPublicationTimerCounter > getPublishBloodFlowDataInterval() ) { S32 flowStPt = (S32)getTargetBloodFlowRate(); F32 measFlow = getMeasuredBloodFlowRate(); F32 measSpd = getMeasuredBloodPumpSpeed(); F32 measCurr = getMeasuredBloodPumpCurrent(); #ifdef DEBUG_ENABLED S32 pwm = (S32)(100.0*bloodPumpPWMDutyCyclePctSet); char debugFlowStr[256]; sprintf( debugFlowStr, "Target Flow:%5d, Meas. Flow:%5d, Speed:%5d RPM, Current:%5d mA, PWM:%5d \n", flowStPt, (S32)measFlow, (S32)measSpd, (S32)measCurr, pwm ); sendDebugData( (U08*)debugFlowStr, strlen(debugFlowStr) ); #endif broadcastBloodFlowData( flowStPt, measFlow, measSpd, measCurr ); bloodFlowDataPublicationTimerCounter = 0; } } /************************************************************************* * @brief execBloodFlowController * The execBloodFlowController function executes the blood flow controller. * @details * Inputs : bloodPumpState * Outputs : bloodPumpState * @param none * @return none *************************************************************************/ void execBloodFlowController( void ) { switch ( bloodPumpState ) { case BLOOD_PUMP_OFF_STATE: bloodPumpState = handleBloodPumpOffState(); break; case BLOOD_PUMP_RAMPING_UP_STATE: bloodPumpState = handleBloodPumpRampingUpState(); break; case BLOOD_PUMP_RAMPING_DOWN_STATE: bloodPumpState = handleBloodPumpRampingDownState(); break; case BLOOD_PUMP_CONTROL_TO_TARGET_STATE: bloodPumpState = handleBloodPumpControlToTargetState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_FLOW_INVALID_BLOOD_PUMP_STATE, bloodPumpState ) break; } } /************************************************************************* * @brief handleBloodPumpOffState * The handleBloodPumpOffState function handles the blood pump off state \n * of the blood pump controller state machine. * @details * Inputs : targetBloodFlowRate, bloodPumpDirection * Outputs : bloodPumpPWMDutyCyclePctSet, bloodPumpDirectionSet, isBloodPumpOn * @param none * @return next state *************************************************************************/ static BLOOD_PUMP_STATE_T handleBloodPumpOffState( void ) { BLOOD_PUMP_STATE_T result = BLOOD_PUMP_OFF_STATE; // if we've been given a flow rate, setup ramp up and transition to ramp up state if ( getTargetBloodFlowRate() != 0 ) { // set initial PWM duty cycle bloodPumpPWMDutyCyclePctSet = MAX_BLOOD_PUMP_PWM_STEP_CHANGE; etpwmSetCmpA( etpwmREG1, (U32)(bloodPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD)) ); // allow blood pump to run in requested direction setBloodPumpDirection( bloodPumpDirection ); releaseBloodPumpStop(); // start PWM for blood pump etpwmStartTBCLK(); isBloodPumpOn = TRUE; result = BLOOD_PUMP_RAMPING_UP_STATE; } return result; } /************************************************************************* * @brief handleBloodPumpRampingUpState * The handleBloodPumpRampingUpState function handles the ramp up state \n * of the blood pump controller state machine. * @details * Inputs : bloodPumpPWMDutyCyclePctSet * Outputs : bloodPumpPWMDutyCyclePctSet * @param none * @return next state *************************************************************************/ static BLOOD_PUMP_STATE_T handleBloodPumpRampingUpState( void ) { BLOOD_PUMP_STATE_T result = BLOOD_PUMP_RAMPING_UP_STATE; // have we been asked to stop the blood pump? if ( 0 == getTargetBloodFlowRate() ) { // start ramp down to stop bloodPumpPWMDutyCyclePctSet -= MAX_BLOOD_PUMP_PWM_STEP_CHANGE; etpwmSetCmpA( etpwmREG1, (U32)(bloodPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD)) ); result = BLOOD_PUMP_RAMPING_DOWN_STATE; } // have we reached end of ramp up? else if ( bloodPumpPWMDutyCyclePctSet >= bloodPumpPWMDutyCyclePct ) { result = BLOOD_PUMP_CONTROL_TO_TARGET_STATE; } // continue ramp up else { bloodPumpPWMDutyCyclePctSet += MAX_BLOOD_PUMP_PWM_STEP_CHANGE; etpwmSetCmpA( etpwmREG1, (U32)(bloodPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD)) ); } return result; } /************************************************************************* * @brief handleBloodPumpRampingDownState * The handleBloodPumpRampingDownState function handles the ramp down state \n * of the blood pump controller state machine. * @details * Inputs : bloodPumpPWMDutyCyclePctSet * Outputs : bloodPumpPWMDutyCyclePctSet * @param none * @return next state *************************************************************************/ static BLOOD_PUMP_STATE_T handleBloodPumpRampingDownState( void ) { BLOOD_PUMP_STATE_T result = BLOOD_PUMP_RAMPING_DOWN_STATE; // have we essentially reached zero speed if ( bloodPumpPWMDutyCyclePctSet < (MAX_BLOOD_PUMP_PWM_STEP_CHANGE + BP_PWM_ZERO_OFFSET) ) { stopBloodPump(); result = BLOOD_PUMP_OFF_STATE; } // have we reached end of ramp down? else if ( bloodPumpPWMDutyCyclePctSet <= bloodPumpPWMDutyCyclePct ) { result = BLOOD_PUMP_CONTROL_TO_TARGET_STATE; } // continue ramp down else { bloodPumpPWMDutyCyclePctSet -= MAX_BLOOD_PUMP_PWM_STEP_CHANGE; etpwmSetCmpA( etpwmREG1, (U32)(bloodPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD)) ); } return result; } /************************************************************************* * @brief handleBloodPumpControlToTargetState * The handleBloodPumpControlToTargetState function handles the "control to \n * target" state of the blood pump controller state machine. * @details * Inputs : none * Outputs : bloodPumpState * @param none * @return next state *************************************************************************/ static BLOOD_PUMP_STATE_T handleBloodPumpControlToTargetState( void ) { BLOOD_PUMP_STATE_T result = BLOOD_PUMP_CONTROL_TO_TARGET_STATE; F32 tgtFlow = (F32)getTargetBloodFlowRate(); F32 actFlow = getMeasuredBloodFlowRate(); F32 pTerm, iTerm; F32 newPWM; // control at set interval if ( ++bpControlTimerCounter >= BP_CONTROL_INTERVAL ) { // compute P term if ( MOTOR_DIR_FORWARD == bloodPumpDirectionSet ) { bpFlowError = tgtFlow - actFlow; } else { bpFlowError = (tgtFlow * -1.0) - (actFlow * -1.0); } pTerm = bpFlowError * BP_P_COEFFICIENT; pTerm = RANGE( pTerm, BP_MIN_PWM_DC_DELTA, BP_MAX_PWM_DC_DELTA ); // compute I term bpFlowErrorSum += bpFlowError; iTerm = RANGE( bpFlowErrorSum, BP_MIN_ERROR_SUM, BP_MAX_ERROR_SUM ); iTerm *= BP_I_COEFFICIENT; iTerm = RANGE( iTerm, BP_MIN_PWM_DC_DELTA, BP_MAX_PWM_DC_DELTA ); // compute new PWM duty cycle % for blood pump motor newPWM = bloodPumpPWMDutyCyclePctSet + pTerm + iTerm; newPWM = RANGE( newPWM, MIN_BLOOD_PUMP_PWM_DUTY_CYCLE, MAX_BLOOD_PUMP_PWM_DUTY_CYCLE ); bloodPumpPWMDutyCyclePctSet = newPWM; etpwmSetCmpA( etpwmREG1, (U32)(bloodPumpPWMDutyCyclePctSet * (F32)(etpwmREG1->TBPRD)) ); bpControlTimerCounter = 0; } return result; } /************************************************************************* * @brief stopBloodPump * The stopBloodPump function sets the blood pump stop signal. * @details * Inputs : none * Outputs : blood pump stop signal activated, PWM duty cycle zeroed * @param none * @return none *************************************************************************/ static void stopBloodPump( void ) { isBloodPumpOn = FALSE; bloodPumpPWMDutyCyclePctSet = 0.0; etpwmSetCmpA( etpwmREG1, 0 ); etpwmStopTBCLK(); SET_BP_STOP(); } /************************************************************************* * @brief releaseBloodPumpStop * The releaseBloodPumpStop function clears the blood pump stop signal. * @details * Inputs : none * Outputs : blood pump stop signal * @param none * @return none *************************************************************************/ static void releaseBloodPumpStop( void ) { CLR_BP_STOP(); } /************************************************************************* * @brief setBloodPumpDirection * The setBloodPumpDirection function sets the set blood pump direction to \n * the given direction. * @details * Inputs : bloodPumpState * Outputs : bloodPumpState * @param dir : blood pump direction to set * @return none *************************************************************************/ static void setBloodPumpDirection( MOTOR_DIR_T dir ) { switch ( dir ) { case MOTOR_DIR_FORWARD: bloodPumpDirectionSet = dir; SET_BP_DIR(); break; case MOTOR_DIR_REVERSE: bloodPumpDirectionSet = dir; CLR_BP_DIR(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_FLOW_INVALID_BLOOD_PUMP_DIRECTION, dir ) break; } } /************************************************************************* * @brief getPublishBloodFlowDataInterval * The getPublishBloodFlowDataInterval function gets the blood flow data \n * publication interval. * @details * Inputs : bloodFlowDataPublishInterval * Outputs : none * @param none * @return the current blood flow data publication interval (in ms). *************************************************************************/ DATA_GET( U32, getPublishBloodFlowDataInterval, bloodFlowDataPublishInterval ) /************************************************************************* * @brief getTargetBloodFlowRate * The getTargetBloodFlowRate function gets the current target blood flow \n * rate. * @details * Inputs : targetBloodFlowRate * Outputs : none * @param none * @return the current target blood flow rate (in mL/min). *************************************************************************/ DATA_GET( S32, getTargetBloodFlowRate, targetBloodFlowRate ) /************************************************************************* * @brief getMeasuredBloodFlowRate * The getMeasuredBloodFlowRate function gets the measured blood flow \n * rate. * @details * Inputs : measuredBloodFlowRate * Outputs : none * @param none * @return the current blood flow rate (in mL/min). *************************************************************************/ DATA_GET( F32, getMeasuredBloodFlowRate, measuredBloodFlowRate ) /************************************************************************* * @brief getMeasuredBloodPumpSpeed * The getMeasuredBloodPumpSpeed function gets the measured blood pump \n * speed. * @details * Inputs : adcBloodPumpSpeedRPM * Outputs : none * @param none * @return the current blood pump speed (in RPM). *************************************************************************/ DATA_GET( F32, getMeasuredBloodPumpSpeed, adcBloodPumpSpeedRPM ) /************************************************************************* * @brief getMeasuredBloodPumpCurrent * The getMeasuredBloodPumpCurrent function gets the measured blood pump \n * current. * @details * Inputs : adcBloodPumpCurrentmA * Outputs : none * @param none * @return the current blood pump current (in mA). *************************************************************************/ DATA_GET( F32, getMeasuredBloodPumpCurrent, adcBloodPumpCurrentmA ) /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /************************************************************************* * @brief testSetBloodFlowDataPublishIntervalOverride * The testSetBloodFlowDataPublishIntervalOverride function overrides the \n * blood flow data publish interval. * @details * Inputs : none * Outputs : bloodFlowDataPublishInterval * @param value : override blood flow data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBloodFlowDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; result = TRUE; bloodFlowDataPublishInterval.ovData = intvl; bloodFlowDataPublishInterval.override = OVERRIDE_KEY; } return result; } /************************************************************************* * @brief testResetBloodFlowDataPublishIntervalOverride * The testResetBloodFlowDataPublishIntervalOverride function resets the override \n * of the blood flow data publish interval. * @details * Inputs : none * Outputs : bloodFlowDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetBloodFlowDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodFlowDataPublishInterval.override = OVERRIDE_RESET; bloodFlowDataPublishInterval.ovData = bloodFlowDataPublishInterval.ovInitData; } return result; } /************************************************************************* * @brief testSetTargetBloodFlowRateOverride and testResetTargetBloodFlowRateOverride * The testSetTargetBloodFlowRateOverride function overrides the target \n * blood flow rate. \n * The testResetTargetBloodFlowRateOverride function resets the override of the \n * target blood flow rate. * @details * Inputs : none * Outputs : targetBloodFlowRate * @param value : override target blood flow rate (in mL/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( S32, testSetTargetBloodFlowRateOverride, testResetTargetBloodFlowRateOverride, targetBloodFlowRate ) /************************************************************************* * @brief testSetMeasuredBloodFlowRateOverride and testResetMeasuredBloodFlowRateOverride * The testResetMeasuredBloodFlowRateOverride function overrides the measured \n * blood flow rate. \n * The testResetOffButtonStateOverride function resets the override of the \n * measured blood flow rate. * @details * Inputs : none * Outputs : measuredBloodFlowRate * @param value : override measured blood flow rate (in mL/min) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredBloodFlowRateOverride, testResetMeasuredBloodFlowRateOverride, measuredBloodFlowRate ) /************************************************************************* * @brief testSetMeasuredBloodPumpSpeedOverride and testResetMeasuredBloodPumpSpeedOverride * The testSetMeasuredBloodPumpSpeedOverride function overrides the measured \n * blood pump motor speed. \n * The testResetMeasuredBloodPumpSpeedOverride function resets the override of the \n * measured blood pump motor speed. * @details * Inputs : none * Outputs : adcBloodPumpSpeedRPM * @param value : override measured blood pump speed (in RPM) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredBloodPumpSpeedOverride, testResetMeasuredBloodPumpSpeedOverride, adcBloodPumpSpeedRPM ) /************************************************************************* * @brief testSetMeasuredBloodPumpCurrentOverride and testResetMeasuredBloodPumpCurrentOverride * The testSetMeasuredBloodPumpCurrentOverride function overrides the measured \n * blood pump motor current. \n * The testResetMeasuredBloodPumpCurrentOverride function resets the override of the \n * measured blood pump motor current. * @details * Inputs : none * Outputs : adcBloodPumpCurrentmA * @param value : override measured blood pump current (in mA) * @return TRUE if override successful, FALSE if not *************************************************************************/ DATA_OVERRIDE_FUNC( F32, testSetMeasuredBloodPumpCurrentOverride, testResetMeasuredBloodPumpCurrentOverride, adcBloodPumpCurrentmA )