Index: App/Services/FPGA.c =================================================================== diff -u -rcb47c5f896477ceae7597cb1a4191b3972e93f0d -ra1c9eabfc633bc7e3ef370096b655b87a08e2e52 --- App/Services/FPGA.c (.../FPGA.c) (revision cb47c5f896477ceae7597cb1a4191b3972e93f0d) +++ App/Services/FPGA.c (.../FPGA.c) (revision a1c9eabfc633bc7e3ef370096b655b87a08e2e52) @@ -16,46 +16,103 @@ * **************************************************************************/ -#include // for memcpy() +#include // for memset(), memcpy() #include "sci.h" #include "sys_dma.h" -#include "Common.h" +#include "FPGA.h" +#include "Comm.h" +#include "SystemCommMessages.h" +#include "Utilities.h" // ********** private definitions ********** -#define FPGA_WRITE_CMD_BUFFER_LEN 16 +typedef enum FPGA_States +{ + FPGA_STATE_START = 0, + FPGA_STATE_READ_HEADER, + FPGA_STATE_RCV_HEADER, + FPGA_STATE_WRITE_ALL_ACTUATORS, + FPGA_STATE_RCV_ALL_SENSORS, + FPGA_STATE_FAILED, + NUM_OF_FPGA_STATES +} FPGA_STATE_T; + +#define FPGA_PAGE_SIZE 256 +#define FPGA_EXPECTED_ID 0x59 + +#define FPGA_WRITE_CMD_BUFFER_LEN (FPGA_PAGE_SIZE+8) #define FPGA_READ_CMD_BUFFER_LEN 8 -#define FPGA_WRITE_RSP_BUFFER_LEN 10 -#define FPGA_READ_RSP_BUFFER_LEN 100 +#define FPGA_WRITE_RSP_BUFFER_LEN 8 +#define FPGA_READ_RSP_BUFFER_LEN (FPGA_PAGE_SIZE+8) +#define FPGA_WRITE_CMD_CODE 0x55 +#define FPGA_READ_CMD_CODE 0x5A +#define FPGA_WRITE_CMD_ACK 0xA5 +#define FPGA_WRITE_CMD_NAK 0xAE +#define FPGA_READ_CMD_ACK 0xAA +#define FPGA_READ_CMD_NAK 0xAF + +#define FPGA_CRC_LEN 2 +#define FPGA_WRITE_CMD_HDR_LEN 4 +#define FPGA_READ_CMD_HDR_LEN 4 +#define FPGA_WRITE_RSP_HDR_LEN 1 +#define FPGA_READ_RSP_HDR_LEN 1 + #define SCI2_RECEIVE_DMA_REQUEST 28 #define SCI2_TRANSMIT_DMA_REQUEST 29 +#define MAX_COMM_ERROR_RETRIES 5 + // FPGA Sensors Record #pragma pack(push,1) typedef struct { - U08 artBloodValveState; // arterial blood valve state - U08 venBloodValveState; // venous blood valve state + U08 fpgaId; + U08 fpgaRev; + U08 fpgaDiag; + U08 gap1; + U16 fpgaStatus; + U16 fpgaControl; +} FPGA_HEADER_T; + +typedef struct +{ + U16 bloodLeak; + U32 adc1b; + U32 adc2b; + U32 dialysateTemp1; + U32 venousPressure; + U32 arterialPressure; + U32 adc1a; + U32 adc2a; + U32 dialysateTemp2; } FPGA_SENSORS_T; typedef struct { - U08 artBloodValveState; // arterial blood valve set state } FPGA_ACTUATORS_T; #pragma pack(pop) // ********** private data ********** -// FPGA received sensor data from DMA bulk read -static FPGA_SENSORS_T fpgaSensors; +// FPGA state +static FPGA_STATE_T fpgaState = FPGA_STATE_START; +static U32 fpgaCommRetryCount = 0; +static U32 fpgaReceiptCounter = 0; +static U32 fpgaTransmitCounter = 0; +static BOOL fpgaWriteCommandInProgress = FALSE; +static BOOL fpgaReadCommandInProgress = FALSE; +static BOOL fpgaBulkWriteAndReadInProgress = FALSE; +static BOOL fpgaWriteCommandResponseReceived = FALSE; +static BOOL fpgaReadCommandResponseReceived = FALSE; + // FPGA comm buffers -static U08 fpgaWriteCmdBuffer[FPGA_WRITE_CMD_BUFFER_LEN] = {1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,0}; -static U08 fpgaReadCmdBuffer[FPGA_READ_CMD_BUFFER_LEN] = {0,0,0,0,0,0,0,0}; -static U08 fpgaWriteResponseBuffer[FPGA_WRITE_RSP_BUFFER_LEN] = {0,0,0,0,0,0,0,0,0,0}; +static U08 fpgaWriteCmdBuffer[FPGA_WRITE_CMD_BUFFER_LEN]; +static U08 fpgaReadCmdBuffer[FPGA_READ_CMD_BUFFER_LEN]; +static U08 fpgaWriteResponseBuffer[FPGA_WRITE_RSP_BUFFER_LEN]; static U08 fpgaReadResponseBuffer[FPGA_READ_RSP_BUFFER_LEN]; // DMA control records @@ -65,22 +122,29 @@ static g_dmaCTRL fpgaDMAReadRespControlRecord; // FPGA data +static FPGA_HEADER_T fpgaHeader; +static FPGA_SENSORS_T fpgaSensorReadings; +static FPGA_ACTUATORS_T fpgaActuatorSetPoints; -U08 version; // FPGA version -U08 diagnostic; // FPGA diagnostic register - -DATA_DECL( TWO_WAY_STATE_T, BloodValveState, dataArterialBloodValveState, STATE_CLOSED, STATE_CLOSED ); - // ********** private function prototypes ********** +static FPGA_STATE_T handleFPGAReadHeaderState( void ); +static FPGA_STATE_T handleFPGAReceiveHeaderState( void ); +static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ); +static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ); + +static void resetFPGACommFlags( void ); static void setupDMAForWriteCmd( U32 bytes2Transmit ); static void startDMAWriteCmd( void ); static void setupDMAForWriteResp( U32 bytes2Receive ); static void startDMAReceiptOfWriteResp( void ); static void setupDMAForReadCmd( U32 bytes2Transmit ); static void startDMAReadCmd( void ); static void setupDMAForReadResp( U32 bytes2Receive ); +static void startDMAReceiptOfReadResp( void ); +static void consumeUnexpectedData( void ); + /************************************************************************* * @brief initFPGA * The initFPGA function initializes the FPGA module. @@ -92,39 +156,46 @@ *************************************************************************/ void initFPGA( void ) { - sciEnableLoopback( scilinREG, Digital_Lbk ); // TODO - for test only + // initialize fpga data structures + memset( &fpgaHeader, 0, sizeof(FPGA_HEADER_T) ); + memset( &fpgaSensorReadings, 0, sizeof(FPGA_SENSORS_T) ); + memset( &fpgaActuatorSetPoints, 0, sizeof(FPGA_ACTUATORS_T) ); + // initialize fpga comm buffers + memset( &fpgaWriteCmdBuffer, 0, FPGA_WRITE_CMD_BUFFER_LEN ); + memset( &fpgaReadCmdBuffer, 0, FPGA_READ_CMD_BUFFER_LEN ); + memset( &fpgaWriteResponseBuffer, 0, FPGA_WRITE_RSP_BUFFER_LEN ); + memset( &fpgaReadResponseBuffer, 0, FPGA_READ_RSP_BUFFER_LEN ); + // enable interrupt notifications for FPGA serial port - //sciEnableNotification( scilinREG, SCI_TX_INT | SCI_RX_INT | SCI_OE_INT | SCI_FE_INT ); - //sciEnableNotification( scilinREG, SCI_RX_INT | SCI_OE_INT | SCI_FE_INT ); sciEnableNotification( scilinREG, SCI_OE_INT | SCI_FE_INT ); - // Enable DMA block transfer complete interrupts - dmaEnableInterrupt( DMA_CH0, BTC ); - dmaEnableInterrupt( DMA_CH2, BTC ); // assign DMA channels to h/w DMA requests dmaReqAssign( DMA_CH0, SCI2_RECEIVE_DMA_REQUEST ); dmaReqAssign( DMA_CH2, SCI2_TRANSMIT_DMA_REQUEST ); // set DMA channel priorities dmaSetPriority( DMA_CH0, HIGHPRIORITY ); dmaSetPriority( DMA_CH2, LOWPRIORITY ); + // Enable DMA block transfer complete interrupts + dmaEnableInterrupt( DMA_CH0, BTC ); + dmaEnableInterrupt( DMA_CH2, BTC ); // initialize FPGA DMA Write Control Record fpgaDMAWriteControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + fpgaDMAWriteControlRecord.SADD = (U32)fpgaWriteCmdBuffer; // transfer source address fpgaDMAWriteControlRecord.DADD = (U32)(&(scilinREG->TD)); // dest. is SCI2 xmit register - fpgaDMAWriteControlRecord.SADD = (U32)fpgaWriteResponseBuffer; // transfer source address fpgaDMAWriteControlRecord.CHCTRL = 0; // no chaining fpgaDMAWriteControlRecord.ELCNT = 1; // frame is 1 element fpgaDMAWriteControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known fpgaDMAWriteControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte fpgaDMAWriteControlRecord.WRSIZE = ACCESS_8_BIT; // fpgaDMAWriteControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - fpgaDMAWriteControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed fpgaDMAWriteControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment + fpgaDMAWriteControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed fpgaDMAWriteControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - fpgaDMAWriteControlRecord.ELSOFFSET = 0; // # of bytes to advance at source memory after each element + fpgaDMAWriteControlRecord.ELSOFFSET = 0; // not used fpgaDMAWriteControlRecord.ELDOFFSET = 0; // not used - fpgaDMAWriteControlRecord.FRSOFFSET = 0; // # of bytes to advance at source memory after each frame + fpgaDMAWriteControlRecord.FRSOFFSET = 0; // not used fpgaDMAWriteControlRecord.FRDOFFSET = 0; // not used // initialize FPGA DMA Write Response Control Record @@ -140,33 +211,33 @@ fpgaDMAWriteRespControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed fpgaDMAWriteRespControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment fpgaDMAWriteRespControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - fpgaDMAWriteRespControlRecord.ELDOFFSET = 0; // # of bytes to advance at destination memory after each element + fpgaDMAWriteRespControlRecord.ELDOFFSET = 0; // not used fpgaDMAWriteRespControlRecord.ELSOFFSET = 0; // not used - fpgaDMAWriteRespControlRecord.FRDOFFSET = 0; // # of bytes to advance at destination memory after each frame + fpgaDMAWriteRespControlRecord.FRDOFFSET = 0; // not used fpgaDMAWriteRespControlRecord.FRSOFFSET = 0; // not used // initialize FPGA DMA Read Control Record fpgaDMAReadControlRecord.PORTASGN = 4; // port B (only choice per datasheet) + fpgaDMAReadControlRecord.SADD = (U32)fpgaReadCmdBuffer; // transfer source address fpgaDMAReadControlRecord.DADD = (U32)(&(scilinREG->TD)); // dest. is SCI2 xmit register - fpgaDMAReadControlRecord.SADD = (U32)fpgaWriteResponseBuffer;// transfer source address fpgaDMAReadControlRecord.CHCTRL = 0; // no chaining fpgaDMAReadControlRecord.ELCNT = 1; // frame is 1 element fpgaDMAReadControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known fpgaDMAReadControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte fpgaDMAReadControlRecord.WRSIZE = ACCESS_8_BIT; // fpgaDMAReadControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer - fpgaDMAReadControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed fpgaDMAReadControlRecord.ADDMODERD = ADDR_INC1; // source addressing mode is post-increment + fpgaDMAReadControlRecord.ADDMODEWR = ADDR_FIXED; // dest. addressing mode is fixed fpgaDMAReadControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - fpgaDMAReadControlRecord.ELSOFFSET = 0; // # of bytes to advance at source memory after each element + fpgaDMAReadControlRecord.ELSOFFSET = 0; // not used fpgaDMAReadControlRecord.ELDOFFSET = 0; // not used - fpgaDMAReadControlRecord.FRSOFFSET = 0; // # of bytes to advance at source memory after each frame + fpgaDMAReadControlRecord.FRSOFFSET = 0; // not used fpgaDMAReadControlRecord.FRDOFFSET = 0; // not used // initialize FPGA DMA Read Response Control Record fpgaDMAReadRespControlRecord.PORTASGN = 4; // port B (only choice per datasheet) fpgaDMAReadRespControlRecord.SADD = (U32)(&(scilinREG->RD)); // source is SCI2 recv register - fpgaDMAReadRespControlRecord.DADD = (U32)fpgaWriteResponseBuffer; // transfer destination address + fpgaDMAReadRespControlRecord.DADD = (U32)fpgaReadResponseBuffer; // transfer destination address fpgaDMAReadRespControlRecord.CHCTRL = 0; // no chaining fpgaDMAReadRespControlRecord.ELCNT = 1; // frame is 1 element fpgaDMAReadRespControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known @@ -176,136 +247,653 @@ fpgaDMAReadRespControlRecord.ADDMODERD = ADDR_FIXED; // source addressing mode is fixed fpgaDMAReadRespControlRecord.ADDMODEWR = ADDR_INC1; // dest. addressing mode is post-increment fpgaDMAReadRespControlRecord.AUTOINIT = AUTOINIT_OFF; // auto-init off - fpgaDMAReadRespControlRecord.ELDOFFSET = 0; // # of bytes to advance at destination memory after each element + fpgaDMAReadRespControlRecord.ELDOFFSET = 0; // not used fpgaDMAReadRespControlRecord.ELSOFFSET = 0; // not used - fpgaDMAReadRespControlRecord.FRDOFFSET = 0; // # of bytes to advance at destination memory after each frame + fpgaDMAReadRespControlRecord.FRDOFFSET = 0; // not used fpgaDMAReadRespControlRecord.FRSOFFSET = 0; // not used - // TODO - this is a DMA xmit and recv via loopback test - setupDMAForWriteResp( 8 ); - startDMAReceiptOfWriteResp(); - setupDMAForWriteCmd( 8 ); - startDMAWriteCmd(); + // there shouldn't be any data pending yet + consumeUnexpectedData(); } /************************************************************************* - * @brief execFPGA - * The execFPGA function manages data exchanges with the FPGA. + * @brief resetFPGACommFlags + * The resetFPGACommFlags function resets the various fpga comm flags and \n + * counters. * @details * Inputs : none - * Outputs : none + * Outputs : fpga comm flags & counters reset * @param none * @return none *************************************************************************/ -void execFPGA( void ) +static void resetFPGACommFlags( void ) { - U08 x; - x = fpgaWriteResponseBuffer[0]; + fpgaWriteCommandResponseReceived = FALSE; + fpgaReadCommandResponseReceived = FALSE; + fpgaWriteCommandInProgress = FALSE; + fpgaReadCommandInProgress = FALSE; + fpgaBulkWriteAndReadInProgress = FALSE; + fpgaTransmitCounter = 0; + fpgaReceiptCounter = 0; } +/************************************************************************* + * @brief signalFPGAReceiptCompleted + * The signalFPGAReceiptCompleted function increments a counter to indicate \n + * that another DMA receipt from the FPGA has completed. + * @details + * Inputs : none + * Outputs : fpgaReceiptCounter + * @param none + * @return none + *************************************************************************/ +void signalFPGAReceiptCompleted( void ) +{ + fpgaReceiptCounter++; + // did FPGA Ack last command? + if ( TRUE == fpgaWriteCommandInProgress ) + { + fpgaWriteCommandInProgress = FALSE; + fpgaWriteCommandResponseReceived = TRUE; + } + else if ( TRUE == fpgaReadCommandInProgress ) + { + fpgaReadCommandInProgress = FALSE; + fpgaReadCommandResponseReceived = TRUE; + } + // see if we want to follow up with a bulk read command + if ( TRUE == fpgaBulkWriteAndReadInProgress ) + { + fpgaBulkWriteAndReadInProgress = FALSE; + fpgaReadCommandInProgress = TRUE; + // initiate bulk read command + startDMAReceiptOfReadResp(); + startDMAReadCmd(); + } +} +/************************************************************************* + * @brief signalFPGATransmitCompleted + * The signalFPGATransmitCompleted function increments a counter to indicate \n + * that another DMA transmit to the FPGA has completed. + * @details + * Inputs : none + * Outputs : fpgaReceiptCounter + * @param none + * @return none + *************************************************************************/ +void signalFPGATransmitCompleted( void ) +{ + fpgaTransmitCounter++; +} +/************************************************************************* + * @brief execFPGAIn + * The execFPGA function manages incoming data exchanges with the FPGA. + * @details + * Inputs : fpgaState + * Outputs : fpgaState + * @param none + * @return none + *************************************************************************/ +void execFPGAIn( void ) +{ + // FPGA incoming state machine + switch ( fpgaState ) + { + case FPGA_STATE_START: + fpgaState = FPGA_STATE_READ_HEADER; + break; + case FPGA_STATE_RCV_HEADER: + fpgaState = handleFPGAReceiveHeaderState(); + break; + + // TODO - sensor/ADC init/configuration states + + case FPGA_STATE_RCV_ALL_SENSORS: + fpgaState = handleFPGAReceiveAllSensorsState(); + break; + + case FPGA_STATE_FAILED: + // do nothing - we'll be stuck here + break; + + default: + if ( fpgaState >= NUM_OF_FPGA_STATES ) + { + // TODO - s/w fault + } + else + { + // ok, some states handled in the outgoing state machine + } + break; + } + + // if retries for commands exceeds limit, fault + if ( fpgaCommRetryCount > MAX_COMM_ERROR_RETRIES ) + { + // TODO - FPGA comm fault + } + + // reset comm flags after processing incoming responses + resetFPGACommFlags(); +} + +/************************************************************************* + * @brief execFPGAOut + * The execFPGAOut function manages outgoing data exchanges with the FPGA. + * @details + * Inputs : fpgaState + * Outputs : fpgaState + * @param none + * @return none + *************************************************************************/ +void execFPGAOut( void ) +{ + // FPGA outgoing state machine + switch ( fpgaState ) + { + case FPGA_STATE_READ_HEADER: + fpgaState = handleFPGAReadHeaderState(); + break; + + // TODO - sensor/ADC init/configuration states + + case FPGA_STATE_WRITE_ALL_ACTUATORS: + fpgaState = handleFPGAWriteAllActuatorsState(); + break; + + case FPGA_STATE_FAILED: + // do nothing - we'll be stuck here + break; + + default: + if ( fpgaState >= NUM_OF_FPGA_STATES ) + { + // TODO - s/w fault + } + else + { + // ok, some states handled in the incoming state machine + } + break; + } +} + +/************************************************************************* + * @brief handleFPGAReadHeaderState + * The handleFPGAReadHeaderState function handles the FPGA state where \n + * the read header registers command is sent to the FPGA. + * @details + * Inputs : none + * Outputs : read command sent to FPGA + * @param none + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReadHeaderState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_RCV_HEADER; + U16 crc; + + // construct read command to read 3 registers starting at address 0 + fpgaReadCmdBuffer[0] = FPGA_READ_CMD_CODE; + fpgaReadCmdBuffer[1] = 0x00; // start at FPGA address 0 + fpgaReadCmdBuffer[2] = 0x00; + fpgaReadCmdBuffer[3] = sizeof(FPGA_HEADER_T); + crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); + fpgaReadCmdBuffer[4] = GET_LSB_OF_WORD( crc ); + fpgaReadCmdBuffer[5] = GET_MSB_OF_WORD( crc ); + // prep DMA for sending the read cmd and receiving the response + fpgaReadCommandInProgress = TRUE; + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_HEADER_T) + FPGA_CRC_LEN ); + setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); + startDMAReceiptOfReadResp(); + startDMAReadCmd(); + + return result; +} + +/************************************************************************* + * @brief handleFPGAReceiveHeaderState + * The handleFPGAReceiveHeaderState function handles the FPGA state \n + * where the header registers read response should be ready to take in. + * @details + * Inputs : none + * Outputs : header register values updated + * @param none + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReceiveHeaderState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_READ_HEADER; + + // did we get an FPGA response? + if ( TRUE == fpgaReadCommandResponseReceived ) + { + // did FPGA Ack the read command? + if ( fpgaReadResponseBuffer[0] == FPGA_READ_CMD_ACK ) + { + U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_HEADER_T); + U32 crcPos = rspSize; + U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[crcPos+1], fpgaReadResponseBuffer[crcPos] ); + + // does the FPGA response CRC check out? + if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) +// if ( 1 ) // TODO - remove when FPGA CRCs are implemented + { + fpgaCommRetryCount = 0; + // capture the read values + memcpy( &fpgaHeader, &fpgaReadResponseBuffer[1], sizeof(FPGA_HEADER_T) ); + result = FPGA_STATE_WRITE_ALL_ACTUATORS; + } + else + { + fpgaCommRetryCount++; + } + } + else // header read was NAK'd + { + fpgaCommRetryCount++; + } + } + else // no response to read command + { + fpgaCommRetryCount++; + } + + // shouldn't be any data received at this time + consumeUnexpectedData(); + + return result; +} + +/************************************************************************* + * @brief handleFPGAWriteAllActuatorsState + * The handleFPGAWriteAllActuatorsState function handles the FPGA state \n + * where the bulk write command is sent to the FPGA. + * @details + * Inputs : actuator set points + * Outputs : actuator set points sent to FPGA + * @param none + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAWriteAllActuatorsState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_RCV_ALL_SENSORS; + U16 crc; + + // construct bulk write command to write actuator data registers starting at address 3 (TODO - change address later) + fpgaWriteCmdBuffer[0] = FPGA_WRITE_CMD_CODE; + fpgaWriteCmdBuffer[1] = 0x08; // start at FPGA address 8 + fpgaWriteCmdBuffer[2] = 0x00; + fpgaWriteCmdBuffer[3] = 1; // TODO - replace 1 with sizeof(FPGA_ACTUATORS_T) +// memcpy( &(fpgaWriteCmdBuffer[FPGA_WRITE_CMD_HDR_LEN]), &fpgaActuatorSetPoints, sizeof(FPGA_ACTUATORS_T) ); + fpgaWriteCmdBuffer[FPGA_WRITE_CMD_HDR_LEN] = 99; // TODO - remove and replace with memcpy above + crc = crc16( fpgaWriteCmdBuffer, FPGA_WRITE_CMD_HDR_LEN+1 ); // TODO - replace +1 with +sizeof(FPGA_ACTUATORS_T) + fpgaWriteCmdBuffer[FPGA_WRITE_CMD_HDR_LEN+1] = GET_LSB_OF_WORD( crc ); // TODO - replace +1 with +sizeof(FPGA_ACTUATORS_T) + fpgaWriteCmdBuffer[FPGA_WRITE_CMD_HDR_LEN+1+1] = GET_MSB_OF_WORD( crc ); // TODO - replace +1 with +sizeof(FPGA_ACTUATORS_T) + // construct bulk read command to read sensor data registers starting at address 8 + fpgaReadCmdBuffer[0] = FPGA_READ_CMD_CODE; + fpgaReadCmdBuffer[1] = 0x08; // start at FPGA address 8 + fpgaReadCmdBuffer[2] = 0x00; + fpgaReadCmdBuffer[3] = sizeof(FPGA_SENSORS_T); + crc = crc16( fpgaReadCmdBuffer, FPGA_READ_CMD_HDR_LEN ); + fpgaReadCmdBuffer[4] = GET_LSB_OF_WORD( crc ); + fpgaReadCmdBuffer[5] = GET_MSB_OF_WORD( crc ); + // prep DMA for sending the bulk write cmd and receiving its response + setupDMAForWriteCmd( FPGA_WRITE_CMD_HDR_LEN + 1 + FPGA_CRC_LEN ); // TODO s/b sizeof(FPGA_ACTUATORS_T) instead of 1 + setupDMAForWriteResp( FPGA_WRITE_RSP_HDR_LEN ); + // prep DMA for sending the bulk read cmd and receiving its response + setupDMAForReadCmd( FPGA_READ_CMD_HDR_LEN + FPGA_CRC_LEN ); + setupDMAForReadResp( FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_SENSORS_T) + FPGA_CRC_LEN ); + // set fpga comm flags for bulk write cmd and follow-up bulk read command + fpgaWriteCommandInProgress = TRUE; + fpgaBulkWriteAndReadInProgress = TRUE; + // initiate bulk write command and it's receipt - read will follow + startDMAReceiptOfWriteResp(); + startDMAWriteCmd(); + + return result; +} + +/************************************************************************* + * @brief handleFPGAReceiveAllSensorsState + * The handleFPGAReceiveAllSensorsState function handles the FPGA state \n + * where the bulk read response should be ready to parse. + * @details + * Inputs : none + * Outputs : sensor values updated + * @param none + * @return next FPGA state + *************************************************************************/ +static FPGA_STATE_T handleFPGAReceiveAllSensorsState( void ) +{ + FPGA_STATE_T result = FPGA_STATE_WRITE_ALL_ACTUATORS; + + // check bulk write command success + if ( ( FALSE == fpgaWriteCommandResponseReceived ) || ( fpgaWriteResponseBuffer[0] != FPGA_WRITE_CMD_ACK ) ) + { + fpgaCommRetryCount++; + } + + // if bulk read command is ACK'd, collect the readings + if ( TRUE == fpgaReadCommandResponseReceived ) + { + // did FPGA Ack the read command? + if ( fpgaReadResponseBuffer[0] == FPGA_READ_CMD_ACK ) + { + U32 rspSize = FPGA_READ_RSP_HDR_LEN + sizeof(FPGA_SENSORS_T); + U32 crcPos = rspSize; + U16 crc = MAKE_WORD_OF_BYTES( fpgaReadResponseBuffer[crcPos+1], fpgaReadResponseBuffer[crcPos] ); + + // does the FPGA response CRC check out? + if ( crc == crc16( fpgaReadResponseBuffer, rspSize ) ) +// if ( 1 ) // TODO - remove when FPGA CRCs are implemented + { + fpgaCommRetryCount = 0; + // capture the read values + memcpy( &fpgaSensorReadings, &fpgaReadResponseBuffer[1], sizeof(FPGA_SENSORS_T) ); + result = FPGA_STATE_WRITE_ALL_ACTUATORS; + } + else // bad CRC + { + fpgaCommRetryCount++; + } + } + else // read command was NAK'd + { + fpgaCommRetryCount++; + } + } + else // no response to read command + { + fpgaCommRetryCount++; + } + + // shouldn't be any data received at this time + consumeUnexpectedData(); + + return result; +} + +/************************************************************************* + * @brief execFPGATest + * The execFPGATest function executes the FPGA self-test. \n + * @details + * Inputs : fpgaHeader + * Outputs : none + * @param none + * @return passed, or failed + *************************************************************************/ +SELF_TEST_STATUS_T execFPGATest( void ) +{ + SELF_TEST_STATUS_T result = SELF_TEST_STATUS_FAILED; + + // check FPGA reported correct ID + if ( FPGA_EXPECTED_ID == fpgaHeader.fpgaId ) + { + result = SELF_TEST_STATUS_PASSED; + } + + return result; +} + +/************************************************************************* + * @brief setupDMAForWriteCmd + * The setupDMAForWriteCmd function sets the byte count for the next DMA \n + * write command to the FPGA. + * @details + * Inputs : none + * Outputs : # of bytes for next FPGA write command is set + * @param bytes2Transmit : # of bytes to be transmitted via DMA to the FPGA. + * @return none + *************************************************************************/ static void setupDMAForWriteCmd( U32 bytes2Transmit ) { - fpgaDMAWriteControlRecord.FRCNT = bytes2Transmit; + // verify # of bytes does not exceed buffer length + if ( bytes2Transmit <= FPGA_WRITE_CMD_BUFFER_LEN ) + { + fpgaDMAWriteControlRecord.FRCNT = bytes2Transmit; + } + else + { + // TODO - s/w fault + } } +/************************************************************************* + * @brief startDMAWriteCmd + * The startDMAWriteCmd function initiates the DMA transmit for the next \n + * DMA write command to the FPGA. + * @details + * Inputs : none + * Outputs : DMA write command to FPGA is initiated + * @param none + * @return none + *************************************************************************/ static void startDMAWriteCmd( void ) { dmaSetCtrlPacket( DMA_CH2, fpgaDMAWriteControlRecord ); dmaSetChEnable( DMA_CH2, DMA_HW ); - scilinREG->SETINT = (uint32)((uint32)1U << 16U); /* Tx DMA */ + setSCI2DMATransmitInterrupt(); } +/************************************************************************* + * @brief setupDMAForWriteResp + * The setupDMAForWriteResp function sets the expected byte count for the \n + * next DMA write command response from the FPGA. + * @details + * Inputs : none + * Outputs : # of expected bytes for next FPGA write command response is set + * @param bytes2Receive : # of bytes expected to be transmitted via DMA from the FPGA. + * @return none + *************************************************************************/ static void setupDMAForWriteResp( U32 bytes2Receive ) { - fpgaDMAWriteRespControlRecord.FRCNT = bytes2Receive; + // verify # of bytes does not exceed buffer length + if ( bytes2Receive <= FPGA_WRITE_RSP_BUFFER_LEN ) + { + fpgaDMAWriteRespControlRecord.FRCNT = bytes2Receive; + } + else + { + // TODO - s/w fault + } } +/************************************************************************* + * @brief startDMAReceiptOfWriteResp + * The startDMAReceiptOfWriteResp function initiates readiness of the DMA \n + * receiver for the next DMA write command response from the FPGA. + * @details + * Inputs : none + * Outputs : DMA write command response is ready to be received from the FPGA + * @param none + * @return none + *************************************************************************/ static void startDMAReceiptOfWriteResp( void ) { dmaSetCtrlPacket( DMA_CH0, fpgaDMAWriteRespControlRecord ); dmaSetChEnable( DMA_CH0, DMA_HW ); - scilinREG->SETINT = (uint32)((uint32)1U << 18U); /* Rx DMA All */ - scilinREG->SETINT = (uint32)((uint32)1U << 17U); /* Rx DMA */ + setSCI2DMAReceiveInterrupt(); } +/************************************************************************* + * @brief setupDMAForReadCmd + * The setupDMAForReadCmd function sets the byte count for the next DMA \n + * read command to the FPGA. + * @details + * Inputs : none + * Outputs : # of bytes for next FPGA read command is set + * @param bytes2Transmit : # of bytes to be transmitted via DMA to the FPGA. + * @return none + *************************************************************************/ static void setupDMAForReadCmd( U32 bytes2Transmit ) { - fpgaDMAReadControlRecord.FRCNT = bytes2Transmit; + // verify # of bytes does not exceed buffer length + if ( bytes2Transmit <= FPGA_READ_CMD_BUFFER_LEN ) + { + fpgaDMAReadControlRecord.FRCNT = bytes2Transmit; + } + else + { + // TODO - s/w fault + } } +/************************************************************************* + * @brief startDMAReadCmd + * The startDMAReadCmd function initiates the DMA transmit for the next \n + * DMA read command to the FPGA. + * @details + * Inputs : none + * Outputs : DMA read command to FPGA is initiated + * @param none + * @return none + *************************************************************************/ static void startDMAReadCmd( void ) { dmaSetCtrlPacket( DMA_CH2, fpgaDMAReadControlRecord ); dmaSetChEnable( DMA_CH2, DMA_HW ); - scilinREG->SETINT = (uint32)((uint32)1U << 16U); /* Tx DMA */ + setSCI2DMATransmitInterrupt(); } +/************************************************************************* + * @brief setupDMAForReadResp + * The setupDMAForReadResp function sets the expected byte count for the \n + * next DMA read command response from the FPGA. + * @details + * Inputs : none + * Outputs : # of expected bytes for next FPGA read command response is set + * @param bytes2Receive : # of expected bytes to be transmitted via DMA from the FPGA. + * @return none + *************************************************************************/ static void setupDMAForReadResp( U32 bytes2Receive ) { - fpgaDMAReadRespControlRecord.FRCNT = bytes2Receive; + // verify # of bytes does not exceed buffer length + if ( bytes2Receive <= FPGA_READ_RSP_BUFFER_LEN ) + { + fpgaDMAReadRespControlRecord.FRCNT = bytes2Receive; + } + else + { + // TODO - s/w fault + } } +/************************************************************************* + * @brief startDMAReceiptOfReadResp + * The startDMAReceiptOfReadResp function initiates readiness of the DMA \n + * receiver for the next DMA read command response from the FPGA. + * @details + * Inputs : none + * Outputs : DMA read command response is ready to be received from the FPGA + * @param none + * @return none + *************************************************************************/ static void startDMAReceiptOfReadResp( void ) { dmaSetCtrlPacket( DMA_CH0, fpgaDMAReadRespControlRecord ); dmaSetChEnable( DMA_CH0, DMA_HW ); - scilinREG->SETINT = (uint32)((uint32)1U << 18U); /* Rx DMA All */ - scilinREG->SETINT = (uint32)((uint32)1U << 17U); /* Rx DMA */ + setSCI2DMAReceiveInterrupt(); } - - -U08 getFPGAVersion( void ) +/************************************************************************* + * @brief getFPGAId + * The getFPGAId function gets the version read from the Id register \n + * of the FPGA. + * @details + * Inputs : fpgaHeader + * Outputs : none + * @param none + * @return Id + *************************************************************************/ +U08 getFPGAId( void ) { + return fpgaHeader.fpgaId; +} +/************************************************************************* + * @brief getFPGARev + * The getFPGARev function gets the revision read from the Rev register \n + * of the FPGA. + * @details + * Inputs : fpgaHeader + * Outputs : none + * @param none + * @return Revision + *************************************************************************/ +U08 getFPGARev( void ) +{ + return fpgaHeader.fpgaRev; } +/************************************************************************* + * @brief getFPGADiag + * The getFPGADiag function gets the version read from the diagnostic register \n + * of the FPGA. + * @details + * Inputs : fpgaHeader + * Outputs : none + * @param none + * @return fpgaDiag + *************************************************************************/ U08 getFPGADiag( void ) { - U08 result = 0; - - return result; + return fpgaHeader.fpgaDiag; } -void setFPGADiag( void ) +/************************************************************************* + * @brief getFPGAStatus + * The getFPGAStatus function gets the version read from the diagnostic register \n + * of the FPGA. + * @details + * Inputs : fpgaHeader + * Outputs : none + * @param none + * @return fpgaDiag + *************************************************************************/ +U16 getFPGAStatus( void ) { - + return fpgaHeader.fpgaStatus; } -DATA_GET( TWO_WAY_STATE_T, getArterialBloodValveState, dataArterialBloodValveState ) - -BOOL dialinSetArterialBloodValveStateOverride( TWO_WAY_STATE_T state ) +/************************************************************************* + * @brief getFPGADiag + * The getFPGADiag function gets the version read from the diagnostic register \n + * of the FPGA. + * @details + * Inputs : fpgaHeader + * Outputs : none + * @param none + * @return fpgaDiag + *************************************************************************/ +void setFPGAControl( U16 ctrl ) { - BOOL result = FALSE; - - // verify dialin login successfully completed before executing override - if ( 1 ) // TODO - call function to check login - { - result = TRUE; - dataArterialBloodValveState.ovData = state; - dataArterialBloodValveState.override = OVERRIDE_KEY; - } - - return result; + fpgaHeader.fpgaControl = ctrl; } -BOOL dialinResetArterialBloodValveStateOverride( void ) +/************************************************************************* + * @brief consumeUnexpectedData + * The consumeUnexpectedData function checks to see if a byte is sitting in \n + * the SCI2 received data register. + * @details + * Inputs : fpgaHeader + * Outputs : none + * @param none + * @return fpgaDiag + *************************************************************************/ +static void consumeUnexpectedData( void ) { - BOOL result = FALSE; - - // verify dialin login successfully completed before executing override reset - if ( 1 ) // TODO - call function to check login + // clear any errors + sciRxError( scilinREG ); + // if a byte is pending read, read it + if ( 0 != sciIsRxReady( scilinREG ) ) { - result = TRUE; - dataArterialBloodValveState.override = OVERRIDE_RESET; - dataArterialBloodValveState.ovData = dataArterialBloodValveState.ovInitData; + sciReceiveByte( scilinREG ); } - - return result; } -