Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -reb877ae36c28eb83553ee11ccccf42e2c4a5b4d2 -r97a2c1e5f702a7d70d5a6fa46fac333b296aa5b3 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision eb877ae36c28eb83553ee11ccccf42e2c4a5b4d2) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 97a2c1e5f702a7d70d5a6fa46fac333b296aa5b3) @@ -1,308 +1,388 @@ -/************************************************************************** - * - * Copyright (c) 2019-2019 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 SystemComm.c - * - * @date 08-Oct-2019 - * @author S. Nash - * - * @brief SystemComm service module. Provides system message communication \n - * functionality. Messages can be queued for transmission. Incoming messages \n - * are processed. - * - **************************************************************************/ +/************************************************************************** +* +* Copyright (c) 2019-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 SystemComm.c +* +* @author (last) Dara Navaei +* @date (last) 14-Jun-2022 +* +* @author (original) Dara Navaei +* @date (original) 05-Nov-2019 +* +***************************************************************************/ -#include // for memcpy() +#include // For memcpy() #include "can.h" #include "sci.h" #include "sys_dma.h" -#include "SystemComm.h" #include "Comm.h" #include "Interrupts.h" -#include "MsgQueues.h" -#include "SystemCommMessages.h" +#include "OperationModes.h" +#include "SystemComm.h" +#include "SystemCommMessages.h" +#include "Interrupts.h" +#include "OperationModes.h" +#include "Timers.h" +#include "Utilities.h" -#ifdef RM46_EVAL_BOARD_TARGET - #include "CPLD.h" -#endif - +/** + * @addtogroup SystemComm + * @{ + */ + // ********** private definitions ********** -#define NUM_OF_CAN_OUT_BUFFERS 4 // # of CAN buffers for transmit -#define NUM_OF_CAN_IN_BUFFERS 6 // # of CAN buffers for receiving -#define NUM_OF_MSG_IN_BUFFERS 7 // # of Msg buffers for receiving +#define NUM_OF_CAN_OUT_BUFFERS 5 ///< Number of CAN buffers for transmit +#define NUM_OF_CAN_IN_BUFFERS 7 ///< Number of CAN buffers for receiving +#define NUM_OF_MSG_IN_BUFFERS 7 ///< Number of Msg buffers for receiving -#define SCI1_RECEIVE_DMA_REQUEST 30 -#define SCI1_TRANSMIT_DMA_REQUEST 31 +#define CAN_XMIT_PACKET_TIMEOUT_MS 200 ///< If transmitted CAN frame does not cause a transmit complete interrupt within this time, re-send or move on +#define MAX_XMIT_RETRIES 5 ///< Maximum number of retries on no transmit complete interrupt timeout +#define UI_COMM_TIMEOUT_IN_MS 5000 ///< UI has not checked in for this much time +#define DG_COMM_TIMEOUT_IN_MS 2000 ///< DG has not checked in for this much time + +#define MAX_COMM_CRC_FAILURES 5 ///< Maximum number of CRC errors within window period before alarm +#define MAX_COMM_CRC_FAILURE_WINDOW_MS (10 * SEC_PER_MIN * MS_PER_SECOND) ///< CRC error window + +#define MSG_NOT_ACKED_TIMEOUT_MS 150 ///< Maximum time for a Denali message that requires ACK to be ACK'd + +#define MSG_NOT_ACKED_TIMEOUT_MS_INIT 5000 ///< Maximum time for a Denali message that requires ACK to be ACK'd on the INIT state for the first (UI version request) message of the POST +#define MSG_NOT_ACKED_MAX_RETRIES 3 ///< Maximum number of times a message that requires ACK that was not ACK'd can be re-sent before alarm +#define PENDING_ACK_LIST_SIZE 25 ///< Maximum number of Denali messages that can be pending ACK at any given time + +#pragma pack(push, 1) + +/// Record for transmitted message that is pending acknowledgment from receiver. +typedef struct +{ + BOOL used; + U16 seqNo; + U16 retries; + U32 timeStamp; + COMM_BUFFER_T channel; + U32 msgSize; + U08 msg[ MAX_ACK_MSG_SIZE ]; +} PENDING_ACK_RECORD_T; + +#pragma pack(pop) + // ********** private data ********** -const COMM_BUFFER_T CAN_OUT_BUFFERS[NUM_OF_CAN_OUT_BUFFERS] = +/// Array of out-going CAN buffers. +const COMM_BUFFER_T CAN_OUT_BUFFERS[ NUM_OF_CAN_OUT_BUFFERS ] = { COMM_BUFFER_OUT_CAN_HD_ALARM, COMM_BUFFER_OUT_CAN_HD_2_DG, COMM_BUFFER_OUT_CAN_HD_2_UI, - COMM_BUFFER_OUT_CAN_HD_BROADCAST + COMM_BUFFER_OUT_CAN_HD_BROADCAST, + COMM_BUFFER_OUT_CAN_PC }; -const COMM_BUFFER_T MSG_IN_BUFFERS[NUM_OF_MSG_IN_BUFFERS] = +/// Array of in-coming CAN buffers. +const COMM_BUFFER_T MSG_IN_BUFFERS[ NUM_OF_MSG_IN_BUFFERS ] = { COMM_BUFFER_IN_CAN_DG_ALARM, COMM_BUFFER_IN_CAN_UI_ALARM, COMM_BUFFER_IN_CAN_DG_2_HD, COMM_BUFFER_IN_CAN_DG_BROADCAST, COMM_BUFFER_IN_CAN_UI_2_HD, COMM_BUFFER_IN_CAN_UI_BROADCAST, - COMM_BUFFER_IN_UART_PC + COMM_BUFFER_IN_CAN_PC, }; -static U08 pcXmitPacket[PC_MESSAGE_PACKET_SIZE] = {0,0,0,0,0,0,0,0};// = {1,2,3,4,5,6,7,8}; -static U08 pcRecvPacket[PC_MESSAGE_PACKET_SIZE] = {0,0,0,0,0,0,0,0}; +static U08 lastCANPacketSent[ CAN_MESSAGE_PAYLOAD_SIZE ]; ///< Keep last packet sent on CAN bus in case we need to re-send. +static CAN_MESSAGE_BOX_T lastCANPacketSentChannel = (CAN_MESSAGE_BOX_T)0; ///< Keep channel last packet was sent on CAN bus in case we need to re-send. +static U32 lastCANPacketSentTimeStamp = 0; ///< Keep time last packet sent on CAN bus so we can timeout on transmission attempt. -// DMA control records -static g_dmaCTRL pcDMAXmitControlRecord; -static g_dmaCTRL pcDMARecvControlRecord; +static volatile PENDING_ACK_RECORD_T pendingAckList[ PENDING_ACK_LIST_SIZE ]; ///< List of outgoing messages that are awaiting an ACK +static volatile BOOL hdIsOnlyCANNode = TRUE; ///< Flag indicating whether HD is alone on CAN bus. +static U32 canXmitRetryCtr = 0; ///< Counter for CAN transmit retries. +static volatile BOOL dgIsCommunicating = FALSE; ///< Has DG sent a message since last check +static U32 timeOfLastDGCheckIn = 0; ///< Last time DG checked in +static volatile BOOL uiIsCommunicating = FALSE; ///< Has UI sent a message since last check +static U32 timeOfLastUICheckIn = 0; ///< Last time UI checked in +static volatile BOOL uiDidCommunicate = FALSE; ///< Has UI every sent a message + +#ifdef EMC_TEST_BUILD + static U32 badCANCount; // Test code in support of EMC testing +#endif + // ********** private function prototypes ********** -static void initUARTAndDMA( void ); -static BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ); -static BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ); +static void clearCANXmitBuffers( void ); static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ); -static void transmitNextCANPacket( void ); -static void transmitNextUARTPacket( void ); +static U32 transmitNextCANPacket( void ); static void processIncomingData( void ); -static U32 parseMessageFromBuffer( U08 *data, U32 len ); +static S32 parseMessageFromBuffer( U08 *data, U32 len ); static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ); static void processReceivedMessages( void ); static void processReceivedMessage( MESSAGE_T *message ); -/************************************************************************* - * @brief initSystemComm +static void checkForCommTimeouts( void ); +static void checkTooManyBadMsgCRCs( void ); + +static BOOL matchACKtoPendingACKList( S16 seqNo ); +static void checkPendingACKList( void ); + +/*********************************************************************//** + * @brief * The initSystemComm function initializes the SystemComm module. - * @details - * Inputs : none - * Outputs : SystemComm module initialized. - * @param none + * @details Inputs: none + * @details Outputs: SystemComm module initialized. * @return none *************************************************************************/ void initSystemComm( void ) { - // initialize UART and DMA for PC communication - initUARTAndDMA(); + U32 i; - // TODO - remove this test code that sends a packet -// dmaSetCtrlPacket( DMA_CH3, pcDMAXmitControlRecord ); -// dmaSetChEnable( DMA_CH3, DMA_HW ); -// setSCI1DMATransmitInterrupt(); + // Initialize bad message CRC time windowed count + initTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC, MAX_COMM_CRC_FAILURES, MAX_COMM_CRC_FAILURE_WINDOW_MS ); + + // Initialize pending ACK list + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + pendingAckList[ i ].used = FALSE; + } } -/************************************************************************* - * @brief execSystemCommRx +/*********************************************************************//** + * @brief + * The checkInFromDG function checks in the DG with the HD - indicating that + * the DG is communicating. + * @details Inputs: none + * @details Outputs: dgIsCommunicating + * @return none + *************************************************************************/ +void checkInFromDG( void ) +{ + dgIsCommunicating = TRUE; + timeOfLastDGCheckIn = getMSTimerCount(); + + if ( TRUE == isAlarmActive( ALARM_ID_DG_COMM_TIMEOUT ) ) + { + clearAlarmCondition( ALARM_ID_DG_COMM_TIMEOUT ); + } +} + +/*********************************************************************//** + * @brief + * The checkInFromUI function checks in the UI with the HD - indicating that + * the UI is communicating. + * @details Inputs: none + * @details Outputs: uiIsCommunicating + * @return none + *************************************************************************/ +void checkInFromUI( void ) +{ + if ( FALSE == uiDidCommunicate ) + { // Start DG check-in timer when UI first communicates + timeOfLastDGCheckIn = getMSTimerCount(); + } + + uiIsCommunicating = TRUE; + timeOfLastUICheckIn = getMSTimerCount(); + uiDidCommunicate = TRUE; +} + +/*********************************************************************//** + * @brief + * The isDGCommunicating function determines whether the DG is communicating + * with the HD. + * @details Inputs: dgIsCommunicating + * @details Outputs: none + * @return TRUE if DG has checked in since last call, FALSE if not + *************************************************************************/ +BOOL isDGCommunicating( void ) +{ + return dgIsCommunicating; +} + +/*********************************************************************//** + * @brief + * The isUICommunicating function determines whether the UI is communicating + * with the HD. + * @details Inputs: uiIsCommunicating + * @details Outputs: none + * @return TRUE if UI has checked in since last call, FALSE if not + *************************************************************************/ +BOOL isUICommunicating( void ) +{ + BOOL result = uiIsCommunicating; + + uiIsCommunicating = FALSE; + + return result; +} + +/*********************************************************************//** + * @brief + * The uiCommunicated function determines whether the UI has communicated. + * @details Inputs: uiDidCommunicate + * @details Outputs: none + * @return TRUE if UI has communicated since power up, FALSE if not + *************************************************************************/ +BOOL uiCommunicated( void ) +{ + return uiDidCommunicate; +} + +/*********************************************************************//** + * @brief + * The isHDOnlyCANNode function determines whether the HD is the only node + * currently on the CAN bus. + * @details Inputs: hdIsOnlyCANNode + * @details Outputs: none + * @return TRUE if HD is only node on CAN bus, FALSE if not + *************************************************************************/ +BOOL isHDOnlyCANNode( void ) +{ + return hdIsOnlyCANNode; +} + +/*********************************************************************//** + * @brief * The execSystemCommRx function manages received data from other sub-systems. - * @details - * Inputs : none - * Outputs : none - * @param none + * @details Inputs: none + * @details Outputs: Incoming messages parsed and processed. * @return none *************************************************************************/ void execSystemCommRx( void ) { - // parse messages from comm buffers and queue them + // Parse messages from comm buffers and queue them processIncomingData(); - // process received messages in the queue + // Process received messages in the queue processReceivedMessages(); + + // Check for sub-system comm timeouts + checkForCommTimeouts(); + + // Check ACK list for messages that need to be re-sent because they have not been ACK'd + checkPendingACKList(); } -/************************************************************************* - * @brief execSystemCommTx - * The execSystemCommTx function manages data to be transmitted to other \n +/*********************************************************************//** + * @brief + * The execSystemCommTx function manages data to be transmitted to other * sub-systems. - * @details - * Inputs : none - * Outputs : none - * @param none + * @details Inputs: none + * @details Outputs: Outgoing messages transmitted. * @return none *************************************************************************/ void execSystemCommTx( void ) { - // if CAN transmitter is idle, start transmitting any pending packets - if ( FALSE == isCAN1TransmitInProgress() ) - { - transmitNextCANPacket(); - } - - // if UART transmitter is idle, start transmitting any pending packets - if ( FALSE == isSCI1DMATransmitInProgress() ) - { - transmitNextUARTPacket(); - } + // Do not transmit if no other nodes on CAN bus + if ( FALSE == hdIsOnlyCANNode ) + { + // If CAN transmitter is idle, start transmitting any pending packets + if ( FALSE == isCAN1TransmitInProgress() ) + { + transmitNextCANPacket(); + } + else + { + // Generally, transmitter should not be busy at time of this function call - check timeout just in case so we do not get stuck waiting forever + if ( TRUE == didTimeout( lastCANPacketSentTimeStamp, CAN_XMIT_PACKET_TIMEOUT_MS ) ) + { + // Assume last packet was not successfully transmitted. Re-send last packet. + if ( ++canXmitRetryCtr <= MAX_XMIT_RETRIES ) + { + // Ensure we have a previous CAN packet/channel to resend - canTransmit() channel param MUST be valid + if ( ( lastCANPacketSentChannel > COMM_BUFFER_NOT_USED ) && ( lastCANPacketSentChannel <= COMM_BUFFER_LAST_CAN_BUFFER ) ) + { + canTransmit( canREG1, lastCANPacketSentChannel, lastCANPacketSent ); + } + } + // We must be only node on CAN bus - nobody is ACKing our transmitted frames + else + { + hdIsOnlyCANNode = TRUE; // Set only CAN node flag + canXmitRetryCtr = MAX_XMIT_RETRIES; + signalCANXmitsCompleted(); // Clear pending xmit flag + clearCANXmitBuffers(); // Clear xmit buffers - nothing is going out right now + } // end - are we retrying xmit or are we alone on CAN bus + } // end - pending xmit timeout? + } // end - transmit in progress or not + } // end - DG not alone on CAN bus } -/************************************************************************* - * @brief handleCANMsgInterrupt - * The handleCANMsgInterrupt function handles a CAN message interrupt. \n - * This may have occurred because a CAN packet transmission has completed \n - * or because a CAN packet has been received. The appropriate handler is \n +/*********************************************************************//** + * @brief + * The handleCANMsgInterrupt function handles a CAN message interrupt. + * This may have occurred because a CAN packet transmission has completed + * or because a CAN packet has been received. The appropriate handler is * called. - * @details - * Inputs : none - * Outputs : message interrupt handled - * @param srcCANBox : which CAN message box triggered this interrupt + * @details Inputs: none + * @details Outputs: message interrupt handled + * @param srcCANBox which CAN message box triggered this interrupt * @return none *************************************************************************/ void handleCANMsgInterrupt( CAN_MESSAGE_BOX_T srcCANBox ) { - // message interrupt is for a transmit message box? + // Message interrupt is for a transmit message box? if ( TRUE == isCANBoxForXmit( srcCANBox ) ) { - transmitNextCANPacket(); + U32 bytesXmitted; + + bytesXmitted = transmitNextCANPacket(); + + // If nothing more to send, signal that transmitter is available + if ( 0 == bytesXmitted ) + { + signalCANXmitsCompleted(); + } } else if ( TRUE == isCANBoxForRecv( srcCANBox ) ) { - U08 data[CAN_MESSAGE_CARGO_SIZE]; + U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; - // get CAN packet received on given CAN message box + // Get CAN packet received on given CAN message box if ( FALSE != canIsRxMessageArrived( canREG1, srcCANBox ) ) { - canGetData( canREG1, srcCANBox, data ); - // add CAN packet to appropriate comm buffer based on the message box it came in on (s/b same #) - addToCommBuffer( srcCANBox, data, CAN_MESSAGE_CARGO_SIZE ); + U32 result = canGetData( canREG1, srcCANBox, data ); + + // If packet retrieved, add to buffer + if ( result != 0 ) + { + // Add CAN packet to appropriate comm buffer based on the message box it came in on (s/b same #) + addToCommBuffer( srcCANBox, data, CAN_MESSAGE_PAYLOAD_SIZE ); + } } } else { - // shouldn't get here - not an active message box - // s/w fault? + // Should not get here - not an active message box + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CAN_MESSAGE_BOX, srcCANBox ) } } -/************************************************************************* - * @brief handleUARTMsgRecvPacketInterrupt - * The handleUARTMsgRecvPacketInterrupt function handles a DMA UART receive \n - * packet completed interrupt. - * @details - * Inputs : none - * Outputs : none - * @param none - * @return none - *************************************************************************/ -void handleUARTMsgRecvPacketInterrupt( void ) -{ - // buffer received packet - addToCommBuffer( COMM_BUFFER_IN_UART_PC, pcRecvPacket, PC_MESSAGE_PACKET_SIZE ); - // prepare to receive next packet - dmaSetCtrlPacket( DMA_CH1, pcDMARecvControlRecord ); - dmaSetChEnable( DMA_CH1, DMA_HW ); - setSCI1DMAReceiveInterrupt(); -} - -/************************************************************************* - * @brief handleUARTMsgXmitPacketInterrupt - * The handleUARTMsgXmitPacketInterrupt function handles a DMA UART transmit \n - * packet completed interrupt. - * @details - * Inputs : none - * Outputs : none - * @param none - * @return none - *************************************************************************/ -void handleUARTMsgXmitPacketInterrupt( void ) -{ - transmitNextUARTPacket(); -} - -/************************************************************************* - * @brief initUARTAndDMA - * The initUARTAndDMA function initializes the SCI1 peripheral and the DMA \n - * to go with it for PC communication. - * @details - * Inputs : none - * Outputs : SCI1 and DMA initialized - * @param none - * @return none - *************************************************************************/ -static void initUARTAndDMA( void ) -{ - // Enable DMA block transfer complete interrupts - dmaEnableInterrupt( DMA_CH1, BTC ); - dmaEnableInterrupt( DMA_CH3, BTC ); - // assign DMA channels to h/w DMA requests - dmaReqAssign( DMA_CH1, SCI1_RECEIVE_DMA_REQUEST ); - dmaReqAssign( DMA_CH3, SCI1_TRANSMIT_DMA_REQUEST ); - // set DMA channel priorities - dmaSetPriority( DMA_CH1, HIGHPRIORITY ); - dmaSetPriority( DMA_CH3, LOWPRIORITY ); - - // initialize PC DMA Transmit Control Record - pcDMAXmitControlRecord.PORTASGN = 4; // port B (only choice per datasheet) - pcDMAXmitControlRecord.DADD = (U32)(&(sciREG->TD)); // dest. is SCI2 xmit register - pcDMAXmitControlRecord.SADD = (U32)pcXmitPacket; // source - pcDMAXmitControlRecord.CHCTRL = 0; // no chaining - pcDMAXmitControlRecord.ELCNT = 1; // frame is 1 element - pcDMAXmitControlRecord.FRCNT = PC_MESSAGE_PACKET_SIZE; // block is 8 frames - pcDMAXmitControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte - pcDMAXmitControlRecord.WRSIZE = ACCESS_8_BIT; // - pcDMAXmitControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - pcDMAXmitControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed - pcDMAXmitControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment - pcDMAXmitControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - pcDMAXmitControlRecord.ELSOFFSET = 0; // not used - pcDMAXmitControlRecord.ELDOFFSET = 0; // not used - pcDMAXmitControlRecord.FRSOFFSET = 0; // not used - pcDMAXmitControlRecord.FRDOFFSET = 0; // not used - - // initialize PC DMA Receipt Control Record - pcDMARecvControlRecord.PORTASGN = 4; // port B (only choice per datasheet) - pcDMARecvControlRecord.SADD = (U32)(&(sciREG->RD)); // source is SCI2 recv register - pcDMARecvControlRecord.DADD = (U32)pcRecvPacket; // transfer destination address - pcDMARecvControlRecord.CHCTRL = 0; // no chaining - pcDMARecvControlRecord.ELCNT = 1; // frame is 1 element - pcDMARecvControlRecord.FRCNT = PC_MESSAGE_PACKET_SIZE; // block is 8 frames - pcDMARecvControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte - pcDMARecvControlRecord.WRSIZE = ACCESS_8_BIT; // - pcDMARecvControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - pcDMARecvControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed - pcDMARecvControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment - pcDMARecvControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - pcDMARecvControlRecord.ELDOFFSET = 0; // not used - pcDMARecvControlRecord.ELSOFFSET = 0; // not used - pcDMARecvControlRecord.FRDOFFSET = 0; // not used - pcDMARecvControlRecord.FRSOFFSET = 0; // not used - - // initiate PC packet receiving readiness via DMA - dmaSetCtrlPacket( DMA_CH1, pcDMARecvControlRecord ); - dmaSetChEnable( DMA_CH1, DMA_HW ); - setSCI1DMAReceiveInterrupt(); -} - -/************************************************************************* - * @brief isCANBoxForXmit - * The isCANBoxForXmit function determines whether a given CAN message box \n +/*********************************************************************//** + * @brief + * The isCANBoxForXmit function determines whether a given CAN message box * is configured for transmit. - * @details - * Inputs : CAN_OUT_BUFFERS[] - * Outputs : none - * @param srcCANBox : which CAN message box to check + * @details Inputs: CAN_OUT_BUFFERS[] + * @details Outputs: none + * @param srcCANBox which CAN message box to check * @return TRUE if the given CAN message box is configured for transmit, FALSE if not. *************************************************************************/ -static BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ) +BOOL isCANBoxForXmit( CAN_MESSAGE_BOX_T srcCANBox ) { BOOL result = FALSE; U32 i; for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) { - if ( CAN_OUT_BUFFERS[i] == srcCANBox ) + if ( CAN_OUT_BUFFERS[ i ] == srcCANBox ) { result = TRUE; break; @@ -312,31 +392,47 @@ return result; } -/************************************************************************* - * @brief isCANBoxForRecv - * The isCANBoxForRecv function determines whether a given CAN message box \n +/*********************************************************************//** + * @brief + * The isCANBoxForRecv function determines whether a given CAN message box * is configured for receiving. - * @details - * Inputs : MSG_IN_BUFFERS[] - * Outputs : none - * @param srcCANBox : which CAN message box to check + * @details Inputs: MSG_IN_BUFFERS[] + * @details Outputs: none + * @param srcCANBox which CAN message box to check * @return TRUE if the given CAN message box is configured for receiving, FALSE if not. *************************************************************************/ -static BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ) +BOOL isCANBoxForRecv( CAN_MESSAGE_BOX_T srcCANBox ) { BOOL result = FALSE; U32 i; for ( i = 0; i < NUM_OF_CAN_IN_BUFFERS; i++ ) { - if ( MSG_IN_BUFFERS[i] == srcCANBox ) + if ( MSG_IN_BUFFERS[ i ] == srcCANBox ) { result = TRUE; break; } } return result; +} + +/*********************************************************************//** + * @brief + * The clearCANXmitBuffers function clears all CAN transmit buffers. + * @details Inputs: CAN_OUT_BUFFERS[] + * @details Outputs: CAN transmit buffers cleared. + * @return none + *************************************************************************/ +static void clearCANXmitBuffers( void ) +{ + U32 i; + + for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) + { + clearBuffer( CAN_OUT_BUFFERS[ i ] ); + } } @@ -345,85 +441,79 @@ *************************************************************************/ -/************************************************************************* - * @brief findNextHighestPriorityCANPacketToTransmit - * The findNextHighestPriorityCANPacketToTransmit function gets the next \n - * 8 byte packet and initiates a CAN transmit on the appropriate CAN channel. \n - * @details - * Inputs : Output CAN Comm Buffer(s) - * Outputs : none - * @param msg : none - * @return buffer with highest priority CAN packet to transmit, \n +/*********************************************************************//** + * @brief + * The findNextHighestPriorityCANPacketToTransmit function gets the next + * 8 byte packet and initiates a CAN transmit on the appropriate CAN channel. + * @details Inputs: Output CAN Comm Buffer(s) + * @details Outputs: none + * @return buffer with highest priority CAN packet to transmit, * COMM_BUFFER_NOT_USED if not CAN packets pending transmit found *************************************************************************/ static COMM_BUFFER_T findNextHighestPriorityCANPacketToTransmit( void ) { COMM_BUFFER_T result = COMM_BUFFER_NOT_USED; U32 i; - // search for next priority CAN packet to transmit + // Search for next priority CAN packet to transmit for ( i = 0; i < NUM_OF_CAN_OUT_BUFFERS; i++ ) { - if ( numberOfBytesInCommBuffer( CAN_OUT_BUFFERS[i] ) >= CAN_MESSAGE_CARGO_SIZE ) + if ( numberOfBytesInCommBuffer( CAN_OUT_BUFFERS[ i ] ) >= CAN_MESSAGE_PAYLOAD_SIZE ) { - result = CAN_OUT_BUFFERS[i]; - break; // found highest priority packet to transmit - we're done + result = CAN_OUT_BUFFERS[ i ]; + break; // Found highest priority packet to transmit - we are done } } return result; } -/************************************************************************* - * @brief transmitNextCANPacket - * The transmitNextCANPacket function gets the next 8 byte packet and initiates \n +/*********************************************************************//** + * @brief + * The transmitNextCANPacket function gets the next 8 byte packet and initiates * a CAN transmit on the appropriate CAN channel. - * @details - * Inputs : Output CAN Comm Buffers - * Outputs : CAN packet transmit initiated. - * @param msg : none - * @return none + * @details Inputs: Output CAN Comm Buffers + * @details Outputs: CAN packet transmit initiated. + * @return number of bytes transmitted *************************************************************************/ -static void transmitNextCANPacket( void ) +static U32 transmitNextCANPacket( void ) { + U32 result = 0; COMM_BUFFER_T buffer = findNextHighestPriorityCANPacketToTransmit(); - // if a buffer is found with a packet to transmit, get packet from buffer and transmit it + // If a buffer is found with a packet to transmit, get packet from buffer and transmit it if ( buffer != COMM_BUFFER_NOT_USED ) { - U08 data[CAN_MESSAGE_CARGO_SIZE]; - U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_CARGO_SIZE ); + U08 data[ CAN_MESSAGE_PAYLOAD_SIZE ]; + U32 dataSize = getFromCommBuffer( buffer, data, CAN_MESSAGE_PAYLOAD_SIZE ); CAN_MESSAGE_BOX_T mBox = buffer; // CAN message boxes and comm buffers are aligned - // if there's another CAN packet to send, send it - if ( dataSize == CAN_MESSAGE_CARGO_SIZE ) + // If there is another CAN packet to send, send it + if ( dataSize == CAN_MESSAGE_PAYLOAD_SIZE ) { - canTransmit( canREG1, mBox, data ); + // We are transmitting another packet - signal transmitter is busy + signalCANXmitsInitiated(); + // Remember packet data being transmitted here in case transmission fails and we need to re-send + memcpy( lastCANPacketSent, data, CAN_MESSAGE_PAYLOAD_SIZE ); + lastCANPacketSentChannel = mBox; + lastCANPacketSentTimeStamp = getMSTimerCount(); + if ( 0 != canTransmit( canREG1, mBox, data ) ) + { + result = CAN_MESSAGE_PAYLOAD_SIZE; + } + else + { + signalCANXmitsCompleted(); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_SYSTEM_CMMM_CAN_TRANSMIT_REJECTED, (U32)mBox ) + } } + else + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_SYSTEM_COMM_INVALID_FRAME_SIZE, ((U32)buffer << 16) | dataSize ) + } } -} -/************************************************************************* - * @brief transmitNextUARTPacket - * The transmitNextUARTPacket function sets up and initiates a DMA transmit \n - * of the next packet pending transmit (if any) via UART. - * @details - * Inputs : Output UART Comm Buffer(s) - * Outputs : UART DMA transmit initiated. - * @param msg : none - * @return none - *************************************************************************/ -static void transmitNextUARTPacket( void ) -{ - U32 dataSize = getFromCommBuffer( COMM_BUFFER_OUT_UART_PC, pcXmitPacket, PC_MESSAGE_PACKET_SIZE ); - - // if there's another UART packet to send, send it - if ( dataSize == PC_MESSAGE_PACKET_SIZE ) - { - dmaSetCtrlPacket( DMA_CH3, pcDMAXmitControlRecord ); - dmaSetChEnable( DMA_CH3, DMA_HW ); - setSCI1DMATransmitInterrupt(); - } + return result; } @@ -432,226 +522,645 @@ *************************************************************************/ -/************************************************************************* - * @brief processIncomingData - * The processIncomingData function parses out messages from the Input \n +/*********************************************************************//** + * @brief + * The processIncomingData function parses out messages from the Input * Comm Buffers and adds them to the Received Message Queue. - * @details - * Inputs : Input Comm Buffers - * Outputs : Parsed message(s) added to Received Message Queue - * @param msg : none + * @details Inputs: Input Comm Buffers + * @details Outputs: Parsed message(s) added to Received Message Queue * @return none *************************************************************************/ static void processIncomingData( void ) { - U08 data[sizeof(MESSAGE_WRAPPER_T)+1]; + U08 data[ 512 ]; // Message work space U32 i; + BOOL badCRCDetected = FALSE; - // queue any received messages + // Queue any received messages for ( i = 0; i < NUM_OF_MSG_IN_BUFFERS; i++ ) { - BOOL messagesInBuffer = TRUE; // assume true at first to get into while loop + BOOL messagesInBuffer = TRUE; // Assume true at first to get into while loop while ( TRUE == messagesInBuffer ) { U32 numOfBytesInBuffer; - // assume false so we don't get stuck in loop - only set to true if we find another complete message in buffer + // Assume false so we do not get stuck in loop. Set to true only if we find another complete message in buffer messagesInBuffer = FALSE; - // since messages can have 8-byte alignment padding left unconsumed by last get, get padding out of buffer - consumeBufferPaddingBeforeSync( MSG_IN_BUFFERS[i] ); - // do we have enough bytes in buffer for smallest message? - numOfBytesInBuffer = numberOfBytesInCommBuffer( MSG_IN_BUFFERS[i] ); + // Since messages can have 8-byte alignment padding left unconsumed by last get, get padding out of buffer + consumeBufferPaddingBeforeSync( MSG_IN_BUFFERS[ i ] ); + // Do we have enough bytes in buffer for smallest message? + numOfBytesInBuffer = numberOfBytesInCommBuffer( MSG_IN_BUFFERS[ i ] ); if ( numOfBytesInBuffer >= MESSAGE_OVERHEAD_SIZE ) - { // peek at minimum of all bytes available or max message size (+1 for sync byte) - U32 bytesPeeked = peekFromCommBuffer( MSG_IN_BUFFERS[i], data, MIN(numOfBytesInBuffer,sizeof(MESSAGE_WRAPPER_T)+1) ); - U32 msgSize = parseMessageFromBuffer( data, bytesPeeked ); + { // Peek at minimum of all bytes available or max message size (+1 for sync byte) + U32 bytesPeeked = peekFromCommBuffer( MSG_IN_BUFFERS[ i ], data, MIN( numOfBytesInBuffer, sizeof( MESSAGE_WRAPPER_T ) + 1 ) ); + S32 msgSize = parseMessageFromBuffer( data, bytesPeeked ); + + hdIsOnlyCANNode = FALSE; // Since we are getting a message, this indicates we are not the only node on the CAN bus + canXmitRetryCtr = 0; - if ( msgSize > 0 ) + if ( msgSize > 0 ) // Valid, complete message found? { - // consume message (+sync byte) - msgSize = getFromCommBuffer( MSG_IN_BUFFERS[i], data, msgSize+1 ); - // if message data is at least minimum size, convert received message data to a message and add to message queue - if ( msgSize > MESSAGE_OVERHEAD_SIZE ) - { - MESSAGE_WRAPPER_T rcvMsg; - U08 *dataPtr = data+1; // skip over sync byte + MESSAGE_WRAPPER_T rcvMsg; + U08 *dataPtr = data+1; // Skip over sync byte - messagesInBuffer = TRUE; - // blank the new message record - blankMessageInWrapper( &rcvMsg ); - // copy message header portion of message data to the new message - memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof(MESSAGE_HEADER_T) ); - dataPtr += sizeof(MESSAGE_HEADER_T); - // copy message cargo portion of message data to the new message - memcpy( &(rcvMsg.msg.cargo), dataPtr, rcvMsg.msg.hdr.cargoLen ); - dataPtr += rcvMsg.msg.hdr.cargoLen; - // copy CRC portion of message data to the new message - rcvMsg.crc = *dataPtr; - // add new message to queue for later processing - addToMsgQueue( MSG_Q_IN, &rcvMsg ); - } // message is at least as large as minimum size - } // looks like there is a complete message in the comm buffer - } // enough data left in comm buffer to possibly be a complete message - } // while loop to get all complete messages for each comm buffer - } // for loop to check all comm buffers for messages + // Consume message (+sync byte) + msgSize = getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, msgSize + 1 ); + // Convert received message data to a message and add to message queue + messagesInBuffer = TRUE; // Keep processing this buffer + // Blank the new message record + blankMessageInWrapper( &rcvMsg ); + // Copy message header portion of message data to the new message + memcpy( &(rcvMsg.msg.hdr), dataPtr, sizeof(MESSAGE_HEADER_T) ); + dataPtr += sizeof(MESSAGE_HEADER_T); + // Copy message payload portion of message data to the new message + memcpy( &(rcvMsg.msg.payload), dataPtr, rcvMsg.msg.hdr.payloadLen ); + dataPtr += rcvMsg.msg.hdr.payloadLen; + // Copy CRC portion of message data to the new message + rcvMsg.crc = *dataPtr; + // Add new message to queue for later processing + addToMsgQueue( MSG_Q_IN, &rcvMsg ); + // If message from DG broadcast channel, update DG comm status + if ( COMM_BUFFER_IN_CAN_DG_BROADCAST == MSG_IN_BUFFERS[ i ] ) + { + dgIsCommunicating = TRUE; + timeOfLastDGCheckIn = getMSTimerCount(); + } + } + else if ( -1 == msgSize ) // Candidate message with bad CRC found? + { + badCRCDetected = TRUE; +#ifdef EMC_TEST_BUILD + badCANCount++; + broadcastCANErrorCount( badCANCount ); +#endif + getFromCommBuffer( MSG_IN_BUFFERS[ i ], data, 1 ); // Consume sync byte so we can re-sync + messagesInBuffer = TRUE; // Keep processing this buffer + } // Looks like there is a complete message in the comm buffer + } // Enough data left in comm buffer to possibly be a complete message + } // While loop to get all complete messages for each comm buffer + } // For loop to check all comm buffers for messages + + // If any bad CRCs detected, see if too many + if ( TRUE == badCRCDetected ) + { + checkTooManyBadMsgCRCs(); + } } -/************************************************************************* - * @brief consumeBufferPaddingBeforeSync - * The consumeBufferPaddingBeforeSync function removes any bytes in a given \n +/*********************************************************************//** + * @brief + * The consumeBufferPaddingBeforeSync function removes any bytes in a given * buffer that lie before a sync byte. - * @details - * Inputs : none - * Outputs : none - * @param msg : buffer : the comm buffer to process + * @details Inputs: none + * @details Outputs: Any padding at front of buffer is consumed. + * @param buffer the comm buffer to process * @return none *************************************************************************/ static void consumeBufferPaddingBeforeSync( COMM_BUFFER_T buffer ) { U08 data; U32 numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); - // consume bytes out of buffer 1 at a time until we find the sync byte or it's empty + // Consume bytes out of buffer 1 at a time until we find the sync byte or it is empty while ( numOfBytesInBuffer > 0 ) { peekFromCommBuffer( buffer, &data, 1 ); if ( MESSAGE_SYNC_BYTE == data ) { - break; // we found a sync - we're done + break; // We found a sync - we are done } - else // not a sync byte, so consume it + else // Not a sync byte, so consume it { getFromCommBuffer( buffer, &data, 1 ); numOfBytesInBuffer = numberOfBytesInCommBuffer( buffer ); } } } -/************************************************************************* - * @brief parseMessageFromBuffer - * The parseMessageFromBuffer function looks for a complete message in a \n +/*********************************************************************//** + * @brief + * The parseMessageFromBuffer function looks for a complete message in a * given buffer. If a message is found, its size is returned. - * @details - * Inputs : none - * Outputs : none - * @param data : pointer to byte array to search for a message - * @param len : # of bytes in the data to search - * @return size of message if found, zero if no complete message found. + * @details Inputs: none + * @details Outputs: none + * @param data pointer to byte array to search for a message + * @param len number of bytes in the data to search + * @return size of message if found, zero if no complete message found, + * -1 if message found but CRC fails. *************************************************************************/ -static U32 parseMessageFromBuffer( U08 *data, U32 len ) +static S32 parseMessageFromBuffer( U08 *data, U32 len ) { U32 i; - U32 cargoSize; + U32 payloadSize; U32 msgSize; - U32 result = 0; + S32 result = 0; for ( i = 0; i < len; i++ ) { - // find sync byte - if ( MESSAGE_SYNC_BYTE == data[i] ) + // Find sync byte + if ( MESSAGE_SYNC_BYTE == data[ i ] ) { - U32 pos = i + 1; // skip past sync byte implemented + U32 pos = i + 1; // Skip past sync byte implemented U32 remSize = len - pos; - // if a minimum sized msg would fit in remaining, continue + // If a minimum sized msg would fit in remaining, continue if ( remSize >= MESSAGE_OVERHEAD_SIZE ) { - cargoSize = data[pos+sizeof(U16)]; - msgSize = MESSAGE_OVERHEAD_SIZE + cargoSize; - // we now know the size of the message - we can now know if full message is contained in buffer + payloadSize = data[ pos + sizeof(MESSAGE_HEADER_T) - sizeof(U08) ]; + msgSize = MESSAGE_OVERHEAD_SIZE + payloadSize; + // We now know the size of the message - we can now know if full message is contained in buffer if ( msgSize <= remSize ) - { - result = msgSize; // we found a complete message of this size + { // Check CRC to make sure it is a valid message + if ( data[i+msgSize] == crc8( &data[pos], msgSize - 1 ) ) + { + result = msgSize; // We found a complete, valid message of this size + } + else // CRC failed + { + result = -1; // We found a complete, invalid message + } } } - break; } } return result; } -/************************************************************************* - * @brief processReceivedMessages - * The processReceivedMessages function processes any messages in the \n +/*********************************************************************//** + * @brief + * The processReceivedMessages function processes any messages in the * received message queues. - * @details - * Inputs : Received Message Queues - * Outputs : Message(s) processed. - * @param msg : none + * @details Inputs: Received Message Queues + * @details Outputs: Message(s) processed. * @return none *************************************************************************/ static void processReceivedMessages( void ) { - BOOL isThereMsgRcvd = TRUE; // assume TRUE at first to get into while loop + BOOL isThereMsgRcvd = TRUE; // Assume TRUE at first to get into while loop MESSAGE_WRAPPER_T message; while ( TRUE == isThereMsgRcvd ) { - // see if any messages received + // See if any messages received isThereMsgRcvd = getFromMsgQueue( MSG_Q_IN, &message ); if ( TRUE == isThereMsgRcvd ) - { - // TODO - check CRC before processing a message - if ( 1 ) + { // CRC should be good because we checked it during parsing before adding to queue - but check it again for good measure + if ( message.crc == crc8( (U08*)(&message), sizeof(MESSAGE_HEADER_T) + message.msg.hdr.payloadLen ) ) { - processReceivedMessage( &message.msg ); + // If ACK, mark pending message ACK'd + if ( MSG_ID_ACK_MESSAGE_THAT_REQUIRES_ACK == message.msg.hdr.msgID ) + { + matchACKtoPendingACKList( message.msg.hdr.seqNo ); + } + else + { + // If received message requires ACK, queue one up + if ( message.msg.hdr.seqNo < 0 ) + { + sendACKMsg( &message.msg ); + } + // Process the received message + processReceivedMessage( &message.msg ); + } } else // CRC failed { - // TODO - probably wouldn't want to fault on this. ignore? +#ifdef EMC_TEST_BUILD + badCANCount++; + broadcastCANErrorCount( badCANCount ); +#endif + checkTooManyBadMsgCRCs(); } } } +} - // TODO - process UART (script) messages too +/*********************************************************************//** + * @brief + * The checkForCommTimeouts function checks for sub-system communication + * timeout errors. + * @details Inputs: timeOfLastDGCheckIn, timeOfLastUICheckIn + * @details Outputs: possibly a comm t/o alarm + * @return none + *************************************************************************/ +static void checkForCommTimeouts( void ) +{ + if ( TRUE == uiDidCommunicate ) + { + if ( TRUE == didTimeout( timeOfLastUICheckIn, UI_COMM_TIMEOUT_IN_MS ) ) + { +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_UI_COMM_ALARMS ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + activateAlarmNoData( ALARM_ID_UI_COMM_TIMEOUT ); + } + } + + if ( TRUE == didTimeout( timeOfLastDGCheckIn, DG_COMM_TIMEOUT_IN_MS ) ) + { +#ifndef RUN_WITHOUT_DG + activateAlarmNoData( ALARM_ID_DG_COMM_TIMEOUT ); + dgIsCommunicating = FALSE; +#endif + } + } } -/************************************************************************* - * @brief processReceivedMessage +/*********************************************************************//** + * @brief + * The checkTooManyBadMsgCRCs function checks for too many bad message CRCs + * within a set period of time. Assumed function is being called when a new + * bad CRC is detected so a new bad CRC will be added to the list. + * @details Inputs: badCRCTimeStamps[], badCRCListIdx, badCRCListCount + * @details Outputs: possibly a "too many bad CRCs" alarm + * @return none + *************************************************************************/ +static void checkTooManyBadMsgCRCs( void ) +{ + if ( TRUE == incTimeWindowedCount( TIME_WINDOWED_COUNT_BAD_MSG_CRC ) ) + { + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_COMM_TOO_MANY_BAD_CRCS, (U32)ALARM_SOURCE_HD ); + } +} + +/*********************************************************************//** + * @brief + * The addMsgToPendingACKList function adds a given message to the pending + * ACK list. Messages in this list will require receipt of an ACK message + * for this particular message within a limited time. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @param msg pointer to msg within the message data + * @param msgData pointer to message data to add to pending ACK list + * @param len number of bytes of message data + * @return TRUE if message added successfully, FALSE if not + *************************************************************************/ +BOOL addMsgToPendingACKList( MESSAGE_T *msg, COMM_BUFFER_T channel, U08 *msgData, U32 len ) +{ + BOOL result = FALSE; + U32 i; + + // Find first open slot in pending ACK list and add given msg data to it + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + _disable_IRQ(); // Slot selection needs interrupt protection + if ( FALSE == pendingAckList[ i ].used ) + { + S16 seqNo = msg->hdr.seqNo * -1; // Remove ACK bit from seq # + + pendingAckList[ i ].used = TRUE; + _enable_IRQ(); + pendingAckList[ i ].seqNo = seqNo; + pendingAckList[ i ].channel = channel; + pendingAckList[ i ].timeStamp = getMSTimerCount(); + pendingAckList[ i ].retries = MSG_NOT_ACKED_MAX_RETRIES; + pendingAckList[ i ].msgSize = len; + memcpy( (U08*)pendingAckList[ i ].msg, msgData, len ); + result = TRUE; + break; + } + else + { + _enable_IRQ(); + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The matchACKtoPendingACKList function searches the pending ACK list to + * see if the sequence # from a received ACK msg matches any. If found, + * the list entry is removed. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @param seqNo sequence # to match to an entry in the list + * @return TRUE if a match was found, FALSE if not + *************************************************************************/ +static BOOL matchACKtoPendingACKList( S16 seqNo ) +{ + BOOL result = FALSE; + U32 i; + + // Find match + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { + if ( ( TRUE == pendingAckList[ i ].used ) && ( pendingAckList[ i ].seqNo == seqNo ) ) + { // Remove message pending ACK from list + pendingAckList[ i ].used = FALSE; + result = TRUE; + break; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The checkPendingACKList function searches the pending ACK list to + * see if any have expired. Any such messages will be queued for retransmission + * and if max retries reached a fault is triggered. + * @details Inputs: pendingAckList[] + * @details Outputs: pendingAckList[] + * @return none + *************************************************************************/ +static void checkPendingACKList( void ) +{ + U32 i; + + // Find expired messages pending ACK + for ( i = 0; i < PENDING_ACK_LIST_SIZE; i++ ) + { // Pending ACK expired? + U32 timeoutPeriod = MSG_NOT_ACKED_TIMEOUT_MS; // set the timeout as default + + if ( MODE_INIT == getCurrentOperationMode() ) + { // change it to longer timeout if the HD is in INIT state + timeoutPeriod = MSG_NOT_ACKED_TIMEOUT_MS_INIT; + } + if ( ( TRUE == pendingAckList[ i ].used ) && ( TRUE == didTimeout( pendingAckList[ i ].timeStamp, timeoutPeriod ) ) ) + { // If retries left, reset and resend pending message + if ( pendingAckList[ i ].retries > 0 ) + { // Re-queue message for transmit + pendingAckList[ i ].retries--; + pendingAckList[ i ].timeStamp = getMSTimerCount(); + addToCommBuffer( pendingAckList[ i ].channel, (U08*)pendingAckList[ i ].msg, pendingAckList[ i ].msgSize ); + } + // If no retries left, alarm + else + { + U16 msgID; + + memcpy( &msgID, (U08*)&pendingAckList[ i ].msg[ sizeof( U08 ) + sizeof( U16) ], sizeof( U16 ) ); + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_CAN_MESSAGE_NOT_ACKED, (U32)msgID ); + pendingAckList[ i ].used = FALSE; // Take pending message off of list + } + } + } +} + +/*********************************************************************//** + * @brief * The processReceivedMessage function processes a given message. - * @details - * Inputs : none - * Outputs : message processed - * @param msg : + * @details Inputs: none + * @details Outputs: message processed + * @param message pointer to message to process * @return none *************************************************************************/ static void processReceivedMessage( MESSAGE_T *message ) { U16 msgID = message->hdr.msgID; + // Handle any messages from other sub-systems switch ( msgID ) { case MSG_ID_OFF_BUTTON_PRESS: handleOffButtonConfirmMsgFromUI( message ); -#ifdef RM46_EVAL_BOARD_TARGET - setUserLED( TRUE ); -#endif break; + case MSG_ID_ALARM_TRIGGERED: + handleAlarmTriggered( message ); + break; + + case MSG_ID_ALARM_CONDITION_CLEARED: + handleAlarmCleared( message ); + break; + + case MSG_ID_UI_ALARM_USER_ACTION: + handleAlarmUserAction( message ); + break; + + case MSG_ID_DG_CHECK_IN: + handleDGCheckIn( message ); + break; + case MSG_ID_UI_CHECK_IN: + handleUICheckIn( message ); + break; - case MSG_ID_TESTER_LOGIN_REQUEST: - handleTesterLogInRequest( message ); + case MSG_ID_LOAD_CELL_READINGS: + handleLoadCellReadingsFromDG( message ); break; - default: - // TODO - unrecognized message ID received - ignore + case MSG_ID_USER_UF_PAUSE_RESUME_REQUEST: + handleUFPauseResumeRequest( message ); break; + + case MSG_ID_USER_UF_SETTINGS_CHANGE_REQUEST: + handleChangeUFSettingsRequest( message ); + break; + + case MSG_ID_USER_SALINE_BOLUS_REQUEST: + handleSalineBolusRequest( message ); + break; + + case MSG_ID_USER_CONFIRM_UF_SETTINGS_CHANGE: + handleChangeUFSettingsConfirmation( message ); + break; + + case MSG_ID_USER_TREATMENT_TIME_CHANGE_REQUEST: + handleChangeTreatmentDurationRequest( message ); + break; + + case MSG_ID_USER_BLOOD_DIAL_RATE_CHANGE_REQUEST: + handleChangeBloodDialysateRateChangeRequest( message ); + break; + + case MSG_ID_REQUEST_FW_VERSIONS: + handleFWVersionRequest( message ); + handleHDSerialNumberRequest(); + break; + + case MSG_ID_DG_VERSION: + handleDGVersionResponse( message ); + break; + + case MSG_ID_DG_TEMPERATURE_DATA: + handleDGTemperatureData( message ); + break; + + case MSG_ID_DG_DIALYSATE_FLOW_METER_DATA: + handleDialysateFlowData( message ); + break; + + case MSG_ID_DG_OP_MODE: + handleDGOpMode( message ); + break; + + case MSG_ID_DG_RESERVOIRS_DATA: + handleDGReservoirData( message ); + break; + + case MSG_ID_USER_REQUEST_ALARM_SILENCE: + handleUIAlarmSilenceRequest( message ); + break; + + case MSG_ID_UI_NEW_TREATMENT_PARAMS: + handleTreatmentParametersFromUI( message ); + break; + + case MSG_ID_UI_INITIATE_TREATMENT_REQUEST: + handleInitiateTreatmentRequest( message ); + break; + + case MSG_ID_UI_USER_CONFIRM_TREATMENT_PARAMS: + handleUIUserConfirmTreatmentParameters( message ); + break; + + case MSG_ID_UI_PRESSURE_LIMITS_CHANGE_REQUEST: + handleChangePressureLimitsRequest( message ); + break; + + case MSG_ID_UI_HEPARIN_PAUSE_RESUME_REQUEST: + handleHeparinCommandRequest( message ); + break; + + case MSG_ID_UI_SET_ALARM_AUDIO_VOLUME_LEVEL_CMD: + handleAlarmAudioVolumeSetCmd( message ); + break; + + case MSG_ID_UI_SET_UF_VOLUME_PARAMETER: + handleUFVolumeSetRequest( message ); + break; + + case MSG_ID_UI_SAMPLE_WATER_CMD: + handleSampleWaterCmd( message ); + break; + + case MSG_ID_UI_SAMPLE_WATER_RESULT: + handleSampleWaterResult( message ); + break; + + case MSG_ID_UI_CONSUMABLE_INSTALL_CONFIRM: + handleConsumableInstallConfirm( message ); + break; + + case MSG_ID_UI_INSTALLATION_CONFIRM: + handleInstallationConfirm( message ); + break; + + case MSG_ID_UI_START_PRIME_REQUEST: + handleStartPrimeCmd( message ); + break; + + case MSG_ID_UI_PATIENT_CONNECTION_BEGIN_REQUEST: + handleContinueToTreatmentCmd( message ); + break; + + case MSG_ID_UI_PATIENT_CONNECTION_CONFIRM: + handlePatientConnectionConfirmCmd( message ); + break; + + case MSG_ID_UI_START_TREATMENT_REQUEST: + handleStartTreatmentRequest( message ); + break; + + case MSG_ID_UI_RINSEBACK_CMD: + handlRinsebackCmd( message ); + break; + + case MSG_ID_UI_RECIRC_CMD: + handleTreatmentRecircCmd( message ); + break; + + case MSG_ID_UI_TX_END_CMD: + handleTreatmentEndCmd( message ); + break; + + case MSG_ID_UI_PATIENT_DISCONNECTION_CONFIRM: + handlePatientDisconnectionConfirmCmd( message ); + break; + + case MSG_ID_UI_DISPOSABLE_REMOVAL_CONFIRM: + handleDisposableRemovalConfirmCmd( message ); + break; + + case MSG_ID_UI_TREATMENT_LOG_DATA_REQUEST: + handleUITreatmentLogDataRequest( message ); + break; + + case MSG_ID_UI_DISINFECT_REQUEST: + handleUIDisinfectRequest( message ); + break; + + case MSG_ID_DG_COMMAND_RESPONSE: + handleDGCmdResp( message ); + break; + + case MSG_ID_DG_FLUSH_DATA: + handleFlushUIStateReadingFromDG( message ); + break; + + case MSG_ID_DG_HEAT_DISINFECT_DATA: + handleHeatDisinfectUIStateReadingFromDG( message ); + break; + + case MSG_ID_DG_CHEM_DISINFECT_DATA: + handleChemDisinfectUIStateReadingFromDG( message ); + break; + + case MSG_ID_UI_HD_SET_RTC_REQUEST: + handleUIClockSyncRequest( message ); + break; + + case MSG_ID_DG_POST_FINAL_TEST_RESULT: + handleDGPOSTFinalResult( message ); + break; + + case MSG_ID_UI_POST_FINAL_TEST_RESULT: + handleUIPOSTFinalResult( message ); + break; + + case MSG_ID_HD_UI_VERSION_INFO_RESPONSE: + handleUIVersionResponse( message ); + break; + + case MSG_ID_UI_ACTIVE_ALARMS_LIST_REQUEST: + handleUIActiveAlarmsListRequest( message ); + break; + + case MSG_ID_HD_SET_STANDBY_DISINFECT_SUB_MODE_REQUEST: + handleSetHDStandbyDisinfectSubmodeRequest( message ); + break; + + case MSG_ID_UI_REQUEST_SERVICE_INFO: + handleHDServiceScheduleRequest( message ); + break; + + case MSG_ID_REQUEST_HD_USAGE_INFO: + handleHDUsageInfoRequest( message ); + break; + + case MSG_ID_DG_CONCENTRATE_MIXING_RATIOS_DATA: + handleDGMixingRatios( message ); + break; + + case MSG_ID_UI_REQUEST_SERVICE_MODE: + handleUIServiceModeRequest( message ); + break; + + // NOTE: this always must be the last case + case MSG_ID_TESTER_LOGIN_REQUEST: + handleTesterLogInRequest( message ); + break; + + // The default cannot be reached in VectorCAST since the cases are run in a for loop + default: + // Un-recognized or un-handled message ID received - ignore + break; } - // handle any test messages if tester has logged in successfully - if ( ( msgID > MSG_ID_FIRST_TESTER_MESSAGE ) && ( TRUE == isTestingActivated() ) ) + // Handle any test messages if tester has logged in successfully + if ( ( msgID > MSG_ID_FIRST_TESTER_MESSAGE ) && ( msgID <= END_OF_MSG_IDS ) && ( TRUE == isTestingActivated() ) ) { switch ( msgID ) { - case MSG_ID_HD_MESSAGE: - handleTestHDMessageRequest( message ); - break; - case MSG_ID_OFF_BUTTON_STATE_OVERRIDE: handleTestOffButtonStateOverrideRequest( message ); break; @@ -668,9 +1177,499 @@ handleTestWatchdogCheckInStateOverrideRequest( message ); break; - default: - // TODO - unrecognized message ID received - ignore + case MSG_ID_ALARM_STATE_OVERRIDE: + handleTestAlarmStateOverrideRequest( message ); break; + + case MSG_ID_ALARM_TIME_OVERRIDE: + handleTestAlarmTimeOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_FLOW_SET_PT_OVERRIDE: + handleTestBloodFlowSetPointOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_FLOW_MEAS_OVERRIDE: + handleTestBloodFlowMeasuredOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_PUMP_MC_MEAS_SPEED_OVERRIDE: + handleTestBloodPumpMCMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_PUMP_MC_MEAS_CURR_OVERRIDE: + handleTestBloodPumpMCMeasuredCurrentOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_FLOW_SEND_INTERVAL_OVERRIDE: + handleTestBloodFlowBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_TREATMENT_TIME_REMAINING_OVERRIDE: + handleTestTreatmentTimeRemainingOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_PUMP_MEAS_SPEED_OVERRIDE: + handleTestBloodPumpMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_BLOOD_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: + handleTestBloodPumpRotorMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_FLOW_SET_PT_OVERRIDE: + handleTestDialInFlowSetPointOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_FLOW_MEAS_OVERRIDE: + handleTestDialInFlowMeasuredOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_MC_MEAS_SPEED_OVERRIDE: + handleTestDialInPumpMCMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_MC_MEAS_CURR_OVERRIDE: + handleTestDialInPumpMCMeasuredCurrentOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_FLOW_SEND_INTERVAL_OVERRIDE: + handleTestDialInFlowBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_MEAS_SPEED_OVERRIDE: + handleTestDialInPumpMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: + handleTestDialInPumpRotorMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_PRESSURE_ARTERIAL_OVERRIDE: + handleTestArterialPressureOverrideRequest( message ); + break; + + case MSG_ID_PRESSURE_VENOUS_OVERRIDE: + handleTestVenousPressureOverrideRequest( message ); + break; + + case MSG_ID_OCCLUSION_BLOOD_PUMP_OVERRIDE: + handleTestBloodPumpOcclusionOverrideRequest( message ); + break; + + case MSG_ID_PRES_OCCL_SEND_INTERVAL_OVERRIDE: + handleTestPresOcclBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_SET_RTC_DATE_TIME: + handleSetRTCTimestamp( message ); + break; + + case MSG_ID_DIAL_OUT_FLOW_SEND_INTERVAL_OVERRIDE: + handleTestDialOutFlowBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_UF_REF_VOLUME_OVERRIDE: + handleTestDialOutUFReferenceVolumeOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_UF_MEAS_VOLUME_OVERRIDE: + handleTestDialOutUFMeasuredVolumeOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_MC_MEAS_SPEED_OVERRIDE: + handleTestDialOutPumpMCMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_MC_MEAS_CURR_OVERRIDE: + handleTestDialOutPumpMCMeasuredCurrentOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_MEAS_SPEED_OVERRIDE: + handleTestDialOutPumpMeasuredSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_MEAS_ROTOR_SPEED_OVERRIDE: + handleTestDialOutPumpMeasuredRotorSpeedOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_LOAD_CELL_WEIGHT_OVERRIDE: + handleTestDialOutLoadCellWeightOverrideRequest( message ); + break; + + case MSG_ID_HD_SAFETY_SHUTDOWN_OVERRIDE: + handleTestHDSafetyShutdownOverrideRequest( message ); + break; + + case MSG_ID_HD_ACCEL_OVERRIDE: + handleTestHDAccelOverrideRequest( message ); + break; + + case MSG_ID_HD_ACCEL_MAX_OVERRIDE: + handleTestHDAccelMaxOverrideRequest( message ); + break; + + case MSG_ID_HD_ACCEL_SEND_INTERVAL_OVERRIDE: + handleTestHDAccelBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_DIAL_OUT_FLOW_SET_PT_OVERRIDE: + handleTestDialOutFlowSetPointOverrideRequest( message ); + break; + + case MSG_ID_HD_SET_PARAMETER_TREATMENT_PARAMETER: + handleTestSetTreatmentParameter( message ); + break; + + case MSG_ID_VALVES_STATES_PUBLISH_INTERVAL_OVERRIDE: + handleTestHDValvesBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_VALVES_HOME: + handleHomeHDValve( message ); + break; + + case MSG_ID_HD_VALVES_SET_AIR_TRAP_VALVE: + handleSetAirTrapValve( message ); + break; + + case MSG_ID_HD_VALVES_POSITION_OVERRIDE: + handleSetHDValvePositionOverrideRequest( message ); + break; + +#ifdef DEBUG_ENABLED + case MSG_ID_HD_VALVES_SET_PWM_OVERRIDE: + handleSetHDValvePWMOverrideRequest( message ); + break; +#endif + + case MSG_ID_HD_AIR_TRAP_SEND_INTERVAL_OVERRIDE: + handleSetAirTrapBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_AIR_TRAP_LEVEL_SENSOR_OVERRIDE: + handleSetAirTrapLevelSensorOverrideRequest( message ); + break; + + case MSG_ID_HD_SOFTWARE_RESET_REQUEST: + handleHDSoftwareResetRequest( message ); + break; + + case MSG_ID_BLOOD_ROTOR_COUNT_OVERRIDE: + handleHDBloodPumpRotorCountOverrideRequest( message ); + break; + + case MSG_ID_SET_ARTERIAL_PRESSURE_OFFSET: + handleHDSetArterialPressureOffsetRequest( message ); + break; + + case MSG_ID_BLOOD_PUMP_HOME_CMD: + handleTestBloodPumpHomeRequest( message ); + break; + + case MSG_ID_DIAL_IN_PUMP_HOME_CMD: + handleTestDialInPumpHomeRequest( message ); + break; + + case MSG_ID_DIAL_OUT_PUMP_HOME_CMD: + handleTestDialOutPumpHomeRequest( message ); + break; + + case MSG_ID_SUPER_CLEAR_ALARMS_CMD: + handleTestSuperClearAlarmsRequest( message ); + break; + + case MSG_ID_HD_SET_OP_MODE_REQUEST: + handleTestSetOpModeRequest( message ); + break; + + case MSG_ID_HD_FLUID_LEAK_SEND_INTERVAL_OVERRIDE: + handleSetFluidLeakBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_FLUID_LEAK_STATE_OVERRIDE: + handleSetFluidLeakStateOverrideRequest( message ); + break; + + case MSG_ID_HD_BLOOD_LEAK_DATA_SEND_INTERVAL_OVERRIDE: + handleSetBloodLeakDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_BLOOD_LEAK_STATUS_OVERRIDE: + handleSetBloodLeakStatusOverrideRequest( message ); + break; + + case MSG_ID_HD_BLOOD_LEAK_ZERO_REQUEST: + handleBloodLeakZeroRequest( message ); + break; + + case MSG_ID_HD_BUBBLES_DATA_SEND_INTERVAL_OVERRIDE: + handleSetBubblesDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_BUBBLE_STATUS_OVERRIDE: + handleSetBubbleStatusOverrideRequest( message ); + break; + + case MSG_ID_HD_BUBBLE_SELF_TEST_REQUEST: + handleBubbleSelfTestRequest( message ); + break; + + case MSG_ID_HD_BLOOD_PRIME_VOLUME_OVERRIDE: + handleBloodPrimeVolumeOverrideRequest( message ); + break; + + case MSG_ID_HD_SWITCHES_STATUS_OVERRIDE: + handleSetSwitchesStatusOverrideRequest( message ); + break; + + case MSG_ID_HD_SWITCHES_PUBLISH_INTERVAL_OVERRIDE: + handleTestSwitchesPublishIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_BATTERY_REMAINING_PERCENT_OVERRIDE: + handleBatteryRemainingPercentOverrideRequest( message ); + break; + + case MSG_ID_HD_RINSEBACK_VOLUME_OVERRIDE: + handleRinsebackVolumeOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_SEND_INTERVAL_OVERRIDE: + handleTestSyringePumpDataBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_OPERATION_REQUEST: + handleTestSyringePumpOperationRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_RATE_OVERRIDE: + handleTestSyringePumpMeasuredRateOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_FORCE_OVERRIDE: + handleTestSyringePumpMeasuredForceOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_SYRINGE_DETECT_OVERRIDE: + handleTestSyringePumpMeasuredSyringeDetectOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_HOME_OVERRIDE: + handleTestSyringePumpMeasuredHomeOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_POSITION_OVERRIDE: + handleTestSyringePumpMeasuredPositionOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_MEASURED_VOLUME_OVERRIDE: + handleTestSyringePumpMeasuredVolumeOverrideRequest( message ); + break; + + case MSG_ID_HD_VALVES_CURRENT_OVERRIDE: + handleTestValvesCurrentOverrideRequest( message ); + break; + + case MSG_ID_HD_VALVES_POSITION_COUNT_OVERRIDE: + handleTestValvesPositionCountOverrideRequest( message ); + break; + + case MSG_ID_HD_MONITORED_VOLTAGES_SEND_INTERVAL_OVERRIDE: + handleTestMonitoredVoltagesSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_MONITORED_VOLTAGES_OVERRIDE: + handleTestMonitoredVoltageOverrideRequest( message ); + break; + + case MSG_ID_HD_ALARM_INFO_SEND_INTERVAL_OVERRIDE: + handleTestAlarmInfoSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_ALARM_AUDIO_VOLUME_LEVEL_OVERRIDE: + handleTestAlarmAudioVolumeOverrideRequest( message ); + break; + + case MSG_ID_HD_ALARM_AUDIO_CURRENT_HG_OVERRIDE: + handleTestAlarmAudioCurrentHgOverrideRequest( message ); + break; + + case MSG_ID_HD_ALARM_AUDIO_CURRENT_LG_OVERRIDE: + handleTestAlarmAudioCurrentLgOverrideRequest( message ); + break; + + case MSG_ID_HD_ALARM_BACKUP_AUDIO_CURRENT_OVERRIDE: + handleTestAlarmBackupAudioCurrentOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_STATUS_OVERRIDE: + handleTestSyringePumpStatusOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_ENCODER_STATUS_OVERRIDE: + handleTestSyringePumpEncoderStatusOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_ADC_DAC_STATUS_OVERRIDE: + handleTestSyringePumpADCandDACStatusOverrideRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_ADC_READ_COUNTER_OVERRIDE: + handleTestSyringePumpADCReadCtrOverrideRequest( message ); + break; + + case MSG_ID_HD_TEMPERATURES_VALUE_OVERRIDE: + handleTestTemperaturesValueOverrideRequest( message ); + break; + + case MSG_ID_HD_TEMPERATURES_PUBLISH_INTERVAL_OVERRIDE: + handleTestTemperaturesBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_FANS_PUBLISH_INTERVAL_OVERRIDE: + handleTestFansBroadcastIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_FANS_RPM_OVERRIDE: + handleFansRPMOverride( message ); + break; + + case MSG_ID_HD_SET_CALIBRATION_RECORD: + handleSetHDCalibrationRecord( message ); + break; + + case MSG_ID_HD_GET_CALIBRATION_RECORD: + handleGetHDCalibrationRecord( message ); + break; + + case MSG_ID_HD_SET_SYSTEM_RECORD: + handleSetHDSystemRecord( message ); + break; + + case MSG_ID_HD_GET_SYSTEM_RECORD: + handleGetHDSystemRecord( message ); + break; + + case MSG_ID_HD_GET_SERVICE_RECORD: + handleGetHDServiceRecord( message ); + break; + + case MSG_ID_HD_SET_SERVICE_RECORD: + handleSetHDServiceRecord( message ); + break; + + case MSG_ID_HD_ALARM_STATUS_PUBLISH_INTERVAL_OVERRIDE: + handleTestAlarmStatusSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_TREATMENT_TIME_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestTreatmentTimeDataSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_TREATMENT_RANGES_PUBLISH_INTERVAL_OVERRIDE: + handleTestTreatmentRangesSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_TREATMENT_STOP_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestTreatmentStopDataSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_BLOOD_PRIME_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestBloodPrimeDataSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_RINSEBACK_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestRinsebackDataSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_STANDBY_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestStandbyModeDataSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_OP_MODE_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestOpModeDataSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_PRE_TREATMENT_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestPreTreatmentModeDataSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_TREATMENT_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestTreatmentModeSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_POST_TREATMENT_DATA_PUBLISH_INTERVAL_OVERRIDE: + handleTestPostTreatmentModeSendIntervalOverrideRequest( message ); + break; + + case MSG_ID_HD_BLOCK_MESSAGE_TRANSMISSION: + handleTestBlockMessagesRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_FORCE_SENSOR_DAC_CALIBRATE: + handleTestSyringePumpForceSensorCalibrateRequest( message ); + break; + + case MSG_ID_HD_SET_FANS_RPM_ALARM_START_TIME_OFFSET: + handleTestFansRPMAlarmStartTimeOffsetRequest( message ); + break; + + case MSG_ID_HD_SYRINGE_PUMP_HEPRIN_BOLUS_TARGET_RATE_OVERRIDE: + handleTestSyringePumpHeprinBolusTargetRateOverrideRequest( message ); + break; + + case MSG_ID_HD_REQ_CURRENT_TREATMENT_PARAMETERS: + handleTestCurrentTreamtmentParametersRequest( message ); + break; + + case MSG_ID_HD_FANS_DUTY_CYCLE_OVERRIDE: + handleSetFansDutyCycleOverrideRequest( message ); + break; + + case MSG_ID_HD_GET_SW_CONFIG_RECORD: + handleGetHDSoftwareConfigRecord( message ); + break; + + case MSG_ID_HD_SET_SW_CONFIG_RECORD: + handleSetHDSoftwareConfigRecord( message ); + break; + + case MSG_ID_HD_STOP_RTC_CLOCK: + handleStopHDRTCClock( message ); + break; + + case MSG_ID_HD_GET_USAGE_INFO_RECORD: + handleGetHDUsageInfoRecord( message ); + break; + + case MSG_ID_HD_SET_USAGE_INFO_RECORD: + handleSetHDUsageInfoRecord( message ); + break; + + case MSG_ID_HD_SET_BLOOD_LEAK_2_EMB_MODE: + handleSetBloodLeak2EmbeddedMode( message ); + break; + + case MSG_ID_HD_SET_BLOOD_LEAK_EMB_MODE_COMMAND: + handleSetBloodLeakEmbeddedModeCommand( message ); + break; + + case MSG_ID_HD_SEND_ALARMS_COMMAND: + handleResendAllAlarmsCommand( message ); + break; + + case MSG_ID_HD_REQ_CURRENT_TREATMENT_PARAMETERS: + handleTestCurrentTreamtmentParametersRequest( message ); + break; + + + // The default cannot be reached in VectorCAST since the cases are run in a for loop + default: + // Unrecognized message ID received - ignore + break; } } } + +/**@}*/