/************************************************************************** * * 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 Bubbles.c * * @author (last) Sean * @date (last) 07-Aug-2024 * * @author (original) Sean * @date (original) 07-Aug-2024 * ***************************************************************************/ #include "AlarmMgmtTD.h" #include "Bubbles.h" #include "FpgaTD.h" #include "Messaging.h" #include "OperationModes.h" #include "TaskPriority.h" #include "Timers.h" /** * @addtogroup Bubbles * @{ */ // ********** private definitions ********** #define BUBBLE_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the air bubble detector data is published on the CAN bus. #define BUBBLE_TIMEOUT_MS 500 ///< Air bubble detector timeout for self-test (15 ms extended edge detection) #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. /// Defined states for the air bubble detectors state machine. typedef enum BubbleStates { BUBBLE_DISABLED_STATE = 0, ///< Disabled state BUBBLE_ENABLED_STATE, ///< Enabled state BUBBLE_SELF_TEST_STATE, ///< Self-test state NUM_OF_BUBBLE_STATES ///< Number of bubble detector states } BUBBLE_STATES_T; // ********** private data ********** static BUBBLE_STATES_T bubblesState[ NUM_OF_BUBBLE_DETECTORS ]; ///< Current state of air bubble detectors state machines. static SELF_TEST_STATUS_T bubblesSelfTestStatus[ NUM_OF_BUBBLE_DETECTORS ]; ///< Current status of air bubble detectors self-tests. static U32 bubblesSelfTestStartTime[ NUM_OF_BUBBLE_DETECTORS ]; ///< Air bubble detectors self-test start times. static BOOL bubblesSelfTestRequested[ NUM_OF_BUBBLE_DETECTORS ]; ///< Air bubble detectors self-test requested flags. static BOOL bubbleDetectionEnabled[ NUM_OF_BUBBLE_DETECTORS ]; ///< Flag indicates whether air bubble alarm detection is enabled. static OVERRIDE_U32_T bubblesDataPublishInterval = { BUBBLE_PUB_INTERVAL, BUBBLE_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish air bubble detectors data on CAN bus. static U32 bubblesDataPublicationTimerCounter; ///< Timer counter used to schedule air bubble detectors data publication to CAN bus. // ********** private function prototypes ********** static BUBBLE_STATES_T handleBubbleEnabledState( BUBBLE_DETECTOR_T bubble ); static BUBBLE_STATES_T handleBubbleDisabledState( BUBBLE_DETECTOR_T bubble ); static BUBBLE_STATES_T handleBubbleSelfTestState( BUBBLE_DETECTOR_T bubble ); static void publishBubblesData( void ); /*********************************************************************//** * @brief * The initBubbles function initializes the air bubble monitor unit. * @details \b Inputs: none * @details \b Outputs: Air bubble monitor unit initialized. * @return none *************************************************************************/ void initBubbles( void ) { BUBBLE_DETECTOR_T bubble; // initialize low-level driver initBubbleDetector(); // initialize unit data for ( bubble = (BUBBLE_DETECTOR_T)0; bubble < NUM_OF_BUBBLE_DETECTORS; bubble++ ) { bubblesState[ bubble ] = BUBBLE_DISABLED_STATE; bubblesSelfTestStatus[ bubble ] = SELF_TEST_STATUS_IN_PROGRESS; bubblesSelfTestRequested[ bubble ] = FALSE; bubblesSelfTestStartTime[ bubble ] = 0; bubbleDetectionEnabled[ bubble ] = FALSE; } bubblesDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; } /*********************************************************************//** * @brief * The execBubbles function executes the air bubble monitor state machine. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if invalid bubble monitor state. * @details \b Inputs: bubblesState[] * @details \b Outputs: bubblesState[] * @return none *************************************************************************/ void execBubbles( void ) { BUBBLE_DETECTOR_T bubble; // Read all bubble detectors readBubbleDetectors(); if ( getCurrentOperationMode() != MODE_INIT ) { // Loop through all of the air bubble detectors for ( bubble = (BUBBLE_DETECTOR_T)0; bubble < NUM_OF_BUBBLE_DETECTORS; bubble++ ) { // Execute the air bubble detector state machine switch( bubblesState[ bubble ] ) { case BUBBLE_ENABLED_STATE: bubblesState[ bubble ] = handleBubbleEnabledState( bubble ); break; case BUBBLE_DISABLED_STATE: bubblesState[ bubble ] = handleBubbleDisabledState( bubble ); break; case BUBBLE_SELF_TEST_STATE: bubblesState[ bubble ] = handleBubbleSelfTestState( bubble ); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_BUBBLES_INVALID_STATE, bubblesState[ bubble ] ) break; } } } // Publish air bubble detectors data if due publishBubblesData(); } /*********************************************************************//** * @brief * The setVenousBubbleDetectionEnabled function enabled or disables venous * bubble detection. * @details \b Inputs: none * @details \b Outputs: bubbleDetectionEnabled[] * @param bubble ID of bubble detector to set enabled status for * @param enabled flag indicates whether bubble detection is enabled for the * given bubble detector * @return none *************************************************************************/ void setVenousBubbleDetectionEnabled( BUBBLE_DETECTOR_T bubble, BOOL enabled ) { bubbleDetectionEnabled[ bubble ] = enabled; } /*********************************************************************//** * @brief * The getVenousBubbleDetectionEnabled function returns the state of the * given bubble detector's enable flag. * @details \b Inputs: bubbleDetectionEnabled[] * @details \b Outputs: none * @param bubble ID of bubble detector to get enabled status for * @return TRUE if given bubble detector is enabled, FALSE if not *************************************************************************/ BOOL getVenousBubbleDetectionEnabled( BUBBLE_DETECTOR_T bubble ) { return bubbleDetectionEnabled[ bubble ]; } /*********************************************************************//** * @brief * The selfTestBubble function requests that a specified air bubble detector * be self-tested. * @details Inputs: none * @details Outputs: bubblesSelfTestRequested * @param bubble ID of bubble detector to request self-test for * @return none *************************************************************************/ void selfTestBubble( BUBBLE_DETECTOR_T bubble ) { bubblesSelfTestRequested[ bubble ] = TRUE; } /*********************************************************************//** * @brief * The getBubbleSelfTestStatus function gets the status for a given air bubble * detector self-test. * @details \b Inputs: bubblesSelfTestStatus * @details \b Outputs: none * @param bubble ID of bubble detector to get self-test status for * @return status of air bubble detector self-test. *************************************************************************/ SELF_TEST_STATUS_T getBubbleSelfTestStatus( BUBBLE_DETECTOR_T bubble ) { return bubblesSelfTestStatus[ bubble ]; } /*********************************************************************//** * @brief * The handleBubbleEnabledState function handles a given air bubble module * in enabled state. * @details \b Alarm: ALARM_ID_TD_VENOUS_BUBBLE_DETECTED if venous bubble detected. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given bubble sensor is invalid. * @details \b Inputs: none * @details \b Outputs: bubblesSelfTestStatus * @param bubble ID of bubble detector to execute enabled state for * @return next state *************************************************************************/ static BUBBLE_STATES_T handleBubbleEnabledState( BUBBLE_DETECTOR_T bubble ) { BUBBLE_STATES_T state = BUBBLE_ENABLED_STATE; if ( bubble < NUM_OF_BUBBLE_DETECTORS ) { // check for bubble detection #ifndef _RELEASE_ // if ( getSoftwareConfigStatus( SW_CONFIG_DISABLED_BUBBLE_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) #endif { // Check for venous bubble alarm if enabled. if ( ( BUBBLE_DETECTED == getBubbleDetectedState( bubble ) )) { activateAlarmNoData( ALARM_ID_TD_VENOUS_BUBBLE_DETECTED ); } } // if self-test requested, initiate self-test if ( TRUE == bubblesSelfTestRequested[ bubble ] ) { state = BUBBLE_SELF_TEST_STATE; bubblesSelfTestRequested[ bubble ] = FALSE; bubblesSelfTestStatus[ bubble ] = SELF_TEST_STATUS_IN_PROGRESS; if ( H18_BBLD == bubble ) { setFPGAVenousBubbleSelfTest(); } bubblesSelfTestStartTime[ bubble ] = getMSTimerCount(); } else if ( FALSE == bubbleDetectionEnabled[ bubble ] ) { state = BUBBLE_DISABLED_STATE; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_BUBBLES_INVALID_SENSOR_ID1, bubble ) } return state; } /*********************************************************************//** * @brief * The handleBubbleDisabledState function handles a given air bubble module * in disable state. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given bubble sensor is invalid. * @details \b Inputs: none * @details \b Outputs: bubblesSelfTestStatus * @param bubble ID of bubble detector to execute disable state for * @return next state *************************************************************************/ static BUBBLE_STATES_T handleBubbleDisabledState( BUBBLE_DETECTOR_T bubble ) { BUBBLE_STATES_T state = BUBBLE_DISABLED_STATE; if ( bubble < NUM_OF_BUBBLE_DETECTORS ) { // if self-test requested, initiate self-test if ( TRUE == bubblesSelfTestRequested[ bubble] ) { state = BUBBLE_SELF_TEST_STATE; bubblesSelfTestRequested[ bubble ] = FALSE; bubblesSelfTestStatus[ bubble ] = SELF_TEST_STATUS_IN_PROGRESS; if ( H18_BBLD == bubble ) { setFPGAVenousBubbleSelfTest(); } bubblesSelfTestStartTime[ bubble ] = getMSTimerCount(); } else if ( bubbleDetectionEnabled[ bubble ] != FALSE ) { state = BUBBLE_ENABLED_STATE; } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_BUBBLES_INVALID_SENSOR_ID3, bubble ) } return state; } /*********************************************************************//** * @brief * The handleBubbleSelfTestState function handles a given air bubble detector * in self-test state. * @details \b Alarm: ALARM_ID_TD_SOFTWARE_FAULT if given bubble sensor is invalid. * @details \b Inputs: bubblesSelfTestStatus * @details \b Outputs: bubblesSelfTestStatus * @param bubble ID of bubble detector to execute self-test state for * @return next state *************************************************************************/ static BUBBLE_STATES_T handleBubbleSelfTestState( BUBBLE_DETECTOR_T bubble ) { BUBBLE_STATES_T state = BUBBLE_SELF_TEST_STATE; if ( bubble < NUM_OF_BUBBLE_DETECTORS ) { if ( SELF_TEST_STATUS_IN_PROGRESS == bubblesSelfTestStatus[ bubble ] ) { if ( BUBBLE_DETECTED == getBubbleDetectedState( bubble ) ) // Faked air bubble caused { bubblesSelfTestStatus[ bubble ] = SELF_TEST_STATUS_PASSED; if ( H18_BBLD == bubble ) { clearFPGAVenousBubbleSelfTest(); } } else if ( TRUE == didTimeout( bubblesSelfTestStartTime[ bubble ], BUBBLE_TIMEOUT_MS ) ) { bubblesSelfTestStatus[ bubble ] = SELF_TEST_STATUS_FAILED; // activateAlarmNoData( ALARM_ID_TD_VENOUS_BUBBLE_SELF_TEST_FAILURE ); } } else { // Air bubble self-test finished, wait for self-test faked air bubble detector clear if ( ( NO_BUBBLE_DETECTED == getBubbleDetectedState( bubble ) ) || ( TRUE == didTimeout( bubblesSelfTestStartTime[ bubble ], BUBBLE_TIMEOUT_MS + 100 ) ) ) { if ( bubbleDetectionEnabled[ bubble ] != FALSE ) { state = BUBBLE_ENABLED_STATE; } else { state = BUBBLE_DISABLED_STATE; } } } } else { SET_ALARM_WITH_2_U32_DATA( ALARM_ID_TD_SOFTWARE_FAULT, SW_FAULT_ID_BUBBLES_INVALID_SENSOR_ID2, bubble ) } return state; } /*********************************************************************//** * @brief * The publishBubblesData function publishes air bubble detectors data at * the set interval. * @details \b Inputs: status, bubblesState * @details \b Outputs: if broadcast is due, send air bubble detectors data * @return none *************************************************************************/ static void publishBubblesData( void ) { // Publish air bubble detectors data on interval if ( ++bubblesDataPublicationTimerCounter >= getU32OverrideValue( &bubblesDataPublishInterval ) ) { BUBBLES_DATA_T bubbleData; bubbleData.h18Status = (U32)getBubbleDetectedState( H18_BBLD ); bubbleData.h18State = (U32)bubblesState[ H18_BBLD ]; broadcastData( MSG_ID_TD_BUBBLES_DATA, COMM_BUFFER_OUT_CAN_TD_BROADCAST, (U08*)&bubbleData, sizeof( BUBBLES_DATA_T ) ); bubblesDataPublicationTimerCounter = 0; } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testBubblesDataPublishIntervalOverride function overrides the interval * at which the TD bubbles data is published. * @details \b Inputs: none * @details \b Outputs: bubblesDataPublishInterval * @param message Override message from Dialin which includes the interval * (in ms) to override the bubbles data broadcast interval to. * @return TRUE if override request is successful, FALSE if not *************************************************************************/ BOOL testBubblesDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &bubblesDataPublishInterval, TASK_PRIORITY_INTERVAL ); return result; } /**@}*/