Index: firmware/App/Controllers/AirTrap.c =================================================================== diff -u -r552a7de419344b43a3307c61141c99bfbbee7345 -r16219f68040cc257728be31ce24f7e23e2769f48 --- firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision 552a7de419344b43a3307c61141c99bfbbee7345) +++ firmware/App/Controllers/AirTrap.c (.../AirTrap.c) (revision 16219f68040cc257728be31ce24f7e23e2769f48) @@ -18,6 +18,7 @@ #include "AirPump.h" #include "AirTrap.h" #include "AlarmMgmtTD.h" +#include "BloodFlow.h" #include "LevelSensors.h" #include "Messaging.h" #include "OperationModes.h" @@ -38,7 +39,7 @@ #define AIR_TRAP_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the air trap data is published on the CAN bus. #define AIR_TRAP_FILL_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Air trap fill timeout period (in ms). #define AIR_PUMP_ON_DELAY_TIME_MS ( 10 * MS_PER_SECOND ) ///< Delay between air pump On (in ms). -#define AIR_PUMP_ON_STOP_TIME_MIN_MS 200 ///< Stop air Pump time. +#define AIR_PUMP_LOWER_OP_TIME_MIN_MS 200 ///< Air trap lower operation minimum time (in ms). #define AIR_PUMP_ON_ERROR_MAX_CNT 6 ///< Maximum number of air pump on events within time window before alarm triggered. Do not exceed MAX_TIME_WINDOWED_COUNT. #define AIR_PUMP_ON_ERROR_TIME_WIN_MS ( 60 * MS_PER_SECOND ) ///< Time window for Air Pump on count error. #define AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Air trap illegal values timeout (in ms) @@ -51,11 +52,12 @@ /// Defined states for the air trap controller state machine. typedef enum AirTrap_States { - AIR_TRAP_INIT_STATE = 0, ///< Initialization state - AIR_TRAP_MANUAL_CONTROL_STATE, ///< Manually control air trap valve state - AIR_TRAP_VALVE_CLOSED_STATE, ///< Valve closed state - until air detected at lower level - AIR_TRAP_VALVE_OPEN_STATE, ///< Valve open state - until fluid detected at upper level - NUM_OF_AIR_TRAP_STATES ///< Number of air trap controller states + AIR_TRAP_INIT_STATE = 0, ///< Initialization state. + AIR_TRAP_MANUAL_CONTROL_STATE, ///< Manually control air trap valve state. + AIR_TRAP_CLOSED_STATE, ///< Closed state - level between lower and upper sensors. + AIR_TRAP_RAISE_LEVEL_STATE, ///< Raise level state. + AIR_TRAP_LOWER_LEVEL_STATE, ///< Lower level state. + NUM_OF_AIR_TRAP_STATES ///< Number of air trap controller states. } AIR_TRAP_STATE_T; // ********** private data ********** @@ -68,18 +70,20 @@ static BOOL pendingStartAirTrapController = FALSE; ///< Flag indicates an air trap controller start request is pending. static BOOL pendingStopAirTrapController = FALSE; ///< Flag indicates an air trap controller stop request is pending. -static U32 fillStartTime; ///< Time stamp for start of air trap fill. +static U32 airTrapFillStartTime; ///< Air trap fill (raise level) operation start time. +static U32 airTrapLowerStartTime; ///< Air trap lower level operation start time. +static U32 airTrapLowerDelayStartTime; ///< Air trap lower level operation delay start time. -static U32 airPumpOnDelayStartTime; ///< Air pump On start time. -static U32 stopAirPumpStartTime; ///< Stop air pump start time. +static BOOL airTrapWasFilledAtStartOfTreatement; ///< To ensure the fluid level high during start of treatment, we need to do a fill operation. -static BOOL airTrapValveOpenAtStartOfTreatement; ///< To Keep the fluid level high close to Air trap upper level during start of treatment +static BOOL airTrapHasDetectedFaultMode; ///< Flag indicates air trap unit has handled transition to fault mode. // ********** private function prototypes ********** static AIR_TRAP_STATE_T handleAirTrapManualControlState( void ); -static AIR_TRAP_STATE_T handleAirTrapValveClosedState( void ); -static AIR_TRAP_STATE_T handleAirTrapValveOpenState( void ); +static AIR_TRAP_STATE_T handleAirTrapClosedState( void ); +static AIR_TRAP_STATE_T handleAirTrapRaiseLevelState( void ); +static AIR_TRAP_STATE_T handleAirTrapLowerlevelState( void ); static void publishAirTrapData( void ); /*********************************************************************//** @@ -102,10 +106,10 @@ airTrapDataPublishInterval.ovData = AIR_TRAP_DATA_PUB_INTERVAL; airTrapDataPublishInterval.ovInitData = AIR_TRAP_DATA_PUB_INTERVAL; airTrapDataPublishInterval.override = OVERRIDE_RESET; - fillStartTime = 0; - airPumpOnDelayStartTime = 0; - stopAirPumpStartTime = 0; - airTrapValveOpenAtStartOfTreatement = FALSE; + airTrapFillStartTime = 0; + airTrapLowerDelayStartTime = 0; + airTrapLowerStartTime = 0; + airTrapHasDetectedFaultMode = FALSE; } /*********************************************************************//** @@ -119,6 +123,7 @@ void resetAirTrap( void ) { airTrapControllerState = AIR_TRAP_INIT_STATE; + airTrapWasFilledAtStartOfTreatement = FALSE; pendingStartAirTrapController = FALSE; pendingStopAirTrapController = FALSE; } @@ -151,9 +156,7 @@ if ( TRUE == isAirTrapControlling() ) { pendingStopAirTrapController = TRUE; - set3WayValveState( H13_VALV, STATE_CLOSED ); // Always exit air trap valve control w/ valve closed. - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); - signalLowVenousPressureCheck(); // Venous pressure check should continue even after ending auto air trap control + signalLowVenousPressureCheck(); // Venous pressure check should continue even after ending auto air trap control } } @@ -169,7 +172,7 @@ { BOOL result = FALSE; - if ( airTrapControllerState >= AIR_TRAP_VALVE_CLOSED_STATE ) + if ( airTrapControllerState >= AIR_TRAP_CLOSED_STATE ) { result = TRUE; } @@ -189,7 +192,6 @@ void execAirTrapMonitor( void ) { BOOL isAirTrapLevelsValid = FALSE; - AIR_TRAP_LEVELS_T lowerAirTrap, upperAirTrap; // Update level sensors from FPGA readLevelSensors(); @@ -202,8 +204,9 @@ } else { - lowerAirTrap = getLevelSensorState( H17_LEVL ); - upperAirTrap = getLevelSensorState( H16_LEVL ); + AIR_TRAP_LEVELS_T lowerAirTrap = getLevelSensorState( H17_LEVL ); + AIR_TRAP_LEVELS_T upperAirTrap = getLevelSensorState( H16_LEVL ); + isAirTrapLevelsValid = ( ( ( AIR_TRAP_LEVEL_AIR == lowerAirTrap ) && ( AIR_TRAP_LEVEL_FLUID == upperAirTrap ) ) ? TRUE : FALSE ); #ifndef _RELEASE_ @@ -225,12 +228,12 @@ * @details \b Outputs: none * @return none *************************************************************************/ -void execAirTrapMonitorTreatment( void ) +void execAirTrapMonitorTreatment( void ) // TODO - call from treatment mode when ready { // Check air trap fill timeout during treatment - if ( AIR_TRAP_VALVE_OPEN_STATE == airTrapControllerState ) + if ( AIR_TRAP_RAISE_LEVEL_STATE == airTrapControllerState ) { - if ( TRUE == didTimeout( fillStartTime, AIR_TRAP_FILL_TIMEOUT_MS ) ) + if ( TRUE == didTimeout( airTrapFillStartTime, AIR_TRAP_FILL_TIMEOUT_MS ) ) { #ifndef _RELEASE_ // if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_TRAP_LEVELING_ALARM ) != SW_CONFIG_ENABLE_VALUE ) @@ -255,12 +258,10 @@ void execAirTrapController( void ) { // If we have faulted, close valve and go to manual control - if ( MODE_FAUL == getCurrentOperationMode() ) + if ( ( MODE_FAUL == getCurrentOperationMode() ) && ( airTrapHasDetectedFaultMode != TRUE ) ) { - airTrapControllerState = AIR_TRAP_MANUAL_CONTROL_STATE; - set3WayValveState( H13_VALV, STATE_CLOSED ); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); - pendingStartAirTrapController = FALSE; + endAirTrapControl(); + airTrapHasDetectedFaultMode = TRUE; } // Execute air trap state machine @@ -274,14 +275,18 @@ airTrapControllerState = handleAirTrapManualControlState(); break; - case AIR_TRAP_VALVE_CLOSED_STATE: - airTrapControllerState = handleAirTrapValveClosedState(); + case AIR_TRAP_CLOSED_STATE: + airTrapControllerState = handleAirTrapClosedState(); break; - case AIR_TRAP_VALVE_OPEN_STATE: - airTrapControllerState = handleAirTrapValveOpenState(); + case AIR_TRAP_RAISE_LEVEL_STATE: + airTrapControllerState = handleAirTrapRaiseLevelState(); break; + case AIR_TRAP_LOWER_LEVEL_STATE: + airTrapControllerState = handleAirTrapLowerlevelState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, (U32)SW_FAULT_ID_AIR_TRAP_INVALID_STATE, (U32)airTrapControllerState ) airTrapControllerState = AIR_TRAP_INIT_STATE; @@ -308,134 +313,145 @@ if ( TRUE == pendingStartAirTrapController ) { pendingStartAirTrapController = FALSE; + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); set3WayValveState( H13_VALV, STATE_CLOSED ); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); - result = AIR_TRAP_VALVE_CLOSED_STATE; + set3WayValveState( H20_VALV, STATE_CLOSED ); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, 0, 0 ); + result = AIR_TRAP_CLOSED_STATE; } return result; } /*********************************************************************//** * @brief - * The handleAirTrapValveClosedState function handles the valve closed state - * of the air trap. - * @details \b Message \b Sent: MSG_ID_TD_EVENT if opening air trap valve. + * The handleAirTrapClosedState function handles the closed state of the + * air trap. + * @details \b Message \b Sent: MSG_ID_TD_EVENT if starting a level change. * @details \b Inputs: pendingStopAirTrapController * @details \b Outputs: none * @return next state *************************************************************************/ -static AIR_TRAP_STATE_T handleAirTrapValveClosedState( void ) +static AIR_TRAP_STATE_T handleAirTrapClosedState( void ) { - AIR_TRAP_STATE_T result = AIR_TRAP_VALVE_CLOSED_STATE; + AIR_TRAP_STATE_T result = AIR_TRAP_CLOSED_STATE; - // Air pump stop time based on the blood flow rate - S32 qB = 0; // TODO abs( getTargetBloodFlowRate() ); - U32 qBx = 0; // TODO ( 0 == qB ? MIN_SET_BLOOD_FLOW_RATE : (U32)qB ); - U32 airPumpStopTime = 0; // TODO AIR_PUMP_ON_STOP_TIME_MIN_MS + ( ( qBx - MIN_SET_BLOOD_FLOW_RATE ) / 2 ); - - // Transition to manual valve control state when requested + // Transition to manual control state when requested if ( TRUE == pendingStopAirTrapController ) { pendingStopAirTrapController = FALSE; result = AIR_TRAP_MANUAL_CONTROL_STATE; - - if ( AIR_PUMP_STATE_ON == getAirPumpState() ) - { - setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); - } } - // Open valve once at start of treatment (blood priming) - else if ( TRUE == airTrapValveOpenAtStartOfTreatement ) - { - airTrapValveOpenAtStartOfTreatement = FALSE; - if ( AIR_PUMP_STATE_ON == getAirPumpState() ) - { - setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); - } - - set3WayValveState( H13_VALV, STATE_OPEN ); - fillStartTime = getMSTimerCount(); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_OPEN, 0 ); - result = AIR_TRAP_VALVE_OPEN_STATE; - } - - // Turn air pump off after defined time or air detected at upper level - else if ( ( AIR_PUMP_STATE_ON == getAirPumpState() ) && - ( ( TRUE == didTimeout( stopAirPumpStartTime, airPumpStopTime ) ) || - ( ( AIR_TRAP_LEVEL_AIR == getRawLevelSensorState( H16_LEVL ) ) && - ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) ) ) ) - - { - setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); - airPumpOnDelayStartTime = getMSTimerCount(); - } - - // Turn on air pump if fluid reaches upper level. + // Lower air trap level if fluid reaches upper level. else if ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H16_LEVL ) ) { if ( ( AIR_PUMP_STATE_OFF == getAirPumpState() ) && - ( TRUE == didTimeout( airPumpOnDelayStartTime, AIR_PUMP_ON_DELAY_TIME_MS ) ) ) + ( TRUE == didTimeout( airTrapLowerDelayStartTime, AIR_PUMP_ON_DELAY_TIME_MS ) ) ) { - setAirPumpState( AIR_PUMP_STATE_ON, 100 ); // TODO - set this depending on level direction, make #define for it - stopAirPumpStartTime = getMSTimerCount(); + set3WayValveState( H13_VALV, STATE_OPEN ); // open valve H13 to allow air to be pumped into air trap from atmosphere + setAirPumpState( AIR_PUMP_STATE_ON, AIR_PUMP_MOTOR_LOWER_PWM ); + airTrapLowerStartTime = getMSTimerCount(); signalInitiatePressureStabilization( USE_SHORT_STABILIZATION_PERIOD ); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_LOWER, 1, 0 ); + result = AIR_TRAP_LOWER_LEVEL_STATE; } } - // Transition to open valve state when air detected at lower level - else if ( ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H16_LEVL ) ) && - ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H17_LEVL ) ) ) + // Raise air trap level once at start of treatment (blood priming) or when air detected at lower level + else if ( ( TRUE == airTrapWasFilledAtStartOfTreatement ) || + ( ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H16_LEVL ) ) && + ( AIR_TRAP_LEVEL_AIR == getLevelSensorState( H17_LEVL ) ) ) ) { - if ( AIR_PUMP_STATE_ON == getAirPumpState() ) - { - setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); - } - - set3WayValveState( H13_VALV, STATE_OPEN ); - fillStartTime = getMSTimerCount(); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_OPEN, 0 ); - result = AIR_TRAP_VALVE_OPEN_STATE; + setAirPumpState( AIR_PUMP_STATE_ON, AIR_PUMP_MOTOR_FILL_PWM ); + set3WayValveState( H20_VALV, STATE_OPEN ); // open valve H20 to allow air to be pumped out of air trap to atmosphere + airTrapFillStartTime = getMSTimerCount(); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, 1, 0 ); + result = AIR_TRAP_RAISE_LEVEL_STATE; } return result; } /*********************************************************************//** * @brief - * The handleAirTrapValveOpenState function handles the valve open state of - * the air trap. - * @details \b Message \b Sent: MSG_ID_TD_EVENT if closing air trap valve + * The handleAirTrapRaiseLevelState function handles the raise level state + * of the air trap. + * @details \b Message \b Sent: MSG_ID_TD_EVENT if raising level completed * @details \b Inputs: pendingStopAirTrapController * @details \b Outputs: none * @return next state *************************************************************************/ -static AIR_TRAP_STATE_T handleAirTrapValveOpenState( void ) +static AIR_TRAP_STATE_T handleAirTrapRaiseLevelState( void ) { - AIR_TRAP_STATE_T result = AIR_TRAP_VALVE_OPEN_STATE; + AIR_TRAP_STATE_T result = AIR_TRAP_RAISE_LEVEL_STATE; // Transition to manual valve control state when requested if ( TRUE == pendingStopAirTrapController ) { pendingStopAirTrapController = FALSE; + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H20_VALV, STATE_CLOSED ); result = AIR_TRAP_MANUAL_CONTROL_STATE; } - // Transition to closed valve state when fluid detected at upper level + // Transition back to closed state when air trap fill completed else if ( AIR_TRAP_LEVEL_FLUID == getRawLevelSensorState( H16_LEVL ) ) { - set3WayValveState( H13_VALV, STATE_CLOSED ); - airPumpOnDelayStartTime = u32DiffWithWrap( AIR_PUMP_ON_DELAY_ADJUST_AFTER_FILL, getMSTimerCount() ); + airTrapWasFilledAtStartOfTreatement = TRUE; + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H20_VALV, STATE_CLOSED ); + airTrapLowerDelayStartTime = calcTimeBetween( AIR_PUMP_ON_DELAY_ADJUST_AFTER_FILL, getMSTimerCount() ); signalLowVenousPressureCheck(); - SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); - result = AIR_TRAP_VALVE_CLOSED_STATE; + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_FILL, 0, 0 ); + result = AIR_TRAP_CLOSED_STATE; } return result; } /*********************************************************************//** * @brief + * The handleAirTrapLowerlevelState function handles the lower level state + * of the air trap. + * @details \b Message \b Sent: MSG_ID_TD_EVENT if lowering air trap level completed. + * @details \b Inputs: none + * @details \b Outputs: none + * @return next state + *************************************************************************/ +static AIR_TRAP_STATE_T handleAirTrapLowerlevelState( void ) +{ + AIR_TRAP_STATE_T result = AIR_TRAP_LOWER_LEVEL_STATE; + // Air pump stop time based on the blood flow rate + S32 qB = 500; // TODO abs( getTargetBloodFlowRate() ); + U32 qBx = ( 0 == qB ? MIN_SET_BLOOD_FLOW_RATE : (U32)qB ); + U32 airPumpStopTime = AIR_PUMP_LOWER_OP_TIME_MIN_MS + ( ( qBx - MIN_SET_BLOOD_FLOW_RATE ) / 2 ); + + // Transition to manual valve control state when requested + if ( TRUE == pendingStopAirTrapController ) + { + pendingStopAirTrapController = FALSE; + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, STATE_CLOSED ); + result = AIR_TRAP_MANUAL_CONTROL_STATE; + } + // Transition back to closed state when air trap lower level operation completed + else if ( ( TRUE == didTimeout( airTrapLowerStartTime, airPumpStopTime ) ) || + ( ( AIR_TRAP_LEVEL_AIR == getRawLevelSensorState( H16_LEVL ) ) && + ( AIR_TRAP_LEVEL_FLUID == getLevelSensorState( H17_LEVL ) ) ) ) + + { + setAirPumpState( AIR_PUMP_STATE_OFF, AIR_PUMP_MOTOR_OFF ); + set3WayValveState( H13_VALV, STATE_CLOSED ); + airTrapLowerDelayStartTime = getMSTimerCount(); + SEND_EVENT_WITH_2_U32_DATA( TD_EVENT_AIR_TRAP_LOWER, 0, 0 ); + result = AIR_TRAP_CLOSED_STATE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The publishAirTrapData function constructs and sends the air trap data * broadcast message. * @details \b Message \b Sent: MSG_ID_TD_AIR_TRAP_DATA