/************************************************************************** * * Copyright (c) 2024-2024 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 PistonPumpControl.c * * @author (last) Vinayakam Mani * @date (last) 07-Jan-2025 * * @author (original) Vinayakam Mani * @date (original) 07-Jan-2025 * ***************************************************************************/ #include "ConcentratePumps.h" #include "FpgaDD.h" #include "Level.h" #include "Messaging.h" #include "PistonPumpControl.h" #include "TaskGeneral.h" #include "Valves.h" #ifdef __PUMPTEST__ /** * @addtogroup PistonPumpControl * @{ */ // ********** private definitions ********** #define PISTON_PUMP_CONTROL_DATA_PUBLISH_INTERVAL ( 1000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the piston pump control data published. #define PISTON_PUMP_FILL_PERIOD ( 4000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the piston pump filling cycle time #define PISTON_PUMP_DISPENSE_PERIOD ( 4000 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the piston pump dispense cycle time #define PISTON_PUMP_MIN_SPEED 3.0F ///< Piston pump minimum speed in ml/min. #define PISTON_PUMP_NOMINAL_SPEED 40.0F ///< Nominal piston pump speed in ml/min. #define PISTON_PUMP_MAX_SPEED 48.0F ///< Maximum speed for piston pump in mL/min. /// Enumeration of piston pump states. typedef enum PistonPumpState { PISTON_PUMP_OFF_STATE = 0, ///< Piston pump off state. PISTON_PUMP_FILL_START_STATE, ///< Piston pump fill start state. PISTON_PUMP_FILL_COMPLETE_STATE, ///< Piston pump fill complete state. PISTON_PUMP_DISPENSE_START_STATE, ///< Piston pump dispense start state. PISTON_PUMP_DISPENSE_COMPLETE_STATE, ///< Piston pump dispense complete state. NUM_OF_PISTON_PUMP_STATES ///< Number of piston pump states. } PISTON_PUMP_EXEC_STATE_T; /// Payload record structure for piston pump start/stop request typedef struct { U32 pumpId; ///< Piston pump ID (0:Acid ,1:Bicarb, 2: UF pump) U32 startStop; ///< Piston pump start:1,stop :0. U32 cycleCount; ///< Piston pump cycle count F32 volume; ///< Target volume in ml F32 speed; ///< Speed range from 0.3 ml/min to 48.0 ml/min. } PISTON_PUMP_START_STOP_CMD_PAYLOAD_T; // ********** private data ********** static PISTON_PUMP_EXEC_STATE_T pistonPumpExecState[ NUM_OF_PISTON_PUMPS ]; ///< Current piston pump control executive state. static F32 pistonPumpSetSpeed[ NUM_OF_PISTON_PUMPS ]; ///< Current piston pump set speed. static F32 pistonPumpVolumeinMl[ NUM_OF_PISTON_PUMPS ]; ///< Current piston pump set volume to deliver. static U32 pistonPumpCycleCount[ NUM_OF_PISTON_PUMPS ]; ///< Number of piston pump (fill and dispense) cycle count static OVERRIDE_U32_T pistonPumpControlDataPublishInterval; ///< Piston Pump control data publish interval. static OVERRIDE_U32_T pistonPumpFillAfterDispense; ///< Piston Pump fill after dispense on each cycle. static U32 currentDosingTriggerStatus; ///< Read Current Dosing Trigger status static U32 prevDosingTriggerStatus; ///< Previous Current Dosing status static U32 pistonPumpControlDataPublicationTimerCounter; ///< Piston pump data publish timer counter static BOOL readyToDose[ NUM_OF_PISTON_PUMPS ]; ///< Ready to dose status // ********** private function prototypes ********** static void pistonPumpInletOutletValveControl( PISTON_PUMPS_T pumpId, VALVE_STATE_NAMES_T inletValveState, VALVE_STATE_NAMES_T outletValveState ); static PISTON_PUMP_EXEC_STATE_T handlePistonPumpOffState( PISTON_PUMPS_T pumpId ); static PISTON_PUMP_EXEC_STATE_T handlePistonPumpFillStartState( PISTON_PUMPS_T pumpId ); static PISTON_PUMP_EXEC_STATE_T handlePistonPumpFillCompleteState( PISTON_PUMPS_T pumpId ); static PISTON_PUMP_EXEC_STATE_T handlePistonPumpDispenseStartState( PISTON_PUMPS_T pumpId ); static PISTON_PUMP_EXEC_STATE_T handlePistonPumpDispenseCompleteState( PISTON_PUMPS_T pumpId ); static U32 getPistonPumpControlDataPublishInterval( void ); static void publishPistonPumpControlData( void ); static U32 getPistonPumpFillafterDispenseControl( void ); /*********************************************************************//** * @brief * The initPistonPump function initializes the piston pump control * ( Dosing and ultrafilteraion control) unit. * @details \b Inputs: none * @details \b Outputs: unit variables initialized. * @return none *************************************************************************/ void initPistonPump( void ) { pistonPumpExecState[ PISTONPUMPS_ACID ] = PISTON_PUMP_OFF_STATE; pistonPumpExecState[ PISTONPUMPS_BICARB ] = PISTON_PUMP_OFF_STATE; pistonPumpExecState[ PISTONPUMPS_UF ] = PISTON_PUMP_OFF_STATE; pistonPumpCycleCount[ PISTONPUMPS_ACID ] = 0; pistonPumpCycleCount[ PISTONPUMPS_BICARB ] = 0; pistonPumpCycleCount[ PISTONPUMPS_UF ] = 0; pistonPumpVolumeinMl[ PISTONPUMPS_ACID ] = DEFAULT_ACID_VOLUME_ML; pistonPumpVolumeinMl[ PISTONPUMPS_BICARB ] = DEFAULT_BICARB_VOLUME_ML; pistonPumpVolumeinMl[ PISTONPUMPS_UF ] = 0.0F; pistonPumpSetSpeed[ PISTONPUMPS_ACID ] = PISTON_PUMP_NOMINAL_SPEED; pistonPumpSetSpeed[ PISTONPUMPS_BICARB ] = PISTON_PUMP_NOMINAL_SPEED; pistonPumpSetSpeed[ PISTONPUMPS_UF ] = PISTON_PUMP_NOMINAL_SPEED; pistonPumpControlDataPublishInterval.data = PISTON_PUMP_CONTROL_DATA_PUBLISH_INTERVAL; pistonPumpControlDataPublishInterval.ovData = PISTON_PUMP_CONTROL_DATA_PUBLISH_INTERVAL; pistonPumpControlDataPublishInterval.ovInitData = 0; pistonPumpControlDataPublishInterval.override = OVERRIDE_RESET; pistonPumpFillAfterDispense.data = TRUE; pistonPumpFillAfterDispense.ovData = TRUE; pistonPumpFillAfterDispense.ovInitData = 0; pistonPumpFillAfterDispense.override = OVERRIDE_RESET; currentDosingTriggerStatus = 0; prevDosingTriggerStatus = 0; readyToDose[ PISTONPUMPS_ACID ] = FALSE; readyToDose[ PISTONPUMPS_BICARB ] = FALSE; readyToDose[ PISTONPUMPS_UF ] = FALSE; pistonPumpControlDataPublicationTimerCounter = 0; } /*********************************************************************//** * @brief * The execPistonPumpController function executes the piston pump control state machine. * @details \b Inputs: pistonPumpExecState * @details \b Outputs: pistonPumpExecState * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when wrong piston pump control state invoked. * @return current state. *************************************************************************/ void execPistonPumpController( void ) { PISTON_PUMPS_T pumpId; for ( pumpId = PISTONPUMPS_FIRST; pumpId < NUM_OF_PISTON_PUMPS; pumpId++ ) { switch ( pistonPumpExecState[pumpId] ) { case PISTON_PUMP_OFF_STATE: pistonPumpExecState[ pumpId ] = handlePistonPumpOffState( pumpId ); break; case PISTON_PUMP_FILL_START_STATE: pistonPumpExecState[ pumpId ] = handlePistonPumpFillStartState( pumpId ); break; case PISTON_PUMP_FILL_COMPLETE_STATE: pistonPumpExecState[ pumpId ] = handlePistonPumpFillCompleteState( pumpId ); break; case PISTON_PUMP_DISPENSE_START_STATE: pistonPumpExecState[ pumpId ] = handlePistonPumpDispenseStartState( pumpId ); break; case PISTON_PUMP_DISPENSE_COMPLETE_STATE: pistonPumpExecState[ pumpId ] = handlePistonPumpDispenseCompleteState( pumpId ); break; #ifndef _VECTORCAST_ // The switch case is in a for loop so the default case cannot be covered in VectorCAST default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_PISTON_PUMP_EXEC_INVALID_STATE, pumpId ) pistonPumpExecState[ pumpId ] = PISTON_PUMP_OFF_STATE; break; #endif } } //Publish piston control pump data publishPistonPumpControlData(); } /*********************************************************************//** * @brief * The pistonPumpInletOutletValveControl function actuates the inlet and * Outlet valve for given pump ( dosing/UF ). * @details \b Inputs: none * @details \b Outputs: valve states * @param pumpId pump id to configure valve settings * @param inletValveState Inlet Valve open/close state * @param outletValveState Outlet Valve open/close state * @return none. *************************************************************************/ static void pistonPumpInletOutletValveControl( PISTON_PUMPS_T pumpId, VALVE_STATE_NAMES_T inletValveState, VALVE_STATE_NAMES_T outletValveState ) { switch ( pumpId ) { case PISTONPUMPS_ACID: // TODO : Valves assocaited to Acid concentrate Pumps setValveState( D14_VALV, inletValveState ); setValveState( D52_VALV, outletValveState ); break; case PISTONPUMPS_BICARB: // TODO: Valves assocaited to Bicarb concentrate Pumps setValveState( D8_VALV, inletValveState ); setValveState( D54_VALV, outletValveState ); break; case PISTONPUMPS_UF: // TODO: Valves assocaited to Ultrafilteration setValveState( D53_VALV, inletValveState ); setValveState( D34_VALV, outletValveState ); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_PISTON_PUMP_INVALID_PUMP_ID, pumpId ); break; } } /*********************************************************************//** * @brief * The processPistonPumpDosingTrigger function sets the dosing trigger * status for given pump. * @details \b Inputs: Dosing pump trigger. * @details \b Outputs: readyToDose. * @return none. *************************************************************************/ void processPistonPumpDosingTrigger( void ) { currentDosingTriggerStatus = getLevelStatus( PUMP_TRIG_LEVEL ); if ( currentDosingTriggerStatus != prevDosingTriggerStatus ) { // Trigger dosing only high to low transition if ( ( LEVEL_STATE_HIGH == prevDosingTriggerStatus ) && ( LEVEL_STATE_LOW == currentDosingTriggerStatus ) ) { readyToDose[ PISTONPUMPS_ACID ] = TRUE; readyToDose[ PISTONPUMPS_BICARB ] = TRUE; readyToDose[ PISTONPUMPS_UF ] = TRUE; } prevDosingTriggerStatus = currentDosingTriggerStatus; } } /*********************************************************************//** * @brief * The startPistonPumpCycle function sets the given piston pump parameters * for dosing/UF operations. * @details \b Inputs: none * @details \b Outputs: piston pump parameters. * @param pumpId pump id to configure pump parameters * @param cycleCount Number of piston pump cycle. * @param targetVolume_ml Volume to be filled/dispensed * @param speed The flow rate in ml/min * @return none. *************************************************************************/ void startPistonPumpCycle( PISTON_PUMPS_T pumpId, U32 cycleCount, F32 targetVolume_ml, F32 speed ) { if ( pumpId < NUM_OF_PISTON_PUMPS ) { pistonPumpCycleCount[ pumpId ] = cycleCount; pistonPumpVolumeinMl[ pumpId ] = targetVolume_ml; pistonPumpSetSpeed[ pumpId ] = speed; } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_PISTON_PUMP_INVALID_PUMP_ID, pumpId ); } } /*********************************************************************//** * @brief * The stopPistonPumpCycle function stops the given piston pump * @details \b Inputs: none * @details \b Outputs: pistonPumpCycleCount,pistonPumpVolumeinMl,pistonPumpSetSpeed, * pistonPumpExecState. * @param pumpId pump id to stop the pump * @return none. *************************************************************************/ void stopPistonPumpCycle( PISTON_PUMPS_T pumpId ) { if ( pumpId < NUM_OF_PISTON_PUMPS ) { pistonPumpCycleCount[ pumpId ] = 0; pistonPumpVolumeinMl[ pumpId ] = 0.0F; pistonPumpSetSpeed[ pumpId ] = 0.0F; pistonPumpExecState[ pumpId ] = PISTON_PUMP_OFF_STATE; // Close Inlet and Outlet valve pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_CLOSED, VALVE_STATE_CLOSED ); //Stop the pump requestConcentratePumpOff( (CONCENTRATE_PUMPS_T)pumpId, FALSE ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_PISTON_PUMP_INVALID_PUMP_ID, pumpId ); } } /*********************************************************************//** * @brief * The handlePistonPumpOffState function handles the piston pump * Off state to handle piston pump control initiation when asked to. * @details \b Inputs: pump Id * @details \b Outputs: valve states and motor control * @param pumpId pump id to start/stop the pump * @return next piston pump control state. *************************************************************************/ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpOffState( PISTON_PUMPS_T pumpId ) { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_OFF_STATE; // Initiate piston pump control when cycle count is more than 1 or // fill cycle to be completed for dispensing when asked. // Will redefine the off state later if required if ( ( pistonPumpCycleCount[ pumpId ] > 0 ) || ( TRUE == (BOOL)getPistonPumpFillafterDispenseControl() ) ) { state = PISTON_PUMP_FILL_START_STATE; if ( pistonPumpCycleCount[ pumpId ] > 0 ) { pistonPumpCycleCount[ pumpId ]--; } } return state; } /*********************************************************************//** * @brief * The handlePistonPumpFillStartState function handles the inlet and outlet * valve control and start the piston pumps with the set speed and volume * @details \b Inputs: pump Id * @details \b Outputs: Valve actuation and motor control * @param pumpId pump id to actuate valves pair and control stepper motor * @return next piston pump control state. *************************************************************************/ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpFillStartState( PISTON_PUMPS_T pumpId ) { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_FILL_START_STATE; // Open Inlet and Outlet valve pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_OPEN, VALVE_STATE_CLOSED ); // start stepper motor with the expected quantity setConcentratePumpTargetSpeed( (CONCENTRATE_PUMPS_T)pumpId, pistonPumpSetSpeed[ pumpId ], pistonPumpVolumeinMl[ pumpId ] ); requestConcentratePumpOn( (CONCENTRATE_PUMPS_T)pumpId ); //Move to next state state = PISTON_PUMP_FILL_COMPLETE_STATE; return state; } /*********************************************************************//** * @brief * The handlePistonPumpFillCompleteState function check for the piston pump * fill complete and close the currently opened valve. * @details \b Inputs: None * @details \b Outputs: None * @param pumpId pump id to actuate valves pair and control stepper motor * @return next piston pump control state. *************************************************************************/ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpFillCompleteState( PISTON_PUMPS_T pumpId ) { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_FILL_COMPLETE_STATE; if ( TRUE == isConcentratePumpDosingCompleted( (CONCENTRATE_PUMPS_T)pumpId ) ) { // Close Inlet and Outlet valve pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_CLOSED, VALVE_STATE_CLOSED ); //Stop the pump requestConcentratePumpOff( (CONCENTRATE_PUMPS_T)pumpId, FALSE ); //Move to next state state = PISTON_PUMP_DISPENSE_START_STATE; } return state; } /*********************************************************************//** * @brief * The handlePistonPumpDispenseStartState function handles the inlet and outlet * valve control for dispensing fluid and start the piston pumps with the set * speed and volume * @details \b Inputs: pump Id * @details \b Outputs: Valve actuation and motor control * @param pumpId pump id to actuate valves pair and control stepper motor * @return next piston pump control state. *************************************************************************/ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpDispenseStartState( PISTON_PUMPS_T pumpId ) { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_DISPENSE_START_STATE; // On regular piston pump cycle continue to dispense or when dosing trigger initiated if ( ( FALSE == (BOOL)getPistonPumpFillafterDispenseControl() ) || ( ( TRUE == (BOOL)getPistonPumpFillafterDispenseControl() && ( TRUE == readyToDose[ pumpId ] ) ) ) ) { F32 pumpSpeed = pistonPumpSetSpeed[ pumpId ] * -1.0 ; // This is to rotate motor in reverse direction // Close Inlet and Open Outlet valve pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_CLOSED, VALVE_STATE_OPEN ); // start stepper motor with the expected quantity setConcentratePumpTargetSpeed( (CONCENTRATE_PUMPS_T)pumpId, pumpSpeed, pistonPumpVolumeinMl[ pumpId ] ); requestConcentratePumpOn( (CONCENTRATE_PUMPS_T)pumpId ); //Reset the dosing flag readyToDose[ pumpId ] = FALSE; //Move to next state state = PISTON_PUMP_DISPENSE_COMPLETE_STATE; } return state; } /*********************************************************************//** * @brief * The handlePistonPumpDispenseCompleteState function check for the piston pump * dispense complete and close the currently opened valve. * @details \b Inputs: None * @details \b Outputs: None * @param pumpId pump id to actuate valves pair and control stepper motor * @return next piston pump control state. *************************************************************************/ static PISTON_PUMP_EXEC_STATE_T handlePistonPumpDispenseCompleteState( PISTON_PUMPS_T pumpId ) { PISTON_PUMP_EXEC_STATE_T state = PISTON_PUMP_DISPENSE_COMPLETE_STATE; if ( TRUE == isConcentratePumpDosingCompleted( (CONCENTRATE_PUMPS_T)pumpId ) ) { // Close Inlet and Outlet valve pistonPumpInletOutletValveControl( pumpId, VALVE_STATE_CLOSED, VALVE_STATE_CLOSED ); //Stop the pump requestConcentratePumpOff( (CONCENTRATE_PUMPS_T)pumpId, FALSE ); //Move to next state state = PISTON_PUMP_OFF_STATE; } return state; } /*********************************************************************//** * @brief * The getPistonPumpControlDataPublishInterval function gets the piston pump * control data publish interval. * @details \b Inputs: pistonPumpControlDataPublishInterval * @details \b Outputs: none * @return the interval at piston pump control data being published. *************************************************************************/ static U32 getPistonPumpControlDataPublishInterval( void ) { U32 result = pistonPumpControlDataPublishInterval.data; if ( OVERRIDE_KEY == pistonPumpControlDataPublishInterval.override ) { result = pistonPumpControlDataPublishInterval.ovData; } return result; } /*********************************************************************//** * @brief * The getPistonPumpFillafterDispenseControl function gets the piston pump * fill after dispense control. * @details \b Inputs: pistonPumpFillAfterDispense * @details \b Outputs: none * @return the fill after dispense control status. *************************************************************************/ static U32 getPistonPumpFillafterDispenseControl( void ) { U32 result = pistonPumpFillAfterDispense.data; if ( OVERRIDE_KEY == pistonPumpFillAfterDispense.override ) { result = pistonPumpFillAfterDispense.ovData; } return result; } /*********************************************************************//** * @brief * The publishPistonPumpControlData function broadcasts the piston pump * control execution data at defined interval. * @details \b Inputs: pistonPumpControlDataPublicationTimerCounter * @details \b Outputs: DD piston pump control data broadcast message sent * @details \b Message \Sent: MSG_ID_DD_PISTON_PUMP_CONTROL_DATA to publish the balancing * chamber data. * @return none *************************************************************************/ static void publishPistonPumpControlData( void ) { if ( ++pistonPumpControlDataPublicationTimerCounter >= getPistonPumpControlDataPublishInterval() ) { PISTON_PUMP_CONTROL_DATA_T data; data.acidPumpControlExecState = (U32)pistonPumpExecState[ PISTONPUMPS_ACID ]; data.bicarbPumpControlExecState = (U32)pistonPumpExecState[ PISTONPUMPS_BICARB ]; data.ufPumpControlExecState = (U32)pistonPumpExecState[ PISTONPUMPS_UF ]; data.acidPistonPumpSwCounter = (U32)readyToDose[ PISTONPUMPS_ACID ]; data.bicarbPistonPumpSwCounter = (U32)readyToDose[ PISTONPUMPS_BICARB ]; data.ufPistonPumpSwCounter = (U32)readyToDose[ PISTONPUMPS_UF ]; data.acidPistonPumpCycleCount = pistonPumpCycleCount[ PISTONPUMPS_ACID ]; data.bicarbPistonPumpCycleCount = pistonPumpCycleCount[ PISTONPUMPS_BICARB ]; data.ufPistonPumpCycleCount = pistonPumpCycleCount[ PISTONPUMPS_UF ]; broadcastData( MSG_ID_DD_PISTON_PUMP_CONTROL_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( PISTON_PUMP_CONTROL_DATA_T ) ); pistonPumpControlDataPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testDDPistonPumpControlDataPublishIntervalOverride function overrides the * DD piston pump data publish interval. * @details \b Inputs: pistonPumpControlDataPublishInterval * @details \b Outputs: pistonPumpControlDataPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the DD piston pump data publish interval to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDDPistonPumpControlDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &pistonPumpControlDataPublishInterval, TASK_GENERAL_INTERVAL ); return result; } /*********************************************************************//** * @brief * The testDDPistonPumpStartStopOverride function sets the override * of start/stop piston pump. * @details Inputs: piston pump parameters * @details Outputs: valve and motor control * @param message Override message from Dialin which includes the override * value to override the piston pump control parameters. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDDPistonPumpStartStopOverride( MESSAGE_T *message ) { BOOL result = FALSE; // Verify tester has logged in with DD if ( TRUE == isTestingActivated() ) { // Verify payload length is valid if ( sizeof( PISTON_PUMP_START_STOP_CMD_PAYLOAD_T ) == message->hdr.payloadLen ) { PISTON_PUMP_START_STOP_CMD_PAYLOAD_T payload; memcpy( &payload, message->payload, sizeof(PISTON_PUMP_START_STOP_CMD_PAYLOAD_T) ); if ( (PISTON_PUMPS_T)payload.pumpId < NUM_OF_PISTON_PUMPS ) { // Handle start command if ( ( TRUE == payload.startStop ) && ( ( payload.speed >= PISTON_PUMP_MIN_SPEED ) && ( payload.speed <= PISTON_PUMP_MAX_SPEED ) ) && ( payload.volume > 0.0 ) ) { startPistonPumpCycle( (PISTON_PUMPS_T)payload.pumpId, payload.cycleCount, payload.volume, payload.speed ); result = TRUE; } //Handle stop command if ( FALSE == payload.startStop ) { stopPistonPumpCycle( (PISTON_PUMPS_T)payload.pumpId ); result = TRUE; } } } } return result; } /*********************************************************************//** * @brief * The testDDPistonPumpFillAfterDispenseOverride function sets the override value * of the piston pump fill after dispense control. * @details Inputs: pistonPumpFillAfterDispense * @details Outputs: pistonPumpFillAfterDispense * @param message Override message from Dialin which includes the read * counter value to override for the piston pump fill after dispense control. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDDPistonPumpFillAfterDispenseOverride( MESSAGE_T *message ) { BOOL result = u32Override( message, &pistonPumpFillAfterDispense, 0, 1 ); return result; } /**@}*/ #endif