/************************************************************************** * * 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) Darren Cox * @date (last) 10-Mar-2022 * * @author (original) Peman Montazemi * @date (original) 18-Mar-2021 * ***************************************************************************/ #include // For sprintf and strlen #include "AlarmMgmt.h" #include "BloodLeak.h" #include "FPGA.h" #include "NVDataMgmtHDRecords.h" #include "OperationModes.h" #include "SystemCommMessages.h" #include "TaskPriority.h" #include "Timers.h" /** * @addtogroup BloodLeak * @{ */ // ********** 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 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. #define BLOOD_LEAK_UART_COMM_ACTIVE_LOW 0 ///< Blood leak UART communication active low command. #define BLOOD_LEAK_UART_COMM_ACTIVE_HIGH 1 ///< Blood leak UART communication active high command. #define BLOOD_LEAK_STARTUP_SEQ_LENGTH 6 ///< Blood leak start up sequence array length. #define BLOOD_LEAK_START_FIFO_CTRL_U_INDEX 2 ///< Blood leak start communication sequence ^U index. #define BLOOD_LEAK_START_FIFO_STOP_INDEX 3 ///< Blood leak start communication sequence stop write to FIFO index. #define BLOOD_LEAK_SET_POINT_MAX_CHAR_LENGTH 11 ///< Blood leak set point maximum character length. #define BLOOD_LEAK_SET_POINT_START_CHAR_ASCII 83 ///< Blood leak set point sequence start character in ASCII (letter S). #define BLOOD_LEAK_STOP_WRITE_FIFO_COMMAND 0 ///< Blood leak set point stop writing to FIFO command. #define BLOOD_LEAK_SET_POINT_START_CHAR_INDEX 0 ///< Blood leak set point sequence start character index number. #define BLOOD_LEAK_CARRIAGE_RETURN_ASCII 13 ///< Blood leak set point sequence carriage return character in ASCII. #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. // Calibration mode defines #define BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH 4 ///< Blood leak embedded mode command sequence length. #define BLOOD_LEAK_EMB_MODE_STOP_INDEX 1 ///< Blood leak embedded mode stop writing to FIFO index. #define BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_HIGH 5 ///< Blood leak embedded mode communication active high command. #define BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW 4 ///< Blood leak embedded mode communication active low command. #define BLOOD_LEAK_EMB_MODE_RX_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Blood leak embedded mode calibration receive timeout in milliseconds. #define BLOOD_LEAK_EMB_MODE_RX_BUFFER_EMPTY 0x80 ///< Blood leak embedded mode buffer empty value. #define BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN 5 ///< Blood leak embedded mode number of commands. #define BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES 4 ///< Blood leak embedded mode max number of command tries. #define BLOOD_LEAK_EMB_MODE_0_NUM_ASCII 48 ///< Blood leak embedded mode character 0 in ASCII. #define BLOOD_LEAK_EMB_MODE_9_NUM_ASCII 57 ///< Blood leak embedded mode character 9 in ASCII. #define BLOOD_LEAK_EMB_MODE_SET_PNT_RESP_LEN 4 ///< Blood leak embedded mode set point response length. /// Defined states for the blood leak detector state machine. typedef enum BloodLeakStates { 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. BLOOD_LEAK_ZERO_STATE, ///< Zero state. BLOOD_LEAK_SELF_TEST_STATE, ///< Self-test state. BLOOD_LEAK_NORMAL_STATE, ///< Normal state. BLOOD_LEAK_CALIBRATION_STATE, ///< Calibration state. NUM_OF_BLOOD_LEAK_STATES ///< Number of blood leak detector states. } BLOOD_LEAK_STATE_T; /// Defined embedded states typedef enum EmbStates { BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE = 0, ///< Blood leak calibration state wait for command state. BLOOD_LEAK_CAL_SEND_COMMAND_STATE, ///< Blood leak calibration state send command state. BLOOD_LEAK_CAL_WAIT_FOR_COMMAND_RESPONSE_STATE, ///< Blood leak calibration state wait for command response state. NUM_CAL_STATES ///< Number of blood leak calibration states. } BLOOD_LEAK_EMB_MODE_STATE_T; enum EmbCommands { NU = 0, ///< Null command. CS, ///< Control S command to switch to embedded mode. SP, ///< Set point command to set the set point. T, ///< Self test command. G, ///< Get self test command. I, ///< Intensity command. V, ///< Blood detection level command. Z, ///< Zero sensor command. Q, ///< Zero sensor confirm command. D, ///< Display blood detection command. C, ///< Calibration sensor command. NUM_OF_EMB_CMDS, ///< Number of embedded mode commands. }; /// Embedded mode commands specifications typedef struct { U08 commandASCII; ///< Blood leak sensor command ID number in ASCII. U08 expChar1; ///< Blood leak sensor expected response in character. U08 expChar2; ///< Blood leak sensor expected response in character. U08 length; ///< Blood leak sensor expected response length in bytes. } EMB_MODE_CMD_T; // ********** private data ********** static BLOOD_LEAK_STATE_T bloodLeakState; ///< Current state of blood leak state machine. static OVERRIDE_U32_T bloodLeakStatus; ///< Detected blood leak status for blood leak detector. static SELF_TEST_STATUS_T bloodLeakSelfTestStatus; ///< Current status of blood leak self-test. static BOOL bloodLeakZeroRequested; ///< Blood leak zero requested flag static U32 bloodLeakZeroStartTime; ///< Blood leak zeroing start time. static U32 bloodLeakSelfTestStartTime; ///< Blood leak self-test start time. static BOOL bloodLeakIsPOSTComplete; ///< Blood leak is POST complete flag. static U32 bloodLeakPersistenceCtr; ///< 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; ///< Timer counter used to schedule blood leak data publication to CAN bus. static U32 bloodLeakUARTCmdIndex; ///< Blood leak UART command index. static U32 bloodLeakSetPointSeqLength; ///< 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 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; ///< Blood leak get calibration start time. static U32 bloodLeakPrevFPGARegisterCount; ///< Blood leak previous FPGA communications counter. static BOOL bloodLeakExitNormalRequested; ///< Blood leak exit normal state requested. /// Blood leak start up sequence array. static const U08 BLOOD_LEAK_START_UP_SEQUENCE[ BLOOD_LEAK_STARTUP_SEQ_LENGTH ] = { BLOOD_LEAK_RESET_TX_FIFO, BLOOD_LEAK_UART_COMM_ACTIVE_LOW, BLOOD_LEAK_START_COMM_CTRL_U_ASCII, BLOOD_LEAK_STOP_WRITE_FIFO_COMMAND, BLOOD_LEAK_UART_COMM_ACTIVE_HIGH, BLOOD_LEAK_UART_COMM_ACTIVE_LOW }; // Embedded mode variables static BOOL bloodLeakSignalEmbModeReq; ///< Blood leak signal embedded mode has been requested. static U08 bloodLeakEmbModeRqstedCmd; ///< Blood leak signal embedded mode requested command. static U08 bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ]; ///< Blood leak embedded mode command sequence. static BLOOD_LEAK_EMB_MODE_STATE_T bloodLeakEmbModeSubstate; ///< Blood leak embedded mode state. static U32 bloodLeakEmbModeOpsStartTime; ///< Blood leak embedded mode operations start time. static U16 bloodLeakEmbModeSetPoint; ///< Blood leak embedded mode set point command. static EMB_MODE_CMD_T bloodLeakEmbModeCmd [ NUM_OF_EMB_CMDS ]; ///< Blood leak embedded mode commands. static U08 bloodLeakEmbModeRespBuffer[ BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ]; ///< Blood leak embedded mode response buffer. static U32 bloodLeakEmbModeRespIndex; ///< Blood leak embedded mode response buffer index. static U32 bloodLeakEmbModeNumOfCmdTries; ///< Blood leak embedded mode number of command trials. // ********** private function prototypes ********** static BLOOD_LEAK_STATE_T handleBloodLeakWaitForPostState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakStartupState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakCheckCommState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakCheckSetPointState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakSetSetPointState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakInitState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakZeroState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakSelfTestState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakNormalState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakCalibrationState( void ); static BLOOD_LEAK_EMB_MODE_STATE_T handleCalBloodLeakWaitForCommandState( void ); static BLOOD_LEAK_EMB_MODE_STATE_T handleCalBloodLeakSendCommandState( void ); static BLOOD_LEAK_EMB_MODE_STATE_T handleCalBloodLeakWaitForCommandResponseState( void ); static void prepareSetPointSeq( U16 setPoint ); static void publishBloodLeakData( void ); static void initEmbModeSpecs( void ); /*********************************************************************//** * @brief * The initBloodLeak function initializes the Blood Leak module. * @details Inputs: none * @details Outputs: bloodLeakState, bloodLeakStatus, bloodLeakSelfTestStatus, * bloodLeakZeroRequested, bloodLeakZeroRequested, bloodLeakSelfTestStartTime, * bloodLeakUARTCmdIndex, bloodLeakSetPointSequence, bloodLeakPrevFPGARegisterCount * bloodLeakWait2ReadResponseCounter, bloodLeakDataPublicationTimerCounter, * bloodLeakCommandWriteTryCount, bloodLeakGetCalStartTime, bloodLeakEmbModeSubstate * bloodLeakIsPOSTComplete, bloodLeakPersistenceCtr, bloodLeakSignalEmbModeReq, * bloodLeakEmbModeRqstedCmd, bloodLeakEmbModeOpsStartTime, bloodLeakEmbModeRespBuffer, * bloodLeakEmbModeRespIndex, bloodLeakEmbModeNumOfCmdTries, bloodLeakExitNormalRequested * @return none *************************************************************************/ void initBloodLeak( void ) { 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; bloodLeakStatus.override = OVERRIDE_RESET; bloodLeakSelfTestStatus = SELF_TEST_STATUS_IN_PROGRESS; bloodLeakZeroRequested = FALSE; bloodLeakZeroStartTime = 0; bloodLeakSelfTestStartTime = 0; bloodLeakUARTCmdIndex = 0; bloodLeakSetPointSeqLength = 0; bloodLeakWait2ReadResponseCounter = 0; bloodLeakCommandWriteTryCount = 0; bloodLeakGetCalStartTime = getMSTimerCount(); bloodLeakIsPOSTComplete = FALSE; bloodLeakPrevFPGARegisterCount = 0; bloodLeakPersistenceCtr = 0; bloodLeakSignalEmbModeReq = FALSE; bloodLeakEmbModeRqstedCmd = NU; bloodLeakEmbModeSubstate = BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE; bloodLeakEmbModeOpsStartTime = 0; bloodLeakEmbModeRespIndex = 0; bloodLeakEmbModeNumOfCmdTries = 0; bloodLeakExitNormalRequested = FALSE; // Set the blood leak set pint sequence to 0 to be initialized memset( bloodLeakSetPointSequence, 0x0, BLOOD_LEAK_SET_POINT_SEQ_MAX_LENGTH ); // Initialize the blood leak embedded mode response buffer memset( bloodLeakEmbModeRespBuffer, 0x0, BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ); // Initialize the blood leak calibration command sequence array. // The first index is the command character so it can be changed upon request. // The reset of the commands are never changing. bloodLeakEmbModeCmdSquence[ 0 ] = 0; bloodLeakEmbModeCmdSquence[ 1 ] = BLOOD_LEAK_STOP_WRITE_FIFO_COMMAND; bloodLeakEmbModeCmdSquence[ 2 ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_HIGH; bloodLeakEmbModeCmdSquence[ 3 ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW; // Initialize the embedded mode specifications initEmbModeSpecs(); } /*********************************************************************//** * @brief * The execBloodLeak function executes the blood leak detector driver. * @details Inputs: bloodLeakGetCalStartTime, bloodLeakSignalEmbeddedModeReq * @details Outputs: bloodLeakStatus, bloodLeakGetCalStartTime * @return none *************************************************************************/ void execBloodLeak( void ) { // Check if there is a new calibration data available and whether there has been sufficient time elapsed from the last data calibration get // The elapsed time is used to make sure the prepare buffer is not called several time when the new calibration signal is TRUE for one second // otherwise, the prepareSetPointSeq is called multiple time and zeros the start index. In the mean time, the state might have changed to set // the set point and with the start index being reset to 0, it keeps sending the first character of the set point ('S'). if ( ( TRUE == isNewCalibrationRecordAvailable() ) && ( calcTimeSince( bloodLeakGetCalStartTime ) > BLOOD_LEAK_MIN_WAIT_TIME_2_GET_CAL_MS ) ) { U32 length = sizeof( HD_BLOOD_LEAK_SENSOR_CAL_RECORD_T ); getNVRecord2Driver( GET_CAL_BLOOD_LEAK_SENSOR, (U08*)&bloodLeakCalRecord, length, 0, ALARM_ID_HD_BLOOD_LEAK_INVALID_CAL_RECORD ); prepareSetPointSeq( bloodLeakCalRecord.setPoint ); // Force the state machine to go back to set the set point that has been received from // the calibration data bloodLeakState = BLOOD_LEAK_SET_SET_POINT_STATE; // Set the calibration start time to make sure the prepare buffer is not set multiple times in a row bloodLeakGetCalStartTime = getMSTimerCount(); } // If a request to transition to embedded mode has been made, change the state to calibration state, and request a transition to service mode. // This type of work can only be done in the service mode and then the user has to restart the device to return to the normal operations of BLD. if ( TRUE == bloodLeakSignalEmbModeReq ) { bloodLeakState = BLOOD_LEAK_CALIBRATION_STATE; requestNewOperationMode( MODE_SERV ); } // Check if the mode is not in init and then run the sensor if ( getCurrentOperationMode() != MODE_INIT ) { 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; case BLOOD_LEAK_SET_SET_POINT_STATE: bloodLeakState = handleBloodLeakSetSetPointState(); break; case BLOOD_LEAK_INIT_STATE: bloodLeakState = handleBloodLeakInitState(); break; case BLOOD_LEAK_ZERO_STATE: bloodLeakState = handleBloodLeakZeroState(); break; case BLOOD_LEAK_SELF_TEST_STATE: bloodLeakState = handleBloodLeakSelfTestState(); break; case BLOOD_LEAK_NORMAL_STATE: bloodLeakState = handleBloodLeakNormalState(); break; case BLOOD_LEAK_CALIBRATION_STATE: bloodLeakState = handleBloodLeakCalibrationState(); break; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_HD_INVALID_BLOOD_LEAK_STATE, bloodLeakState ) bloodLeakState = BLOOD_LEAK_INIT_STATE; break; } } // Publish blood leak data if due publishBloodLeakData(); } /*********************************************************************//** * @brief * The zeroBloodLeak function requests that the Blood Leak Detector be * zeroed. * @details Inputs: none * @details Outputs: Blood Leak module zeroing. * @return none *************************************************************************/ void zeroBloodLeak( void ) { bloodLeakZeroRequested = TRUE; bloodLeakUARTCmdIndex = 0; } /*********************************************************************//** * @brief * The exitBloodLeakNormalState requests that the blood leak sensor to exit * its normal state. * @details Inputs: none * @details Outputs: bloodLeakExitNormalRequested * @return none *************************************************************************/ void exitBloodLeakNormalState( void ) { bloodLeakExitNormalRequested = TRUE; } /*********************************************************************//** * @brief * The execBloodLeakSelfTest function executes the blood leak self-test. * @details Inputs: none * @details Outputs: none * @return blood leak self test results (SELF_TEST_STATUS_T) *************************************************************************/ SELF_TEST_STATUS_T execBloodLeakSelfTest( void ) { SELF_TEST_STATUS_T result = SELF_TEST_STATUS_IN_PROGRESS; U32 length = sizeof( HD_BLOOD_LEAK_SENSOR_CAL_RECORD_T ); ALARM_ID_T alarm = ALARM_ID_HD_BLOOD_LEAK_INVALID_CAL_RECORD; BOOL calStatus = getNVRecord2Driver( GET_CAL_BLOOD_LEAK_SENSOR, (U08*)&bloodLeakCalRecord, length, 0, alarm ); if ( TRUE == calStatus ) { result = SELF_TEST_STATUS_PASSED; bloodLeakIsPOSTComplete = TRUE; } else { result = SELF_TEST_STATUS_FAILED; } return result; } /*********************************************************************//** * @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_STATE_T handleBloodLeakWaitForPostState( void ) { BLOOD_LEAK_STATE_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 * @details Outputs: bloodLeakUARTCmdIndex * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakStartupState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_START_UP_STATE; U32 command = BLOOD_LEAK_START_UP_SEQUENCE[ bloodLeakUARTCmdIndex ]; // Check if ^U index <= index <= 0 to Tx index. If the current value is either ^U or the 0 to command the FIFO to stop writing // use the transmit function otherwise, use the UART control. if ( ( bloodLeakUARTCmdIndex >= BLOOD_LEAK_START_FIFO_CTRL_U_INDEX ) && ( bloodLeakUARTCmdIndex <= BLOOD_LEAK_START_FIFO_STOP_INDEX ) ) { setFPGABloodLeakUARTTransmit( (U08)command ); } else { setFPGABloodLeakUARTControl( (U08)command ); } // Done with writing all the commands, reset the index and transition if ( bloodLeakUARTCmdIndex >= ( BLOOD_LEAK_STARTUP_SEQ_LENGTH - 1 ) ) { // 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 { bloodLeakUARTCmdIndex++; } return state; } /*********************************************************************//** * @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_STATE_T handleBloodLeakCheckCommState( void ) { BLOOD_LEAK_STATE_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 * @details Outputs: bloodLeakUARTCmdIndex * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakCheckSetPointState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_CHECK_SET_POINT_STATE; 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 ( bloodLeakCommandWriteTryCount < BLOOD_LEAK_MAX_SET_POINT_WRITE_TRIALS ) { prepareSetPointSeq( bloodLeakCalRecord.setPoint ); bloodLeakCommandWriteTryCount++; state = BLOOD_LEAK_SET_SET_POINT_STATE; } else { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SENSOR_SET_POINT_SET_FAILURE ); } } } else { state = BLOOD_LEAK_INIT_STATE; bloodLeakCommandWriteTryCount = 0; } return state; } /*********************************************************************//** * @brief * The handleBloodLeakSetSetPointState function handles the set set point state. * @details Inputs: bloodLeakUARTCmdIndex * @details Outputs: bloodLeakUARTCmdIndex, bloodLeakSetPointSeqLength * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakSetSetPointState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_SET_SET_POINT_STATE; // Check if the current buffer index is less than the buffer length if( bloodLeakUARTCmdIndex < bloodLeakSetPointSeqLength ) { U32 command = bloodLeakSetPointSequence[ bloodLeakUARTCmdIndex ]; // The active high index is the length - 2 they are the last two elements U32 activeHighIndex = bloodLeakSetPointSeqLength - 2; // Check if the current index towards the end of the buffer which are FIFO set and FIFO reset if( activeHighIndex > bloodLeakUARTCmdIndex ) { setFPGABloodLeakUARTTransmit( (U08)command ); } else { setFPGABloodLeakUARTControl( (U08)command ); } bloodLeakUARTCmdIndex++; } else { if ( ++bloodLeakWait2ReadResponseCounter > BLOOD_LEAK_WAIT_2_READ_SET_POINT ) { bloodLeakWait2ReadResponseCounter = 0; bloodLeakUARTCmdIndex = 0; // Done with writing the set point state = BLOOD_LEAK_CHECK_SET_POINT_STATE; } } return state; } /*********************************************************************//** * @brief * The handleBloodLeakInitState function handles the Blood Leak module in init * state. * @details Inputs: none * @details Outputs: none * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakInitState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_INIT_STATE; if ( TRUE == bloodLeakZeroRequested ) { state = BLOOD_LEAK_ZERO_STATE; bloodLeakZeroRequested = FALSE; bloodLeakZeroStartTime = getMSTimerCount(); setFPGABloodLeakZero(); } return state; } /*********************************************************************//** * @brief * The handleBloodLeakZeroState function handles the Blood Leak module in zeroing * state. * @details Inputs: none * @details Outputs: Blood Leak module zeroing. * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakZeroState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_ZERO_STATE; if ( TRUE == FPGABloodLeakZeroDetected() ) { state = BLOOD_LEAK_SELF_TEST_STATE; bloodLeakSelfTestStatus = SELF_TEST_STATUS_IN_PROGRESS; bloodLeakSelfTestStartTime = getMSTimerCount(); clearFPGABloodLeakZero(); setFPGABloodLeakSelfTest(); } else { if ( TRUE == didTimeout( bloodLeakZeroStartTime, BLOOD_LEAK_TIMEOUT_MS ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_FAULT ); } } } return state; } /*********************************************************************//** * @brief * The handleBloodLeakSelfTestState function handles the Blood Leak module * in self-test state. * @details Inputs: none * @details Outputs: Blood Leak module self test. * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakSelfTestState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_SELF_TEST_STATE; if ( SELF_TEST_STATUS_IN_PROGRESS == bloodLeakSelfTestStatus ) { if ( FALSE == noFPGABloodLeakDetected() ) // Faked blood leak caused by independent MCU board { bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; clearFPGABloodLeakSelfTest(); } else if ( TRUE == didTimeout( bloodLeakSelfTestStartTime, BLOOD_LEAK_TIMEOUT_MS ) ) { bloodLeakSelfTestStatus = SELF_TEST_STATUS_FAILED; activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SELF_TEST_FAILURE ); } } else { // Blood leak self-test finished, wait for self-test faked blood leak clear if ( TRUE == noFPGABloodLeakDetected() ) { state = BLOOD_LEAK_NORMAL_STATE; } } return state; } /*********************************************************************//** * @brief * The handleBloodLeakNormalState function handles the Blood Leak module * in normal state. * @details Inputs: none * @details Outputs: Blood Leak module normal. * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakNormalState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_NORMAL_STATE; if ( TRUE == noFPGABloodLeakDetected() ) { bloodLeakStatus.data = BLOOD_LEAK_NOT_DETECTED; } else { bloodLeakStatus.data = BLOOD_LEAK_DETECTED; } // Check status reading and act upon if ( BLOOD_LEAK_DETECTED == getBloodLeakStatus() ) { if ( ++bloodLeakPersistenceCtr > BLOOD_LEAK_PERSISTENCE ) { bloodLeakPersistenceCtr = BLOOD_LEAK_PERSISTENCE; #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); } } } else // Blood leak not detected { if ( bloodLeakPersistenceCtr > 0 ) { bloodLeakPersistenceCtr--; } else { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { clearAlarmCondition( ALARM_ID_HD_BLOOD_LEAK_DETECTED ); } } } if ( TRUE == bloodLeakZeroRequested ) { state = BLOOD_LEAK_ZERO_STATE; bloodLeakZeroRequested = FALSE; setFPGABloodLeakZero(); bloodLeakZeroStartTime = getMSTimerCount(); } if ( TRUE == bloodLeakExitNormalRequested ) { state = BLOOD_LEAK_INIT_STATE; bloodLeakZeroRequested = FALSE; bloodLeakExitNormalRequested = TRUE; } return state; } /*********************************************************************//** * @brief * The handleBloodLeakCalibrationState function handles the Blood leak * calibration state. * @details Inputs: bloodLeakCalSubstate * @details Outputs: bloodLeakCalSubstate * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakCalibrationState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_CALIBRATION_STATE; switch ( bloodLeakEmbModeSubstate ) { case BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE: bloodLeakEmbModeSubstate = handleCalBloodLeakWaitForCommandState(); break; case BLOOD_LEAK_CAL_SEND_COMMAND_STATE: bloodLeakEmbModeSubstate = handleCalBloodLeakSendCommandState(); break; case BLOOD_LEAK_CAL_WAIT_FOR_COMMAND_RESPONSE_STATE: bloodLeakEmbModeSubstate = handleCalBloodLeakWaitForCommandResponseState(); break; } return state; } /*********************************************************************//** * @brief * The getBloodLeakStatus function gets the current reading for the blood * leak detector. * @details Inputs: bloodLeakStatus * @details Outputs: none * @return the current blood leak status. *************************************************************************/ BLOOD_LEAK_STATUS_T getBloodLeakStatus( void ) { BLOOD_LEAK_STATUS_T result = (BLOOD_LEAK_STATUS_T)bloodLeakStatus.data; if ( OVERRIDE_KEY == bloodLeakStatus.override ) { result = (BLOOD_LEAK_STATUS_T)bloodLeakStatus.ovData; } return result; } /*********************************************************************//** * @brief * The getBloodLeakSelfTestStatus function gets the status for the blood * leak detector self-test. * @details Inputs: bloodLeakSelfTestStatus * @details Outputs: none * @return status of blood leak detector self-test. *************************************************************************/ SELF_TEST_STATUS_T getBloodLeakSelfTestStatus( void ) { #ifndef _RELEASE_ if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_SELF_TEST ) ) { bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; } #endif return bloodLeakSelfTestStatus; } /*********************************************************************//** * @brief * The handleCalBloodLeakWaitForCommandState function handles the wait for * command state. The state prepares the message to be sent to the blood leak * sensor. * @details Inputs: bloodLeakCalCharacter * @details Outputs: bloodLeakCalCommandSquence, bloodLeakUARTCmdIndex * @return next state *************************************************************************/ static BLOOD_LEAK_EMB_MODE_STATE_T handleCalBloodLeakWaitForCommandState( void ) { BLOOD_LEAK_EMB_MODE_STATE_T state = BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE; U08 test = getFPGABloodLeakTxFIFOCount(); switch( bloodLeakEmbModeRqstedCmd ) { case NU: // Null command do nothing break; case CS: case T: case G: case I: case V: case Z: case Q: case D: case C: // The requested command is not set point and so update the command sequence buffer. // The first index of calibration command sequence is the requested command in ASCII. bloodLeakEmbModeCmdSquence[ 0 ] = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].commandASCII; bloodLeakUARTCmdIndex = 0; bloodLeakEmbModeNumOfCmdTries = 0; state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; break; case SP: prepareSetPointSeq( bloodLeakEmbModeSetPoint ); bloodLeakEmbModeNumOfCmdTries = 0; state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; break; } return state; } /*********************************************************************//** * @brief * The handleCalBloodLeakSendCommandState function handles the send command * state. The state sends the command sequence to the blood leak sensor one by * one. * @details Inputs: bloodLeakCalCharacter, bloodLeakUARTCmdIndex * @details Outputs: bloodLeakCalCommandSquence, bloodLeakUARTCmdIndex * @return next state *************************************************************************/ static BLOOD_LEAK_EMB_MODE_STATE_T handleCalBloodLeakSendCommandState( void ) { U32 command; BLOOD_LEAK_EMB_MODE_STATE_T state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; BOOL isUARTTxDone = FALSE; BOOL isUARTCtrlDone = TRUE; switch ( bloodLeakEmbModeRqstedCmd ) { case CS: case T: case G: case I: case V: case Z: case Q: case D: case C: command = bloodLeakEmbModeCmdSquence[ bloodLeakUARTCmdIndex ]; isUARTTxDone = ( bloodLeakUARTCmdIndex <= BLOOD_LEAK_EMB_MODE_STOP_INDEX ? FALSE : TRUE ); isUARTCtrlDone = ( bloodLeakUARTCmdIndex > ( BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH - 1 ) ? TRUE : FALSE ); bloodLeakUARTCmdIndex++; break; case SP: // Check if the current buffer index is less than the buffer length if( bloodLeakUARTCmdIndex < bloodLeakSetPointSeqLength ) { // The active high index is the length - 2 they are the last two elements U32 activeHighIndex = bloodLeakSetPointSeqLength - 2; command = bloodLeakSetPointSequence[ bloodLeakUARTCmdIndex ]; isUARTTxDone = ( bloodLeakUARTCmdIndex >= activeHighIndex ? TRUE : FALSE ); isUARTCtrlDone = ( bloodLeakUARTCmdIndex > bloodLeakSetPointSeqLength ? TRUE : FALSE ); bloodLeakUARTCmdIndex++; } break; } // Check if the current index towards the end of the buffer which are FIFO set and FIFO reset if ( FALSE == isUARTCtrlDone ) { // TODO test this //FALSE == isUARTTxDone ? setFPGABloodLeakUARTTransmit( (U08)command ) : setFPGABloodLeakUARTControl( (U08)command ); if( FALSE == isUARTTxDone ) { setFPGABloodLeakUARTTransmit( (U08)command ); } else { setFPGABloodLeakUARTControl( (U08)command ); } } else { // Reset the variables for the next bloodLeakEmbModeOpsStartTime = getMSTimerCount(); bloodLeakUARTCmdIndex = 0; bloodLeakEmbModeRespIndex = 0; state = BLOOD_LEAK_CAL_WAIT_FOR_COMMAND_RESPONSE_STATE; memset( bloodLeakEmbModeRespBuffer, 0x0, BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ); } return state; } /*********************************************************************//** * @brief * The handleCalBloodLeakWaitForCommandResponseState function handles the * wait for command responses state. The state receives data in the buffer. * @details Inputs: TODO fill up * @details Outputs: TODo fill up * @return next state *************************************************************************/ static BLOOD_LEAK_EMB_MODE_STATE_T handleCalBloodLeakWaitForCommandResponseState( void ) { BLOOD_LEAK_EMB_MODE_STATE_T state = BLOOD_LEAK_CAL_WAIT_FOR_COMMAND_RESPONSE_STATE; U08 rxFIFOCount = getFPGABloodLeakRxFIFOCount(); U08 length = 0; if ( rxFIFOCount > 0 ) { /* * There are 3 types of data that can be received from the the sensor: * 1. It could be a start character and the length (i.e. VXXXX) * 2. It could be two discrete characters (i.e. P, F) * 3. It could be none of the two characters (i.e. XXXX) */ length = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].length; U08 data = getFPGABloodLeakRxFIFODataOut(); U08 expChar1 = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].expChar1; U08 expChar2 = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].expChar2; U08 command = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].commandASCII; if ( ( expChar1 != NU ) && ( NU == expChar2 ) ) { // This is the case that there is a start character. If current character buffer index is less than the // length of the expected response of the command. if ( bloodLeakEmbModeRespIndex < length ) { // Check if the expected char is received and the response buffer is empty because the index is 0, // insert the buffer data if ( ( expChar1 == data ) && ( 0 == bloodLeakEmbModeRespIndex ) ) { bloodLeakEmbModeRespBuffer[ bloodLeakEmbModeRespIndex ] = data; bloodLeakEmbModeRespIndex++; } // Check if the buffer index is > 0 so the first char has been inserted and the rest is data but it is not the echo of the command // For instance, V has been inserted and XXXX is inserted that is followed by V. So V123 and not VVV12. else if ( ( bloodLeakEmbModeRespIndex > 0 ) && ( data != expChar1 ) ) { bloodLeakEmbModeRespBuffer[ bloodLeakEmbModeRespIndex ] = data; bloodLeakEmbModeRespIndex++; } } } else if ( ( expChar1 != NU ) && ( expChar2 != NU ) ) { // This is the case that both expected chars are not null. Either of the chars are accepted like P or F if ( bloodLeakEmbModeRespIndex < length ) { // Check if either of the expected chars are received and if they are insert it into the response buffer if ( ( expChar1 == data ) || ( expChar2 == data ) ) { bloodLeakEmbModeRespBuffer[ bloodLeakEmbModeRespIndex ] = data; bloodLeakEmbModeRespIndex++; } } if ( BLOOD_LEAK_SET_POINT_START_CHAR_ASCII == command ) { // There is an exception in this case which is the set point command. // The set point command can either receive X for timeout or F if the command failed. // But if the command was received properly, the response is XXXX. For example if set point is 200, the response is 0200 // The response buffer length of a successful set point is 4 characters (XXXX) if ( bloodLeakEmbModeRespIndex < BLOOD_LEAK_EMB_MODE_SET_PNT_RESP_LEN ) { U08 spResponse = bloodLeakEmbModeRespBuffer[ 0 ]; length = BLOOD_LEAK_EMB_MODE_SET_PNT_RESP_LEN; if ( ( spResponse != expChar1 ) && ( spResponse != expChar2 ) ) { // Check if the failed and timeout characters are not inserted // Check if the response buffer has not been filled and the current received data is a number in between 0 to 9 if ( ( data >= BLOOD_LEAK_EMB_MODE_0_NUM_ASCII ) && ( data <= BLOOD_LEAK_EMB_MODE_9_NUM_ASCII ) ) { bloodLeakEmbModeRespBuffer[ bloodLeakEmbModeRespIndex ] = data; bloodLeakEmbModeRespIndex++; } } } } } else if ( ( NU == expChar1 ) && ( NU == expChar2 ) ) { // This is the case that there are no expected characters and the received value are numbers if ( bloodLeakEmbModeRespIndex < length ) { // If the received character is in the range of numbers chars (0 to 9), then insert them into the response buffer if ( ( data >= BLOOD_LEAK_EMB_MODE_0_NUM_ASCII ) && ( data <= BLOOD_LEAK_EMB_MODE_9_NUM_ASCII ) ) { bloodLeakEmbModeRespBuffer[ bloodLeakEmbModeRespIndex ] = data; bloodLeakEmbModeRespIndex++; } } } } // If wait for the receive FIFO has timed out or all there is no buffer left in the Rx FIFO transition back to wait for command state for the next command if ( ( TRUE == didTimeout( bloodLeakEmbModeOpsStartTime, BLOOD_LEAK_EMB_MODE_RX_TIMEOUT_MS ) ) || ( BLOOD_LEAK_EMB_MODE_RX_BUFFER_EMPTY == rxFIFOCount ) ) { // Check if the first element of the response buffer is null and the number of tries has not exceeded. When the response buffer is // null but it is the end of the receive buffer it means no response has been received back if ( ( NU == bloodLeakEmbModeRespBuffer[ 0 ] ) && ( ++bloodLeakEmbModeNumOfCmdTries < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) ) { state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; } else { U08 i; BOOL isNull = FALSE; for ( i = 0; i < length; i++ ) { // Loop through the elements of the buffer and make sure none of the elements are not NULL. // The elements are checked until the specified length that is expected for a command isNull |= ( bloodLeakEmbModeRespBuffer[ i ] != NU ? FALSE : TRUE ); } // Check if the failed command is Control S which is switch to embedded mode and if // it failed set the embedded mode request to false so the other commands cannot be sent again bloodLeakSignalEmbModeReq = ( ( CS == bloodLeakEmbModeRqstedCmd ) && ( NU == bloodLeakEmbModeRespBuffer[ 0 ] ) ? FALSE : TRUE ); if ( ( TRUE == isNull ) && ( ++bloodLeakEmbModeNumOfCmdTries < BLOOD_LEAK_EMB_MODE_MAX_NUM_CMD_TRIES ) ) { state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; } else { bloodLeakEmbModeRqstedCmd = NU; state = BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE; handleSendBloodLeakEmbeddedModeCommandResponse( length, bloodLeakEmbModeRespBuffer ); } } } return state; } /*********************************************************************//** * @brief * The prepareSetPointSeq function prepares the set point sequence to be * written to the blood leak sensor. * @details Inputs: none * @details Outputs: bloodLeakSetPointSequence, bloodLeakSetPointSeqLength * @param setPoint the set point that has to be prepared to be sent to the sensor * @return none *************************************************************************/ static void prepareSetPointSeq( U16 setPoint ) { U08 i; U32 digitCount; char tempCharBuffer[ BLOOD_LEAK_SET_POINT_MAX_CHAR_LENGTH ]; U32 bufferIndex = BLOOD_LEAK_SET_POINT_START_CHAR_INDEX; memset( tempCharBuffer, 0x0, BLOOD_LEAK_SET_POINT_MAX_CHAR_LENGTH ); // Convert the set point number to the equivalent ASCII number with the unsigned integer data type sprintf( tempCharBuffer, "%u", (U32)setPoint ); // Calculate the length of the character buffer. strlen does not count the null character. digitCount = strlen( tempCharBuffer ); // Set the first item to the ASCII character of S. The format to set the set point is // SXXXCR10. It starts with S followed by the characters up to 3 digits, carriage return and a 1 and a 0 to write to the buffer. bloodLeakSetPointSequence[ bufferIndex ] = BLOOD_LEAK_SET_POINT_START_CHAR_ASCII; // Increment the buffer index bufferIndex++; // 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++; } // After the characters, insert the carriage return into the buffer bloodLeakSetPointSequence[ bufferIndex ] = BLOOD_LEAK_CARRIAGE_RETURN_ASCII; bufferIndex++; // After the characters, insert the stop write to FIFO character which is number 0 bloodLeakSetPointSequence[ bufferIndex ] = BLOOD_LEAK_STOP_WRITE_FIFO_COMMAND; bufferIndex++; // Set active high and active low into the buffer bloodLeakSetPointSequence[ bufferIndex ] = ( TRUE == bloodLeakSignalEmbModeReq ? BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_HIGH : BLOOD_LEAK_UART_COMM_ACTIVE_HIGH ); bufferIndex++; bloodLeakSetPointSequence[ bufferIndex ] = ( TRUE == bloodLeakSignalEmbModeReq ? BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW : BLOOD_LEAK_UART_COMM_ACTIVE_LOW ); // Update the sequence length for writing to the sensor bloodLeakSetPointSeqLength = bufferIndex + 1; // Get ready for the next write to the sensor bloodLeakUARTCmdIndex = 0; } /*********************************************************************//** * @brief * The publishBloodLeakData function publishes blood leak data at the set interval. * @details Inputs: bloodLeakDataPublicationTimerCounter * @details Outputs: bloodLeakDataPublicationTimerCounter * @return none *************************************************************************/ static void publishBloodLeakData( void ) { // Publish blood leak data on interval if ( ++bloodLeakDataPublicationTimerCounter >= getU32OverrideValue( &bloodLeakDataPublishInterval ) ) { BLOOD_LEAK_DATA_T data; data.bloodLeakStatus = (U32)getBloodLeakStatus(); data.bloodLeakState = (U32)bloodLeakState; data.bloodLeakZeroStatusCounter = (U32)getFPGABloodLeakZeroStatusCounter(); data.bloodLeakCounter = (U32)getFPGABloodLeakCounter(); data.bloodLeakZeroedStatus = (U32)getFPGABloodLeakZeroedStatus(); data.bloodLeakDetectSetPoint = (U32)getFPGABloodLeakDetectSetPoint(); data.bloodLeakDetectLevel = (U32)getFPGABloodLeakDetectLevel(); data.bloodLeakStCount = (U32)getFPGABloodLeakStCount(); data.bloodLeakLEDIntesity = (U32)getFPGABloodLeakLEDIntensity(); data.bloodLeakRegisterCounter = (U32)getFPGABloodLeakRegisterCounter(); broadcastData( MSG_ID_HD_BLOOD_LEAK_DATA, COMM_BUFFER_OUT_CAN_HD_BROADCAST, (U08*)&data, sizeof( BLOOD_LEAK_DATA_T ) ); bloodLeakDataPublicationTimerCounter = 0; } } /*********************************************************************//** * @brief * The initEmbModeSpecs function initializes the embedded mode specifications * structure. * @details Inputs: none * @details Outputs: bloodLeakEmbModeCmd * @return none *************************************************************************/ static void initEmbModeSpecs( void ) { // Null command bloodLeakEmbModeCmd[ NU ].commandASCII = NU; bloodLeakEmbModeCmd[ NU ].expChar1 = NU; bloodLeakEmbModeCmd[ NU ].expChar2 = NU; bloodLeakEmbModeCmd[ NU ].length = 0; // Control S command bloodLeakEmbModeCmd[ CS ].commandASCII = 19; // ASCII for Control S bloodLeakEmbModeCmd[ CS ].expChar1 = 69; // ASCII for E (Embedded ...) bloodLeakEmbModeCmd[ CS ].expChar2 = NU; bloodLeakEmbModeCmd[ CS ].length = 5; // Set point command bloodLeakEmbModeCmd[ SP ].commandASCII = 83; // ASCII for S bloodLeakEmbModeCmd[ SP ].expChar1 = 88; // ASCII for X (Timeout) bloodLeakEmbModeCmd[ SP ].expChar2 = 70; // ASCII for F (Fail) bloodLeakEmbModeCmd[ SP ].length = 1; // Self test command bloodLeakEmbModeCmd[ T ].commandASCII = 84; // ASCII for T bloodLeakEmbModeCmd[ T ].expChar1 = 80; // ASCII for P bloodLeakEmbModeCmd[ T ].expChar2 = 70; // ASCII for F bloodLeakEmbModeCmd[ T ].length = 1; // Get self test command bloodLeakEmbModeCmd[ G ].commandASCII = 71; // ASCII for G bloodLeakEmbModeCmd[ G ].expChar1 = 71; bloodLeakEmbModeCmd[ G ].expChar2 = NU; bloodLeakEmbModeCmd[ G ].length = 5; // Intensity command bloodLeakEmbModeCmd[ I ].commandASCII = 73; // ASCII for I bloodLeakEmbModeCmd[ I ].expChar1 = 73; bloodLeakEmbModeCmd[ I ].expChar2 = NU; bloodLeakEmbModeCmd[ I ].length = 5; // Blood detection command bloodLeakEmbModeCmd[ V ].commandASCII = 86; // ASCII for V bloodLeakEmbModeCmd[ V ].expChar1 = 86; bloodLeakEmbModeCmd[ V ].expChar2 = NU; bloodLeakEmbModeCmd[ V ].length = 5; // Zero sensor command bloodLeakEmbModeCmd[ Z ].commandASCII = 90; // ASCII for Z bloodLeakEmbModeCmd[ Z ].expChar1 = 89; // ASCII for Y bloodLeakEmbModeCmd[ Z ].expChar2 = NU; bloodLeakEmbModeCmd[ Z ].length = 1; // Zero confirm command bloodLeakEmbModeCmd[ Q ].commandASCII = 81; // ASCII for Q bloodLeakEmbModeCmd[ Q ].expChar1 = 80; // ASCII for P bloodLeakEmbModeCmd[ Q ].expChar2 = 70; // ASCII for F bloodLeakEmbModeCmd[ Q ].length = 1; // Display blood detection command bloodLeakEmbModeCmd[ D ].commandASCII = 68; bloodLeakEmbModeCmd[ D ].expChar1 = 68; // ASCII for D bloodLeakEmbModeCmd[ D ].expChar2 = NU; bloodLeakEmbModeCmd[ D ].length = 5; // Calibrate command bloodLeakEmbModeCmd[ C ].commandASCII = 67; bloodLeakEmbModeCmd[ C ].expChar1 = 67; // ASCII for C bloodLeakEmbModeCmd[ C ].expChar2 = NU; bloodLeakEmbModeCmd[ C ].length = 4; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetBloodLeakDataPublishIntervalOverride function overrides the * blood leak data publish interval. * @details Inputs: none * @details Outputs: bloodLeakDataPublishInterval * @param value override blood leak data publish interval with (in ms) * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBloodLeakDataPublishIntervalOverride( U32 value ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { U32 intvl = value / TASK_PRIORITY_INTERVAL; result = TRUE; bloodLeakDataPublishInterval.ovData = intvl; bloodLeakDataPublishInterval.override = OVERRIDE_KEY; } return result; } /*********************************************************************//** * @brief * The testResetBloodLeakDataPublishIntervalOverride function resets the override * of the blood leak data publish interval. * @details Inputs: none * @details Outputs: bloodLeakDataPublishInterval * @return TRUE if override reset successful, FALSE if not *************************************************************************/ BOOL testResetBloodLeakDataPublishIntervalOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodLeakDataPublishInterval.override = OVERRIDE_RESET; bloodLeakDataPublishInterval.ovData = bloodLeakDataPublishInterval.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetBloodLeakStatusOverride function overrides the status * of the blood leak detector. * @details Inputs: none * @details Outputs: bloodLeakStatus * @param none * @param status override blood leak detector with this * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testSetBloodLeakStatusOverride( BLOOD_LEAK_STATUS_T status ) { BOOL result = FALSE; if ( status < NUM_OF_BLOOD_LEAK_STATUS ) { if ( TRUE == isTestingActivated() ) { result = TRUE; bloodLeakStatus.ovData = (U32)status; bloodLeakStatus.override = OVERRIDE_KEY; } } return result; } /*********************************************************************//** * @brief * The testResetBloodLeakStatusOverride function resets the override of the * blood leak detector status. * @details Inputs: none * @details Outputs: bloodLeakStatus * @param none * @return TRUE if reset successful, FALSE if not *************************************************************************/ BOOL testResetBloodLeakStatusOverride( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { result = TRUE; bloodLeakStatus.override = OVERRIDE_RESET; bloodLeakStatus.ovData = bloodLeakStatus.ovInitData; } return result; } /*********************************************************************//** * @brief * The testSetBloodLeak2EmbeddedMode function sets the blood leak driver to the * embedded more for calibration. * @details Inputs: none * @details Outputs: bloodLeakSignalEmbeddedModeReq * @return TRUE if switching to embedded mode was accepted otherwise, FALSE *************************************************************************/ BOOL testSetBloodLeak2EmbeddedMode( void ) { BOOL result = FALSE; if ( TRUE == isTestingActivated() ) { HD_OP_MODE_T mode = getCurrentOperationMode(); // Check if the mode is fault, service or standby before accepting a transition to // the embedded mode if ( ( MODE_FAUL == mode ) || ( MODE_SERV == mode ) || ( MODE_STAN == mode ) ) { bloodLeakSignalEmbModeReq = TRUE; bloodLeakEmbModeRqstedCmd = CS; result = TRUE; } } return result; } /*********************************************************************//** * @brief * The testSetBloodLeakEmbeddedModeCommand function sets the blood leak * calibration command. * @details Inputs: bloodLeakSignalEmbeddedModeReq, bloodLeakCalSubstate * @details Outputs: bloodLeakCalASCIIChar * @param command the command ID to be sent to blood leak in embedded mode * @param setpointPayload the set point value that is sent with the set point * command. This value is 0 with other commands since they do not have a payload * @return TRUE if the command is accepted otherwise, FALSE *************************************************************************/ BOOL testSetBloodLeakEmbeddedModeCommand( U08 command, U16 setPointPayload ) { BOOL result = FALSE; if ( ( TRUE == isTestingActivated() ) && ( command < NUM_OF_EMB_CMDS ) ) { // If the HD is already in service mode and in the blood leak is in the embedded mode and the sensor is waiting for another command if ( ( MODE_SERV == getCurrentOperationMode() ) && ( TRUE == bloodLeakSignalEmbModeReq ) && ( BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE == bloodLeakEmbModeSubstate ) ) { bloodLeakEmbModeRqstedCmd = command; bloodLeakEmbModeSetPoint = setPointPayload; result = TRUE; } } return result; } /**@}*/