/************************************************************************** * * 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) Dara Navaei * @date (last) 23-May-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_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 17 ///< 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_ZERO_CMD_STATUS_READY 0x80 ///< Blood leak zero command status ready value. #define BLOOD_LEAK_SELF_TEST_CMD_STATUS_READY 0x80 ///< Blood leak self test command status ready value. #define BLOOD_LEAK_STATUS_BIT_HIGH 1 ///< Blood leak status bit high. #define BLOOD_LEAK_STATUS_BIT_LOW 0 ///< Blood leak status bit low. #define BLOOD_LEAK_ZERO_CMD_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Blood leak zero command timeout in milliseconds. #define BLOOD_LEAK_SELF_TEST_CMD_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Blood leak self test command timeout in milliseconds. #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. // Embedded mode defines #define BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH 6 ///< Blood leak embedded mode command sequence length. #define BLOOD_LEAK_EMB_MODE_RQST_RX_LENGTH 2 ///< Blood leak embedded mode request new Rx data length. #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_COMM_RESET 6 ///< Blood leak embedded mode communication reset. #define BLOOD_LEAK_EMB_MODE_COMM_READ_REQST 12 ///< Blood leak embedded mode communication read Rx byte request. #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. #define BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX 0 ///< Blood leak embedded mode command (UART/Transmit) column index number. #define BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX 1 ///< Blood leak embedded mode is command type UART or transmit flag. #define BLOOD_LEAK_EMB_MODE_PASS_ASCII 80 ///< Blood leak embedded mode P (pass) in ASCII. #define BLOOD_LEAK_EMB_MODE_FAIL_ASCII 70 ///< Blood leak embedded mode F (fail) in ASCII. #define BLOOD_LEAK_EMB_MODE_RESET_INDEX 0 ///< Blood leak embedded mode reset FIFO command index. #define BLOOD_LEAK_EMB_MODE_CMD_INDEX 2 ///< Blood leak embedded mode command index. #define BLOOD_LEAK_EMB_MODE_STOP_WRITE_INDEX 3 ///< Blood leak embedded mode stop write to FIFO index. #define BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX 4 ///< Blood leak embedded mode active high command index. #define BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX 0 ///< Blood leak embedded mode request Rx to read index. /// 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_PREP_FOR_ZERO_CMD_STATE, ///< Prepare for zero command state. BLOOD_LEAK_ZERO_STATE, ///< Zero state. BLOOD_LEAK_PREP_FOR_SELF_TEST_CMD_STATE, ///< Prepare for self test command 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_EMB_MODE_CMD = 0, ///< Null command. CS_EMB_MODE_CMD, ///< Control S command to switch to embedded mode. SP_EMB_MODE_CMD, ///< Set point command to set the set point. T_EMB_MODE_CMD, ///< Self test command. G_EMB_MODE_CMD, ///< Get self test command. I_EMB_MODE_CMD, ///< Intensity command. V_EMB_MODE_CMD, ///< Blood detection level command. Z_EMB_MODE_CMD, ///< Zero sensor command. Q_EMB_MODE_CMD, ///< Zero sensor confirm command. D_EMB_MODE_CMD, ///< Display blood detection command. C_EMB_MODE_CMD, ///< 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. U32 length; ///< Blood leak sensor expected response length in bytes. U32 timeoutMS; ///< Blood leak sensor receive timeout in milliseconds. } EMB_MODE_CMD_T; /// Zero command structure typedef struct { BOOL zeroCmdRequested; ///< Blood leak zero command requested. U08 cmdPrevStatus; ///< Blood leak previous zero/self test status. U32 cmdStartTimeMS; ///< Blood leak zero/self test command start time in milliseconds. } BLOOD_LEAK_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 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 ][ 2 ]; ///< 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. static BLOOD_LEAK_CMD_T bloodLeakCmd; ///< Blood leak zero/self test command. /// 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 ][ 2 ]; ///< 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 bloodLeakEmbModeCmdSeqLength; ///< Blood leak embedded mode command sequence length. static BOOL bloodLeakEmbModeHasRxRqstBeenSent; ///< Blood leak embedded mode Rx request has been sent signal. // ********** 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 handleBloodLeakPrepForZeroCmdState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakZeroState( void ); static BLOOD_LEAK_STATE_T handleBloodLeakPrepForSelfTestCmdState( 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 processReceivedEmbModeChar( U08 data ); static void prepareSetPointSeq( U16 setPoint ); static void publishBloodLeakData( void ); static void initEmbModeSpecs( void ); static BOOL hasZeroBloodLeakBeenRequested( void ); /*********************************************************************//** * @brief * The initBloodLeak function initializes the Blood Leak module. * @details Inputs: none * @details Outputs: bloodLeakState, bloodLeakStatus, bloodLeakSelfTestStatus, * bloodLeakUARTCmdIndex, bloodLeakSetPointSequence, bloodLeakPrevFPGARegisterCount * bloodLeakWait2ReadResponseCounter, bloodLeakDataPublicationTimerCounter, * bloodLeakCommandWriteTryCount, bloodLeakGetCalStartTime, bloodLeakEmbModeSubstate * bloodLeakIsPOSTComplete, bloodLeakPersistenceCtr, bloodLeakSignalEmbModeReq, * bloodLeakEmbModeRqstedCmd, bloodLeakEmbModeOpsStartTime, bloodLeakEmbModeRespBuffer, * bloodLeakEmbModeRespIndex, bloodLeakExitNormalRequested, * bloodLeakEmbModeCmdSeqLength, bloodLeakEmbModeHasRxRqstBeenSent * @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; bloodLeakUARTCmdIndex = 0; bloodLeakSetPointSeqLength = 0; bloodLeakWait2ReadResponseCounter = 0; bloodLeakCommandWriteTryCount = 0; bloodLeakGetCalStartTime = getMSTimerCount(); bloodLeakIsPOSTComplete = FALSE; bloodLeakPrevFPGARegisterCount = 0; bloodLeakPersistenceCtr = 0; bloodLeakSignalEmbModeReq = FALSE; bloodLeakEmbModeRqstedCmd = NU_EMB_MODE_CMD; bloodLeakEmbModeSubstate = BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE; bloodLeakEmbModeOpsStartTime = 0; bloodLeakEmbModeRespIndex = 0; bloodLeakExitNormalRequested = FALSE; bloodLeakEmbModeCmdSeqLength = 0; bloodLeakEmbModeHasRxRqstBeenSent = 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 embedded mode command sequence memset( bloodLeakEmbModeCmdSquence, 0x0, BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ); // 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_PREP_FOR_ZERO_CMD_STATE: bloodLeakState = handleBloodLeakPrepForZeroCmdState(); break; case BLOOD_LEAK_ZERO_STATE: bloodLeakState = handleBloodLeakZeroState(); break; case BLOOD_LEAK_PREP_FOR_SELF_TEST_CMD_STATE: bloodLeakState = handleBloodLeakPrepForSelfTestCmdState(); 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: bloodLeakCmd.zeroCmdRequested, bloodLeakUARTCmdIndex * @return none *************************************************************************/ void zeroBloodLeak( void ) { bloodLeakCmd.zeroCmdRequested = TRUE; bloodLeakUARTCmdIndex = 0; } /*********************************************************************//** * @brief * The exitBloodLeakNormalState requests that the blood leak sensor to exit * its normal state. * @details Inputs: bloodLeakState * @details Outputs: bloodLeakExitNormalRequested * @return none *************************************************************************/ void exitBloodLeakNormalState( void ) { if ( BLOOD_LEAK_NORMAL_STATE == bloodLeakState ) { 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(); // TODO this has been disabled for the systems team testing. In their test, ^U is not sent //state = BLOOD_LEAK_START_UP_STATE; // TODO decide whether we need to go to ^U upon startup state = BLOOD_LEAK_INIT_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 ) { // TODO NOTE: This function is bypassed until the use of ^U is finalized by the system's team 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 ) { // TODO NOTE: This function is bypassed until the use of ^U is finalized by the system's team 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(); // TODO is this working in embedded mode? #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 ) { // TODO remove this function 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 ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ]; // 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; // Check if the zero command has been requested state = ( TRUE == hasZeroBloodLeakBeenRequested() ? BLOOD_LEAK_PREP_FOR_ZERO_CMD_STATE : state ); return state; } /*********************************************************************//** * @brief * The handleBloodLeakPrepForZeroCmdState function handles the blood leak * prepare for zero command state. * @details Inputs: bloodLeakCmd * @details Outputs: bloodLeakCmd * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakPrepForZeroCmdState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_PREP_FOR_ZERO_CMD_STATE; U08 zeroCmdStatus = getFPGABloodLeakZeroErrorCounter() & BLOOD_LEAK_ZERO_CMD_STATUS_READY; // Check if the zero command is ready to receive a command and the zero status is high if ( ( BLOOD_LEAK_ZERO_CMD_STATUS_READY == zeroCmdStatus ) && ( BLOOD_LEAK_STATUS_BIT_HIGH == getFPGABloodLeakZeroStatus() ) ) { // The conditions are met start the command // Start with the previous status bit is high state = BLOOD_LEAK_ZERO_STATE; bloodLeakCmd.cmdStartTimeMS = getMSTimerCount(); bloodLeakCmd.cmdPrevStatus = BLOOD_LEAK_STATUS_BIT_HIGH; setFPGABloodLeakZero(); } else if ( TRUE == didTimeout( bloodLeakCmd.cmdStartTimeMS, BLOOD_LEAK_ZERO_CMD_TIMEOUT_MS ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_ZERO_CMD_TIMEOUT ); } state = BLOOD_LEAK_INIT_STATE; } 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; U08 bloodLeakZeroStatus = getFPGABloodLeakZeroStatus(); // Check if the previous zero status bit was a 0 (low) and the current zero status bit is a 1 (high) // Clear the blood leak zero and self test commands and get ready to do the self test if ( ( BLOOD_LEAK_STATUS_BIT_LOW == bloodLeakCmd.cmdPrevStatus ) && ( BLOOD_LEAK_STATUS_BIT_HIGH == bloodLeakZeroStatus ) ) { // Clear the zero command since it is done and clear the self test since we are getting ready to do a self test. clearFPGABloodLeakZero(); clearFPGABloodLeakSelfTest(); state = BLOOD_LEAK_PREP_FOR_SELF_TEST_CMD_STATE; } else if ( TRUE == didTimeout( bloodLeakCmd.cmdStartTimeMS, BLOOD_LEAK_ZERO_CMD_TIMEOUT_MS ) ) { // Zero command timed out #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_ZERO_CMD_TIMEOUT ); } // Get back to init state state = BLOOD_LEAK_INIT_STATE; } else { // Update the previous status with the current zero status since the low to high edge has been observed yet bloodLeakCmd.cmdPrevStatus = bloodLeakZeroStatus; } return state; } /*********************************************************************//** * @brief * The handleBloodLeakPrepForSelfTestCmdState function handles the blood leak * prepare for self test command state. * @details Inputs: bloodLeakCmd * @details Outputs: bloodLeakCmd * @return next state *************************************************************************/ static BLOOD_LEAK_STATE_T handleBloodLeakPrepForSelfTestCmdState( void ) { BLOOD_LEAK_STATE_T state = BLOOD_LEAK_PREP_FOR_SELF_TEST_CMD_STATE; U08 selfTestCmdStatus = getFPGABloodLeakSelfTestErrorCounter() & BLOOD_LEAK_SELF_TEST_CMD_STATUS_READY; // Check if the self test command status is ready and self test status bit is low (0) if ( ( BLOOD_LEAK_SELF_TEST_CMD_STATUS_READY == selfTestCmdStatus ) && ( BLOOD_LEAK_STATUS_BIT_LOW == getFPGABloodLeakStatus() ) ) { // Update the variables and set the self test state = BLOOD_LEAK_SELF_TEST_STATE; bloodLeakCmd.cmdStartTimeMS = getMSTimerCount(); bloodLeakCmd.cmdPrevStatus = BLOOD_LEAK_STATUS_BIT_LOW; setFPGABloodLeakSelfTest(); } else if ( TRUE == didTimeout( bloodLeakCmd.cmdStartTimeMS, BLOOD_LEAK_SELF_TEST_CMD_TIMEOUT_MS ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SELF_TEST_FAILURE ); } // Self test command failed state = BLOOD_LEAK_INIT_STATE; } 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; U08 bloodLeakSelfTestStatus = getFPGABloodLeakStatus(); // Check if the previous status bit was a high (1) and the current status bit is a low (0). This means that the self test was // successfully finished if ( ( BLOOD_LEAK_STATUS_BIT_HIGH == bloodLeakCmd.cmdPrevStatus ) && ( BLOOD_LEAK_STATUS_BIT_LOW == bloodLeakSelfTestStatus ) ) { // Clear the self test command since it is done clearFPGABloodLeakSelfTest(); state = BLOOD_LEAK_NORMAL_STATE; bloodLeakSelfTestStatus = SELF_TEST_STATUS_PASSED; } else if ( TRUE == didTimeout( bloodLeakCmd.cmdStartTimeMS, BLOOD_LEAK_SELF_TEST_CMD_TIMEOUT_MS ) ) { #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_BLOOD_LEAK_ALARM ) != SW_CONFIG_ENABLE_VALUE ) #endif { activateAlarmNoData( ALARM_ID_HD_BLOOD_LEAK_SELF_TEST_FAILURE ); } // Self test failed due to timeout state = BLOOD_LEAK_INIT_STATE; bloodLeakSelfTestStatus = SELF_TEST_STATUS_FAILED; } else { bloodLeakCmd.cmdPrevStatus = bloodLeakSelfTestStatus; } 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; // TODO remove /*if ( TRUE == noFPGABloodLeakDetected() ) // TODO remove noFPGABloodLeakDetected() { bloodLeakStatus.data = BLOOD_LEAK_NOT_DETECTED; } else { bloodLeakStatus.data = BLOOD_LEAK_DETECTED; }*/ // If the blood leak status bit is low (0) it means blood has not been detected, otherwise, blood has been detected bloodLeakStatus.data = ( BLOOD_LEAK_STATUS_BIT_LOW == getFPGABloodLeakStatus() ? BLOOD_LEAK_NOT_DETECTED : 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 ); } } } // Check whether zeroing the sensor has been requested or not if yes, transition to zero command state otherwise, stay in this state state = ( TRUE == hasZeroBloodLeakBeenRequested() ? BLOOD_LEAK_PREP_FOR_ZERO_CMD_STATE : state ); if ( TRUE == bloodLeakExitNormalRequested ) { state = BLOOD_LEAK_INIT_STATE; bloodLeakExitNormalRequested = FALSE; } 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 command = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].commandASCII; switch( bloodLeakEmbModeRqstedCmd ) { case NU_EMB_MODE_CMD: // Null command do nothing break; case CS_EMB_MODE_CMD: case T_EMB_MODE_CMD: case G_EMB_MODE_CMD: case I_EMB_MODE_CMD: case V_EMB_MODE_CMD: case Z_EMB_MODE_CMD: case Q_EMB_MODE_CMD: case D_EMB_MODE_CMD: case C_EMB_MODE_CMD: // First clear the buffer from the older data memset( bloodLeakEmbModeCmdSquence, 0x0, 2 * BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ); // Set the command sequence bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_RESET_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_RESET; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_RESET_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_RESET_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_RESET_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_CMD_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = command; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_CMD_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = FALSE; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_STOP_WRITE_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_STOP_WRITE_FIFO_COMMAND; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_STOP_WRITE_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = FALSE; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_HIGH; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; // Set the variables for the next state bloodLeakUARTCmdIndex = 0; bloodLeakEmbModeRespIndex = 0; bloodLeakEmbModeCmdSeqLength = BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH; bloodLeakEmbModeOpsStartTime = getMSTimerCount(); state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; // Clear the response buffer to able to receive fresh data memset( bloodLeakEmbModeRespBuffer, 0x0, BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ); break; case SP_EMB_MODE_CMD: prepareSetPointSeq( bloodLeakEmbModeSetPoint ); bloodLeakEmbModeRespIndex = 0; bloodLeakEmbModeOpsStartTime = getMSTimerCount(); state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; // Clear the command sequence buffer in case it is needed to send byte read request. The byte // read requests are sent using this buffer while the set point is set using the set point buffer memset( bloodLeakEmbModeCmdSquence, 0x0, 2 * BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ); // Clear the response buffer to able to receive fresh data memset( bloodLeakEmbModeRespBuffer, 0x0, BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ); 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 ) { U08 command; BLOOD_LEAK_EMB_MODE_STATE_T state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; BOOL isUARTCtrlCmd = FALSE; BOOL isUARTCtrlDone = TRUE; switch ( bloodLeakEmbModeRqstedCmd ) { case CS_EMB_MODE_CMD: case T_EMB_MODE_CMD: case G_EMB_MODE_CMD: case I_EMB_MODE_CMD: case V_EMB_MODE_CMD: case Z_EMB_MODE_CMD: case Q_EMB_MODE_CMD: case D_EMB_MODE_CMD: case C_EMB_MODE_CMD: command = bloodLeakEmbModeCmdSquence[ bloodLeakUARTCmdIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ]; isUARTCtrlCmd = bloodLeakEmbModeCmdSquence[ bloodLeakUARTCmdIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ]; isUARTCtrlDone = ( bloodLeakUARTCmdIndex > ( bloodLeakEmbModeCmdSeqLength - 1 ) ? TRUE : FALSE ); bloodLeakUARTCmdIndex++; break; case SP_EMB_MODE_CMD: // Check if the first element in the command sequence buffer is the read request. If it is, the set point command sequence has already been sent // and we are requesting the buffer to read and get its response back so use this buffer to send data to the sensor // Otherwise, send the set point command sequence to the sensor since the set point is sent prior to reading the response back from the sensor if ( BLOOD_LEAK_EMB_MODE_COMM_READ_REQST == bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] ) { command = bloodLeakEmbModeCmdSquence[ bloodLeakUARTCmdIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ]; isUARTCtrlCmd = bloodLeakEmbModeCmdSquence[ bloodLeakUARTCmdIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ]; isUARTCtrlDone = ( bloodLeakUARTCmdIndex > ( bloodLeakEmbModeCmdSeqLength - 1 ) ? TRUE : FALSE ); } else { command = bloodLeakSetPointSequence[ bloodLeakUARTCmdIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ]; isUARTCtrlCmd = bloodLeakSetPointSequence[ bloodLeakUARTCmdIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ]; isUARTCtrlDone = ( bloodLeakUARTCmdIndex > ( bloodLeakSetPointSeqLength - 1 ) ? TRUE : FALSE ); } bloodLeakUARTCmdIndex++; break; } if ( ( bloodLeakEmbModeRqstedCmd != CS_EMB_MODE_CMD ) && ( bloodLeakUARTCmdIndex - 1 > BLOOD_LEAK_EMB_MODE_RESET_INDEX ) && ( bloodLeakUARTCmdIndex - 1 <= BLOOD_LEAK_EMB_MODE_RESET_INDEX + 1 ) ) { if ( BLOOD_LEAK_EMB_MODE_RX_BUFFER_EMPTY == getFPGABloodLeakRxFIFOCount() ) { // TODO do nothing right now. I case it was decided to use the terminal mode again, make sure the reset went through prior to sending the // reset of the command sequence } } // Check if the current index towards the end of the buffer which are FIFO set and FIFO reset if ( FALSE == isUARTCtrlDone ) { FALSE == isUARTCtrlCmd ? setFPGABloodLeakUARTTransmit( command ) : setFPGABloodLeakUARTControl( command ); } else { // If the element in the first index of the command sequence buffer is the read a byte request, set the variable to TRUE so the // wait for data to receive state knows that the request has been sent and it can read the byte. U08 commandInIndex0 = bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ]; bloodLeakEmbModeHasRxRqstBeenSent = ( BLOOD_LEAK_EMB_MODE_COMM_READ_REQST == commandInIndex0 ? TRUE : FALSE ); bloodLeakUARTCmdIndex = 0; bloodLeakEmbModeCmdSeqLength = 0; state = BLOOD_LEAK_CAL_WAIT_FOR_COMMAND_RESPONSE_STATE; } return state; } /*********************************************************************//** * @brief * The handleCalBloodLeakWaitForCommandResponseState function handles the * wait for command responses state. The state receives data in the buffer. * @details Inputs: bloodLeakEmbModeCmd, bloodLeakEmbModeRespIndex * @details Outputs: bloodLeakEmbModeRespBuffer, bloodLeakEmbModeRespIndex * @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(); BOOL hasCharBeenReceived = FALSE; U32 commandTimeoutMS = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].timeoutMS; U32 length = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].length; if ( TRUE == bloodLeakEmbModeHasRxRqstBeenSent ) { // If the read request sequence has been sent already, read the next byte in the buffer and process it U08 data = getFPGABloodLeakRxFIFODataOut(); hasCharBeenReceived = TRUE; bloodLeakEmbModeHasRxRqstBeenSent = FALSE; processReceivedEmbModeChar( data ); } else if ( ( rxFIFOCount > 0 ) && ( FALSE == bloodLeakEmbModeHasRxRqstBeenSent ) ) { // If there is still more data in the buffer and a read sequence has not been sent, create the sequence and send it // First clear the buffer from the older data. Set to 2 times the length because the array is 2D memset( bloodLeakEmbModeCmdSquence, 0x0, 2 * BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ); bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_READ_REQST; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW; bloodLeakEmbModeCmdSquence[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; // Set the variables for the next state bloodLeakUARTCmdIndex = 0; bloodLeakEmbModeCmdSeqLength = BLOOD_LEAK_EMB_MODE_RQST_RX_LENGTH; state = BLOOD_LEAK_CAL_SEND_COMMAND_STATE; } // 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 == hasCharBeenReceived ) { if ( bloodLeakEmbModeRespIndex >= length ) { 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_EMB_MODE_CMD ? 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_EMB_MODE_CMD == bloodLeakEmbModeRqstedCmd ) && ( NU_EMB_MODE_CMD == bloodLeakEmbModeRespBuffer[ 0 ] ) ? FALSE : TRUE ); if ( TRUE == isNull ) { // There is null in the characters that were supposed to be received and not be null but null was found // Clear the response buffer and write the ASCII fail in the first element of the response buffer // Set the length to be 1 because there is only 1 character (fail) is in the buffer memset( bloodLeakEmbModeRespBuffer, 0x0, BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ); length = 1; bloodLeakEmbModeRespBuffer[ 0 ] = BLOOD_LEAK_EMB_MODE_FAIL_ASCII; } else if ( CS_EMB_MODE_CMD == bloodLeakEmbModeRqstedCmd ) { memset( bloodLeakEmbModeRespBuffer, 0x0, BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ); length = 1; bloodLeakEmbModeRespBuffer[ 0 ] = BLOOD_LEAK_EMB_MODE_PASS_ASCII; } else if ( 1 == length ) { U08 passChar = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].expChar1; U08 data = bloodLeakEmbModeRespBuffer[ 0 ]; bloodLeakEmbModeRespBuffer[ 0 ] = ( passChar == data ? BLOOD_LEAK_EMB_MODE_PASS_ASCII : BLOOD_LEAK_EMB_MODE_FAIL_ASCII ); } // Done with receiving the data bloodLeakEmbModeRqstedCmd = NU_EMB_MODE_CMD; state = BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE; handleSendBloodLeakEmbeddedModeCommandResponse( length, bloodLeakEmbModeRespBuffer ); } } if ( TRUE == didTimeout( bloodLeakEmbModeOpsStartTime, commandTimeoutMS ) ) { // Command timed out. Clear the receive buffer from any data and put a Fail in there to be sent up memset( bloodLeakEmbModeRespBuffer, 0x0, BLOOD_LEAK_EMB_MODE_RESP_BUFFER_LEN ); // Only F (fail) will be sent so the length of the buffer is 1 length = 1; bloodLeakEmbModeRespBuffer[ 0 ] = BLOOD_LEAK_EMB_MODE_FAIL_ASCII; bloodLeakEmbModeRqstedCmd = NU_EMB_MODE_CMD; state = BLOOD_LEAK_CAL_WAIT_FOR_COMAND_STATE; handleSendBloodLeakEmbeddedModeCommandResponse( length, bloodLeakEmbModeRespBuffer ); } return state; } /*********************************************************************//** * @brief * The processReceivedEmbModeChar function processes the character that * has been received. * @details Inputs: bloodLeakEmbModeCmd, bloodLeakEmbModeRespIndex * @details Outputs: bloodLeakEmbModeRespBuffer, bloodLeakEmbModeRespIndex * @param data which is the data that has been received from the BLD * @return none *************************************************************************/ static void processReceivedEmbModeChar( U08 data ) { /* * 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) */ U08 length = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].length; U08 expChar1 = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].expChar1; U08 expChar2 = bloodLeakEmbModeCmd[ bloodLeakEmbModeRqstedCmd ].expChar2; if ( ( expChar1 != NU_EMB_MODE_CMD ) && ( NU_EMB_MODE_CMD == 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_EMB_MODE_CMD ) && ( expChar2 != NU_EMB_MODE_CMD ) ) { // 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++; } } } else if ( ( NU_EMB_MODE_CMD == expChar1 ) && ( NU_EMB_MODE_CMD == 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++; } } } } /*********************************************************************//** * @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 ]; U08 command; 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 ); command = ( TRUE == bloodLeakSignalEmbModeReq ? BLOOD_LEAK_EMB_MODE_COMM_RESET : BLOOD_LEAK_RESET_TX_FIFO ); bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = command; bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bufferIndex++; command = ( TRUE == bloodLeakSignalEmbModeReq ? BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW : BLOOD_LEAK_UART_COMM_ACTIVE_LOW ); bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = command; bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bufferIndex++; // 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_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_SET_POINT_START_CHAR_ASCII; bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = FALSE; bufferIndex++; // Loop through the number of digits and get each ASCII value for ( i = 0; i < digitCount; i++ ) { // Write the characters bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = tempCharBuffer[ i ]; bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = FALSE; bufferIndex++; } // After the characters, insert the carriage return into the buffer bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_CARRIAGE_RETURN_ASCII; bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = FALSE; bufferIndex++; // After the characters, insert the stop write to FIFO character which is number 0 bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_STOP_WRITE_FIFO_COMMAND; bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = FALSE; bufferIndex++; // Set active high into the buffer. // If the mode is embedded mode, the active high (and active low) values are different than in the Ctrl U mode since the bit values are different command = ( TRUE == bloodLeakSignalEmbModeReq ? BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_HIGH : BLOOD_LEAK_UART_COMM_ACTIVE_HIGH ); bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = command; bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bufferIndex++; command = ( TRUE == bloodLeakSignalEmbModeReq ? BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW : BLOOD_LEAK_UART_COMM_ACTIVE_LOW ); bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = command; bloodLeakSetPointSequence[ bufferIndex ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; // Update the sequence length for writing to the sensor bloodLeakSetPointSeqLength = bufferIndex + 1; 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_EMB_MODE_CMD ].commandASCII = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ NU_EMB_MODE_CMD ].expChar1 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ NU_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ NU_EMB_MODE_CMD ].length = 0; bloodLeakEmbModeCmd[ NU_EMB_MODE_CMD ].timeoutMS = 0; // Control S command bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandASCII = 19; // ASCII for Control S bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].expChar1 = 69; // ASCII for E (Embedded ...) bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].length = 5; bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].timeoutMS = 5 * MS_PER_SECOND; // Set point command bloodLeakEmbModeCmd[ SP_EMB_MODE_CMD ].commandASCII = 83; // ASCII for S bloodLeakEmbModeCmd[ SP_EMB_MODE_CMD ].expChar1 = 32; // For space (Set point is returned by a space at the beginning of returning the set point value) bloodLeakEmbModeCmd[ SP_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ SP_EMB_MODE_CMD ].length = 5; bloodLeakEmbModeCmd[ SP_EMB_MODE_CMD ].timeoutMS = 10 * MS_PER_SECOND; // Self test command bloodLeakEmbModeCmd[ T_EMB_MODE_CMD ].commandASCII = 84; // ASCII for T bloodLeakEmbModeCmd[ T_EMB_MODE_CMD ].expChar1 = 80; // ASCII for P bloodLeakEmbModeCmd[ T_EMB_MODE_CMD ].expChar2 = 70; // ASCII for F bloodLeakEmbModeCmd[ T_EMB_MODE_CMD ].length = 1; bloodLeakEmbModeCmd[ T_EMB_MODE_CMD ].timeoutMS = 5 * MS_PER_SECOND; // Get self test command bloodLeakEmbModeCmd[ G_EMB_MODE_CMD ].commandASCII = 71; // ASCII for G bloodLeakEmbModeCmd[ G_EMB_MODE_CMD ].expChar1 = 71; bloodLeakEmbModeCmd[ G_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ G_EMB_MODE_CMD ].length = 5; bloodLeakEmbModeCmd[ G_EMB_MODE_CMD ].timeoutMS = 10 * MS_PER_SECOND; // Intensity command bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].commandASCII = 73; // ASCII for I bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].expChar1 = 73; bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].length = 5; bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].timeoutMS = 5 * MS_PER_SECOND; // Blood detection command bloodLeakEmbModeCmd[ V_EMB_MODE_CMD ].commandASCII = 86; // ASCII for V bloodLeakEmbModeCmd[ V_EMB_MODE_CMD ].expChar1 = 86; bloodLeakEmbModeCmd[ V_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ V_EMB_MODE_CMD ].length = 5; bloodLeakEmbModeCmd[ V_EMB_MODE_CMD ].timeoutMS = 5 * MS_PER_SECOND; // Zero sensor command bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandASCII = 90; // ASCII for Z bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].expChar1 = 89; // ASCII for Y bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].length = 1; bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].timeoutMS = 10 * MS_PER_SECOND; // Zero confirm command bloodLeakEmbModeCmd[ Q_EMB_MODE_CMD ].commandASCII = 81; // ASCII for Q bloodLeakEmbModeCmd[ Q_EMB_MODE_CMD ].expChar1 = 80; // ASCII for P bloodLeakEmbModeCmd[ Q_EMB_MODE_CMD ].expChar2 = 70; // ASCII for F bloodLeakEmbModeCmd[ Q_EMB_MODE_CMD ].length = 1; bloodLeakEmbModeCmd[ Q_EMB_MODE_CMD ].timeoutMS = 5 * MS_PER_SECOND; // Display blood detection command bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandASCII = 68; bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].expChar1 = 68; // ASCII for D bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].length = 5; bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].timeoutMS = 5 * MS_PER_SECOND; // Calibrate command bloodLeakEmbModeCmd[ C_EMB_MODE_CMD ].commandASCII = 67; bloodLeakEmbModeCmd[ C_EMB_MODE_CMD ].expChar1 = 67; // ASCII for C bloodLeakEmbModeCmd[ C_EMB_MODE_CMD ].expChar2 = NU_EMB_MODE_CMD; bloodLeakEmbModeCmd[ C_EMB_MODE_CMD ].length = 4; bloodLeakEmbModeCmd[ C_EMB_MODE_CMD ].timeoutMS = 5 * MS_PER_SECOND; } /*********************************************************************//** * @brief * The hasZeroBloodLeakBeenRequested function checks whether zeroing blood * leak has been requested or not. * @details Inputs: bloodLeakCmd * @details Outputs: bloodLeakCmd * @return TURE if request otherwise, FLASE *************************************************************************/ static BOOL hasZeroBloodLeakBeenRequested( void ) { BOOL status = FALSE; if ( TRUE == bloodLeakCmd.zeroCmdRequested ) { status = TRUE; bloodLeakCmd.zeroCmdRequested = FALSE; bloodLeakCmd.cmdStartTimeMS = getMSTimerCount(); clearFPGABloodLeakZero(); } return status; } /************************************************************************* * 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_EMB_MODE_CMD; 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; } /**@}*/