/************************************************************************** * * Copyright (c) 2025-2026 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 BloodLeakDriver.c * * @author (last) Dara Navaei * @date (last) 10-Sep-2024 * * @author (original) Dara Navaei * @date (original) 10-Sep-2024 * ***************************************************************************/ #include #include #include #include "AlarmMgmtDD.h" #include "BloodLeak.h" #include "BloodLeakDriver.h" #include "FpgaDD.h" #include "Messaging.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "TaskPriority.h" #include "TDInterface.h" #include "Timers.h" #include "Utilities.h" /** * @addtogroup BloodLeak * @{ */ // ********** private definitions ********** #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_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_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_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_BETWEEN_ZERO_ST_WAIT_MS 250 ///< Blood leak wait time in between zero and self test commands in milliseconds. #define DATA_PUBLISH_COUNTER_START_COUNT 60 ///< Data publish counter start count. #define BLOOD_LEAK_DETECT_RECOVERY_MIN_TIME_MS ( 2 * MS_PER_SECOND ) ///< Blood leak blood detect recovery minimum time in milliseconds. /// 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 3 ///< 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. #define BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE 12 ///< Blood leak embedded mode command queue maximum size. #define BLOOD_LEAK_EMB_MODE_ZERO_CMD_RQRD_Q 5 ///< Blood leak embedded mode zero command required queue count. #define BLOOD_LEAK_EMB_MODE_NUM_OF_RETRIES 3 ///< Blood leak embedded mode number of retries to enqueue. #define BLOOD_LEAK_EMB_MODE_INFO_CMD_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Blood leak embedded mode informative command timeout in milliseconds. #define BLOOD_LEAK_EMB_MODE_NUM_OF_INFO_CMDS 2 ///< Blood leak embedded mode number of informative commands. #define BLOOD_LEAK_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Blood leak embedded mode FPGA error timeout in milliseconds. #define BLOOD_LEAK_RXFIFO_COUNT_MASK 0x03FF ///< Mask high order bits of blood leak sensor rx count. #define COMM_BUFFER_OUT_CAN_PC 15 // ********** private data ********** static BLOOD_LEAK_STATE_T bloodLeakState; static U32 bloodLeakUARTCmdIndex; static U32 bloodLeakSetPointSeqLength; static U08 bloodLeakSetPointSequence[ BLOOD_LEAK_SET_POINT_SEQ_MAX_LENGTH ][ 2 ]; // 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 bloodLeakEmbModeCmdSeq[ 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. static U08 bloodLeakEmbModeCmdQ[ BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE ]; ///< Blood leak embedded mode command queue. static U08 bloodLeakEmbModeCmdQRearIndex; ///< Blood leak embedded mode command queue rear index. static U08 bloodLeakEmbModeCmdQFrontIndex; ///< Blood leak embedded mode command queue front index. static U08 bloodLeakEmbModeCmdQCount; ///< Blood leak embedded mode command queue count. static U32 bloodLeakEmbModeInfoCmdEnqLastTimeStamp; ///< Blood leak embedded mode informative command (i.e. I, V, D) timer. static U32 bloodLeakEmbModeInfoCmdCounter; ///< Blood leak embedded mode informative command counter. static OVERRIDE_U32_T bloodLeakEmbModeIntensityOverride; ///< Blood leak embedded mode intensity override. static OVERRIDE_U32_T bloodLeakEmbModeDetectOverride; ///< Blood leak embedded mode blood detect override. // ********** private function prototypes ********** static BLOOD_LEAK_EMB_MODE_STATE_T handleBloodLeakEmbModeWaitForCommandState( void ); static BLOOD_LEAK_EMB_MODE_STATE_T handleBloodLeakEmbModeSendCommandState( void ); static BLOOD_LEAK_EMB_MODE_STATE_T handleBloodLeakEmbModeWaitForCommandResponseState( void ); static void convertString2Integer( U08 cmd, U32 respLength ); static void prepareSetPointSeq( U16 setPoint ); static void initEmbModeSpecs( void ); static U16 getBloodLeakRxBytesAvailable( void ); static BOOL sendBloodLeakEmbeddedModeCommandResponse( U08 cmd, U32 responseLen, U08 *responseBuffer ); /*********************************************************************//** * @brief * The initBloodLeakDriver function initializes the Blood Leak module. * @details \b Inputs: none * @details \b Outputs: bloodLeakState, bloodLeakStatus, bloodLeakSelfTestStatus, * bloodLeakUARTCmdIndex, bloodLeakSetPointSequence * bloodLeakDataPublicationTimerCounter, bloodLeakEmbModeHasZeroBeenRqustd * bloodLeakEmbModeSubstate, bloodLeakEmbModeCmdEnqueueCount * bloodLeakPersistenceCtr, bloodLeakSignalEmbModeReq, * bloodLeakEmbModeRqstedCmd, bloodLeakEmbModeOpsStartTime, * bloodLeakEmbModeRespBuffer, bloodLeakEmbModeRespIndex, * bloodLeakExitNormalRequested, bloodLeakEmbModeCmdSeqLength, * bloodLeakEmbModeHasRxRqstBeenSent, bloodLeakEmbModeInfoCmdEnqLastTimeStamp, * bloodLeakEmbModeInfoCmdCounter, bloodLeakRecoveryStartTimeMS, * bloodLeakZeroingStatus * @return none *************************************************************************/ void initBloodLeakDriver( void ) { // Initialize the embedded mode specifications initEmbModeSpecs(); bloodLeakEmbModeRespIndex = 0; bloodLeakEmbModeCmdSeqLength = 0; bloodLeakEmbModeHasRxRqstBeenSent = FALSE; bloodLeakEmbModeCmdQFrontIndex = 0; bloodLeakEmbModeCmdQRearIndex = 0; bloodLeakEmbModeCmdQCount = 0; bloodLeakEmbModeInfoCmdEnqLastTimeStamp = getMSTimerCount(); bloodLeakEmbModeInfoCmdCounter = 0; // 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( bloodLeakEmbModeCmdSeq, 0x0, BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ); // Enqueue the commands to set the embedded mode and request the set point of the blood leak sensor enqueueEmbModeCmd( CS_EMB_MODE_CMD ); enqueueEmbModeCmd( D_EMB_MODE_CMD ); } /*********************************************************************//** * @brief * The execBloodLeakEmbModeCommand function executes the blood leak embedded * mode command. * @details \b Inputs: bloodLeakEmbModeSubstate * @details \b Outputs: bloodLeakEmbModeSubstate * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when in an unknown state * @return none *************************************************************************/ void execBloodLeakEmbModeCommand( void ) { switch ( bloodLeakEmbModeSubstate ) { case BLOOD_LEAK_EMB_MODE_WAIT_FOR_COMAND_STATE: bloodLeakEmbModeSubstate = handleBloodLeakEmbModeWaitForCommandState(); break; case BLOOD_LEAK_EMB_MODE_SEND_COMMAND_STATE: bloodLeakEmbModeSubstate = handleBloodLeakEmbModeSendCommandState(); break; case BLOOD_LEAK_EMB_MODE_WAIT_FOR_COMMAND_RESPONSE_STATE: bloodLeakEmbModeSubstate = handleBloodLeakEmbModeWaitForCommandResponseState(); break; default: SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_LEAK_EMBEDDED_MODE_INVALID_STATE ) bloodLeakEmbModeSubstate = BLOOD_LEAK_EMB_MODE_WAIT_FOR_COMAND_STATE; break; } } /*********************************************************************//** * @brief * The processReceivedEmbModeChar function processes the character that * has been received. * @details \b Inputs: bloodLeakEmbModeCmd, bloodLeakEmbModeRespIndex * @details \b Outputs: bloodLeakEmbModeRespBuffer, bloodLeakEmbModeRespIndex * @param data which is the data that has been received from the BLD * @return none *************************************************************************/ 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 ) { // 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 ) { if ( NU_EMB_MODE_CMD == expChar2 ) { // 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 cd ve> 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 { // 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 { // 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 enqueueEmbModeCmd function enqueues an embedded mode command. * @details \b Inputs: none * @details \b Outputs: bloodLeakEmbModeCmdQRearIndex, bloodLeakEmbModeCmdQCount * bloodLeakEmbModeCmdQ, bloodLeakEmbModeCmd * @param cmd the command to enqueue * @return none *************************************************************************/ void enqueueEmbModeCmd( U08 cmd ) { // Enqueue the command and increment the rear embedded mode index // Set the command response to be false so the command was just queued to be read bloodLeakEmbModeCmdQ[ bloodLeakEmbModeCmdQRearIndex ] = cmd; bloodLeakEmbModeCmdQRearIndex = INC_WRAP( bloodLeakEmbModeCmdQRearIndex, 0, BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE - 1 ); bloodLeakEmbModeCmd[ cmd ].isCmdRespRdy = FALSE; bloodLeakEmbModeCmd[ cmd ].commandRqstCount++; bloodLeakEmbModeCmdQCount++; } /*********************************************************************//** * @brief * The resetEmbModeCmdRqstCount function resets embedded mode command request * count. * @details \b Inputs: none * @details \b Outputs: bloodLeakEmbModeCmd * @param cmd the command to reset its request count * @return none *************************************************************************/ void resetEmbModeCmdRqstCount( U08 cmd ) { bloodLeakEmbModeCmd[ cmd ].commandRqstCount = 0; } /*********************************************************************//** * @brief * The dequeueEmbModeCmd function dequeues the embedded mode command. * @details \b Inputs: none * @details \b Outputs: bloodLeakEmbModeCmdQFrontIndex, bloodLeakEmbModeCmdQCount * @return command that is dequeued *************************************************************************/ U08 dequeueEmbModeCmd( void ) { U08 command = 0; U08 tempIndex; _disable_IRQ(); tempIndex = bloodLeakEmbModeCmdQFrontIndex; if ( FALSE == isEmbModeCmdQueueEmpty() ) { bloodLeakEmbModeCmdQFrontIndex = INC_WRAP( bloodLeakEmbModeCmdQFrontIndex, 0, BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE - 1 ); command = bloodLeakEmbModeCmdQ[ tempIndex ]; bloodLeakEmbModeCmdQCount--; } _enable_IRQ(); return command; } /*********************************************************************//** * @brief * The isEmbModeCmdQueueEmpty function checks whether the embedded mode command * queue is empty or not. * @details \b Inputs: bloodLeakEmbModeCmdQCount * @details \b Outputs: none * @return TRUE if the queue is empty otherwise, FALSE *************************************************************************/ BOOL isEmbModeCmdQueueEmpty( void ) { BOOL isEmpty = TRUE; if ( bloodLeakEmbModeCmdQCount > 0 ) { isEmpty = FALSE; } return isEmpty; } /*********************************************************************//** * @brief * The getAvailableEmbModeQueueCount function returns the available embedded * mode queue count. * @details \b ts: bloodLeakEmbModeCmdQCount * @details \b Outputs: none * @return Current available embedded mode queue count *************************************************************************/ U32 getAvailableEmbModeQueueCount( void ) { return BLOOD_LEAK_EMB_MODE_CMD_Q_MAX_SIZE - bloodLeakEmbModeCmdQCount; } /*********************************************************************//** * @brief * The enqueueInfoEmbModeCmds function enqueues the informative embedded * mode commands. * @details \b Inputs: bloodLeakEmbModeInfoCmdEnqueueLastTimeStamp, bloodLeakState, * bloodLeakEmbModeInfoCmdCounter * @details \b Outputs: bloodLeakEmbModeInfoCmdEnqueueLastTimeStamp, bloodLeakState, * bloodLeakEmbModeInfoCmdCounter * @return none *************************************************************************/ void enqueueInfoEmbModeCmds( void ) { if ( TRUE == didTimeout( bloodLeakEmbModeInfoCmdEnqLastTimeStamp, BLOOD_LEAK_EMB_MODE_INFO_CMD_TIMEOUT_MS ) ) { switch ( bloodLeakState ) { case BLOOD_LEAK_INIT_STATE: case BLOOD_LEAK_NORMAL_STATE: case BLOOD_LEAK_RECOVER_BLOOD_DETECT_STATE: // Enqueue the next command. Make sure the blood leak state is greater than init state and it is not the zero and self test state // to make sure setting the embedded mode and getting the set point and zero sequence should go undisturbed. if ( 0 == bloodLeakEmbModeInfoCmdCounter ) { enqueueEmbModeCmd( I_EMB_MODE_CMD ); } else if ( 1 == bloodLeakEmbModeInfoCmdCounter ) { enqueueEmbModeCmd( V_EMB_MODE_CMD ); } // Set the timer for the next time out to enqueue // Reset the counter. The counter starts from 0 bloodLeakEmbModeInfoCmdEnqLastTimeStamp = getMSTimerCount(); bloodLeakEmbModeInfoCmdCounter = INC_WRAP( bloodLeakEmbModeInfoCmdCounter, 0, BLOOD_LEAK_EMB_MODE_NUM_OF_INFO_CMDS - 1 ); break; default: // Do nothing as the other commands are ignored break; } } } /*********************************************************************//** * @brief * The getFPGABloodDetectProcessedStatus function returns the status of the * blood detect from FPGA meaning the status that is read from the sensor. * @details \b Inputs: none * @details \b Outputs: none * @return BLOOD_LEAK_NOT_DETECTED if blood has not been detected otherwise, * BLOOD_LEAK_DETECTED *************************************************************************/ BLOOD_LEAK_STATUS_T getFPGABloodDetectProcessedStatus( void ) { // If the blood leak status bit is low (0) it means blood has not been detected, otherwise, blood has been detected return ( BLOOD_LEAK_STATUS_BIT_LOW == getFPGABloodLeakStatus() ? BLOOD_LEAK_NOT_DETECTED : BLOOD_LEAK_DETECTED ); } /*********************************************************************//** * @brief * The resetEmbModeCmdRespConsumedFlag function sets the cmd response ready flag * to false its flag that fresh data is ready. * @details \b Inputs: none * @details \b Outputs: bloodLeakEmbModeCmd * @param cmd the command to signal its data has been consumed * @return none *************************************************************************/ void resetEmbModeCmdRespConsumedFlag( U08 cmd ) { bloodLeakEmbModeCmd[ cmd ].isCmdRespRdy = FALSE; } /*********************************************************************//** * @brief * The getEmbModeInfoValue function gets the data of the embedded info cmds. * This is only for the info values (I, V). * @details \b Inputs: bloodLeakEmbModeIntensityOverride, * bloodLeakEmbModeDetectOverride * @details \b Outputs: bloodLeakEmbModeCmd * @param cmd the command to get the read data * @return the value of the read command *************************************************************************/ U32 getEmbModeInfoValue( U08 cmd ) { U32 value = bloodLeakEmbModeCmd[ cmd ].commandResp; switch( cmd ) { case I_EMB_MODE_CMD: if ( OVERRIDE_KEY == bloodLeakEmbModeIntensityOverride.override ) { value = bloodLeakEmbModeIntensityOverride.ovData; } break; case V_EMB_MODE_CMD: if ( OVERRIDE_KEY == bloodLeakEmbModeDetectOverride.override ) { value = bloodLeakEmbModeDetectOverride.ovData; } break; default: // Do nothing with the rest of the commands break; } return value; } /*********************************************************************//** * @brief * The handleBloodLeakEmbModeWaitForCommandState function handles the wait for * command state. The state prepares the message to be sent to the blood leak * sensor. * @details \b Inputs: bloodLeakEmbModeRqstedCmd, bloodLeakEmbModeCmd * @details \b Outputs: bloodLeakEmbModeRqstedCmd, bloodLeakEmbModeCmdSeq, * bloodLeakUARTCmdIndex, bloodLeakEmbModeRespIndex, bloodLeakEmbModeCmdSeqLength, * bloodLeakEmbModeOpsStartTime, bloodLeakEmbModeSetPoint, bloodLeakEmbModeRespBuffer * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if incorrect blood leak command has * been selected * @return next state *************************************************************************/ static BLOOD_LEAK_EMB_MODE_STATE_T handleBloodLeakEmbModeWaitForCommandState( void ) { BLOOD_LEAK_EMB_MODE_STATE_T state = BLOOD_LEAK_EMB_MODE_WAIT_FOR_COMAND_STATE; if ( FALSE == isEmbModeCmdQueueEmpty() ) { U08 commandASCII = 0; bloodLeakEmbModeRqstedCmd = dequeueEmbModeCmd(); commandASCII = 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( bloodLeakEmbModeCmdSeq, 0x0, 2 * BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ); // Set the command sequence bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_RESET_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_RESET; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_RESET_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_RESET_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_RESET_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_CMD_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = commandASCII; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_CMD_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = FALSE; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_STOP_WRITE_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_STOP_WRITE_FIFO_COMMAND; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_STOP_WRITE_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = FALSE; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_HIGH; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_ACTIVE_HIGH_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW; bloodLeakEmbModeCmdSeq[ 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_EMB_MODE_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_EMB_MODE_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( bloodLeakEmbModeCmdSeq, 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; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_LEAK_INVALID_EMB_MODE_CMD_SELECTED, bloodLeakEmbModeRqstedCmd ) break; } } return state; } /*********************************************************************//** * @brief * The handleBloodLeakEmbModeSendCommandState function handles the send command * state. The state sends the command sequence to the blood leak sensor one by one. * @details \b Inputs: bloodLeakEmbModeRqstedCmd, bloodLeakCalCharacter, bloodLeakUARTCmdIndex * bloodLeakEmbModeCmdSeqLength * @details \b Outputs: bloodLeakEmbModeRqstedCmd, bloodLeakCalCommandSquence, * bloodLeakUARTCmdIndex, bloodLeakEmbModeCmdSeqLength, bloodLeakEmbModeCmdSeqLength, * bloodLeakSetPointSequence * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if incorrect blood leak command has * been selected * @return next state *************************************************************************/ static BLOOD_LEAK_EMB_MODE_STATE_T handleBloodLeakEmbModeSendCommandState( void ) { U08 command; BLOOD_LEAK_EMB_MODE_STATE_T state = BLOOD_LEAK_EMB_MODE_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 = bloodLeakEmbModeCmdSeq[ bloodLeakUARTCmdIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ]; isUARTCtrlCmd = bloodLeakEmbModeCmdSeq[ 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 == bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] ) { command = bloodLeakEmbModeCmdSeq[ bloodLeakUARTCmdIndex ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ]; isUARTCtrlCmd = bloodLeakEmbModeCmdSeq[ 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; default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_LEAK_INVALID_EMB_MODE_CMD_SELECTED, bloodLeakEmbModeRqstedCmd ) 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 ( 0 == getBloodLeakRxBytesAvailable() ) { // 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 ) { if ( FALSE == isUARTCtrlCmd ) { setFPGABloodLeakUARTTransmit( command ); } else { 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 = bloodLeakEmbModeCmdSeq[ 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_EMB_MODE_WAIT_FOR_COMMAND_RESPONSE_STATE; } return state; } /*********************************************************************//** * @brief * The handleBloodLeakEmbModeWaitForCommandResponseState function handles the * wait for command responses state. The state receives data in the buffer. * @details \b Inputs: bloodLeakEmbModeHasRxRqstBeenSent, bloodLeakEmbModeRespBuffer, * bloodLeakEmbModeRespIndex, bloodLeakEmbModeRqstedCmd, bloodLeakEmbModeOpsStartTime * @details \b Outputs: bloodLeakEmbModeCmd, bloodLeakEmbModeRqstedCmd, * bloodLeakEmbModeCmdSeq, bloodLeakEmbModeRespBuffer * @return next state *************************************************************************/ static BLOOD_LEAK_EMB_MODE_STATE_T handleBloodLeakEmbModeWaitForCommandResponseState( void ) { BLOOD_LEAK_EMB_MODE_STATE_T state = BLOOD_LEAK_EMB_MODE_WAIT_FOR_COMMAND_RESPONSE_STATE; U16 rxFIFOCount = getBloodLeakRxBytesAvailable(); 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( bloodLeakEmbModeCmdSeq, 0x0, 2 * BLOOD_LEAK_EMB_MODE_CMD_SEQ_LENGTH ); bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_READ_REQST; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX ][ BLOOD_LEAK_EMB_MODE_IS_UART_COL_INDEX ] = TRUE; bloodLeakEmbModeCmdSeq[ BLOOD_LEAK_EMB_MODE_REQUEST_RX_INDEX + 1 ][ BLOOD_LEAK_EMB_MODE_CMD_COL_INDEX ] = BLOOD_LEAK_EMB_MODE_COMM_ACTIVE_LOW; bloodLeakEmbModeCmdSeq[ 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_EMB_MODE_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 ) && ( 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 ); } convertString2Integer( bloodLeakEmbModeRqstedCmd, length ); sendBloodLeakEmbeddedModeCommandResponse( bloodLeakEmbModeRqstedCmd, length, bloodLeakEmbModeRespBuffer ); // Done with receiving the data bloodLeakEmbModeRqstedCmd = NU_EMB_MODE_CMD; state = BLOOD_LEAK_EMB_MODE_WAIT_FOR_COMAND_STATE; } 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; convertString2Integer( bloodLeakEmbModeRqstedCmd, length ); sendBloodLeakEmbeddedModeCommandResponse( bloodLeakEmbModeRqstedCmd, length, bloodLeakEmbModeRespBuffer ); bloodLeakEmbModeRqstedCmd = NU_EMB_MODE_CMD; state = BLOOD_LEAK_EMB_MODE_WAIT_FOR_COMAND_STATE; } return state; } /*********************************************************************//** * @brief * The convertString2Integer function converts the buffer of the answers in * string (ASCII) to integer. * @details \b Inputs: bloodLeakEmbModeCmd * @details \b Outputs: bloodLeakEmbModeRespBuffer, bloodLeakEmbModeCmd * @param cmd which is the embedded mode command * @param respLength the length of the received response from the sensor * @return none *************************************************************************/ static void convertString2Integer( U08 cmd, U32 respLength ) { if ( 1 == respLength ) { bloodLeakEmbModeCmd[ cmd ].commandResp = bloodLeakEmbModeRespBuffer[ 0 ]; } else { U08 i; U32 bufferValue; U32 respExpectedLength = bloodLeakEmbModeCmd[ cmd ].length; // Reset the command response bloodLeakEmbModeCmd[ cmd ].commandResp = 0; for ( i = 0; i < respExpectedLength; i++ ) { // The last value is inserted into the response buffer (i.e. S030) // So the buffer array is used from the last element of the array bufferValue = bloodLeakEmbModeRespBuffer[ respExpectedLength - 1 - i ]; if ( ( bufferValue >= BLOOD_LEAK_EMB_MODE_0_NUM_ASCII ) && ( bufferValue <= BLOOD_LEAK_EMB_MODE_9_NUM_ASCII ) ) { // If the value in the response buffer is within the ASCII values of 0 (ASCII 48) to 9 (ASCII 57) then it is a number and needs to be converted to integer // Subtract the buffer value from ASCII 48 to get the offset (i.e. buffer = 50 - 48 = 2) // Add the offset value to the command response in the right order (i.e. if i = 1, then it is 2 x 10 ^1 = 20) bufferValue -= BLOOD_LEAK_EMB_MODE_0_NUM_ASCII; bloodLeakEmbModeCmd[ cmd ].commandResp += ( bufferValue * pow( 10, i ) ); } } } // Set the command response ready bloodLeakEmbModeCmd[ cmd ].isCmdRespRdy = TRUE; } /*********************************************************************//** * @brief * The prepareSetPointSeq function prepares the set point sequence to be * written to the blood leak sensor. * @details \b Inputs: none * @details \b 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 initEmbModeSpecs function initializes the embedded mode specifications * structure. * @details \b Inputs: none * @details \b 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; bloodLeakEmbModeCmd[ NU_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ NU_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ CS_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ SP_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ SP_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ T_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ T_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ G_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ G_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ I_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ V_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ V_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ Z_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ Q_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ Q_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ D_EMB_MODE_CMD ].isCmdRespRdy = FALSE; // 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; bloodLeakEmbModeCmd[ C_EMB_MODE_CMD ].commandResp = 0; bloodLeakEmbModeCmd[ C_EMB_MODE_CMD ].isCmdRespRdy = FALSE; } /*********************************************************************//** * @brief * The getBloodLeakRxBytesAvailable function returns the number of received * bytes available from FPGA. * @details \b Inputs: none * @details \b Outputs: none * @return Number of received bytes available *************************************************************************/ static U16 getBloodLeakRxBytesAvailable( void ) { return getFPGABloodLeakRxFIFOCount() & BLOOD_LEAK_RXFIFO_COUNT_MASK; } /*********************************************************************//** * @brief * The sendBloodLeakEmbeddedModeCommandResponse function sends out * the blood leak embedded mode command response. * @details \b Inputs: none * @details \b Outputs: blood leak embedded mode command response msg constructed and queued * @details \b Message: MSG_ID_DD_SEND_BLOOD_LEAK_EMB_MODE_RESPONSE DD blood leak response command * @param cmd: the command its response is being sent * @param responseLen: the length of the buffer * @param response: pointer to the response buffer * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ static BOOL sendBloodLeakEmbeddedModeCommandResponse( U08 cmd, U32 responseLen, U08 *responseBuffer ) { BLOOD_LEAK_EMB_MODE_RESP_T response; BOOL result = FALSE; response.command = cmd; response.responseLen = responseLen; memcpy( response.responseBuffer, responseBuffer, responseLen ); result = sendMessage( MSG_ID_DD_SEND_BLOOD_LEAK_EMB_MODE_RESPONSE, COMM_BUFFER_OUT_DD_CAN_PC, (U08*)&response, sizeof( BLOOD_LEAK_EMB_MODE_RESP_T ) ); return result; } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testSetBloodLeak2EmbeddedMode function sets the blood leak driver to the * embedded more for calibration. * @details \b Inputs: none * @details \b Outputs: bloodLeakSignalEmbeddedModeReq * @param message Override message from Dialin * @return TRUE if switching to embedded mode was accepted otherwise, FALSE *************************************************************************/ BOOL testSetBloodLeak2EmbeddedMode( MESSAGE_T *message ) { BOOL result = FALSE; TD_OP_MODE_T mode = getTDOpMode(); // 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 \b Inputs: none * @details \b Outputs: bloodLeakEmbModeSetPoint * @param message Override message from Dialin to set the command and the * setpoint payload value * @return TRUE if the command is accepted otherwise, FALSE *************************************************************************/ BOOL testSetBloodLeakEmbeddedModeCommand( MESSAGE_T *message ) { BOOL result = FALSE; U08* payloadPtr = message->payload; U08 command; U16 setPointPayload; memcpy( &command, payloadPtr, sizeof( U08 ) ); payloadPtr += sizeof( U08 ); memcpy( &setPointPayload, payloadPtr, sizeof( U16 ) ); if ( command < NUM_OF_EMB_CMDS ) { enqueueEmbModeCmd( command ); bloodLeakEmbModeSetPoint = setPointPayload; result = TRUE; } return result; } /*********************************************************************//** * @brief * The testBloodLeakEmbeddedModeInfoOverride function overrides the * blood leak embedded mode info values. * @details \b Inputs: none * @details \b Outputs: bloodLeakEmbModeIntensityOverride, * bloodLeakEmbModeDetectOverride * @param message Override message from Dialin to set the command and the * embedded mode info values * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testBloodLeakEmbeddedModeInfoOverride( MESSAGE_T *message ) { BOOL result = FALSE; U08* payloadPtr = message->payload; U08 command; memcpy( &command, payloadPtr, sizeof( U08 ) ); if ( command < NUM_OF_EMB_CMDS ) { U32 min = 0; U32 max = 100000; switch( command ) { case I_EMB_MODE_CMD: result = u32Override( message, &bloodLeakEmbModeIntensityOverride, min, max ); break; case V_EMB_MODE_CMD: result = u32Override( message, &bloodLeakEmbModeDetectOverride, min, max ); break; default: // Do nothing with the rest of the commands. They cannot be overridden. break; } } return result; } /**@}*/