/************************************************************************** * * 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 FPGA.c * * @date 21-Oct-2019 * @author S. Nash * * @brief FPGA interface service module. Provides an interface to the FPGA. \n * Various sensor readings are gathered and get functions provided for them. \n * Various actuator settings are sent and set functions provided for them. * **************************************************************************/ #include // for memcpy() #include "sci.h" #include "sys_dma.h" #include "Common.h" // ********** private definitions ********** #define FPGA_WRITE_CMD_BUFFER_LEN 16 #define FPGA_READ_CMD_BUFFER_LEN 8 #define FPGA_WRITE_RSP_BUFFER_LEN 10 #define FPGA_READ_RSP_BUFFER_LEN 100 #define SCI2_RECEIVE_DMA_REQUEST 28 #define SCI2_TRANSMIT_DMA_REQUEST 29 // FPGA Sensors Record #pragma pack(push,1) typedef struct { U08 artBloodValveState; // arterial blood valve state U08 venBloodValveState; // venous blood valve state } 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 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 fpgaReadResponseBuffer[FPGA_READ_RSP_BUFFER_LEN]; // DMA control records static g_dmaCTRL fpgaDMAWriteControlRecord; static g_dmaCTRL fpgaDMAWriteRespControlRecord; static g_dmaCTRL fpgaDMAReadControlRecord; static g_dmaCTRL fpgaDMAReadRespControlRecord; // FPGA data 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 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 ); /************************************************************************* * @brief initFPGA * The initFPGA function initializes the FPGA module. * @details * Inputs : none * Outputs : FPGA module initialized. * @param none * @return none *************************************************************************/ void initFPGA( void ) { sciEnableLoopback( scilinREG, Digital_Lbk ); // TODO - for test only // 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 ); // initialize FPGA DMA Write Control Record fpgaDMAWriteControlRecord.PORTASGN = 4; // port B (only choice per datasheet) 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.AUTOINIT = AUTOINIT_OFF; // auto-init off fpgaDMAWriteControlRecord.ELSOFFSET = 0; // # of bytes to advance at source memory after each element fpgaDMAWriteControlRecord.ELDOFFSET = 0; // not used fpgaDMAWriteControlRecord.FRSOFFSET = 0; // # of bytes to advance at source memory after each frame fpgaDMAWriteControlRecord.FRDOFFSET = 0; // not used // initialize FPGA DMA Write Response Control Record fpgaDMAWriteRespControlRecord.PORTASGN = 4; // port B (only choice per datasheet) fpgaDMAWriteRespControlRecord.SADD = (U32)(&(scilinREG->RD));// source is SCI2 recv register fpgaDMAWriteRespControlRecord.DADD = (U32)fpgaWriteResponseBuffer; // transfer destination address fpgaDMAWriteRespControlRecord.CHCTRL = 0; // no chaining fpgaDMAWriteRespControlRecord.ELCNT = 1; // frame is 1 element fpgaDMAWriteRespControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known fpgaDMAWriteRespControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte fpgaDMAWriteRespControlRecord.WRSIZE = ACCESS_8_BIT; // fpgaDMAWriteRespControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer 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.ELSOFFSET = 0; // not used fpgaDMAWriteRespControlRecord.FRDOFFSET = 0; // # of bytes to advance at destination memory after each frame fpgaDMAWriteRespControlRecord.FRSOFFSET = 0; // not used // initialize FPGA DMA Read Control Record fpgaDMAReadControlRecord.PORTASGN = 4; // port B (only choice per datasheet) 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.AUTOINIT = AUTOINIT_OFF; // auto-init off fpgaDMAReadControlRecord.ELSOFFSET = 0; // # of bytes to advance at source memory after each element fpgaDMAReadControlRecord.ELDOFFSET = 0; // not used fpgaDMAReadControlRecord.FRSOFFSET = 0; // # of bytes to advance at source memory after each frame 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.CHCTRL = 0; // no chaining fpgaDMAReadRespControlRecord.ELCNT = 1; // frame is 1 element fpgaDMAReadRespControlRecord.FRCNT = 0; // block is TBD frames - will be populated later when known fpgaDMAReadRespControlRecord.RDSIZE = ACCESS_8_BIT; // element size is 1 byte fpgaDMAReadRespControlRecord.WRSIZE = ACCESS_8_BIT; // fpgaDMAReadRespControlRecord.TTYPE = FRAME_TRANSFER; // transfer type is block transfer 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.ELSOFFSET = 0; // not used fpgaDMAReadRespControlRecord.FRDOFFSET = 0; // # of bytes to advance at destination memory after each frame fpgaDMAReadRespControlRecord.FRSOFFSET = 0; // not used // TODO - this is a DMA xmit and recv via loopback test setupDMAForWriteResp( 8 ); startDMAReceiptOfWriteResp(); setupDMAForWriteCmd( 8 ); startDMAWriteCmd(); } /************************************************************************* * @brief execFPGA * The execFPGA function manages data exchanges with the FPGA. * @details * Inputs : none * Outputs : none * @param none * @return none *************************************************************************/ void execFPGA( void ) { U08 x; x = fpgaWriteResponseBuffer[0]; } static void setupDMAForWriteCmd( U32 bytes2Transmit ) { fpgaDMAWriteControlRecord.FRCNT = bytes2Transmit; } static void startDMAWriteCmd( void ) { dmaSetCtrlPacket( DMA_CH2, fpgaDMAWriteControlRecord ); dmaSetChEnable( DMA_CH2, DMA_HW ); scilinREG->SETINT = (uint32)((uint32)1U << 16U); /* Tx DMA */ } static void setupDMAForWriteResp( U32 bytes2Receive ) { fpgaDMAWriteRespControlRecord.FRCNT = bytes2Receive; } 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 */ } static void setupDMAForReadCmd( U32 bytes2Transmit ) { fpgaDMAReadControlRecord.FRCNT = bytes2Transmit; } static void startDMAReadCmd( void ) { dmaSetCtrlPacket( DMA_CH2, fpgaDMAReadControlRecord ); dmaSetChEnable( DMA_CH2, DMA_HW ); scilinREG->SETINT = (uint32)((uint32)1U << 16U); /* Tx DMA */ } static void setupDMAForReadResp( U32 bytes2Receive ) { fpgaDMAReadRespControlRecord.FRCNT = bytes2Receive; } 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 */ } U08 getFPGAVersion( void ) { } U08 getFPGADiag( void ) { U08 result = 0; return result; } void setFPGADiag( void ) { } DATA_GET( TWO_WAY_STATE_T, getArterialBloodValveState, dataArterialBloodValveState ) BOOL dialinSetArterialBloodValveStateOverride( TWO_WAY_STATE_T state ) { 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; } BOOL dialinResetArterialBloodValveStateOverride( void ) { BOOL result = FALSE; // verify dialin login successfully completed before executing override reset if ( 1 ) // TODO - call function to check login { result = TRUE; dataArterialBloodValveState.override = OVERRIDE_RESET; dataArterialBloodValveState.ovData = dataArterialBloodValveState.ovInitData; } return result; }