Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -re5d1d67106a93a6cd1b5692b586625d715732e2f -r44a100f8e5210a02c23b8fcc4527d8e96d577381 --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision e5d1d67106a93a6cd1b5692b586625d715732e2f) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 44a100f8e5210a02c23b8fcc4527d8e96d577381) @@ -20,6 +20,7 @@ #include "ModeTreatmentParams.h" #include "OperationModes.h" #include "PersistentAlarm.h" +#include "SafetyShutdown.h" #include "SyringePump.h" #include "SystemCommMessages.h" #include "TaskPriority.h" @@ -34,8 +35,6 @@ /// Default publication interval for syringe pump data. #define SYRINGE_PUMP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) -/// Speed check interval. -#define SYRINGE_PUMP_SPEED_CHECK_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) #define BD_SYRINGE_ID_RADIUS_CM ( 1.402 / 2.0 ) ///< Radius from inner diameter (in cm) of supported BD syringe. /// Milliliters per mm of syringe plunger travel. @@ -61,12 +60,16 @@ #define MIN_HEPARIN_BOLUS_RATE 1.2 ///< Minimum Heparin bolus flow rate (in mL/hr). #define MAX_HEPARIN_BOLUS_RATE 24.0 ///< Maximum Heparin bolus flow rate (in mL/hr). #define HEPARIN_BOLUS_TIME_HR ( 5.0 / MIN_PER_HOUR ) ///< Duration (in hours) of Heparin bolus. -#define SYRINGE_PUMP_RETRACT_RATE 10800.0 ///< Retract rate is 15 mL/ 5 s = 3 mL/s = 10,800 mL/hr. +#define SYRINGE_PUMP_RETRACT_RATE 3600.0 ///< Retract rate is 5 mL/ 5 s = 1 mL/s = 3,600 mL/hr. #define SYRINGE_PUMP_SEEK_RATE 3600.0 ///< Seek plunger rate is 5 mL/ 5 s = 1 mL/s = 3,600 mL/hr. #define SYRINGE_PUMP_PRIME_RATE 635.0 ///< Prime rate is 0.5 mm ^ 2 x PI x 450 mm = 0.353 mL / 2s = 635 mL/hr. #define SYRINGE_PUMP_MAX_RATE 11000.0 ///< Maximum rate of the syringe pump (in mL/hr). -#define SYRINGE_PUMP_RATE_ALARM_PERSISTENCE ( 1 * MS_PER_SECOND ) ///< Alarm persistence period for syringe pump speed check alarms. +#define SYRINGE_PUMP_RATE_ALARM_PERSISTENCE 2000 ///< Alarm persistence period (in ms) for syringe pump speed check alarms. +#define SYRINGE_PUMP_DIR_ALARM_PERSISTENCE 1000 ///< Alarm persistence period (in ms) for syringe pump direction check alarms. +#define SYRINGE_PUMP_OFF_ALARM_PERSISTENCE 500 ///< Alarm persistence period (in ms) for syringe pump off check alarms. +#define SYRINGE_PUMP_OCCLUSION_ALARM_PERSISTENCE 30 ///< Alarm persistence period (in ms) for syringe pump occlusion alarms. +#define SYRINGE_PUMP_ADC_READ_PERSISTENCE 100 ///< Syringe pump ADC stale read alarm persistence time (in ms). #define STEPS_TO_MICROSTEPS( s ) ( (s) * 32.0 ) ///< Macro conversion from steps to microsteps. #define MICROSTEPS_TO_STEPS( m ) ( (m) / 32.0 ) ///< Macro conversion from microsteps to steps. @@ -86,9 +89,11 @@ #define FIVE_PCT_OVER_ALLOWANCE 1.05 ///< Allow 5 percent over target before alarming on over travel. /// Expected position of empty in relation to home postion. -#define SYRINGE_PUMP_EMPTY_POS ( SYRINGE_ENCODER_COUNTS_PER_ML * 11.0 ) +#define SYRINGE_PUMP_EMPTY_POS ( SYRINGE_ENCODER_COUNTS_PER_ML * 11.0 ) // TODO - get syringe volume from home to empty (11 mL is placeholder) /// Margin of error for empty position determination. #define SYRINGE_PUMP_EMPTY_POS_MARGIN ( SYRINGE_ENCODER_COUNTS_PER_ML * 0.5 ) +/// Minimum retract position. +#define SYRINGE_PUMP_RETRACT_POS_MIN ( SYRINGE_ENCODER_COUNTS_PER_ML * -0.5 ) #define SYRINGE_PUMP_START_RAMP_SPEED 300000 ///< Starting speed for all syringe pump operations to ramp up from. #define SYRINGE_PUMP_RAMP_DIVISOR 5 ///< Used for ramping profile. @@ -136,6 +141,15 @@ #define SYRINGE_PUMP_ENCODER_DIRECTION_ERROR_BITS 0x3F ///< Syringe pump encoder direction error counter bits in FPGA register. #define SYRINGE_PUMP_ENCODER_DIRECTION_BIT 0x80 ///< Syringe pump encoder direction bit in FPGA register. +/// Interval (ms/task time) at which the syringe pump speed is calculated (every 40 ms). +#define SYRINGE_PUMP_SPEED_CALC_INTERVAL ( 40 / TASK_PRIORITY_INTERVAL ) +/// Number of syringe pump encoder positions kept in buffer to hold last 1 second of position data. +#define SYRINGE_PUMP_SPEED_CALC_BUFFER_LEN ( MS_PER_SECOND / SYRINGE_PUMP_SPEED_CALC_INTERVAL / TASK_PRIORITY_INTERVAL ) + +#define SYRINGE_PUMP_RAMP_STALL_TIME ( 500 / TASK_PRIORITY_INTERVAL ) ///< Syringe pump ramp stall timeout. +#define SYRINGE_PUMP_RAMP_STALL_RETRIES 3 ///< Syringe pump ramp stall retries allowed. +#define SYRINGE_PUMP_STALL_SPEED_THRESHOLD 0.05 ///< Minimum syringe pump speed to be considered not stalled. + /// Defined states for the syringe pump control state machine. typedef enum SyringePump_States { @@ -150,39 +164,36 @@ NUM_OF_SYRINGE_PUMP_STATES ///< Number of syringe pump control states } SYRINGE_PUMP_STATE_T; -/// Defined states for the syringe pump self-test state machine. -typedef enum Syringe_Pump_Self_Test_States -{ - SYRINGE_PUMP_SELF_TEST_STATE_START = 0, ///< Self test start state. - SYRINGE_PUMP_TEST_STATE_IN_PROGRESS, ///< Self test in progress state. - SYRINGE_PUMP_TEST_STATE_COMPLETE, ///< Self test completed state. - NUM_OF_SYRINGE_PUMP_SELF_TEST_STATES ///< Number of syringe pump self-test states. -} SYRINGE_PUMP_SELF_TEST_STATE_T; - // ********** private data ********** static SYRINGE_PUMP_STATE_T syringePumpState; ///< Current state of syringe pump control state machine. static U32 syringePumpDataPublicationTimerCounter; ///< Used to schedule syringe pump data publication to CAN bus. -static U32 syringePumpSpeedCalcTimerCounter; ///< Used to calculate measured rate from change in position over time. static U32 syringePumpRampTimerCtr; ///< Used to track ramp up time. static HEPARIN_STATE_T heparinDeliveryState; ///< Current state of Heparin delivery. /// Interval (in ms) at which to publish syringe pump data to CAN bus. static OVERRIDE_U32_T syringePumpDataPublishInterval = { SYRINGE_PUMP_DATA_PUB_INTERVAL, SYRINGE_PUMP_DATA_PUB_INTERVAL, 0, 0 }; -static OVERRIDE_F32_T syringePumpMeasRate = {0.0, 0.0, 0.0, 0 }; ///< Measured rate for syringe pump (in mL/hr). -static OVERRIDE_F32_T syringePumpMeasForce = {0.0, 0.0, 0.0, 0 }; ///< Measured driver force (in V). -static OVERRIDE_F32_T syringePumpMeasSyringeDetectionSwitch = {0, 0, 0, 0 }; ///< Measured syringe detect switch (in V). -static OVERRIDE_F32_T syringePumpMeasHome = {0.0, 0.0, 0.0, 0 }; ///< Measured optical home (in V). -static OVERRIDE_S32_T syringePumpPosition = {0, 0, 0, 0 }; ///< Encoder based position (in steps). -static OVERRIDE_F32_T syringePumpVolumeDelivered = {0.0, 0.0, 0.0, 0 }; ///< Measured volume delivered (in mL). +static OVERRIDE_F32_T syringePumpMeasRate = { 0.0, 0.0, 0.0, 0 }; ///< Measured rate for syringe pump (in mL/hr). +static OVERRIDE_F32_T syringePumpMeasForce = { 0.0, 0.0, 0.0, 0 }; ///< Measured driver force (in V). +static OVERRIDE_F32_T syringePumpMeasSyringeDetectionSwitch = { 0, 0, 0, 0 }; ///< Measured syringe detect switch (in V). +static OVERRIDE_F32_T syringePumpMeasHome = { 0.0, 0.0, 0.0, 0 }; ///< Measured optical home (in V). +static OVERRIDE_S32_T syringePumpPosition = { 0, 0, 0, 0 }; ///< Encoder based position (in steps). +static OVERRIDE_F32_T syringePumpVolumeDelivered = { 0.0, 0.0, 0.0, 0 }; ///< Measured volume delivered (in mL). +static OVERRIDE_U32_T syringePumpStatus = {0, 0, 0, 0}; ///< Syringe pump status reported by FPGA. +static OVERRIDE_U32_T syringePumpEncoderStatus = {0, 0, 0, 0}; ///< Syringe pump encoder status reported by FPGA. +static OVERRIDE_U32_T syringePumpADCandDACStatus = {0, 0, 0, 0}; ///< Syringe pump ADC and DAC status reported by FPGA. +static OVERRIDE_U32_T syringePumpADCReadCtr = {0, 0, 0, 0}; ///< Syringe pump ADC read counter reported by FPGA. static F32 syringePumpSetRate; ///< Set rate for syringe pump (in mL/hr). static U32 syringePumpSetToggleTime; ///< Set rate for syringe pump (in uSec/toggle). static U32 syringePumpRampUpToggleTime; ///< Current ramp rate for syringe pump (in uSec/toggle). static F32 syringePumpSafetyVolumeDelivered; ///< Calculated volume (in mL) (from set rate over time). static S32 syringePumpVolumeStartPosition; ///< Start position for the current volume calculation. static S32 syringePumpHomePositionOffset; ///< FPGA reported position when at home postion. -static S32 syringePumpPosition1SecAgo; ///< Position recorded at last 1 Hz speed check. +static S32 syringePumpLastPosition; ///< Position previously recorded. +static S32 syringePumpLastPositions[ SYRINGE_PUMP_SPEED_CALC_BUFFER_LEN ]; ///< Last encoder positions for the syringe pump. +static U32 syringePumpMotorSpeedCalcIdx; ///< Index into 1 second buffer of syringe pump encoder positions. +static U32 syringePumpSpeedCalcTimerCounter; ///< Used to calculate measured rate from change in position over time. static MOTOR_DIR_T syringePumpControllerMeasuredDirection; ///< Measured direction of syringe pump per controller. static MOTOR_DIR_T syringePumpEncoderMeasuredDirection; ///< Measured direction of syringe pump per encoder position relative to previous. @@ -195,6 +206,7 @@ static BOOL syringePumpPositionKnown; ///< Flag indicates we know position from a prior retract to home. static BOOL syringePumpPlungerFound; ///< Flag indicates plunger was found. +static BOOL syringeVolumeAdequate; ///< Flag indicates whether Heparin volume is sufficient to complete treatment. static BOOL syringePumpPrimeCompleted; ///< Flag indicates prime operation was completed. static BOOL syringePumpDACVrefWriteInProgress; ///< Flag indicates DAC Vref write is in progress. @@ -206,6 +218,9 @@ // static SYRINGE_PUMP_SELF_TEST_STATE_T syringePumpSelfTestState; ///< Current syringe pump self-test state. // static U32 syringePumpSelfTestTimerCount; ///< Timer counter for syringe pump self-test. +static U32 syringePumpStallCtr; ///< Counts time when position is not changing during ramp. +static U32 syringePumpStallRetryCount; ///< Counts pump ramp up stall retries. + // ********** private function prototypes ********** static void resetSyringePumpRequestFlags( void ); @@ -216,6 +231,10 @@ static F32 getSyringePumpSyringeDetectorV( void ); static F32 getSyringePumpHomeDetectorV( void ); static F32 getSyringePumpForceV( void ); +static U08 getSyringePumpStatus( void ); +static U08 getSyringePumpEncoderStatus( void ); +static U08 getSyringePumpADCReadCounter( void ); +static U08 getSyringePumpADCandDACStatus( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpInitState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpOffState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpRetractState( void ); @@ -228,11 +247,13 @@ static void calcStepperToggleTimeForTargetRate( F32 rate ); static void calcMeasRate( void ); static void calcSafetyVolumeDelivered( void ); +static BOOL checkDirection( BOOL stopPump, MOTOR_DIR_T expDir ); static BOOL checkOcclusionOrEmpty( BOOL stopPump ); static BOOL checkSyringeRemoved( BOOL stopPump ); static BOOL checkMaxTravel( BOOL stopPump, S32 maxPos ); static BOOL checkMeasRate( BOOL stopPump, F32 pctMargin ); static BOOL checkVolumeVsSafetyVolume( BOOL stopPump, F32 pctMargin ); +static BOOL checkForStall( BOOL stopPump ); static void publishSyringePumpData( void ); /*********************************************************************//** @@ -244,6 +265,8 @@ *************************************************************************/ void initSyringePump( void ) { + U32 i; + syringePumpState = SYRINGE_PUMP_INIT_STATE; heparinDeliveryState = HEPARIN_STATE_OFF; @@ -252,7 +275,7 @@ syringePumpSafetyVolumeDelivered = 0.0; syringePumpVolumeStartPosition = 0; syringePumpHomePositionOffset = 0; - syringePumpPosition1SecAgo = 0; + syringePumpLastPosition = 0; syringePumpControllerMeasuredDirection = MOTOR_DIR_FORWARD; syringePumpEncoderMeasuredDirection = MOTOR_DIR_FORWARD; @@ -262,10 +285,30 @@ syringePumpPositionKnown = FALSE; syringePumpPlungerFound = FALSE; + syringeVolumeAdequate = FALSE; syringePumpPrimeCompleted = FALSE; lastSyringePumpADCReadCtr = 0; + // Zero pump position counts buffer + syringePumpMotorSpeedCalcIdx = 0; + for ( i = 0; i < SYRINGE_PUMP_SPEED_CALC_BUFFER_LEN; i++ ) + { + syringePumpLastPositions[ i ] = 0; + } + + syringePumpStallCtr = 0; + syringePumpStallRetryCount = 0; + + // Initialize persistent alarms + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR, 0, SYRINGE_PUMP_ADC_READ_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, 0, SYRINGE_PUMP_DIR_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, 0, SYRINGE_PUMP_DIR_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, 0, SYRINGE_PUMP_OFF_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, 0, SYRINGE_PUMP_OFF_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, 0, SYRINGE_PUMP_RATE_ALARM_PERSISTENCE ); + initPersistentAlarm( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, 0, SYRINGE_PUMP_OCCLUSION_ALARM_PERSISTENCE ); + // Reset request flags resetSyringePumpRequestFlags(); } @@ -274,13 +317,13 @@ * @brief * The resetSyringePumpRequestFlags function resets request flags. * @details Inputs: none - * @details Outputs: syringePumpSetRate, syringePumpRetractRequested + * @details Outputs: request flags reset * @return TRUE if request accepted, FALSE if not *************************************************************************/ static void resetSyringePumpRequestFlags( void ) { syringePumpRetractRequested = FALSE; - syringePumpSeekRequested = FALSE;;; + syringePumpSeekRequested = FALSE; syringePumpPrimeRequested = FALSE; syringePumpBolusRequested = FALSE; syringePumpContinuousRequested = FALSE; @@ -428,7 +471,12 @@ *************************************************************************/ BOOL retractSyringePump( void ) { +#ifndef ALWAYS_ALLOW_SYRINGE_PUMP_CMDS if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) ) +#else + heparinDeliveryState = HEPARIN_STATE_STOPPED; + if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) ) +#endif { syringePumpSetRate = SYRINGE_PUMP_RETRACT_RATE; syringePumpRetractRequested = TRUE; @@ -470,6 +518,10 @@ { syringePumpSetRate = SYRINGE_PUMP_PRIME_RATE; syringePumpPrimeRequested = TRUE; + // Reset volume and start pos before starting prime operation + syringePumpVolumeDelivered.data = 0.0; + syringePumpSafetyVolumeDelivered = 0.0; + syringePumpVolumeStartPosition = getSyringePumpPosition(); } return syringePumpPrimeRequested; @@ -497,6 +549,10 @@ { syringePumpSetRate = tgtRate; syringePumpBolusRequested = TRUE; + // Reset volume and start pos before starting bolus operation + syringePumpVolumeDelivered.data = 0.0; + syringePumpSafetyVolumeDelivered = 0.0; + syringePumpVolumeStartPosition = getSyringePumpPosition(); } } else @@ -706,6 +762,85 @@ /*********************************************************************//** * @brief + * The getSyringePumpStatus function gets the current syringe pump status. + * @details Inputs: syringePumpStatus + * @details Outputs: none + * @return the current syringe pump status. + *************************************************************************/ +static U08 getSyringePumpStatus() +{ + U08 result = (U08)(syringePumpStatus.data & MASK_OFF_U32_MSBS); + + if ( OVERRIDE_KEY == syringePumpStatus.override ) + { + result = (U08)(syringePumpStatus.ovData & MASK_OFF_U32_MSBS); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getSyringePumpEncoderStatus function gets the current syringe pump + * encoder status. + * @details Inputs: syringePumpEncoderStatus + * @details Outputs: none + * @return the current syringe pump encoder status. + *************************************************************************/ +static U08 getSyringePumpEncoderStatus() +{ + U08 result = (U08)(syringePumpEncoderStatus.data & MASK_OFF_U32_MSBS); + + if ( OVERRIDE_KEY == syringePumpEncoderStatus.override ) + { + result = (U08)(syringePumpEncoderStatus.ovData & MASK_OFF_U32_MSBS); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getSyringePumpADCReadCounter function gets the current syringe pump + * ADC read counter. + * @details Inputs: syringePumpADCReadCtr + * @details Outputs: none + * @return the current syringe pump ADC read counter. + *************************************************************************/ +static U08 getSyringePumpADCReadCounter() +{ + U08 result = (U08)(syringePumpADCReadCtr.data & MASK_OFF_U32_MSBS); + + if ( OVERRIDE_KEY == syringePumpADCReadCtr.override ) + { + result = (U08)(syringePumpADCReadCtr.ovData & MASK_OFF_U32_MSBS); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getSyringePumpADCandDACStatus function gets the current syringe pump + * ADC and DAC status reported by the FPGA. + * @details Inputs: syringePumpADCandDACStatus + * @details Outputs: none + * @return the current syringe pump ADC and DAC status. + *************************************************************************/ +static U08 getSyringePumpADCandDACStatus() +{ + U08 result = (U08)(syringePumpADCandDACStatus.data & MASK_OFF_U32_MSBS); + + if ( OVERRIDE_KEY == syringePumpADCandDACStatus.override ) + { + result = (U08)(syringePumpADCandDACStatus.ovData & MASK_OFF_U32_MSBS); + } + + return result; +} + +/*********************************************************************//** + * @brief * The isSyringeDetected function determines whether a syringe is currently * detected. * @details Inputs: syringePumpMeasSyringeDetectionSwitch @@ -779,6 +914,20 @@ /*********************************************************************//** * @brief + * The isSyringeVolumeAdequate function determines whether the syringe has + * sufficient Heparin volume to complete the treatment per user settings. + * Call this function after seek operation. + * @details Inputs: syringeVolumeAdequate + * @details Outputs: none + * @return TRUE if syringe volume is sufficient to complete the treatment, FALSE if not. + *************************************************************************/ +BOOL isSyringeVolumeAdequate( void ) +{ + return syringeVolumeAdequate; +} + +/*********************************************************************//** + * @brief * The isSyringePumpPrimed function determines whether the syringe pump * prime operation was completed. * @details Inputs: syringePumpPrimeCompleted @@ -787,7 +936,7 @@ *************************************************************************/ BOOL isSyringePumpPrimed( void ) { - return syringePumpPrimeCompleted;; + return syringePumpPrimeCompleted; } /*********************************************************************//** @@ -800,47 +949,58 @@ static void execSyringePumpMonitor( void ) { S32 encPosition = getFPGASyringePumpEncoderPosition(); - U08 pmpStatus = getFPGASyringePumpStatus(); - U08 encStatus = getFPGASyringePumpEncoderStatus(); - U08 adcReadCtr = getFPGASyringePumpADCReadCounter(); + // Get latest FPGA status + syringePumpStatus.data = (U32)getFPGASyringePumpStatus(); + syringePumpEncoderStatus.data = (U32)getFPGASyringePumpEncoderStatus(); + syringePumpADCandDACStatus.data = (U32)getFPGASyringePumpADCandDACStatus(); + syringePumpADCReadCtr.data = (U32)getFPGASyringePumpADCReadCounter(); + // Get latest ADC data and convert to V syringePumpMeasHome.data = ( (F32)getFPGASyringePumpADCChannel2() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; syringePumpMeasSyringeDetectionSwitch.data = ( (F32)getFPGASyringePumpADCChannel1() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; syringePumpMeasForce.data = ( (F32)getFPGASyringePumpADCChannel0() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; // Apply home offset to encoder position + syringePumpLastPosition = getSyringePumpPosition(); syringePumpPosition.data = encPosition - syringePumpHomePositionOffset; // Calculate volume delivered from position syringePumpVolumeDelivered.data = (F32)(syringePumpPosition.data - syringePumpVolumeStartPosition) / SYRINGE_ENCODER_COUNTS_PER_ML; calcSafetyVolumeDelivered(); // Calculate measured rate (mL/hr) calcMeasRate(); // Get measured direction - syringePumpControllerMeasuredDirection = ( ( encStatus & SYRINGE_PUMP_ENCODER_DIRECTION_BIT ) != 0 ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); - // TODO - calc direction from encoder pos relative to last - // syringePumpEncoderMeasuredDirection = TBD; + syringePumpControllerMeasuredDirection = ( ( getSyringePumpEncoderStatus() & SYRINGE_PUMP_ENCODER_DIRECTION_BIT ) != 0 ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); + // Calculate direction from encoder position relative to last + syringePumpEncoderMeasuredDirection = ( getSyringePumpPosition() - syringePumpLastPosition >= 0 ? MOTOR_DIR_FORWARD : MOTOR_DIR_REVERSE ); - // TODO - check if syringe pump is on while BP is off (w/ a little persistence). - - if ( syringePumpDACVrefWriteInProgress != TRUE ) + // Check if syringe pump is on while BP is off { - // Check ADC read is fresh - if ( lastSyringePumpADCReadCtr == adcReadCtr ) // TODO - add persistence + BOOL runWhileOff = ( ( ( SYRINGE_PUMP_HEP_BOLUS_STATE == syringePumpState ) || ( SYRINGE_PUMP_HEP_CONTINUOUS_STATE == syringePumpState ) ) && + ( isBloodPumpRunning() != TRUE ) ); + + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, runWhileOff ) ) { - // activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR ); // TODO - restore when issue with read counter resolved + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, (U32)syringePumpState ); } - lastSyringePumpADCReadCtr = adcReadCtr; + } - // Check encoder direction error. // TODO check direction in states - if ( ( encStatus & SYRINGE_PUMP_ENCODER_DIRECTION_ERROR_BITS ) != 0) + if ( syringePumpDACVrefWriteInProgress != TRUE ) + { + // Check ADC read is fresh (takes FPGA a while to configure ADC so don't check until after init/POST mode + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR, + ( ( getCurrentOperationMode() > MODE_INIT ) && ( lastSyringePumpADCReadCtr == getSyringePumpADCReadCounter() ) ) ) ) { - // TODO - alarm? +#ifndef DISABLE_SYRINGE_PUMP_ALARMS + activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR ); +#endif } + lastSyringePumpADCReadCtr = getSyringePumpADCReadCounter(); + // Check pump status - if ( pmpStatus != 0 ) + if ( getSyringePumpStatus() != 0 ) { - // TODO - pump failure fault + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_FAULT, (U32)getSyringePumpStatus() ); } } } @@ -937,9 +1097,14 @@ { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_OFF_STATE; - // TODO - check position is not changing while stopped - // activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR ); - // activateSafetyShutdown(); +#ifndef DISABLE_SYRINGE_PUMP_ALARMS + // Check position is not changing while stopped + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, ( syringePumpLastPosition != getSyringePumpPosition() ) ) ) + { + activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR ); + activateSafetyShutdown(); + } +#endif // Check for request flags if ( TRUE == syringePumpRetractRequested ) @@ -990,6 +1155,9 @@ // Calculate target FPGA rate from set rate in mL/hr converted to microstep toggle interval in uSec calcStepperToggleTimeForTargetRate( syringePumpSetRate ); setFPGASyringePumpStepToggleTime( syringePumpRampUpToggleTime ); + // Reset stall detect variables + syringePumpStallRetryCount = 0; + syringePumpStallCtr = 0; } // Reset ramp up timer @@ -1009,14 +1177,15 @@ static SYRINGE_PUMP_STATE_T handleSyringePumpRetractState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_RETRACT_STATE; + BOOL stopPump = FALSE; - // Handle ramp up + // Handle ramp up rampSyringePump(); // Stop retract when home position is detected if ( TRUE == isSyringePumpHome() ) { - stopSyringePump(); + stopPump = TRUE; // Set position to zero after retract reaches home position syringePumpHomePositionOffset = getFPGASyringePumpEncoderPosition(); syringePumpPosition.data = 0; @@ -1027,18 +1196,28 @@ syringePumpSafetyVolumeDelivered = 0.0; // Reset flags syringePumpPlungerFound = FALSE; + syringeVolumeAdequate = FALSE; syringePumpPrimeCompleted = FALSE; - result = SYRINGE_PUMP_OFF_STATE; + // Clear insufficient volume alarm condition in case we're retracting to allow user to resolve alarm + clearAlarmCondition( ALARM_ID_HD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM ); } - else if ( syringePumpControllerMeasuredDirection != MOTOR_DIR_REVERSE ) + // If position known from prior retract, ensure we don't retract beyond minimum position + else if ( ( TRUE == syringePumpPositionKnown ) && ( getSyringePumpPosition() < SYRINGE_PUMP_RETRACT_POS_MIN ) ) { - // TODO - alarm w/ some persistence + stopPump = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OVER_TRAVEL_ERROR, (U32)getSyringePumpPosition(), (U32)SYRINGE_PUMP_RETRACT_STATE ); } - else if ( syringePumpEncoderMeasuredDirection != MOTOR_DIR_REVERSE ) + + stopPump = checkForStall( stopPump ); + + stopPump = checkDirection( stopPump, MOTOR_DIR_REVERSE ); + + // If anything found that would require stopping the pump, stop pump and go to off state + if ( TRUE == stopPump ) { - // TODO - alarm w/ some persistence + stopSyringePump(); + result = SYRINGE_PUMP_OFF_STATE; } - // TODO - if position known from prior retract, ensure we don't go lower than -TBD position return result; } @@ -1062,23 +1241,43 @@ // Is plunger contact detected? if ( getSyringePumpForceV() >= SYRINGE_FORCE_PLUNGER_THRESHOLD_V ) { + S32 pos = getSyringePumpPosition(); + F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 contRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); + U32 preStop = getTreatmentParameterU32( TREATMENT_PARAM_HEPARIN_PRE_STOP_TIME ); + U32 setTxDur = getTreatmentParameterU32( TREATMENT_PARAM_TREATMENT_DURATION ); + F32 hepDurHr = ( (F32)( setTxDur - preStop ) / (F32)MIN_PER_HOUR ) - HEPARIN_BOLUS_TIME_HR; + F32 txVolume = bolusVol + ( hepDurHr * contRate ); + F32 syringeVol = ( SYRINGE_PUMP_EMPTY_POS - (F32)pos ) / SYRINGE_MICRO_STEPS_PER_ML; + stopPump = TRUE; syringePumpPlungerFound = TRUE; syringePumpVolumeDelivered.data = 0.0; syringePumpSafetyVolumeDelivered = 0.0; - syringePumpVolumeStartPosition = syringePumpPosition.data; + syringePumpVolumeStartPosition = pos; + + // Check estimated syringe volume needed for treatment vs. volume detected - if insufficient for treatment needs, alarm + if ( syringeVol >= txVolume ) + { + syringeVolumeAdequate = TRUE; + } + else + { +#ifndef DISABLE_SYRINGE_PUMP_ALARMS + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM, syringeVol, txVolume ); +#endif + } } // Has syringe been removed? stopPump = checkSyringeRemoved( stopPump ); - // Check for occlusion - stopPump = checkOcclusionOrEmpty( stopPump ); + // Check max position > empty + 0.5 mL + stopPump = checkMaxTravel( stopPump, SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_MARGIN ); - // TODO - check max position > TBD + // Check pump direction + stopPump = checkDirection( stopPump, MOTOR_DIR_FORWARD ); - // TODO - calc estimate syringe volume - if insufficient for treatment needs, alarm - // If anything found that would require stopping the pump, stop pump and go to off state if ( TRUE == stopPump ) { @@ -1124,6 +1323,9 @@ // Check position > max travel stopPump = checkMaxTravel( stopPump, syringePumpVolumeStartPosition + ( SYRINGE_PUMP_PRIME_VOLUME_ML * TEN_PCT_OVER_ALLOWANCE * SYRINGE_ENCODER_COUNTS_PER_ML ) ); + // Check pump direction + stopPump = checkDirection( stopPump, MOTOR_DIR_FORWARD ); + // If anything found that would require stopping the pump, stop pump and go to off state if ( TRUE == stopPump ) { @@ -1171,6 +1373,9 @@ // Check position > max travel stopPump = checkMaxTravel( stopPump, syringePumpVolumeStartPosition + ( bolusVol * FIVE_PCT_OVER_ALLOWANCE * SYRINGE_ENCODER_COUNTS_PER_ML ) ); + // Check pump direction + stopPump = checkDirection( stopPump, MOTOR_DIR_FORWARD ); + // If anything found that would require stopping the pump, stop pump and go to off state if ( TRUE == stopPump ) { @@ -1203,7 +1408,7 @@ // Check for occlusion stopPump = checkOcclusionOrEmpty( stopPump ); - // Check position > max travel + // Check position > empty + 0.5 mL stopPump = checkMaxTravel( stopPump, SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_MARGIN ); // Check for commanded vs. meas. rate @@ -1212,6 +1417,9 @@ // Check volume vs. safety volume stopPump = checkVolumeVsSafetyVolume( stopPump, SYRINGE_PUMP_VOLUME_CHECK_MARGIN ); + // Check pump direction + stopPump = checkDirection( stopPump, MOTOR_DIR_FORWARD ); + // If anything found that would require stopping the pump, stop pump and go to off state if ( TRUE == stopPump ) { @@ -1226,18 +1434,18 @@ * @brief * The handleSyringePumpCalibrateForceSensorState function handles the * calibrate force sensor state of the syringe pump control state machine. - * of the pressure/occlusion monitor state machine. + * of the syringe pump control state machine. * @details Inputs: DAC status * @details Outputs: syringePumpDACVrefWriteInProgress, ADC read mode restored * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpCalibrateForceSensorState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE; - U08 adcDACStatus= getFPGASyringePumpADCandDACStatus(); + U08 adcDACStatus= getSyringePumpADCandDACStatus(); // Wait for DAC setting write to EEPROM to complete - if ( ( getFPGASyringePumpADCandDACStatus() & SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE ) != 0 ) + if ( ( adcDACStatus & SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE ) != 0 ) { syringePumpDACVrefWriteInProgress = FALSE; // Switch back from DAC to ADC control @@ -1248,14 +1456,44 @@ // Check DAC write error else if ( ( adcDACStatus & SYRINGE_PUMP_DAC_WRITE_ERROR_BIT ) != 0 ) { - // TODO - alarm + activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_DAC_WRITE_ERROR ); } return result; } /*********************************************************************//** * @brief + * The checkDirection function checks the measured direction of the syringe + * pump vs. the given expected direction. + * @details Inputs: syringePumpMeasForce.data, syringePumpPosition.data + * @details Outputs: alarm triggered if max force detected + * @param stopPump flag passed in by caller indicating whether pump should be stopped + * @param expDir expected direction of syringe pump + * @return TRUE if pump should be stopped, FALSE if not + *************************************************************************/ +static BOOL checkDirection( BOOL stopPump, MOTOR_DIR_T expDir ) +{ + BOOL result = stopPump; + +#ifndef DISABLE_SYRINGE_PUMP_ALARMS + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, ( syringePumpEncoderMeasuredDirection != expDir ) ) ) + { + result = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, (U32)syringePumpEncoderMeasuredDirection, (U32)syringePumpState ); + } + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, ( syringePumpControllerMeasuredDirection != expDir ) ) ) + { + result = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, (U32)syringePumpControllerMeasuredDirection, (U32)syringePumpState ); + } +#endif + + return result; +} + +/*********************************************************************//** + * @brief * The checkOcclusionOrEmpty function checks the force sensor for excessive * pressure. Would indicate occlusion or jam or empty syringe. * @details Inputs: syringePumpMeasForce.data, syringePumpPosition.data @@ -1268,7 +1506,7 @@ BOOL result = stopPump; F32 force = getSyringePumpForceV(); - if ( force >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_V ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, ( force >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_V ) ) ) { S32 pos = getSyringePumpPosition(); @@ -1326,7 +1564,7 @@ BOOL result = stopPump; S32 pos = getSyringePumpPosition(); - if ( pos > ( SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_MARGIN ) ) + if ( pos > ( SYRINGE_PUMP_EMPTY_POS - SYRINGE_PUMP_EMPTY_POS_MARGIN ) ) { result = TRUE; heparinDeliveryState = HEPARIN_STATE_EMPTY; @@ -1335,6 +1573,10 @@ else if ( pos > maxPos ) { result = TRUE; + if ( syringePumpState != SYRINGE_PUMP_PRIME_STATE ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OVER_TRAVEL_ERROR, (U32)pos, (U32)syringePumpState ); + } } return result; @@ -1359,13 +1601,14 @@ F32 delta = max - min; F32 error = ( max > 0.0 ? ( 1.0 - fabs( min / max ) ) : 0.0 ); +#ifndef DISABLE_SYRINGE_PUMP_ALARMS // Alarm on rate if off by more than 5% or 0.1 mL/hr, whichever is greater - if ( ( error > pctMargin ) && ( delta > SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR ) ) + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, ( ( error > pctMargin ) && ( delta > SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR ) ) ) ) { - // TODO - needs persistence -// result = TRUE; -// SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, syringePumpSetRate, rate ) + result = TRUE; + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, syringePumpSetRate, rate ) } +#endif return result; } @@ -1403,18 +1646,60 @@ /*********************************************************************//** * @brief + * The checkForStall function checks whether the syringe pump has stalled. + * If stall detected, the ramp up will be restarted up to 3 times. + * If cannot resolve the stall within 3 retries, a stall fault is triggered. + * @details Inputs: syringePumpMeasRate.data, syringePumpStallCtr, syringePumpStallRetryCount + * @details Outputs: syringePumpStallCtr, syringePumpStallRetryCount + * @param stopPump flag passed in by caller indicating whether pump should be stopped + * @return TRUE if pump should be stopped, FALSE if not +*************************************************************************/ +static BOOL checkForStall( BOOL stopPump ) +{ + BOOL result = stopPump; + + // Check for stall + if ( fabs( getSyringePumpMeasRate() ) < SYRINGE_PUMP_STALL_SPEED_THRESHOLD ) + { + if ( ++syringePumpStallCtr >= SYRINGE_PUMP_RAMP_STALL_TIME ) + { + if ( ++syringePumpStallRetryCount <= SYRINGE_PUMP_RAMP_STALL_RETRIES ) + { + syringePumpSetToggleTime++; // lower target rate (by increasing time between steps) + syringePumpRampTimerCtr = 0; // restart ramp + syringePumpRampUpToggleTime = SYRINGE_PUMP_START_RAMP_SPEED; + syringePumpStallCtr = 0; // reset stall counter + } + else + { + result = TRUE; + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_STALL, (U32)getSyringePumpPosition(), (U32)syringePumpState ); + } + } + } + else + { + syringePumpStallCtr = 0; + } + + return result; +} + +/*********************************************************************//** + * @brief * The rampSyringePump function handles the ramp-up for the syringe pump. * @details Inputs: syringePumpRampTimerCtr, syringePumpSetToggleTime * @details Outputs: syringePumpRampUpToggleTime * @return none *************************************************************************/ static void rampSyringePump( void ) { + // Ramp up syringe pump toward target speed syringePumpRampTimerCtr++; if ( syringePumpRampUpToggleTime > syringePumpSetToggleTime ) { syringePumpRampUpToggleTime = (U32)((F32)SYRINGE_PUMP_START_RAMP_SPEED / - (F32)( syringePumpRampTimerCtr * syringePumpRampTimerCtr * syringePumpRampTimerCtr / SYRINGE_PUMP_RAMP_DIVISOR )); + (F32)( ( syringePumpRampTimerCtr * syringePumpRampTimerCtr * syringePumpRampTimerCtr ) / SYRINGE_PUMP_RAMP_DIVISOR ) ); if ( syringePumpRampUpToggleTime > syringePumpSetToggleTime ) { setFPGASyringePumpStepToggleTime( syringePumpRampUpToggleTime ); @@ -1437,38 +1722,48 @@ *************************************************************************/ static void calcStepperToggleTimeForTargetRate( F32 rate ) { - F32 conv = 0.0; + double temp; + F32 conv; // Convert given rate to stepper toggle period - conv = rate * SYRINGE_MICRO_STEPS_PER_ML; // = uSteps/hr - conv /= (F32)( MIN_PER_HOUR * SEC_PER_MIN); // = uSteps/sec - conv /= MICRO_SECONDS_PER_SECOND; // = uSteps/uSec - conv *= SYRINGE_TOGGLES_PER_STEP; // = toggles/uSec + temp = (double)rate * SYRINGE_MICRO_STEPS_PER_ML; // = uSteps/hr + temp /= (double)( MIN_PER_HOUR * SEC_PER_MIN); // = uSteps/sec + temp /= MICRO_SECONDS_PER_SECOND; // = uSteps/uSec + conv = (F32)temp * SYRINGE_TOGGLES_PER_STEP; // = toggles/uSec conv = 1.0 / conv; // = uSec/toggle // Set stepper toggle time to calculated value syringePumpSetToggleTime = FLOAT_TO_INT_WITH_ROUND( conv ); // Set stepper ramp toggle time to initial ramp up speed initially syringePumpRampUpToggleTime = SYRINGE_PUMP_START_RAMP_SPEED; + // Reset ramp stall timer and retry counters + syringePumpStallCtr = 0; + syringePumpStallRetryCount = 0; } /*********************************************************************//** * @brief * The calcMeasRate function calculates the measured rate from a given delta - * position in last 10 ms. - * @details Inputs: syringePumpPosition1SecAgo, syringePumpSpeedCalcTimerCounter + * position in last 1 second. + * @details Inputs: syringePumpLastPositions[], syringePumpSpeedCalcTimerCounter * @details Outputs: syringePumpMeasRate, syringePumpSpeedCalcTimerCounter * @return none *************************************************************************/ static void calcMeasRate( void ) { - if ( ++syringePumpSpeedCalcTimerCounter > SYRINGE_PUMP_SPEED_CHECK_INTERVAL ) + if ( ++syringePumpSpeedCalcTimerCounter >= SYRINGE_PUMP_SPEED_CALC_INTERVAL ) { - S32 countsPerSec = syringePumpPosition.data - syringePumpPosition1SecAgo; + S32 pos = getSyringePumpPosition(); + U32 nextIdx = INC_WRAP( syringePumpMotorSpeedCalcIdx, 0, SYRINGE_PUMP_SPEED_CALC_BUFFER_LEN - 1 ); + S32 countsPerSec = pos - syringePumpLastPositions[ syringePumpMotorSpeedCalcIdx ]; // Calc delta between pos 1 second ago and pos now S32 countsPerHr = countsPerSec * ( MIN_PER_HOUR * SEC_PER_MIN); - F32 mLPerHr = (F32)countsPerHr / SYRINGE_ENCODER_COUNTS_PER_ML; + F32 mLPerHr = (F32)((double)countsPerHr / (double)SYRINGE_ENCODER_COUNTS_PER_ML); + // Set latest measured rate syringePumpMeasRate.data = mLPerHr; - syringePumpPosition1SecAgo = syringePumpPosition.data; + + // Update last position for next time + syringePumpLastPositions[ syringePumpMotorSpeedCalcIdx ] = pos; + syringePumpMotorSpeedCalcIdx = nextIdx; syringePumpSpeedCalcTimerCounter = 0; } } @@ -1511,31 +1806,18 @@ data.heparinDeliveryState = (U32)heparinDeliveryState; data.syringePumpVolumeDelivered = getSyringePumpVolumeDelivered(); data.syringePumpSafetyVolume = syringePumpSafetyVolumeDelivered; + data.syringePumpStatus = ( (U32)getSyringePumpStatus() << SHIFT_24_BITS ) | + ( (U32)getSyringePumpEncoderStatus() << SHIFT_16_BITS_FOR_WORD_SHIFT ) | + ( (U32)getSyringePumpADCandDACStatus() << SHIFT_8_BITS_FOR_BYTE_SHIFT ) | + ( (U32)getSyringePumpADCReadCounter() ); broadcastSyringePumpData( data ); broadcastHeparinData( data.syringePumpVolumeDelivered ); syringePumpDataPublicationTimerCounter = 0; } } -/*********************************************************************//** - * @brief - * The execSyringePumpTest function executes the state machine for the - * syringe pump self-test. - * @details Inputs: none - * @details Outputs: none - * @return the current state of the syringe pump self-test. - *************************************************************************/ -SELF_TEST_STATUS_T execSyringePumpTest( void ) -{ - SELF_TEST_STATUS_T result = SELF_TEST_STATUS_FAILED; - // TODO - implement self-test(s) - - return result; -} - - /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -1913,4 +2195,184 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetSyringePumpStatus function overrides the syringe pump + * status. + * @details Inputs: none + * @details Outputs: syringePumpStatus + * @param status override syringe pump status with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpStatus( U32 status ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpStatus.ovData = status; + syringePumpStatus.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpStatus function resets the override of the + * syringe pump status. + * @details Inputs: none + * @details Outputs: syringePumpStatus + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpStatus( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpStatus.override = OVERRIDE_RESET; + syringePumpStatus.ovData = syringePumpStatus.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetSyringePumpEncoderStatus function overrides the syringe + * pump encoder status. + * @details Inputs: none + * @details Outputs: syringePumpEncoderStatus + * @param status override syringe pump encoder status with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpEncoderStatus( U32 status ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpEncoderStatus.ovData = status; + syringePumpEncoderStatus.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpEncoderStatus function resets the override + * of the syringe pump encoder status. + * @details Inputs: none + * @details Outputs: syringePumpEncoderStatus + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpEncoderStatus( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpEncoderStatus.override = OVERRIDE_RESET; + syringePumpEncoderStatus.ovData = syringePumpEncoderStatus.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetSyringePumpADCandDACStatus function overrides the syringe + * pump ADC and DAC status. + * @details Inputs: none + * @details Outputs: syringePumpADCandDACStatus + * @param status override syringe pump ADC and DAC status with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpADCandDACStatus( U32 status ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpADCandDACStatus.ovData = status; + syringePumpADCandDACStatus.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpADCandDACStatus function resets the override + * of the syringe pump ADC and DAC status. + * @details Inputs: none + * @details Outputs: syringePumpADCandDACStatus + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpADCandDACStatus( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpADCandDACStatus.override = OVERRIDE_RESET; + syringePumpADCandDACStatus.ovData = syringePumpADCandDACStatus.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetSyringePumpADCReadCounter function overrides the syringe + * pump ADC read counter. + * @details Inputs: none + * @details Outputs: syringePumpADCReadCtr + * @param ctr override syringe pump ADC read counter with this value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpADCReadCounter( U32 ctr ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpADCReadCtr.ovData = ctr; + syringePumpADCReadCtr.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpADCReadCounter function resets the override + * of the syringe pump ADC read counter. + * @details Inputs: none + * @details Outputs: syringePumpADCReadCtr + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpADCReadCounter( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpADCReadCtr.override = OVERRIDE_RESET; + syringePumpADCReadCtr.ovData = syringePumpADCReadCtr.ovInitData; + } + + return result; +} + /**@}*/