/************************************************************************** * * Copyright (c) 2020-2025 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 AirTrap.c * * @author (last) Dara Navaei * @date (last) 12-Nov-2025 * * @author (original) Sean Nash * @date (original) 16-Sep-2020 * ***************************************************************************/ #include "AirPump.h" #include "AirTrap.h" #include "AlarmMgmt.h" #include "FPGA.h" #include "ModeTreatmentParams.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "Switches.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "Timers.h" /** * @addtogroup AirTrap * @{ */ // ********** private definitions ********** #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_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_LEVEL_DEBOUNCE_TIME_MS ( 400 ) ///< Air trap level sensor debounce time /// Persistence period for illegal level sensors fault. #define AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Air trap illegal values timeout (in ms) #define AIR_TRAP_UPPER_LEVEL_FLUID_TIMEOUT_MS ( 60 * MS_PER_SECOND ) ///< Air trap upper level fluid timeout in milliseconds. /// Volume (in mL) of venous portion of blood circuit line. TODO - get actual volume from Systems. #define VENOUS_LINE_VOLUME_ML ( 200.0F ) #define DATA_PUBLISH_COUNTER_START_COUNT 7 ///< Data publish counter start count. /// 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_STATE_T; // ********** private data ********** static AIR_TRAP_STATE_T airTrapControllerState; ///< Current state of air trap controller state machine. static U32 airTrapDataPublicationTimerCounter; ///< Used to schedule air trap data publication to CAN bus. /// Interval (in ms) at which to publish air trap data to CAN bus. static OVERRIDE_U32_T airTrapDataPublishInterval = { AIR_TRAP_DATA_PUB_INTERVAL, AIR_TRAP_DATA_PUB_INTERVAL, AIR_TRAP_DATA_PUB_INTERVAL, 0 }; static OVERRIDE_U32_T airTrapLevels[ NUM_OF_AIR_TRAP_LEVEL_SENSORS ]; ///< Detected air trap level for each level sensor. static OVERRIDE_U32_T rawAirTrapLevels[ NUM_OF_AIR_TRAP_LEVEL_SENSORS ]; ///< Raw air trap level before debouncing time static U32 airTrapLevelsDebounceStartTime[ NUM_OF_AIR_TRAP_LEVEL_SENSORS ]; ///< Debounce start time for airtrap level sensor. 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 = 0; ///< Time stamp for start of air trap fill. static U32 airPumpOnDelayStartTime = 0; ///< Air pump On start time. static U32 stopAirPumpStartTime = 0; ///< Stop air pump start time. /// Air pump on delay after fill adjustment static const U32 AIR_PUMP_ON_DELAY_ADJUST_AFTER_FILL = ( AIR_PUMP_ON_DELAY_TIME_MS - ( 1 * MS_PER_SECOND ) ); static BOOL airTrapValveOpenAtStartOfTreatement = FALSE; ///< To Keep the fluid level high close to Air trap upper level during start of treatment // ********** 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 void checkAirTrapUpperLevelFluidTimeout( void ); static void publishAirTrapData( void ); /*********************************************************************//** * @brief * The initAirTrap function initializes the Air Trap module. * @details Inputs: none * @details Outputs: Air Trap module initialized. * @return none *************************************************************************/ void initAirTrap( void ) { U32 i; resetAirTrap(); airTrapDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; airTrapValveOpenAtStartOfTreatement = TRUE; airPumpOnDelayStartTime = getMSTimerCount(); stopAirPumpStartTime = 0; for ( i = 0; i < NUM_OF_AIR_TRAP_LEVEL_SENSORS; i++ ) { airTrapLevels[i].data = 0; airTrapLevels[i].ovData = 0; airTrapLevels[i].ovInitData = 0; airTrapLevels[i].override = OVERRIDE_RESET; rawAirTrapLevels[i].data = 0; rawAirTrapLevels[i].ovData = 0; rawAirTrapLevels[i].ovInitData = 0; rawAirTrapLevels[i].override = OVERRIDE_RESET; airTrapLevelsDebounceStartTime[i] = 0; } initPersistentAlarm( ALARM_ID_HD_AIR_TRAP_ILLEGAL_LEVELS, AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS, AIR_TRAP_ILLEGAL_LEVELS_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_HD_AIR_TRAP_UPPER_LEVEL_FLUID_TIME_OUT, 0, AIR_TRAP_UPPER_LEVEL_FLUID_TIMEOUT_MS ); } /*********************************************************************//** * @brief * The resetAirTrap function resets certain parts of the air trap module * between treatments. * @details Inputs: none * @details Outputs: Air Trap module reset. * @return none *************************************************************************/ void resetAirTrap( void ) { airTrapControllerState = AIR_TRAP_INIT_STATE; pendingStartAirTrapController = FALSE; pendingStopAirTrapController = FALSE; } /*********************************************************************//** * @brief * The startAirTrapControl function requests a start to air trap control. * @details Inputs: airTrapControllerState * @details Outputs: pendingStartAirTrapController * @return none *************************************************************************/ void startAirTrapControl( void ) { if ( FALSE == isAirTrapControlling() ) { pendingStartAirTrapController = TRUE; } } /*********************************************************************//** * @brief * The endAirTrapControl function requests a stop to air trap control. * @details Inputs: airTrapControllerState * @details Outputs: pendingStopAirTrapController * @return none *************************************************************************/ void endAirTrapControl( void ) { if ( TRUE == isAirTrapControlling() ) { pendingStopAirTrapController = TRUE; setValveAirTrap( STATE_CLOSED ); // Always exit air trap valve control w/ valve closed. signalLowVenousPressureCheck(); // Venous pressure check should continue even after ending auto air trap control SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); } } /*********************************************************************//** * @brief * The isAirTrapControlling function determines whether the air trap is * currently controlling. * @details Inputs: airTrapControllerState * @details Outputs: none * @return TRUE if air trap is currently controlling, FALSE if not. *************************************************************************/ BOOL isAirTrapControlling( void ) { BOOL result = FALSE; if ( airTrapControllerState >= AIR_TRAP_VALVE_CLOSED_STATE ) { result = TRUE; } return result; } /*********************************************************************//** * @brief * The execAirTrapMonitor function executes the air trap monitor. * @details Inputs: FPGA air trap levels GPIO pin levels, airTrapIllegalLevelSensorsCtr * @details Outputs: airTrapLevels[], airTrapIllegalLevelSensorsCtr * @return none *************************************************************************/ void execAirTrapMonitor( void ) { BOOL lower, upper; BOOL isAirTrapLevelsValid = FALSE; AIR_TRAP_LEVELS_T lowerAirTrap, upperAirTrap; AIR_TRAP_LEVEL_SENSORS_T airTrapLevelSensor; // Get latest raw level readings getFPGAAirTrapLevels( &lower, &upper ); rawAirTrapLevels[ AIR_TRAP_LEVEL_SENSOR_LOWER ].data = (U32)( TRUE == lower ? AIR_TRAP_LEVEL_AIR : AIR_TRAP_LEVEL_FLUID ); rawAirTrapLevels[ AIR_TRAP_LEVEL_SENSOR_UPPER ].data = (U32)( TRUE == upper ? AIR_TRAP_LEVEL_AIR : AIR_TRAP_LEVEL_FLUID ); // Read the level after expiry of debouncing time for( airTrapLevelSensor = AIR_TRAP_LEVEL_SENSOR_LOWER; airTrapLevelSensor < NUM_OF_AIR_TRAP_LEVEL_SENSORS; airTrapLevelSensor++ ) { // Check if the raw level sensor status is not the same as the recorded data if ( getRawAirTrapLevel( airTrapLevelSensor ) != (AIR_TRAP_LEVELS_T)airTrapLevels[ airTrapLevelSensor ].data ) { // If the debounce time is 0, start the timer if ( 0 == airTrapLevelsDebounceStartTime[ airTrapLevelSensor ] ) { airTrapLevelsDebounceStartTime[ airTrapLevelSensor ] = getMSTimerCount(); } // If the debounce time has been elapsed, update the level sensor status to the new status else if ( TRUE == didTimeout( airTrapLevelsDebounceStartTime[ airTrapLevelSensor ], AIR_TRAP_LEVEL_DEBOUNCE_TIME_MS ) ) { // reset the debounce time airTrapLevelsDebounceStartTime[ airTrapLevelSensor ] = 0; // update recent level status airTrapLevels[ airTrapLevelSensor ].data = (U32)getRawAirTrapLevel( airTrapLevelSensor ); } } else { airTrapLevelsDebounceStartTime[ airTrapLevelSensor ] = 0; } } if ( STATE_OPEN == getSwitchStatus( PUMP_TRACK_SWITCH ) ) { // If the pump track on open, zero the persistent counter to not check the air trap illegal level alarm checkPersistentAlarm( ALARM_ID_HD_AIR_TRAP_ILLEGAL_LEVELS, FALSE, 0.0, 0.0 ); } else { lowerAirTrap = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ); upperAirTrap = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ); isAirTrapLevelsValid = ( ( AIR_TRAP_LEVEL_AIR == lowerAirTrap ) && ( AIR_TRAP_LEVEL_FLUID == upperAirTrap ) ) ? TRUE : FALSE; #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_ILLEGAL_AIR_TRAP_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { checkPersistentAlarm( ALARM_ID_HD_AIR_TRAP_ILLEGAL_LEVELS, isAirTrapLevelsValid, lowerAirTrap, upperAirTrap ); } } } /*********************************************************************//** * @brief * The execAirTrapMonitorTreatment function executes the air trap monitor * for treatment mode. * @details Inputs: airTrapLevels[], airTrapFillAlarmCtr * @details Outputs: airTrapFillAlarmCtr * @return none *************************************************************************/ void execAirTrapMonitorTreatment( void ) { // Check air trap fill timeout during treatment if ( AIR_TRAP_VALVE_OPEN_STATE == airTrapControllerState ) { if ( TRUE == didTimeout( fillStartTime, AIR_TRAP_FILL_TIMEOUT_MS ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_AIR_TRAP_LEVELING_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { activateAlarmNoData( ALARM_ID_HD_AIR_TRAP_FILL_DURING_TREATMENT ); } } } } /*********************************************************************//** * @brief * The execAirTrapController function executes the air trap control state machine. * @details Inputs: airTrapControllerState * @details Outputs: airTrapControllerState * @return none *************************************************************************/ void execAirTrapController( void ) { // If we have faulted, close valve and go to manual control if ( MODE_FAUL == getCurrentOperationMode() ) { airTrapControllerState = AIR_TRAP_MANUAL_CONTROL_STATE; setValveAirTrap( STATE_CLOSED ); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); pendingStartAirTrapController = FALSE; } // Execute air trap state machine switch( airTrapControllerState ) { case AIR_TRAP_INIT_STATE: airTrapControllerState = AIR_TRAP_MANUAL_CONTROL_STATE; break; case AIR_TRAP_MANUAL_CONTROL_STATE: airTrapControllerState = handleAirTrapManualControlState(); break; case AIR_TRAP_VALVE_CLOSED_STATE: airTrapControllerState = handleAirTrapValveClosedState(); break; case AIR_TRAP_VALVE_OPEN_STATE: airTrapControllerState = handleAirTrapValveOpenState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (U32)SW_FAULT_ID_AIR_TRAP_INVALID_STATE, (U32)airTrapControllerState ) airTrapControllerState = AIR_TRAP_INIT_STATE; break; } // Publish air trap data if due publishAirTrapData(); } /*********************************************************************//** * @brief * The handleAirTrapManualControlState function handles the manual control * state of the air trap. * @details Inputs: pendingStartAirTrapController * @details Outputs: none * @return next state *************************************************************************/ static AIR_TRAP_STATE_T handleAirTrapManualControlState( void ) { AIR_TRAP_STATE_T result = AIR_TRAP_MANUAL_CONTROL_STATE; // Transition to valve control states when requested if ( TRUE == pendingStartAirTrapController ) { pendingStartAirTrapController = FALSE; setValveAirTrap( STATE_CLOSED ); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); result = AIR_TRAP_VALVE_CLOSED_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)result, 0 ) } checkPersistentAlarm( ALARM_ID_HD_AIR_TRAP_UPPER_LEVEL_FLUID_TIME_OUT, FALSE, (F32)AIR_TRAP_LEVEL_FLUID, (F32)AIR_TRAP_LEVEL_FLUID ); return result; } /*********************************************************************//** * @brief * The handleAirTrapValveClosedState function handles the valve closed state * of the air trap. * @details Inputs: pendingStopAirTrapController, airTrapLevels[] * @details Outputs: none * @return next state *************************************************************************/ static AIR_TRAP_STATE_T handleAirTrapValveClosedState( void ) { AIR_TRAP_STATE_T result = AIR_TRAP_VALVE_CLOSED_STATE; // Check whether the air trap upper level is detecting fluid all the time and if it is, trigger an alarm checkAirTrapUpperLevelFluidTimeout(); // Air pump stop time based on the blood flow rate S32 qB = abs( getTargetBloodFlowRate() ); U32 qBx = ( 0 == qB ? MIN_SET_BLOOD_FLOW_RATE : (U32)qB ); U32 airPumpStopTime = AIR_PUMP_ON_STOP_TIME_MIN_MS + ( ( qBx - MIN_SET_BLOOD_FLOW_RATE ) / 2 ); // Transition to manual valve control state when requested if ( TRUE == pendingStopAirTrapController ) { pendingStopAirTrapController = FALSE; result = AIR_TRAP_MANUAL_CONTROL_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)result, 0 ) if ( AIR_PUMP_STATE_ON == getAirPumpState() ) { setAirPumpState( AIR_PUMP_STATE_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 ); } setValveAirTrap( STATE_OPEN ); fillStartTime = getMSTimerCount(); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, STATE_OPEN, 0 ); result = AIR_TRAP_VALVE_OPEN_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)result, 0 ) } // 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 == getRawAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) && ( AIR_TRAP_LEVEL_FLUID == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) ) ) ) { setAirPumpState( AIR_PUMP_STATE_OFF ); airPumpOnDelayStartTime = getMSTimerCount(); } //Turn on air pump if fluid reaches upper level. else if ( AIR_TRAP_LEVEL_FLUID == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) { if ( ( AIR_PUMP_STATE_OFF == getAirPumpState() ) && ( TRUE == didTimeout( airPumpOnDelayStartTime, AIR_PUMP_ON_DELAY_TIME_MS ) ) ) { setAirPumpState( AIR_PUMP_STATE_ON ); stopAirPumpStartTime = getMSTimerCount(); signalInitiatePressureStabilization( USE_SHORT_STABILIZATION_PERIOD ); } } // Transition to open valve state when air detected at lower level else if ( ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) && ( AIR_TRAP_LEVEL_AIR == getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ) ) ) { if ( AIR_PUMP_STATE_ON == getAirPumpState() ) { setAirPumpState( AIR_PUMP_STATE_OFF ); } setValveAirTrap( STATE_OPEN ); fillStartTime = getMSTimerCount(); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, STATE_OPEN, 0 ); result = AIR_TRAP_VALVE_OPEN_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)result, 0 ) } return result; } /*********************************************************************//** * @brief * The handleAirTrapValveOpenState function handles the valve open state of * the air trap. * @details Inputs: pendingStopAirTrapController, airTrapLevels[] * @details Outputs: none * @return next state *************************************************************************/ static AIR_TRAP_STATE_T handleAirTrapValveOpenState( void ) { AIR_TRAP_STATE_T result = AIR_TRAP_VALVE_OPEN_STATE; checkAirTrapUpperLevelFluidTimeout(); // Transition to manual valve control state when requested if ( TRUE == pendingStopAirTrapController ) { pendingStopAirTrapController = FALSE; result = AIR_TRAP_MANUAL_CONTROL_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)result, 0 ) } // Transition to closed valve state when fluid detected at upper level else if ( AIR_TRAP_LEVEL_FLUID == getRawAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ) ) { setValveAirTrap( STATE_CLOSED ); airPumpOnDelayStartTime = u32DiffWithWrap( AIR_PUMP_ON_DELAY_ADJUST_AFTER_FILL, getMSTimerCount() ); signalLowVenousPressureCheck(); SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_FILL, STATE_CLOSED, 0 ); result = AIR_TRAP_VALVE_CLOSED_STATE; SEND_EVENT_WITH_2_U32_DATA( HD_EVENT_AIR_TRAP_STATE_CHANGE, (U32)result, 0 ) } return result; } /*********************************************************************//** * @brief * The getAirTrapLevel function gets the current reading for the given * level sensor. * @details Inputs: airTrapLevels[] * @details Outputs: none * @param sensor ID of level sensor to get reading for * @return the current level sensor reading for the given sensor (air or fluid). *************************************************************************/ AIR_TRAP_LEVELS_T getAirTrapLevel( AIR_TRAP_LEVEL_SENSORS_T sensor ) { AIR_TRAP_LEVELS_T result; if ( sensor < NUM_OF_AIR_TRAP_LEVEL_SENSORS ) { result = (AIR_TRAP_LEVELS_T)getU32OverrideValue( &airTrapLevels[ sensor ] ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (U32)SW_FAULT_ID_AIR_TRAP_INVALID_LEVEL_SENSOR, (U32)sensor ) result = AIR_TRAP_LEVEL_AIR; } return result; } /*********************************************************************//** * @brief * The getRawAirTrapLevel function gets the raw level reading for the given * level sensor. * @details Inputs: rawAirTrapLevels[] * @details Outputs: none * @param sensor ID of level sensor to get reading for * @return the raw level sensor reading for the given sensor (air or fluid). *************************************************************************/ AIR_TRAP_LEVELS_T getRawAirTrapLevel( AIR_TRAP_LEVEL_SENSORS_T sensor ) { AIR_TRAP_LEVELS_T result; if ( sensor < NUM_OF_AIR_TRAP_LEVEL_SENSORS ) { result = (AIR_TRAP_LEVELS_T)getU32OverrideValue( &rawAirTrapLevels[ sensor ] ); } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, (U32)SW_FAULT_ID_AIR_TRAP_INVALID_LEVEL_SENSOR, (U32)sensor ) result = AIR_TRAP_LEVEL_AIR; } return result; } /*********************************************************************//** * @brief * The checkAirTrapUpperLevelFluidTimeout function checks whether the air * trap upper level is detecting fluid and then updates the persistent alarm. * @details Inputs: none * @details Outputs: none * @return none *************************************************************************/ static void checkAirTrapUpperLevelFluidTimeout( void ) { AIR_TRAP_LEVELS_T upperLevel = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ); BOOL isUpperLevelFluid = ( AIR_TRAP_LEVEL_FLUID == upperLevel ? TRUE : FALSE ); checkPersistentAlarm( ALARM_ID_HD_AIR_TRAP_UPPER_LEVEL_FLUID_TIME_OUT, isUpperLevelFluid, (F32)AIR_TRAP_LEVEL_FLUID, (F32)AIR_TRAP_LEVEL_FLUID ); } /*********************************************************************//** * @brief * The publishAirTrapData function publishes air trap data at the set interval. * @details Inputs: airTrapLevels[], rawAirTrapLevels[] * @details Outputs: if broadcast is due, send air trap data * @return none *************************************************************************/ static void publishAirTrapData( void ) { // Publish air trap data on interval if ( ++airTrapDataPublicationTimerCounter >= getU32OverrideValue( &airTrapDataPublishInterval ) ) { AIR_TRAP_PAYLOAD_T data; data.lowerLevel = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ); data.upperLevel = getAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ); data.rawLowerLevel = getRawAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_LOWER ); data.rawUpperLevel = getRawAirTrapLevel( AIR_TRAP_LEVEL_SENSOR_UPPER ); broadcastData( MSG_ID_HD_AIR_TRAP_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( AIR_TRAP_PAYLOAD_T ) ); airTrapDataPublicationTimerCounter = 0; } } /*********************************************************************//** * @brief * The execAirTrapTest function executes the state machine for the air trap * self-test. * @details Inputs: none * @details Outputs: none * @return the current state of the PresOccl self-test. *************************************************************************/ SELF_TEST_STATUS_T execAirTrapTest( void ) { SELF_TEST_STATUS_T status = SELF_TEST_STATUS_PASSED; // TODO - Implement POST return status; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetAirTrapDataPublishIntervalOverride function overrides the * air trap data publish interval. * @details Inputs: none * @details Outputs: airTrapDataPublishInterval * @param value override air trap data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetAirTrapDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_GENERAL_INTERVAL; result = TRUE; airTrapDataPublishInterval.ovData = intvl; airTrapDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetAirTrapDataPublishIntervalOverride function resets the override * of the air trap data publish interval. * @details Inputs: none * @details Outputs: airTrapDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetAirTrapDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; airTrapDataPublishInterval.override = OVERRIDE_RESET; airTrapDataPublishInterval.ovData = airTrapDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetAirTrapLevelOverride function overrides the measured level * for a given level sensor. * @details Inputs: none * @details Outputs: airTrapLevels[] * @param sensor ID of level sensor to override * @param level override level sensor with this * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor, AIR_TRAP_LEVELS_T level ) { BOOL result = FALSE; if ( ( sensor < NUM_OF_AIR_TRAP_LEVEL_SENSORS ) && ( level < NUM_OF_AIR_TRAP_LEVELS ) ) { if ( TRUE == isTestingActivated() ) { result = TRUE; airTrapLevels[ sensor ].ovData = (U32)level; airTrapLevels[ sensor ].override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetAirTrapLevelOverride function resets the override of the * level sensor. * @details Inputs: none * @details Outputs: airTrapLevels[] * @param sensor ID of level sensor to reset override * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor ) { BOOL result = FALSE; if ( sensor < NUM_OF_AIR_TRAP_LEVEL_SENSORS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; airTrapLevels[ sensor ].override = OVERRIDE_RESET; airTrapLevels[ sensor ].ovData = airTrapLevels[ sensor ].ovInitData; } } return result; } /*********************************************************************//** * @brief * The testSetRawAirTrapLevelOverride function overrides the measured raw level * for a given level sensor. * @details Inputs: none * @details Outputs: rawAirTrapLevels[] * @param sensor ID of level sensor to override * @param level override level sensor with this * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetRawAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor, AIR_TRAP_LEVELS_T level ) { BOOL result = FALSE; if ( ( sensor < NUM_OF_AIR_TRAP_LEVEL_SENSORS ) && ( level < NUM_OF_AIR_TRAP_LEVELS ) ) { if ( TRUE == isTestingActivated() ) { result = TRUE; rawAirTrapLevels[ sensor ].ovData = (U32)level; rawAirTrapLevels[ sensor ].override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetRawAirTrapLevelOverride function resets the override of the * level sensor. * @details Inputs: none * @details Outputs: rawAirTrapLevels[] * @param sensor ID of level sensor to reset override * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetRawAirTrapLevelOverride( AIR_TRAP_LEVEL_SENSORS_T sensor ) { BOOL result = FALSE; if ( sensor < NUM_OF_AIR_TRAP_LEVEL_SENSORS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; rawAirTrapLevels[ sensor ].override = OVERRIDE_RESET; rawAirTrapLevels[ sensor ].ovData = rawAirTrapLevels[ sensor ].ovInitData; } } return result; } /**@}*/