Index: firmware/App/Controllers/BloodLeak.c =================================================================== diff -u -r65a0cb19291eda2643e3dd6271b9e278d8cc59ab -r37a9fd8f15e413db5337371a7d1a1cb65567af7c --- firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 65a0cb19291eda2643e3dd6271b9e278d8cc59ab) +++ firmware/App/Controllers/BloodLeak.c (.../BloodLeak.c) (revision 37a9fd8f15e413db5337371a7d1a1cb65567af7c) @@ -1,19 +1,20 @@ /************************************************************************** * -* Copyright (c) 2019-2022 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 BloodLeak.c * -* @author (last) Sean Nash -* @date (last) 12-Nov-2021 +* @author (last) Darren Cox +* @date (last) 10-Mar-2022 * * @author (original) Peman Montazemi * @date (original) 18-Mar-2021 * ***************************************************************************/ + #include // For sprintf and strlen #include "AlarmMgmt.h" @@ -33,7 +34,7 @@ // ********** private definitions ********** #define BLOOD_LEAK_PUB_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Interval (ms/task time) at which the blood leak data is published on the CAN bus. -#define BLOOD_LEAK_TIMEOUT_MS 500 ///< Blood leak detector timeout for zeroing and self-test (15 ms extended edge detection) +#define BLOOD_LEAK_TIMEOUT_MS 2000 ///< Blood leak detector timeout for zeroing and self-test (15 ms extended edge detection) #define BLOOD_LEAK_PERSISTENCE ( 10 * MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Persistence for blood leak detected alarm. #define BLOOD_LEAK_RESET_TX_FIFO 2 ///< Blood leak reset transmit FIFO command. #define BLOOD_LEAK_START_COMM_CTRL_U_ASCII 21 ///< Blood leak start communication command, ^U (Ctrl-U) in ascii. @@ -52,14 +53,20 @@ #define BLOOD_LEAK_SET_POINT_SEQ_MAX_LENGTH 15 ///< Blood leak set point sequence maximum length. #define BLOOD_LEAK_WAIT_2_READ_SET_POINT ( 1 * MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Blood leak wait to read set point in counts. +#define BLOOD_LEAK_WAIT_2_READ_CTRL_U ( 1 * MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Blood leak wait to read control U in counts. #define BLOOD_LEAK_MAX_SET_POINT_WRITE_TRIALS 3 ///< Blood leak maximum number of trials to write the set point. +#define BLOOD_LEAK_MAX_CTRL_U_WRITE_TRIALS 3 ///< Blood leak maximum number of trials to write the control U command. #define BLOOD_LEAK_MIN_WAIT_TIME_2_GET_CAL_MS ( 2 * MS_PER_SECOND ) ///< Blood leak minimum wait time to get calibration in milliseconds. +#define DATA_PUBLISH_COUNTER_START_COUNT 60 ///< Data publish counter start count. + /// Defined states for the blood leak detector state machine. typedef enum BloodLeakStates { - BLOOD_LEAK_START_UP_STATE = 0, ///< Start up state. + BLOOD_LEAK_WAIT_FOR_POST_STATE = 0, ///< Wait for post state. + BLOOD_LEAK_START_UP_STATE, ///< Start up state. + BLOOD_LEAK_CHECK_COMM_STATE, ///< Check communication (Control U) state. BLOOD_LEAK_CHECK_SET_POINT_STATE, ///< Check set point state. BLOOD_LEAK_SET_SET_POINT_STATE, ///< Set set point state. BLOOD_LEAK_INIT_STATE, ///< Init state. @@ -78,19 +85,21 @@ static BOOL bloodLeakZeroRequested = FALSE; ///< Blood leak zero requested flag static U32 bloodLeakZeroStartTime = 0; ///< Blood leak zeroing start time. static U32 bloodLeakSelfTestStartTime = 0; ///< Blood leak self-test start time. +static BOOL bloodLeakIsPOSTComplete; ///< Blood leak is POST complete flag. static U32 bloodLeakPersistenceCtr = 0; ///< Blood leak alarm persistence timer counter. static OVERRIDE_U32_T bloodLeakDataPublishInterval = { BLOOD_LEAK_PUB_INTERVAL, BLOOD_LEAK_PUB_INTERVAL, 0, 0 }; ///< Interval (in ms) at which to publish blood leak data to CAN bus. -static U32 bloodLeakDataPublicationTimerCounter = 0; ///< Timer counter used to schedule blood leak data publication to CAN bus. -static U32 bloodLeakUARTCmdIndex; ///< Blood leak UART command index. +static U32 bloodLeakDataPublicationTimerCounter; ///< Timer counter used to schedule blood leak data publication to CAN bus. +static U32 bloodLeakUARTCmdIndex = 0; ///< Blood leak UART command index. static U32 bloodLeakSetPointSeqLength = 0; ///< Blood leak set point sequence actual length. static U08 bloodLeakSetPointSequence[ BLOOD_LEAK_SET_POINT_SEQ_MAX_LENGTH ]; ///< Blood leak set point sequence array. -static U32 bloodLeakWait2ReadSetPointCounter = 0; ///< Blood leak wait to read delay counter. -static U32 bloodLeakCurrentSetPointWriteTry = 0; ///< Blood leak current set point write try number. +static U32 bloodLeakWait2ReadResponseCounter; ///< Blood leak wait to read response counter. +static U32 bloodLeakCommandWriteTryCount; ///< Blood leak current set point write try number. static HD_BLOOD_LEAK_SENSOR_CAL_RECORD_T bloodLeakCalRecord; ///< Blood leak calibration record structure. -static U32 bloodLeakGetCalStartTime = 0; ///< Blood leak get calibration start time. +static U32 bloodLeakGetCalStartTime; ///< Blood leak get calibration start time. +static U32 bloodLeakPrevFPGARegisterCount; ///< Blood leak previous FPGA communications counter. /// Blood leak start up sequence array. static const U08 BLOOD_LEAK_START_UP_SEQUENCE[ BLOOD_LEAK_STARTUP_SEQ_LENGTH ] = { BLOOD_LEAK_RESET_TX_FIFO, @@ -102,7 +111,9 @@ // ********** private function prototypes ********** +static BLOOD_LEAK_STATES_T handleBloodLeakWaitForPostState( void ); static BLOOD_LEAK_STATES_T handleBloodLeakStartupState( void ); +static BLOOD_LEAK_STATES_T handleBloodLeakCheckCommState( void ); static BLOOD_LEAK_STATES_T handleBloodLeakCheckSetPointState( void ); static BLOOD_LEAK_STATES_T handleBloodLeakSetSetPointState( void ); static BLOOD_LEAK_STATES_T handleBloodLeakInitState( void ); @@ -119,15 +130,16 @@ * @details Inputs: none * @details Outputs: bloodLeakState, bloodLeakStatus, bloodLeakSelfTestStatus, * bloodLeakZeroRequested, bloodLeakZeroRequested, bloodLeakSelfTestStartTime, - * bloodLeakUARTCmdIndex, bloodLeakSetPointSequence, - * bloodLeakWait2ReadSetPointCounter, bloodLeakDataPublicationTimerCounter, - * bloodLeakCurrentSetPointWriteTry, bloodLeakGetCalStartTime + * bloodLeakUARTCmdIndex, bloodLeakSetPointSequence, bloodLeakPrevFPGARegisterCount + * bloodLeakWait2ReadResponseCounter, bloodLeakDataPublicationTimerCounter, + * bloodLeakCommandWriteTryCount, bloodLeakGetCalStartTime, + * bloodLeakIsPOSTComplete * @return none *************************************************************************/ void initBloodLeak( void ) { - bloodLeakDataPublicationTimerCounter = 0; - bloodLeakState = BLOOD_LEAK_START_UP_STATE; + bloodLeakDataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + bloodLeakState = BLOOD_LEAK_WAIT_FOR_POST_STATE; bloodLeakStatus.data = BLOOD_LEAK_NOT_DETECTED; bloodLeakStatus.ovInitData = BLOOD_LEAK_NOT_DETECTED; bloodLeakStatus.ovData = BLOOD_LEAK_NOT_DETECTED; @@ -138,9 +150,11 @@ bloodLeakSelfTestStartTime = 0; bloodLeakUARTCmdIndex = 0; bloodLeakSetPointSeqLength = 0; - bloodLeakWait2ReadSetPointCounter = 0; - bloodLeakCurrentSetPointWriteTry = 0; + bloodLeakWait2ReadResponseCounter = 0; + bloodLeakCommandWriteTryCount = 0; bloodLeakGetCalStartTime = getMSTimerCount(); + bloodLeakIsPOSTComplete = FALSE; + bloodLeakPrevFPGARegisterCount = 0; // Set the blood leak set pint sequence to 0 to be initialized memset( bloodLeakSetPointSequence, 0x0, BLOOD_LEAK_SET_POINT_SEQ_MAX_LENGTH ); @@ -179,10 +193,18 @@ // Execute blood leak state machine switch( bloodLeakState ) { + case BLOOD_LEAK_WAIT_FOR_POST_STATE: + bloodLeakState = handleBloodLeakWaitForPostState(); + break; + case BLOOD_LEAK_START_UP_STATE: bloodLeakState = handleBloodLeakStartupState(); break; + case BLOOD_LEAK_CHECK_COMM_STATE: + bloodLeakState = handleBloodLeakCheckCommState(); + break; + case BLOOD_LEAK_CHECK_SET_POINT_STATE: bloodLeakState = handleBloodLeakCheckSetPointState(); break; @@ -229,6 +251,7 @@ void zeroBloodLeak( void ) { bloodLeakZeroRequested = TRUE; + bloodLeakUARTCmdIndex = 0; } /*********************************************************************//** @@ -248,7 +271,8 @@ if ( TRUE == calStatus ) { - result = SELF_TEST_STATUS_PASSED; + result = SELF_TEST_STATUS_PASSED; + bloodLeakIsPOSTComplete = TRUE; } else { @@ -260,6 +284,29 @@ /*********************************************************************//** * @brief + * The handleBloodLeakWaitForPostState function handles the wait for POST + * state of the of blood leak state machine. + * @details Inputs: bloodLeakIsPOSTComplete, bloodLeakPrevFPGARegisterCount + * @details Outputs: none + * @return next state + *************************************************************************/ +static BLOOD_LEAK_STATES_T handleBloodLeakWaitForPostState( void ) +{ + BLOOD_LEAK_STATES_T state = BLOOD_LEAK_WAIT_FOR_POST_STATE; + + if ( TRUE == bloodLeakIsPOSTComplete ) + { + // Read the value that is in the FPGA counter so it can be used to make sure the blood leak is communicating after + // sending Ctrl U + bloodLeakPrevFPGARegisterCount = getFPGABloodLeakRegisterCounter(); + state = BLOOD_LEAK_START_UP_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleBloodLeakStartupState function handles the startup state of the * of blood leak state machine. * @details Inputs: bloodLeakUARTCmdIndex @@ -286,8 +333,12 @@ // Done with writing all the commands, reset the index and transition if ( bloodLeakUARTCmdIndex >= ( BLOOD_LEAK_STARTUP_SEQ_LENGTH - 1 ) ) { - bloodLeakUARTCmdIndex = 0; - state = BLOOD_LEAK_CHECK_SET_POINT_STATE; + // Wait for the sensor to start communication + if ( ++bloodLeakWait2ReadResponseCounter > BLOOD_LEAK_WAIT_2_READ_CTRL_U ) + { + bloodLeakUARTCmdIndex = 0; + state = BLOOD_LEAK_CHECK_COMM_STATE; + } } else { @@ -299,6 +350,46 @@ /*********************************************************************//** * @brief + * The handleBloodLeakCheckCommState function handles the check communication + * state to ensure the sensor is communicating. + * @details Inputs: bloodLeakCommandWriteTryCount, bloodLeakPrevFPGARegisterCount + * @details Outputs: bloodLeakCommandWriteTryCount, bloodLeakPrevFPGARegisterCount + * @return next state + *************************************************************************/ +static BLOOD_LEAK_STATES_T handleBloodLeakCheckCommState( void ) +{ + BLOOD_LEAK_STATES_T state = BLOOD_LEAK_CHECK_COMM_STATE; + + // Check if the blood leak sensor has started communicating + BOOL isBloodLeakCommunicating = ( bloodLeakPrevFPGARegisterCount != getFPGABloodLeakRegisterCounter() ? TRUE : FALSE ); + + // The sensor is communicating move on + if ( TRUE == isBloodLeakCommunicating ) + { + state = BLOOD_LEAK_CHECK_SET_POINT_STATE; + bloodLeakCommandWriteTryCount = 0; + } + else + { + // If the sensor is not communicating, and the number of writes has not exceeded try again, otherwise alarm + if ( bloodLeakCommandWriteTryCount < BLOOD_LEAK_MAX_CTRL_U_WRITE_TRIALS ) + { + bloodLeakCommandWriteTryCount++; + + bloodLeakPrevFPGARegisterCount = getFPGABloodLeakRegisterCounter(); + state = BLOOD_LEAK_START_UP_STATE; + } + else + { + // TODO alarm. Should we check the BLD communications all the time like in the monitor? + } + } + + return state; +} + +/*********************************************************************//** + * @brief * The handleBloodLeakCheckSetPointState function handles the check set point * state to ensure the set point is set correctly. * @details Inputs: none @@ -311,24 +402,31 @@ U16 bloodLeakSetPoint = getFPGABloodLeakDetectSetPoint(); +#ifdef BOARD_WITH_NO_HARDWARE + // In case it is just a bare board, use this value + bloodLeakCalRecord.setPoint = 20; +#endif + if ( bloodLeakSetPoint != bloodLeakCalRecord.setPoint ) { - if ( bloodLeakCurrentSetPointWriteTry < BLOOD_LEAK_MAX_SET_POINT_WRITE_TRIALS ) + if ( bloodLeakCommandWriteTryCount < BLOOD_LEAK_MAX_SET_POINT_WRITE_TRIALS ) { prepareSetPointSeq(); - bloodLeakCurrentSetPointWriteTry++; + bloodLeakCommandWriteTryCount++; state = BLOOD_LEAK_SET_SET_POINT_STATE; } else { - activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_SET_POINT_SET_FAILURE ); + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_SET_POINT_SET_FAILURE ); + } } - } else { state = BLOOD_LEAK_INIT_STATE; - bloodLeakCurrentSetPointWriteTry = 0; + bloodLeakCommandWriteTryCount = 0; } return state; @@ -367,9 +465,9 @@ } else { - if ( ++bloodLeakWait2ReadSetPointCounter > BLOOD_LEAK_WAIT_2_READ_SET_POINT ) + if ( ++bloodLeakWait2ReadResponseCounter > BLOOD_LEAK_WAIT_2_READ_SET_POINT ) { - bloodLeakWait2ReadSetPointCounter = 0; + bloodLeakWait2ReadResponseCounter = 0; bloodLeakUARTCmdIndex = 0; // Done with writing the set point state = BLOOD_LEAK_CHECK_SET_POINT_STATE; @@ -427,9 +525,10 @@ { if ( TRUE == didTimeout( bloodLeakZeroStartTime, BLOOD_LEAK_TIMEOUT_MS ) ) { -#ifndef IGNORE_BLOOD_LEAK_ALARM - activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_FAULT ); -#endif + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_FAULT ); + } } } @@ -448,7 +547,6 @@ { BLOOD_LEAK_STATES_T state = BLOOD_LEAK_SELF_TEST_STATE; -#ifndef IGNORE_BLOOD_LEAK_ALARM if ( SELF_TEST_STATUS_IN_PROGRESS == bloodLeakSelfTestStatus ) { if ( FALSE == noFPGABloodLeakDetected() ) // Faked blood leak caused by independent MCU board @@ -461,7 +559,7 @@ bloodLeakSelfTestStatus = SELF_TEST_STATUS_FAILED; activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SELF_TEST_FAILURE ); - } + } } else { @@ -471,9 +569,6 @@ state = BLOOD_LEAK_NORMAL_STATE; } } -#else - state = BLOOD_LEAK_NORMAL_STATE; -#endif return state; } @@ -505,9 +600,10 @@ if ( ++bloodLeakPersistenceCtr > BLOOD_LEAK_PERSISTENCE ) { bloodLeakPersistenceCtr = BLOOD_LEAK_PERSISTENCE; -#ifndef IGNORE_BLOOD_LEAK_ALARM - activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); -#endif + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) + { + activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); + } } } else // Blood leak not detected @@ -518,9 +614,10 @@ } else { -#ifndef IGNORE_BLOOD_LEAK_ALARM - clearAlarmCondition( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); -#endif + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) + { + clearAlarmCondition( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); + } } } @@ -603,9 +700,9 @@ // Loop through the number of digits and get each ASCII value for ( i = 0; i < digitCount; i++ ) { - // Write the characters - bloodLeakSetPointSequence[ bufferIndex ] = tempCharBuffer[ i ]; - bufferIndex++; + // Write the characters + bloodLeakSetPointSequence[ bufferIndex ] = tempCharBuffer[ i ]; + bufferIndex++; } // After the characters, insert the carriage return into the buffer