Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r21180e0b65fddfa27f66d8fb59cb55b2db304230 -rd4dfcd3155274d9252ddb5f10d9d081f3ecd6b5a --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 21180e0b65fddfa27f66d8fb59cb55b2db304230) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision d4dfcd3155274d9252ddb5f10d9d081f3ecd6b5a) @@ -1,52 +1,52 @@ /************************************************************************** * -* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* Copyright (c) 2021-2022 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 SyringePump.c +* @file SyringePump.c * -* @author (last) Sean Nash -* @date (last) 02-Mar-2021 +* @author (last) Dara Navaei +* @date (last) 03-Oct-2022 * -* @author (original) Sean Nash -* @date (original) 02-Mar-2021 +* @author (original) Sean Nash +* @date (original) 04-Mar-2021 * ***************************************************************************/ - -#include "AlarmMgmt.h" +#include + +#include "AlarmMgmt.h" #include "FPGA.h" -#include "ModeTreatmentParams.h" +#include "ModeTreatmentParams.h" +#include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "SafetyShutdown.h" -#include "SyringePump.h" -#include "SystemCommMessages.h" -#include "TaskPriority.h" -#include "Timers.h" - -/** - * @addtogroup SyringePump - * @{ - */ - -// ********** private definitions ********** - -/// Default publication interval for syringe pump data. +#include "SyringePump.h" +#include "SystemCommMessages.h" +#include "TaskPriority.h" +#include "Timers.h" + +/** + * @addtogroup SyringePump + * @{ + */ + +// ********** private definitions ********** + +/// 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. +#define BD_SYRINGE_ID_RADIUS_CM ( 1.4427F / 2.0F ) ///< Radius from inner diameter (in cm) of supported BD syringe. /// Milliliters per mm of syringe plunger travel. -#define SYRINGE_ML_PER_MM ( ( BD_SYRINGE_ID_RADIUS_CM * BD_SYRINGE_ID_RADIUS_CM ) * PI * 0.1 ) -#define SYRINGE_MM_PER_REV 0.635 ///< Travel (in mm) per revolution. -#define SYRINGE_ENCODER_COUNTS_PER_REV 4000.0 ///< Number of encoder counts per revolution. -#define SYRINGE_STEPS_PER_REV 200.0 ///< Number of steps per revolution. -#define MICRO_SECONDS_PER_SECOND 1000000.0 ///< Microseconds per second conversion. -#define SYRINGE_TOGGLES_PER_STEP 2.0 ///< Stepper motor driver toggles per step or microstep. -#define SYRINGE_MICRO_STEPS_PER_STEP 32.0 ///< Number of micro-steps per step. +#define SYRINGE_ML_PER_MM ( ( BD_SYRINGE_ID_RADIUS_CM * BD_SYRINGE_ID_RADIUS_CM ) * PI * 0.1F ) +#define SYRINGE_MM_PER_REV 0.635F ///< Travel (in mm) per revolution. +#define SYRINGE_ENCODER_COUNTS_PER_REV 4000.0F ///< Number of encoder counts per revolution. +#define SYRINGE_STEPS_PER_REV 200.0F ///< Number of steps per revolution. +#define MICRO_SECONDS_PER_SECOND 1000000.0F ///< Microseconds per second conversion. +#define SYRINGE_TOGGLES_PER_STEP 2.0F ///< Stepper motor driver toggles per step or microstep. +#define SYRINGE_MICRO_STEPS_PER_STEP 32.0F ///< Number of micro-steps per step. /// Number of micro steps per revolution. #define SYRINGE_MICRO_STEPS_PER_REV ( SYRINGE_STEPS_PER_REV * SYRINGE_MICRO_STEPS_PER_STEP ) @@ -55,53 +55,54 @@ /// Number of encoder counts per mL. #define SYRINGE_ENCODER_COUNTS_PER_ML ( SYRINGE_ENCODER_COUNTS_PER_MM / SYRINGE_ML_PER_MM ) /// Number of micro steps per mL. -#define SYRINGE_MICRO_STEPS_PER_ML ( ( SYRINGE_MICRO_STEPS_PER_REV / SYRINGE_MM_PER_REV ) / SYRINGE_ML_PER_MM ) +#define SYRINGE_MICRO_STEPS_PER_ML ( ( SYRINGE_MICRO_STEPS_PER_REV / SYRINGE_MM_PER_REV ) / SYRINGE_ML_PER_MM ) -#define MIN_HEPARIN_CONTINUOUS_RATE 0.1 ///< Minimum continuous Heparin flow rate (in mL/hr). -#define MAX_HEPARIN_CONTINUOUS_RATE 1.0 ///< Maximum continuous Heparin flow rate (in mL/hr). -#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_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 MIN_HEPARIN_CONTINUOUS_RATE 0.2F ///< Minimum continuous Heparin flow rate (in mL/hr). +#define MAX_HEPARIN_CONTINUOUS_RATE 1.0F ///< Maximum continuous Heparin flow rate (in mL/hr). +#define HEPARIN_BOLUS_TARGET_RATE 720.0F ///< Heparin bolus target rate (in ml/hr); +#define SYRINGE_PUMP_RETRACT_RATE 3600.0F ///< Retract rate is 5 mL/ 5 s = 1 mL/s = 3,600 mL/hr. +#define SYRINGE_PUMP_SEEK_RATE 3600.0F ///< Seek plunger rate is 5 mL/ 5 s = 1 mL/s = 3,600 mL/hr. +#define SYRINGE_PUMP_PRIME_RATE 635.0F ///< 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.0F ///< Maximum rate of the syringe pump (in mL/hr). #define SYRINGE_PUMP_RATE_ALARM_PERSISTENCE 3000 ///< 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 SYRINGE_PUMP_DIR_ALARM_PERSISTENCE 3000 ///< Alarm persistence period (in ms) for syringe pump direction check alarms. +#define SYRINGE_PUMP_OFF_ALARM_PERSISTENCE 1000 ///< Alarm persistence period (in ms) for syringe pump off check alarms. -#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. +#define STEPS_TO_MICROSTEPS( s ) ( (s) * 32.0F ) ///< Macro conversion from steps to microsteps. +#define MICROSTEPS_TO_STEPS( m ) ( (m) / 32.0F ) ///< Macro conversion from microsteps to steps. -#define SYRINGE_PUMP_ADC_REF_V 3.3 ///< Syringe pump ADC reference voltage. -#define SYRINGE_PUMP_ADC_FULL_SCALE_BITS 1024.0 ///< Syringe pump ADC has 1024 full scale counts (10-bit) per channel. -#define SYRINGE_PUMP_DAC_FULL_SCALE_BITS 4096.0 ///< Syringe pump DAC has has 4096 full scale counts (12-bit). +#define SYRINGE_PUMP_ADC_REF_V 3.3F ///< Syringe pump ADC reference voltage. +#define SYRINGE_PUMP_ADC_FULL_SCALE_BITS 1024.0F ///< Syringe pump ADC has 1024 full scale counts (10-bit) per channel. +#define SYRINGE_PUMP_DAC_FULL_SCALE_BITS 4096.0F ///< Syringe pump DAC has has 4096 full scale counts (12-bit). -#define SYRINGE_FORCE_OCCLUSION_THRESHOLD_V 3.2 ///< Force sensor threshold (in V) above which an occlusion is detected. -#define SYRINGE_FORCE_PLUNGER_THRESHOLD_V 0.25 ///< Force sensor threshold (in V) above which we have engaged with plunger. -#define SYRINGE_PUMP_SYRINGE_DETECT_THRESHOLD_V 2.0 ///< Syringe pump syringe detected threshold (in V). -#define SYRINGE_PUMP_HOME_DETECT_THRESHOLD_V 0.25 ///< Syringe pump home detected threshold (in V). -#define SYRINGE_PUMP_PRIME_VOLUME_ML 0.353 ///< Target syringe prime volume (in mL). -#define SYRINGE_PUMP_MAX_VOL_ERROR_ML 0.1 ///< Maximum Heparin volume error (in mL). -#define SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR 0.1 ///< Maximum Heparin delivery rate error (in mL/hr). -#define TEN_PCT_OVER_ALLOWANCE 1.1 ///< Allow 10 percent over target before alarming on over travel. -#define FIVE_PCT_OVER_ALLOWANCE 1.05 ///< Allow 5 percent over target before alarming on over travel. +#define SYRINGE_FORCE_OCCLUSION_THRESHOLD_V 3.2F ///< Force sensor threshold (in V) above which an occlusion is detected. +#define SYRINGE_FORCE_OCCLUSION_DIFF_V 0.5F ///< Force sensor difference (in V) which an occlusion alarm is triggered. +#define SYRINGE_FORCE_PLUNGER_THRESHOLD_V 0.25F ///< Force sensor threshold (in V) above which we have engaged with plunger. +#define SYRINGE_PUMP_SYRINGE_DETECT_THRESHOLD_V 2.0F ///< Syringe pump syringe detected threshold (in V). +#define SYRINGE_PUMP_HOME_DETECT_THRESHOLD_V 0.25F ///< Syringe pump home detected threshold (in V). +#define SYRINGE_PUMP_PRIME_VOLUME_ML 0.353F ///< Target syringe prime volume (in mL). +#define SYRINGE_PUMP_PRELOAD_MARGIN_VOLUME_ML 1.0F ///< Target syringe preload margin volume (in mL). Total to deliver plus this give syringe load position. +#define SYRINGE_PUMP_PRELOAD_MAX_VOLUME_ML 10.0F ///< Target syringe preload max volume (in mL). Leave at home position above this value. +#define SYRINGE_PUMP_MAX_VOL_ERROR_ML 0.1F ///< Maximum Heparin volume error (in mL). +#define SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR 0.1F ///< Maximum Heparin delivery rate error (in mL/hr). +#define TEN_PCT_OVER_ALLOWANCE 1.1F ///< Allow 10 percent over target before alarming on over travel. +#define FIVE_PCT_OVER_ALLOWANCE 1.05F ///< Allow 5 percent over target before alarming on over travel. +#define SYRINGE_PUMP_DAC_VOLTAGE_MAX_ERROR 0.05F ///< Force sensor POST check for DAC voltage - max delta. +#define MIN_SYRINGE_PUMP_RATE_FOR_DIR_ALARM 0.5F ///< Minimum measured rate (in mL/hr) required before enforcing direction alarm. -/// Expected position of empty in relation to home postion. -#define SYRINGE_PUMP_EMPTY_POS ( SYRINGE_ENCODER_COUNTS_PER_ML * 11.0 ) // TODO - get syringe volume from home to empty (11 mL is placeholder) +/// Expected position of empty in relation to home position. +#define SYRINGE_PUMP_EMPTY_POS ( SYRINGE_ENCODER_COUNTS_PER_ML * 10.84F ) /// Margin of error for empty position determination. -#define SYRINGE_PUMP_EMPTY_POS_MARGIN ( SYRINGE_ENCODER_COUNTS_PER_ML * 0.5 ) +#define SYRINGE_PUMP_EMPTY_POS_MARGIN ( SYRINGE_ENCODER_COUNTS_PER_ML * 0.5F ) /// Minimum retract position. -#define SYRINGE_PUMP_RETRACT_POS_MIN ( SYRINGE_ENCODER_COUNTS_PER_ML * -0.5 ) +#define SYRINGE_PUMP_RETRACT_POS_MIN ( SYRINGE_ENCODER_COUNTS_PER_ML * -0.5F ) #define SYRINGE_PUMP_START_RAMP_SPEED 300000 ///< Starting speed for all syringe pump operations to ramp up from. -#define SYRINGE_PUMP_RAMP_DIVISOR 11 ///< Used for ramping profile. +#define SYRINGE_PUMP_RAMP_DIVISOR 5 ///< Used for ramping profile. -#define SYRINGE_PUMP_RATE_CHECK_MARGIN 0.05 ///< 5 pct margin on commanded vs. measured rate check. -#define SYRINGE_PUMP_VOLUME_CHECK_MARGIN 0.05 ///< 5 pct margin on commanded vs. encoder based volume check. +#define SYRINGE_PUMP_RATE_CHECK_MARGIN 0.05F ///< 5 pct margin on commanded vs. measured rate check. +#define SYRINGE_PUMP_VOLUME_CHECK_MARGIN 0.05F ///< 5 pct margin on commanded vs. encoder based volume check. // Bit definitions for syringe pump control register #define SYRINGE_PUMP_CONTROL_SLEEP_OFF 0x40 ///< Syringe pump control register bit for sleep mode (active low). @@ -125,7 +126,9 @@ #define SYRINGE_PUMP_ENCODER_STATUS_ERROR_COUNT_MASK 0x3F ///< Syringe pump encoder status error count bit-mask. // Stepper motor toggle time for zero speed (stopped) #define SYRINGE_PUMP_MICROSTEP_TOGGLE_TIME_FOR_STOP 0xFFFFFFFF ///< Syringe pump microstep toggle time setting to indicate zero speed (stopped). - + +#define DATA_PUBLISH_COUNTER_START_COUNT 10 ///< Data publish counter start count. + /// Control bits to run syringe pump in reverse direction static const U08 SYRINGE_PUMP_CONTROL_RUN_REVERSE = SYRINGE_PUMP_CONTROL_SLEEP_OFF | SYRINGE_PUMP_CONTROL_NOT_RESET | @@ -143,56 +146,74 @@ #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.05F ///< Minimum syringe pump speed to be considered not stalled. -/// Defined states for the syringe pump control state machine. -typedef enum SyringePump_States -{ +#define SYRINGE_PUMP_ADC_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Syringe pump ADC FPGA error timeout in milliseconds. + +/// Defined states for the syringe pump control state machine. +typedef enum SyringePump_States +{ SYRINGE_PUMP_INIT_STATE = 0, ///< Syringe pump initialize state - SYRINGE_PUMP_OFF_STATE, ///< Syringe pump off state + SYRINGE_PUMP_OFF_STATE, ///< Syringe pump off state SYRINGE_PUMP_RETRACT_STATE, ///< Syringe pump retract state + SYRINGE_PUMP_PRELOAD_STATE, ///< Syringe pump preload state SYRINGE_PUMP_SEEK_STATE, ///< Syringe pump seek plunger state SYRINGE_PUMP_PRIME_STATE, ///< Syringe pump prime state SYRINGE_PUMP_HEP_BOLUS_STATE, ///< Syringe pump bolus delivery of Heparin state SYRINGE_PUMP_HEP_CONTINUOUS_STATE, ///< Syringe pump continuous delivery of Heparin state SYRINGE_PUMP_CONFIG_FORCE_SENSOR_STATE, ///< Syringe pump configure DAC gain for force sensor state - NUM_OF_SYRINGE_PUMP_STATES ///< Number of syringe pump control states -} SYRINGE_PUMP_STATE_T; - -// ********** private data ********** - -static SYRINGE_PUMP_STATE_T syringePumpState; ///< Current state of syringe pump control state machine. + NUM_OF_SYRINGE_PUMP_STATES ///< Number of syringe pump control states +} SYRINGE_PUMP_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_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 F32 syringePumpVolumeRequired = 0.0F; ///< Volume required for complete therapy (in mL). +static OVERRIDE_F32_T heparinBolusTargetRate = { HEPARIN_BOLUS_TARGET_RATE, 0.0, HEPARIN_BOLUS_TARGET_RATE, 0 }; ///< Target rate of the heprin bolus in mL/hour + 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 BOOL requireSyringeDetection; ///< Flag indicating whether syringe detection is required in the current state. + static F32 syringePumpSetRate; ///< Set rate for syringe pump (in mL/hr). +static F32 forceAtEndOfSeek; ///< Force sensor reading in Volts at the end of seek. 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 syringePumpRampUpPct; ///< Percentage progress of ramp to target rate. 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 syringePumpLastPosition; ///< Position previously recorded. -static S32 syringePumpPosition1SecAgo; ///< Position recorded at last 1 Hz speed check. +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. static BOOL syringePumpRetractRequested; ///< Flag indicates a retract operation is requested. +static BOOL syringePumpPreloadRequested; ///< Flag indicates a plunger preload operation is requested. static BOOL syringePumpSeekRequested; ///< Flag indicates a plunger seek operation is requested. static BOOL syringePumpPrimeRequested; ///< Flag indicates a Heparin prime operation is requested. static BOOL syringePumpBolusRequested; ///< Flag indicates start or resume of a Heparin bolus operation is requested. @@ -207,28 +228,30 @@ static BOOL syringePumpDACVrefWriteInProgress; ///< Flag indicates DAC Vref write is in progress. static F32 syringePumpDACVref; ///< DAC Vref setting for force sensor. -static U08 lastSyringePumpADCReadCtr; ///< Remember last ADC read counter to check new reads are fresh. - static U32 syringePumpStallCtr; ///< Counts time when position is not changing during ramp. static U32 syringePumpStallRetryCount; ///< Counts pump ramp up stall retries. +static HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T forceSensorCalRecord; ///< HD heparin force sensor calibration record. -// ********** private function prototypes ********** +// ********** private function prototypes ********** static void resetSyringePumpRequestFlags( void ); -static void execSyringePumpMonitor( void ); -static U32 getPublishSyringePumpDataInterval( void ); +static void resetHeparinVolumeDelivered( void ); +static void execSyringePumpMonitor( void ); static S32 getSyringePumpPosition( void ); static F32 getSyringePumpMeasRate( void ); static F32 getSyringePumpSyringeDetectorV( void ); static F32 getSyringePumpHomeDetectorV( void ); static F32 getSyringePumpForceV( void ); +static F32 getHeprinBolusTargetRate( 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 handleSyringePumpInitState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpOffState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpRetractState( void ); +static SYRINGE_PUMP_STATE_T handleSyringePumpPreLoadState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpSeekState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpPrimeState( void ); static SYRINGE_PUMP_STATE_T handleSyringePumpBolusState( void ); @@ -239,59 +262,75 @@ static void calcMeasRate( void ); static void calcSafetyVolumeDelivered( void ); static BOOL checkDirection( BOOL stopPump, MOTOR_DIR_T expDir ); -static BOOL checkOcclusionOrEmpty( BOOL stopPump ); +static BOOL checkSyringeEmpty( 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 ); - -/*********************************************************************//** - * @brief - * The initSyringePump function initializes the syringe pump module. - * @details Inputs: none - * @details Outputs: syringe pump module initialized. - * @return none - *************************************************************************/ -void initSyringePump( void ) + +/*********************************************************************//** + * @brief + * The initSyringePump function initializes the syringe pump module. + * @details Inputs: none + * @details Outputs: syringe pump module initialized. + * @return none + *************************************************************************/ +void initSyringePump( void ) { + U32 i; + syringePumpState = SYRINGE_PUMP_INIT_STATE; heparinDeliveryState = HEPARIN_STATE_OFF; - + requireSyringeDetection = FALSE; syringePumpSetRate = 0.0; syringePumpSetToggleTime = 0; syringePumpSafetyVolumeDelivered = 0.0; syringePumpVolumeStartPosition = 0; syringePumpHomePositionOffset = 0; syringePumpLastPosition = 0; - syringePumpPosition1SecAgo = 0; - syringePumpControllerMeasuredDirection = MOTOR_DIR_FORWARD; - syringePumpEncoderMeasuredDirection = MOTOR_DIR_FORWARD; - syringePumpDataPublicationTimerCounter = 0; +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) + { + syringePumpControllerMeasuredDirection = MOTOR_DIR_FORWARD; + syringePumpEncoderMeasuredDirection = MOTOR_DIR_FORWARD; + } +#endif + + syringePumpDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; syringePumpSpeedCalcTimerCounter = 0; syringePumpRampTimerCtr = 0; + syringePumpSafetyVolumeDelivered = 0.0; syringePumpPositionKnown = FALSE; syringePumpPlungerFound = FALSE; syringeVolumeAdequate = FALSE; syringePumpPrimeCompleted = FALSE; + syringePumpRampUpPct = 0.0; - 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 + initFPGAPersistentAlarm( FPGA_PERS_ERROR_SYRINGE_PUMP_ADC, ALARM_ID_HD_SYRINGE_PUMP_FPGA_ADC_FAULT, + SYRINGE_PUMP_ADC_FPGA_ERROR_TIMEOUT_MS, SYRINGE_PUMP_ADC_FPGA_ERROR_TIMEOUT_MS ); + + // Reset request flags resetSyringePumpRequestFlags(); } @@ -306,6 +345,7 @@ { syringePumpRetractRequested = FALSE; syringePumpSeekRequested = FALSE; + syringePumpPreloadRequested = FALSE; syringePumpPrimeRequested = FALSE; syringePumpBolusRequested = FALSE; syringePumpContinuousRequested = FALSE; @@ -337,6 +377,7 @@ accepted = TRUE; heparinDeliveryState = HEPARIN_STATE_PAUSED; stopSyringePump(); + sendTreatmentLogEventData( HEPARIN_START_RESUME_EVENT, HEPARIN_STATE_DISPENSING, HEPARIN_STATE_PAUSED ); } else { @@ -349,6 +390,7 @@ { accepted = TRUE; startHeparinContinuous(); + sendTreatmentLogEventData( HEPARIN_START_RESUME_EVENT, HEPARIN_STATE_PAUSED, HEPARIN_STATE_DISPENSING ); } else { @@ -430,7 +472,7 @@ * @brief * The stopSyringePump function requests syringe pump be stopped. * @details Inputs: none - * @details Outputs: syringePumpSetRate, syringePumpRetractRequested, syringePumpState + * @details Outputs: syringePumpSetRate, syringePumpState, heparinDeliveryState * @return TRUE if request accepted, FALSE if not *************************************************************************/ void stopSyringePump( void ) @@ -448,19 +490,15 @@ * @brief * The retractSyringePump function requests retract operation. * @details Inputs: syringePumpState - * @details Outputs: syringePumpSetRate, syringePumpRetractRequested + * @details Outputs: syringePumpSetRate, syringePumpRetractRequested, heparinDeliveryState * @return TRUE if request accepted, FALSE if not *************************************************************************/ 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 + if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) { - syringePumpSetRate = SYRINGE_PUMP_RETRACT_RATE; + heparinDeliveryState = HEPARIN_STATE_STOPPED; + syringePumpSetRate = SYRINGE_PUMP_RETRACT_RATE; syringePumpRetractRequested = TRUE; } @@ -469,13 +507,40 @@ /*********************************************************************//** * @brief + * The preloadSyringePlunger function requests plunger preload operation. + * @details Inputs: syringePumpState + * @details Outputs: syringePumpSetRate, syringePumpPreloadRequested + * @return TRUE if request accepted, FALSE if not + *************************************************************************/ +BOOL preloadSyringePlunger( void ) +{ + if ( MODE_SERV == getCurrentOperationMode() ) // Allow syringe pump operations in Service Mode. + { + heparinDeliveryState = HEPARIN_STATE_STOPPED; + } + if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( FALSE == isSyringeDetected() ) && + ( TRUE == syringePumpPositionKnown ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) ) + { + syringePumpSetRate = SYRINGE_PUMP_SEEK_RATE; + syringePumpPreloadRequested = TRUE; + } + + return syringePumpPreloadRequested; +} + +/*********************************************************************//** + * @brief * The seekSyringePlunger function requests plunger seek operation. * @details Inputs: syringePumpState * @details Outputs: syringePumpSetRate, syringePumpSeekRequested * @return TRUE if request accepted, FALSE if not *************************************************************************/ BOOL seekSyringePlunger( void ) { + if ( MODE_SERV == getCurrentOperationMode() ) // Allow syringe pump operations in Service Mode. + { + heparinDeliveryState = HEPARIN_STATE_STOPPED; + } if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( TRUE == isSyringeDetected() ) && ( TRUE == syringePumpPositionKnown ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) ) { @@ -495,53 +560,68 @@ *************************************************************************/ BOOL primeSyringePump( void ) { + if ( MODE_SERV == getCurrentOperationMode() ) // Allow syringe pump operations in Service Mode. + { + heparinDeliveryState = HEPARIN_STATE_STOPPED; + } if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( TRUE == isSyringeDetected() ) && ( heparinDeliveryState != HEPARIN_STATE_OFF ) && ( TRUE == syringePumpPlungerFound ) ) { + forceAtEndOfSeek = getSyringePumpForceV(); // Get the force sensor reading when syringe pump prime has been requested (after seek) 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(); + resetHeparinVolumeDelivered(); } return syringePumpPrimeRequested; } /*********************************************************************//** * @brief + * The resetHeparinVolumeDelivered function resets the Heparin volume delivered. + * @details Inputs: none + * @details Outputs: syringePumpVolumeDelivered, syringePumpSafetyVolumeDelivered, + * syringePumpVolumeStartPosition + * @return none + *************************************************************************/ +static void resetHeparinVolumeDelivered( void ) +{ + syringePumpVolumeDelivered.data = 0.0; + syringePumpSafetyVolumeDelivered = 0.0; + syringePumpVolumeStartPosition = getSyringePumpPosition(); +} + +/*********************************************************************//** + * @brief * The startHeparinBolus function requests Heparin bolus delivery. * @details Inputs: syringePumpState * @details Outputs: syringePumpSetRate, syringePumpBolusRequested * @return TRUE if request accepted, FALSE if not *************************************************************************/ BOOL startHeparinBolus( void ) { - F32 tgtRate = 0.0; - - // Get set Heparin bolus volume (mL) and convert to target rate (mL/hr) - tgtRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ) / HEPARIN_BOLUS_TIME_HR; - // If valid to start a bolus, kick it off - if ( ( tgtRate >= MIN_HEPARIN_BOLUS_RATE ) && ( tgtRate <= MAX_HEPARIN_BOLUS_RATE ) && ( FALSE == isSyringePumpHome() ) ) + if ( FALSE == isSyringePumpHome() ) { + if ( MODE_SERV == getCurrentOperationMode() ) // Allow syringe pump operations in Service Mode. + { + heparinDeliveryState = HEPARIN_STATE_STOPPED; + } if ( ( TRUE == isSyringeDetected() ) && ( TRUE == syringePumpPrimeCompleted ) && ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( HEPARIN_STATE_STOPPED == heparinDeliveryState ) ) { - syringePumpSetRate = tgtRate; + syringePumpSetRate = getHeprinBolusTargetRate(); syringePumpBolusRequested = TRUE; - // Reset volume and start pos before starting bolus operation - syringePumpVolumeDelivered.data = 0.0; - syringePumpSafetyVolumeDelivered = 0.0; - syringePumpVolumeStartPosition = getSyringePumpPosition(); } } else { -#ifndef DISABLE_SYRINGE_PUMP - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (F32)SW_FAULT_ID_HD_SYRINGE_INVALID_BOLUS_CMD, tgtRate ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (F32)SW_FAULT_ID_HD_SYRINGE_INVALID_BOLUS_CMD, syringePumpSetRate ) + } } return syringePumpBolusRequested; @@ -560,6 +640,10 @@ if ( ( flowRate >= MIN_HEPARIN_CONTINUOUS_RATE ) && ( flowRate <= MAX_HEPARIN_CONTINUOUS_RATE ) && ( FALSE == isSyringePumpHome() ) ) { + if ( MODE_SERV == getCurrentOperationMode() ) // Allow syringe pump operations in Service Mode. + { + heparinDeliveryState = HEPARIN_STATE_STOPPED; + } if ( ( TRUE == isSyringeDetected() ) && ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( ( HEPARIN_STATE_STOPPED == heparinDeliveryState ) || ( HEPARIN_STATE_PAUSED == heparinDeliveryState ) ) ) { @@ -569,9 +653,12 @@ } else { -#ifndef DISABLE_SYRINGE_PUMP - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (F32)SW_FAULT_ID_HD_SYRINGE_INVALID_CONT_CMD, flowRate ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) != SW_CONFIG_ENABLE_VALUE ) #endif + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (F32)SW_FAULT_ID_HD_SYRINGE_INVALID_CONT_CMD, flowRate ) + } } return syringePumpContinuousRequested; @@ -582,14 +669,15 @@ * The setSyringePumpDACVref function requests to set the DAC Vref setting. * @details Inputs: none * @details Outputs: syringePumpDACVrefSetRequested, syringePumpDACVref - * @param vRef voltage to set DAC Vref to (in V) * @return TRUE if request accepted, FALSE if not *************************************************************************/ -BOOL setSyringePumpDACVref( F32 vRef ) +BOOL setSyringePumpDACVref( void ) { - if ( ( vRef >= 0.0 ) && ( vRef <= 3.3 ) ) - { - if ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) + F32 vRef = forceSensorCalRecord.hdHeparinForceSensorDACVoltage; + + if ( ( vRef >= 0.0 ) && ( vRef <= SYRINGE_PUMP_ADC_REF_V ) ) + { // Cannot set DAC value if pump is busy or calibration values have not been provided yet + if ( ( SYRINGE_PUMP_OFF_STATE == syringePumpState ) && ( forceSensorCalRecord.calibrationTime != 0 ) ) { syringePumpDACVref = vRef; syringePumpDACVrefSetRequested = TRUE; @@ -605,22 +693,38 @@ /*********************************************************************//** * @brief - * The getPublishSyringePumpDataInterval function gets the syringe pump data - * publication interval. - * @details Inputs: syringePumpDataPublishInterval - * @details Outputs: none - * @return the current syringe pump data publication interval (in task intervals). + * The syringeDetectionRequired function sets a flag indicating whether + * the syringe detection is required in current state. + * @details Inputs: none + * @details Outputs: requireSyringeDetection + * @param req True if syringe detection is required in the current state + * @return none *************************************************************************/ -static U32 getPublishSyringePumpDataInterval( void ) +void syringeDetectionRequired( BOOL req ) { - U32 result = syringePumpDataPublishInterval.data; + requireSyringeDetection = req; +} - if ( OVERRIDE_KEY == syringePumpDataPublishInterval.override ) +/*********************************************************************//** + * @brief + * The syringePumpVerifyForceSensorDACCalibration function verifies that the + * syringe pump force sensor DAC has been calibrated and is reporting no force + * as would be expected when fully retracted (caller should not call this function + * until the syringe pump is homed first). + * @details Inputs: none + * @details Outputs: + * @return none + *************************************************************************/ +void syringePumpVerifyForceSensorDACCalibration( void ) +{ + F32 DACDeltaV = fabs( forceSensorCalRecord.hdHeparinForceSensorDACVoltage - getSyringePumpForceV() ); + + if ( DACDeltaV > SYRINGE_PUMP_DAC_VOLTAGE_MAX_ERROR ) { - result = syringePumpDataPublishInterval.ovData; + SET_ALARM_WITH_1_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SELF_TEST_FAILURE, DACDeltaV ) + // In case DAC not set yet, try to set DAC + setSyringePumpDACVref(); } - - return result; } /*********************************************************************//** @@ -633,14 +737,7 @@ *************************************************************************/ F32 getSyringePumpVolumeDelivered( void ) { - F32 result = syringePumpVolumeDelivered.data; - - if ( OVERRIDE_KEY == syringePumpVolumeDelivered.override ) - { - result = syringePumpVolumeDelivered.ovData; - } - - return result; + return getF32OverrideValue( &syringePumpVolumeDelivered ); } /*********************************************************************//** @@ -653,38 +750,11 @@ *************************************************************************/ static F32 getSyringePumpMeasRate( void ) { - F32 result = syringePumpMeasRate.data; - - if ( OVERRIDE_KEY == syringePumpMeasRate.override ) - { - result = syringePumpMeasRate.ovData; - } - - return result; + return getF32OverrideValue( &syringePumpMeasRate ); } /*********************************************************************//** * @brief - * The getSyringePumpPosition function gets the current syringe pump - * position. - * @details Inputs: syringePumpPosition - * @details Outputs: none - * @return the current syringe pump syringe position (in steps). - *************************************************************************/ -static S32 getSyringePumpPosition( void ) -{ - S32 result = syringePumpPosition.data; - - if ( OVERRIDE_KEY == syringePumpPosition.override ) - { - result = syringePumpPosition.ovData; - } - - return result; -} - -/*********************************************************************//** - * @brief * The getSyringePumpSyringeDetectorV function gets the current syringe pump * syringe detect signal. * @details Inputs: syringePumpMeasSyringeDetectionSwitch @@ -693,14 +763,7 @@ *************************************************************************/ static F32 getSyringePumpSyringeDetectorV( void ) { - F32 result = syringePumpMeasSyringeDetectionSwitch.data; - - if ( OVERRIDE_KEY == syringePumpMeasSyringeDetectionSwitch.override ) - { - result = syringePumpMeasSyringeDetectionSwitch.ovData; - } - - return result; + return getF32OverrideValue( &syringePumpMeasSyringeDetectionSwitch ); } /*********************************************************************//** @@ -713,14 +776,7 @@ *************************************************************************/ static F32 getSyringePumpHomeDetectorV( void ) { - F32 result = syringePumpMeasHome.data; - - if ( OVERRIDE_KEY == syringePumpMeasHome.override ) - { - result = syringePumpMeasHome.ovData; - } - - return result; + return getF32OverrideValue( &syringePumpMeasHome ); } /*********************************************************************//** @@ -732,14 +788,33 @@ *************************************************************************/ static F32 getSyringePumpForceV( void ) { - F32 result = syringePumpMeasForce.data; + return getF32OverrideValue( &syringePumpMeasForce ); +} - if ( OVERRIDE_KEY == syringePumpMeasForce.override ) - { - result = syringePumpMeasForce.ovData; - } +/*********************************************************************//** + * @brief + * The getHeprinBolusTargetRate function gets the heprin bolus target + * flow rate. + * @details Inputs: getHeprinBolusTargetRate + * @details Outputs: getHeprinBolusTargetRate + * @return the current target heprin bolus flow rate (in mL/hour). + *************************************************************************/ +static F32 getHeprinBolusTargetRate( void ) +{ + return getF32OverrideValue( &heparinBolusTargetRate ); +} - return result; +/*********************************************************************//** + * @brief + * The getSyringePumpPosition function gets the current syringe pump + * position. + * @details Inputs: syringePumpPosition + * @details Outputs: none + * @return the current syringe pump syringe position (in steps). + *************************************************************************/ +static S32 getSyringePumpPosition( void ) +{ + return getS32OverrideValue( &syringePumpPosition ); } /*********************************************************************//** @@ -751,14 +826,7 @@ *************************************************************************/ 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; + return getU08OverrideValue( &syringePumpStatus ); } /*********************************************************************//** @@ -771,14 +839,7 @@ *************************************************************************/ 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; + return getU08OverrideValue( &syringePumpEncoderStatus ); } /*********************************************************************//** @@ -791,14 +852,7 @@ *************************************************************************/ 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; + return getU08OverrideValue( &syringePumpADCReadCtr ); } /*********************************************************************//** @@ -811,14 +865,7 @@ *************************************************************************/ 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; + return getU08OverrideValue( &syringePumpADCandDACStatus ); } /*********************************************************************//** @@ -923,13 +970,38 @@ /*********************************************************************//** * @brief + * The isSyringePumpRunning function determines whether the syringe pump + * is currently running an operation. + * @details Inputs: syringePumpState + * @details Outputs: none + * @return TRUE if syringe pump operation is currently running, FALSE if not. + *************************************************************************/ +BOOL isSyringePumpRunning( void ) +{ + BOOL result = ( syringePumpState > SYRINGE_PUMP_OFF_STATE ? TRUE : FALSE ); + + return result; +} + +/*********************************************************************//** + * @brief * The execSyringePumpMonitor function executes the syringe pump monitor. * @details Inputs: FPGA syringe pump readings * @details Outputs: Alarm(s) may be triggered * @return none *************************************************************************/ static void execSyringePumpMonitor( void ) { + BOOL prevSyringeDetected = isSyringeDetected(); + + // Check if a new calibration is available + if ( TRUE == isNewCalibrationRecordAvailable() ) + { + // Get the new calibration data and check its validity + getNVRecord2Driver( GET_CAL_HEPARIN_FORCE_SENSOR, (U08*)&forceSensorCalRecord, sizeof( HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T ), + 0, ALARM_ID_HD_HEPARIN_FORCE_SENSOR_INVALID_CAL_RECORD ); + } + S32 encPosition = getFPGASyringePumpEncoderPosition(); // Get latest FPGA status @@ -940,43 +1012,102 @@ // 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; +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP ) != SW_CONFIG_DISABLE_VALUE ) + { + syringePumpMeasSyringeDetectionSwitch.data = 0.0; // if syringe pump disabled, always report no detection + } + else +#endif + { + syringePumpMeasSyringeDetectionSwitch.data = ( (F32)getFPGASyringePumpADCChannel1() * SYRINGE_PUMP_ADC_REF_V ) / SYRINGE_PUMP_ADC_FULL_SCALE_BITS; + } + + // Log syringe detect switch changes + if ( prevSyringeDetected != isSyringeDetected() ) + { + sendTreatmentLogEventData( SYRINGE_DETECTION_SWITCH_CHANGED_EVENT, (F32)prevSyringeDetected, (F32)isSyringeDetected() ); + } + // Handle syringe detect alarm management +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + F32 bolusVol = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_BOLUS_VOLUME ); + F32 hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); + + // Syringe detection not required if not using Heparin in treatment + if ( ( bolusVol > NEARLY_ZERO ) || ( hepRate > NEARLY_ZERO ) ) + { + // On transition from not detected to detected or if syringe detection not required - clear syringe removed alarm condition + if ( ( ( prevSyringeDetected != TRUE ) && ( TRUE == isSyringeDetected() ) ) || ( requireSyringeDetection != TRUE ) ) + { + clearAlarmCondition( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_REMOVED ); + } + // If no syringe detected and detection is required, trigger alarm condition + else if ( ( FALSE == isSyringeDetected() ) && ( TRUE == requireSyringeDetection ) ) + { + activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_REMOVED ); + } + // On transition from detected to not detected - clear syringe detected alarm condition + if ( ( TRUE == prevSyringeDetected ) && ( isSyringeDetected() != TRUE ) ) + { + clearAlarmCondition( ALARM_ID_HD_SYRINGE_DETECTED ); + } + // If syringe detected and alarm active, maintain alarm condition + else if ( ( TRUE == isSyringeDetected() ) && ( TRUE == isAlarmActive( ALARM_ID_HD_SYRINGE_DETECTED ) ) ) + { + activateAlarmNoData( ALARM_ID_HD_SYRINGE_DETECTED ); + } + } + else + { + clearAlarmCondition( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_REMOVED ); + clearAlarmCondition( ALARM_ID_HD_SYRINGE_DETECTED ); + syringePumpVolumeRequired = 0.0F; + } + } + 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; + syringePumpVolumeDelivered.data = (F32)( syringePumpPosition.data - syringePumpVolumeStartPosition ) / SYRINGE_ENCODER_COUNTS_PER_ML; calcSafetyVolumeDelivered(); // Calculate measured rate (mL/hr) calcMeasRate(); - // Get measured direction - 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 ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + // Get measured direction + 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 ); + } + // Check if syringe pump is on while BP is off { - BOOL runWhileOff = ( ( ( SYRINGE_PUMP_HEP_BOLUS_STATE == syringePumpState ) || ( SYRINGE_PUMP_HEP_CONTINUOUS_STATE == syringePumpState ) ) && - ( isBloodPumpRunning() != TRUE ) ); + BOOL runWhileOff = ( ( SYRINGE_PUMP_HEP_CONTINUOUS_STATE == syringePumpState ) && ( isBloodPumpRunning() != TRUE ) ); if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, runWhileOff ) ) { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_RUNNING_WHILE_BP_OFF_ERROR, (U32)syringePumpState ); } } - if ( syringePumpDACVrefWriteInProgress != TRUE ) + if ( ( FALSE == syringePumpDACVrefWriteInProgress ) && ( getCurrentOperationMode() > MODE_INIT ) ) { - // 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() ) ) ) ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR ); + checkFPGAPersistentAlarms( FPGA_PERS_ERROR_SYRINGE_PUMP_ADC, getSyringePumpADCandDACStatus(), getSyringePumpADCReadCounter() ); } - lastSyringePumpADCReadCtr = getSyringePumpADCReadCounter(); - // Check pump status if ( getSyringePumpStatus() != 0 ) { @@ -985,33 +1116,43 @@ } } -/*********************************************************************//** - * @brief - * The execSyringePump function executes the syringe pump control state machine. - * @details Inputs: syringePumpState - * @details Outputs: syringePumpState - * @return none - *************************************************************************/ -void execSyringePump( void ) +/*********************************************************************//** + * @brief + * The execSyringePump function executes the syringe pump control state machine. + * @details Inputs: syringePumpState + * @details Outputs: syringePumpState + * @return none + *************************************************************************/ +void execSyringePump( void ) { // Execute syringe pump monitor execSyringePumpMonitor(); - - // Execute syringe pump control state machine - switch ( syringePumpState ) - { - case SYRINGE_PUMP_INIT_STATE: - syringePumpState = handleSyringePumpInitState(); - break; - - case SYRINGE_PUMP_OFF_STATE: - syringePumpState = handleSyringePumpOffState(); - break; - + + // Clear pump running while off alarm persistence if not in off state + if ( syringePumpState != SYRINGE_PUMP_OFF_STATE ) + { + isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, FALSE ); + } + + // Execute syringe pump control state machine + switch ( syringePumpState ) + { + case SYRINGE_PUMP_INIT_STATE: + syringePumpState = handleSyringePumpInitState(); + break; + + case SYRINGE_PUMP_OFF_STATE: + syringePumpState = handleSyringePumpOffState(); + break; + case SYRINGE_PUMP_RETRACT_STATE: syringePumpState = handleSyringePumpRetractState(); break; + case SYRINGE_PUMP_PRELOAD_STATE: + syringePumpState = handleSyringePumpPreLoadState(); + break; + case SYRINGE_PUMP_SEEK_STATE: syringePumpState = handleSyringePumpSeekState(); break; @@ -1032,23 +1173,55 @@ syringePumpState = handleSyringePumpCalibrateForceSensorState(); break; - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_SYRINGE_INVALID_STATE, syringePumpState ) - break; - } + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_SYRINGE_INVALID_STATE, syringePumpState ) + break; + } resetSyringePumpRequestFlags(); - - // Publish syringe pump data on interval - publishSyringePumpData(); -} + // Publish syringe pump data on interval + publishSyringePumpData(); +} + /*********************************************************************//** * @brief + * The execSyringePumpSelfTest function executes the state machine for the + * syringe pump self-test. + * @details Inputs: none + * @details Outputs: forceSensorCalRecord + * @return TRUE if the self test passed otherwise, FALSE + *************************************************************************/ +SELF_TEST_STATUS_T execSyringePumpSelfTest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_PASSED; + // Read/check force sensor calibration + BOOL calStatus = getNVRecord2Driver( GET_CAL_HEPARIN_FORCE_SENSOR, (U08*)&forceSensorCalRecord, sizeof( HD_HEPARIN_FORCE_SENSOR_CAL_RECORD_T ), + 0, ALARM_ID_HD_HEPARIN_FORCE_SENSOR_INVALID_CAL_RECORD ); + +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + if ( TRUE == calStatus ) + { + result = SELF_TEST_STATUS_PASSED; + } + else + { + result = SELF_TEST_STATUS_FAILED; + } + } + + return result; +} + +/*********************************************************************//** + * @brief * The handleSyringePumpInitState function handles the initialize state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: none + * @details Outputs: pump speed set to zero, ADC enabled, direction set to reverse * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpInitState( void ) @@ -1069,26 +1242,44 @@ * @brief * The handleSyringePumpOffState function handles the off state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpRetractRequested, syringePumpSeekRequested, + * syringePumpPrimeRequested, syringePumpBolusRequested, syringePumpContinuousRequested, + * syringePumpDACVrefSetRequested + * @details Outputs: Pump speed and direction set if pump command initiated * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpOffState( void ) { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_OFF_STATE; // Check position is not changing while stopped - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, ( syringePumpLastPosition != getSyringePumpPosition() ) ) ) + if ( ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR, ( syringePumpLastPosition != getSyringePumpPosition() ) ) ) ) { +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_NOT_STOPPED_ERROR ); activateSafetyShutdown(); + } } + // Reset persistence for direction alarms while pump is off + isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, FALSE ); + isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, FALSE ); + isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, FALSE ); + // Reset ramp % complete + syringePumpRampUpPct = 0.0; + // Check for request flags if ( TRUE == syringePumpRetractRequested ) { result = SYRINGE_PUMP_RETRACT_STATE; } + else if ( TRUE == syringePumpPreloadRequested ) + { + result = SYRINGE_PUMP_PRELOAD_STATE; + } else if ( TRUE == syringePumpSeekRequested ) { result = SYRINGE_PUMP_SEEK_STATE; @@ -1100,11 +1291,13 @@ else if ( TRUE == syringePumpBolusRequested ) { heparinDeliveryState = HEPARIN_STATE_INITIAL_BOLUS; + sendTreatmentLogEventData( HEPARIN_BOLUS_START_EVENT, 0.0, syringePumpSetRate ); result = SYRINGE_PUMP_HEP_BOLUS_STATE; } else if ( TRUE == syringePumpContinuousRequested ) { heparinDeliveryState = HEPARIN_STATE_DISPENSING; + sendTreatmentLogEventData( HEPARIN_START_RESUME_EVENT, 0.0, syringePumpSetRate ); result = SYRINGE_PUMP_HEP_CONTINUOUS_STATE; } else if ( TRUE == syringePumpDACVrefSetRequested ) @@ -1133,6 +1326,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 @@ -1154,7 +1350,7 @@ 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 @@ -1183,6 +1379,8 @@ SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OVER_TRAVEL_ERROR, (U32)getSyringePumpPosition(), (U32)SYRINGE_PUMP_RETRACT_STATE ); } + 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 @@ -1197,6 +1395,73 @@ /*********************************************************************//** * @brief + * The handleSyringePumpPreLoadState function handles the PreLoad plunger state + * of the syringe pump control state machine. Move to position that limits + * loadable Heparin volume to amount needed for treatment. + * @details Inputs: syringePumpMeasForce.data + * @details Outputs: syringePumpVolumeRequired, Syringe pump moved to preload position, alarm conditions checked + * @return next state + *************************************************************************/ +static SYRINGE_PUMP_STATE_T handleSyringePumpPreLoadState( void ) +{ + SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_PRELOAD_STATE; + BOOL stopPump = FALSE; + 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 ); + F32 txVolumeReq = SYRINGE_PUMP_PRIME_VOLUME_ML + bolusVol + ( hepDurHr * contRate ); + F32 syringeVol = ( SYRINGE_PUMP_EMPTY_POS - (F32)pos ) / SYRINGE_ENCODER_COUNTS_PER_ML; + + syringePumpVolumeRequired = txVolumeReq + SYRINGE_PUMP_PRELOAD_MARGIN_VOLUME_ML; + txVolumeReq = txVolumeReq + SYRINGE_PUMP_PRELOAD_MARGIN_VOLUME_ML; + + // Keep at Home position if large volume to deliver. + if ( SYRINGE_PUMP_PRELOAD_MAX_VOLUME_ML < txVolumeReq ) + { + stopPump = TRUE; + } + + // Handle ramp up + rampSyringePump(); + + // Is plunger Heparin volume position detected? + if ( ( syringeVol <= txVolumeReq ) ) + { + stopPump = TRUE; + syringePumpVolumeDelivered.data = 0.0; + syringePumpSafetyVolumeDelivered = 0.0; + syringePumpVolumeStartPosition = pos; + // TODO Need flag for Preload complete - check for this in SelfTests.c, handleDrySelfTestSyringePumpPrimeState + } + + // Is syringe loaded? + if ( TRUE == isSyringeDetected() ) + { + activateAlarmNoData( ALARM_ID_HD_SYRINGE_DETECTED ); + stopPump = TRUE; + } + + // Check max position > empty + 0.5 mL + stopPump = checkMaxTravel( stopPump, SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_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 ) + { + stopSyringePump(); + result = SYRINGE_PUMP_OFF_STATE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The handleSyringePumpSeekState function handles the seek plunger state * of the syringe pump control state machine. * @details Inputs: syringePumpMeasForce.data @@ -1207,36 +1472,40 @@ { SYRINGE_PUMP_STATE_T result = SYRINGE_PUMP_SEEK_STATE; BOOL stopPump = FALSE; + 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 ); + F32 txVolume = SYRINGE_PUMP_PRIME_VOLUME_ML + bolusVol + ( hepDurHr * contRate ); + F32 syringeVol = ( SYRINGE_PUMP_EMPTY_POS - (F32)pos ) / SYRINGE_ENCODER_COUNTS_PER_ML; // Handle ramp up rampSyringePump(); - // Is plunger contact detected? - if ( getSyringePumpForceV() >= SYRINGE_FORCE_PLUNGER_THRESHOLD_V ) + // Is plunger contact detected or insufficient Heparin volume detected? + if ( ( getSyringePumpForceV() >= SYRINGE_FORCE_PLUNGER_THRESHOLD_V ) || ( syringeVol < txVolume ) ) { - 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 = pos; // Check estimated syringe volume needed for treatment vs. volume detected - if insufficient for treatment needs, alarm if ( syringeVol >= txVolume ) { + syringePumpPlungerFound = TRUE; syringeVolumeAdequate = TRUE; } else { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM, syringeVol, txVolume ); +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_NOT_ENOUGH_HEPARIN_ALARM, syringeVol, txVolume ); + } } } @@ -1288,16 +1557,13 @@ // Has syringe been removed? stopPump = checkSyringeRemoved( stopPump ); - // Check for occlusion - stopPump = checkOcclusionOrEmpty( stopPump ); - // 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 anything found that would require stopping the pump, stop pump if ( TRUE == stopPump ) { stopSyringePump(); @@ -1335,8 +1601,8 @@ // Check volume vs. safety volume stopPump = checkVolumeVsSafetyVolume( stopPump, SYRINGE_PUMP_VOLUME_CHECK_MARGIN ); - // Check for occlusion - stopPump = checkOcclusionOrEmpty( stopPump ); + // Check for syringe pump empty + stopPump = checkSyringeEmpty( stopPump ); // Check for commanded vs. meas. rate stopPump = checkMeasRate( stopPump, SYRINGE_PUMP_RATE_CHECK_MARGIN ); @@ -1351,6 +1617,7 @@ if ( TRUE == stopPump ) { stopSyringePump(); + sendTreatmentLogEventData( HEPARIN_BOLUS_END_EVENT, syringePumpSetRate, 0.0 ); result = SYRINGE_PUMP_OFF_STATE; } @@ -1376,8 +1643,8 @@ // Has syringe been removed? stopPump = checkSyringeRemoved( stopPump ); - // Check for occlusion - stopPump = checkOcclusionOrEmpty( stopPump ); + // Check for syringe pump empty + stopPump = checkSyringeEmpty( stopPump ); // Check position > empty + 0.5 mL stopPump = checkMaxTravel( stopPump, SYRINGE_PUMP_EMPTY_POS + SYRINGE_PUMP_EMPTY_POS_MARGIN ); @@ -1395,6 +1662,7 @@ if ( TRUE == stopPump ) { stopSyringePump(); + sendTreatmentLogEventData( HEPARIN_STOP_PAUSE_EVENT, syringePumpSetRate, 0.0 ); result = SYRINGE_PUMP_OFF_STATE; } @@ -1405,15 +1673,15 @@ * @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= getSyringePumpADCandDACStatus(); + U08 adcDACStatus = getSyringePumpADCandDACStatus(); // Wait for DAC setting write to EEPROM to complete if ( ( adcDACStatus & SYRINGE_PUMP_ADC_DAC_ERROR_COUNT_DAC_WR_DONE ) != 0 ) @@ -1447,47 +1715,78 @@ { BOOL result = stopPump; - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, ( syringePumpEncoderMeasuredDirection != expDir ) ) ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - result = TRUE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, (U32)syringePumpEncoderMeasuredDirection, (U32)syringePumpState ); + // Check direction if rate >= minimum for alarm + if ( getSyringePumpMeasRate() >= MIN_SYRINGE_PUMP_RATE_FOR_DIR_ALARM ) + { + 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 ); + } + } + else + { + isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_ENCODER_DIRECTION_ERROR, FALSE ); + isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, FALSE ); + } } - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, ( syringePumpControllerMeasuredDirection != expDir ) ) ) + + return result; +} + +/*********************************************************************//** + * @brief + * The checkSyringeEmpty function checks the force sensor position + * to determine if the syringe pump is empty. + * @details Inputs: syringePumpMeasForce.data, syringePumpPosition.data + * @details Outputs: alarm triggered if position is empty. + * @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 checkSyringeEmpty( BOOL stopPump ) +{ + BOOL result = stopPump; + F32 force = getSyringePumpForceV(); + S32 pos = getSyringePumpPosition(); + + // If near empty position, assume syringe is empty + if ( fabs( pos - SYRINGE_PUMP_EMPTY_POS ) < SYRINGE_PUMP_EMPTY_POS_MARGIN ) { + heparinDeliveryState = HEPARIN_STATE_EMPTY; + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_EMPTY, (F32)pos, force ) result = TRUE; - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SYRINGE_PUMP_CONTROLLER_DIRECTION_ERROR, (U32)syringePumpControllerMeasuredDirection, (U32)syringePumpState ); } return result; } /*********************************************************************//** * @brief - * The checkOcclusionOrEmpty function checks the force sensor for excessive + * The checkForPrimeOcclusion function checks the force sensor for excessive * pressure. Would indicate occlusion or jam or empty syringe. * @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 * @return TRUE if pump should be stopped, FALSE if not *************************************************************************/ -static BOOL checkOcclusionOrEmpty( BOOL stopPump ) +BOOL checkForPrimeOcclusion( void ) { - BOOL result = stopPump; - F32 force = getSyringePumpForceV(); + BOOL result = FALSE; // Return FALSE if no occlusion is detected + F32 forceAtEndOfPriming = getSyringePumpForceV(); // Read the force sensor at the end of the priming + F32 forceDelta = forceAtEndOfPriming - forceAtEndOfSeek; // Occlusion is detected if force at end of prime is > than force at end of seek by 0.5 volts or more + BOOL occlusionDetected = ( forceDelta >= SYRINGE_FORCE_OCCLUSION_DIFF_V ? TRUE : FALSE ); - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, ( force >= SYRINGE_FORCE_OCCLUSION_THRESHOLD_V ) ) ) + if ( TRUE == occlusionDetected ) { - S32 pos = getSyringePumpPosition(); - - if ( fabs( pos - SYRINGE_PUMP_EMPTY_POS ) < SYRINGE_PUMP_EMPTY_POS_MARGIN ) - { - heparinDeliveryState = HEPARIN_STATE_EMPTY; - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SYRINGE_EMPTY, (F32)pos, force ) - } - else - { - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, (F32)pos, force ) - } + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_OCCLUSION, forceAtEndOfSeek, forceAtEndOfPriming ) result = TRUE; } @@ -1564,17 +1863,23 @@ static BOOL checkMeasRate( BOOL stopPump, F32 pctMargin ) { BOOL result = stopPump; - F32 rate = getSyringePumpMeasRate(); - F32 max = MAX( rate, syringePumpSetRate ); - F32 min = MIN( rate, syringePumpSetRate ); - F32 delta = max - min; - F32 error = ( max > 0.0 ? ( 1.0 - fabs( min / max ) ) : 0.0 ); - // Alarm on rate if off by more than 5% or 0.1 mL/hr, whichever is greater - if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, ( ( error > pctMargin ) && ( delta > SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR ) ) ) ) +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_SYRINGE_PUMP_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif { - result = TRUE; - SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, syringePumpSetRate, rate ) + F32 rate = getSyringePumpMeasRate(); + F32 max = MAX( rate, syringePumpSetRate ); + F32 min = MIN( rate, syringePumpSetRate ); + F32 error = ( max > 0.0 ? ( 1.0 - fabs( min / max ) ) : 0.0 ); + F32 delta = max - min; + + // Alarm on rate if off by more than 5% or 0.1 mL/hr, whichever is greater + if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, ( ( error > pctMargin ) && ( delta > SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR ) ) ) ) + { + result = TRUE; + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_HD_SYRINGE_PUMP_SPEED_ERROR, syringePumpSetRate, rate ) + } } return result; @@ -1613,55 +1918,73 @@ /*********************************************************************//** * @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 ) { - // Check for ramp stall - restart ramp if retry allowed - if ( syringePumpLastPosition == getSyringePumpPosition() ) - { - syringePumpStallCtr++; - if ( syringePumpStallCtr >= SYRINGE_PUMP_RAMP_STALL_TIME ) - { - if ( ++syringePumpStallRetryCount <= SYRINGE_PUMP_RAMP_STALL_RETRIES ) - { - // Restart ramp - syringePumpRampTimerCtr = 0; - syringePumpRampUpToggleTime = SYRINGE_PUMP_START_RAMP_SPEED; - } - else - { - // TODO - stall alarm - stopSyringePump(); - syringePumpState = SYRINGE_PUMP_OFF_STATE; - } - } - else - { - syringePumpStallCtr = 0; - } - } - // 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 ) ); + syringePumpRampUpToggleTime = (U32)( (F32)SYRINGE_PUMP_START_RAMP_SPEED / + ( (F32)( syringePumpRampTimerCtr * syringePumpRampTimerCtr * syringePumpRampTimerCtr ) / (F32)SYRINGE_PUMP_RAMP_DIVISOR ) ); + syringePumpRampUpPct = (F32)syringePumpSetToggleTime / (F32)syringePumpRampUpToggleTime; if ( syringePumpRampUpToggleTime > syringePumpSetToggleTime ) { setFPGASyringePumpStepToggleTime( syringePumpRampUpToggleTime ); } else { + syringePumpRampUpPct = 1.0; // set to 100% ramp completion setFPGASyringePumpStepToggleTime( syringePumpSetToggleTime ); } } } - + /*********************************************************************//** * @brief * The calcStepperToggleTimeForTargetRate function calculates the stepper @@ -1673,13 +1996,14 @@ *************************************************************************/ static void calcStepperToggleTimeForTargetRate( F32 rate ) { - F32 conv = 0.0; + F64 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 = (F64)rate * SYRINGE_MICRO_STEPS_PER_ML; // = uSteps/hr + temp /= (F64)( 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 ); @@ -1693,21 +2017,27 @@ /*********************************************************************//** * @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)((F64)countsPerHr / (F64)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; } } @@ -1722,23 +2052,24 @@ *************************************************************************/ static void calcSafetyVolumeDelivered( void ) { - syringePumpSafetyVolumeDelivered += ( syringePumpSetRate / ( MIN_PER_HOUR * SEC_PER_MIN * ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ) ); + syringePumpSafetyVolumeDelivered += ( syringePumpRampUpPct * ( syringePumpSetRate / (F32)( MIN_PER_HOUR * SEC_PER_MIN * ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ) ) ); } -/*********************************************************************//** - * @brief - * The publishSyringePumpData function publishes syringe pump data at the - * set interval. - * @details Inputs: latest syringe pump data, syringePumpDataPublicationTimerCounter - * @details Outputs: Syringe pump data are published to CAN bus. - * @return none - *************************************************************************/ -static void publishSyringePumpData( void ) -{ - // Publish syringe pump data on interval - if ( ++syringePumpDataPublicationTimerCounter >= getPublishSyringePumpDataInterval() ) +/*********************************************************************//** + * @brief + * The publishSyringePumpData function publishes syringe pump data at the + * set interval. + * @details Inputs: latest syringe pump data, syringePumpDataPublicationTimerCounter + * @details Outputs: syringePumpDataPublicationTimerCounter + * @return none + *************************************************************************/ +static void publishSyringePumpData( void ) +{ + // Publish syringe pump data on interval + if ( ++syringePumpDataPublicationTimerCounter >= getU32OverrideValue( &syringePumpDataPublishInterval ) ) { SYRINGE_PUMP_DATA_PAYLOAD_T data; + SYRINGE_PUMP_VOLUME_DATA_T volData; data.syringePumpMeasForce = getSyringePumpForceV(); data.syringePumpMeasHome = getSyringePumpHomeDetectorV(); @@ -1754,72 +2085,75 @@ ( (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; - } -} - - -/************************************************************************* - * TEST SUPPORT FUNCTIONS - *************************************************************************/ - - -/*********************************************************************//** - * @brief - * The testSetSyringePumpDataPublishIntervalOverride function overrides the - * syringe pump data publish interval. - * @details Inputs: none - * @details Outputs: syringePumpDataPublishInterval - * @param value override syringe pump data publish interval with (in ms) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetSyringePumpDataPublishIntervalOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - U32 intvl = value / TASK_PRIORITY_INTERVAL; - - result = TRUE; - syringePumpDataPublishInterval.ovData = intvl; - syringePumpDataPublishInterval.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetSyringePumpDataPublishIntervalOverride function resets the override - * of the syringe pump data publish interval. - * @details Inputs: none - * @details Outputs: syringePumpDataPublishInterval - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetSyringePumpDataPublishIntervalOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - syringePumpDataPublishInterval.override = OVERRIDE_RESET; - syringePumpDataPublishInterval.ovData = syringePumpDataPublishInterval.ovInitData; - } - - return result; -} + volData.syringePumpVolumeDelivered = getSyringePumpVolumeDelivered(); + volData.syringePumpVolumeRequired = syringePumpVolumeRequired; + + broadcastData( MSG_ID_HD_SYRINGE_PUMP_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( SYRINGE_PUMP_DATA_PAYLOAD_T ) ); + broadcastData( MSG_ID_HD_HEPARIN_DATA_BROADCAST, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&volData, sizeof( SYRINGE_PUMP_VOLUME_DATA_T ) ); + syringePumpDataPublicationTimerCounter = 0; + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + /*********************************************************************//** * @brief + * The testSetSyringePumpDataPublishIntervalOverride function overrides the + * syringe pump data publish interval. + * @details Inputs: none + * @details Outputs: syringePumpDataPublishInterval + * @param value override syringe pump data publish interval with (in ms) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetSyringePumpDataPublishIntervalOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + U32 intvl = value / TASK_PRIORITY_INTERVAL; + + result = TRUE; + syringePumpDataPublishInterval.ovData = intvl; + syringePumpDataPublishInterval.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetSyringePumpDataPublishIntervalOverride function resets the override + * of the syringe pump data publish interval. + * @details Inputs: none + * @details Outputs: syringePumpDataPublishInterval + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetSyringePumpDataPublishIntervalOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + syringePumpDataPublishInterval.override = OVERRIDE_RESET; + syringePumpDataPublishInterval.ovData = syringePumpDataPublishInterval.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief * The testSyringePumpOperationRequest function requests a given syringe pump * operation. * @details Inputs: none - * @details Outputs: TBD + * @details Outputs: pump operation request is handled * @param opParams record containing the requested operation and its parameters * @return TRUE if override successful, FALSE if not *************************************************************************/ @@ -2138,9 +2472,57 @@ return result; } - + /*********************************************************************//** * @brief + * The testSetHeprinBolusTargetRateOverride function overrides the + * heprine bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @param: value : override heprinBolusTargetRate (in mL/hour) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetHeprinBolusTargetRateOverride( F32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + heparinBolusTargetRate.ovInitData = heparinBolusTargetRate.data; + heparinBolusTargetRate.ovData = value; + heparinBolusTargetRate.override = OVERRIDE_KEY; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetHeprinBolusTargetRateOverride function resets the override + * of the heprin bolus target rate. + * @details Inputs: heprinBolusTargetRate + * @details Outputs: heprinBolusTargetRate + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetHeprinBolusTargetRateOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + heparinBolusTargetRate.override = OVERRIDE_RESET; + heparinBolusTargetRate.ovData = heparinBolusTargetRate.ovInitData; + heparinBolusTargetRate.ovInitData = 0.0; + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The testSetSyringePumpStatus function overrides the syringe pump * status. * @details Inputs: none @@ -2319,4 +2701,4 @@ return result; } -/**@}*/ +/**@}*/