/************************************************************************************* * serialStreams.c * * synopsis: Contains routines which build and handle sending of serial streams. * * in this file: interleave, serialOut, serialStreamOut, * initCmdBuffer, makeStreamSet * * related files: * serialStreams_sct.c: SCT-specific stream building & transmission routines. * serialStreams_pxl.c: Pixel-specific stream building & transmission routines. * masterPrimFuncts.c: transSerialData, buildStream, sendStream, and sendConfig * primitives * primFuncts.c: setTrigger primitive ************************************************************************************/ #include #include #include #include #include #include #include #include //dpsf: ? #include #include "resources.h" #include "registerIndices.h" #include "memoryPartitions.h" #include "comRegDfns.h" #include "serialStreams.h" //dpsf: #include "macros.h" extern char genStr[]; extern far ModuleMaskData moduleMaskData[]; extern far RodModeCfg rodModeCfg[]; extern TIMER_Handle timer1; /* general purpose timer, started in main() */ #pragma CODE_SECTION(interleave, "icode"); #pragma CODE_SECTION(serialOut, "xcode"); #pragma CODE_SECTION(serialStreamOut, "icode"); #pragma CODE_SECTION(initCmdBuffer, "xcode"); #pragma CODE_SECTION(initCmdBuff, "xcode"); #pragma CODE_SECTION(makeStreamSet, "xcode"); /* file scope variables */ #pragma DATA_SECTION(cmdStream, "cmdBfr"); UINT32 cmdStream[2][CMD_STREAM_WMAX]; #pragma DATA_SECTION(interleaveBuffer, "burst"); UINT32 interleaveBuffer[2*CMD_STREAM_WMAX]; #pragma DATA_SECTION(cmdBuffer,"idata"); CmdBuff cmdBuffer[2]; /************************************************************************************ * interleave: weave two sets of data together into one buffer for serialStreamOut. ************************************************************************************/ void interleave(UINT32 streamLen[2], UINT32 *stream[2], UINT32 **ptr, UINT32 *nSets) { UINT32 len, i, sLen[2], *s[2]; TransData *data; for (i=0;i<2;++i) { sLen[i]= streamLen[i]; s[i]= stream[i]; } if (sLen[0]==sLen[1]) {len= sLen[0]; } else { if (sLen[0]>sLen[1]) {len= sLen[0]; } else {len= sLen[1]; } } *nSets= len; *ptr= (UINT32 *) &interleaveBuffer; data= (TransData *) *ptr; for (i=0; iport0Data= *s[0]; ++s[0]; } else {data->port0Data= 0; } if (iport1Data= *s[1]; ++s[1]; } else {data->port1Data= 0; } ++data; } } /************************************************************************************ * serialOut: wrapper for serialStreamOut ************************************************************************************/ void serialOut(UINT8 sp){ UINT8 spi, spf, j; UINT32 *ptr, nSets, *stream[2], streamLen[2]; if (sp == SP_BOTH) {spi= SP0; spf= SP_BOTH; } else {spi= sp; spf= sp +1; } for (j=0; j<2; ++j) {stream[j]= NULL; streamLen[j]= 0; } for (j= spi; j NOTE: Routine must remain in IPRAM. <== * * authors: Lukas Tomasek, Richard Jared. ************************************************************************************/ #if ((defined(SIM))||(defined(TI_EVM))) /* dummy fxn */ void serialStreamOut(UINT32 capture, TransData *data, UINT32 nSets) { } #else void serialStreamOut(UINT32 capture, TransData *data, UINT32 nSets) { UINT32 i, k, val; /* loop index */ UINT32 port0Data, port1Data; /* set pointers to serial port control and data registers (fast access) */ UINT32 *spcrReg0= (UINT32*) 0x018C0008, *spcrReg1= (UINT32*) 0x01900008; UINT32 *dataTranReg0= (UINT32*) 0x018c0004, *dataTranReg1= (UINT32*) 0x01900004; /* Disable all interrupts */ IRQ_globalDisable(); /* Data is good so transmit serial data */ i=0; /*!!!*/ k=0; redLed_on; while (iport0Data; port1Data= (data+i)->port1Data; if (i==0) { /* If the input memories are being used for data capture, either by configuration readback (triggered by setting the configuration readback bit in the main ROD FPGA control register), or through event capture (started automatically when an L1A is sensed), reset the FIFOs before sending the serial stream so that they will be ready to capture data (in case the FIFOs were not read out after the last serial stream). */ if((rodModeCfg[0].inmemEvtCapture)||(rodModeCfg[0].cfgReadback)) { readRegister(RRIF_CMND_0, 1, INP_MEM_RST_O, &val); if (val == 0) { //Not currently held in reset. writeRegister(RRIF_CMND_0, 1, INP_MEM_RST_O, 1); writeRegister(RRIF_CMND_0, 1, INP_MEM_RST_O, 0); } /* Start data capture into input memories- RCF cmd reg. 1 */ if (rodModeCfg[0].cfgReadback) writeRegister(RRIF_CMND_1, 1, CONFIGURATION_READBACK_O, 1); } *dataTranReg0= 0; /* preload port 0 */ /* adjust latency between port0 and port1 to 0 */ asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 5"); } /* test that port 0 and 1 need data */ while ((!(*spcrReg0 & 0x00020000))||(!(*spcrReg1 & 0x00020000))) { /* do nothing - serial ports are not empty */; ++k; } /* transmit */ *dataTranReg0= port0Data; *dataTranReg1= port1Data; ++i; } /* set last word to 0 !!!! */ while((!(*spcrReg0 & 0x00020000))||(!(*spcrReg1 & 0x00020000))) { /* do nothing - serial ports are not empty */; } *dataTranReg0= 0; *dataTranReg1= 0; //Always finish by loading 0s. redLed_off; /* Restore interrupts: */ IRQ_globalEnable(); if (rodModeCfg[0].autoInmemReadout) { parseInmem('A', 0x0, (1<<21), (UINT32 *) DEFAULT); parseInmem('B', 0x0, 0, (UINT32 *) DEFAULT); } } #endif #ifdef COMMENTED /************************************************************************************ * serialStreamOut * * synopsis: Sends a serial stream (or streams) out to the front-end electronics, * and optionally captures the return serial data on the input links. * The two stream buffers must be the same length for now. * NOTE: Routine must remain in IPRAM. * * authors: Lukas Tomasek, Richard Jared. ************************************************************************************/ void serialStreamOut(unsigned char capture, UINT32 *stream[2], UINT32 streamLen[2]) { Uns oldCSR; UINT32 i, k; /* loop index */ UINT32 port0Data, port1Data; /* set pointers to serial port control and data registers (fast access) */ UINT32 *spcrReg0= (UINT32 *) 0x018C0008, *spcrReg1= (UINT32 *) 0x01900008; UINT32 *dataTranReg0= (UINT32 *) 0x018c0004, *dataTranReg1= (UINT32 *) 0x01900004; UINT32 streamLength, *ptr, nSets; TransData *data; /* streamLength= streamLen[0]; */ /* streamLength[1]= streamLen[1]; */ interleave(streamLen, stream, &ptr, &nSets); data= (TransData *) ptr; /* Disable all interrupts */ oldCSR= HWI_disable(); SWI_disable(); /* Data is good so transmit serial data */ i=0; /*!!!*/ k=0; while (i < nSets) { /* while (i < streamLength) { */ /* preload next word to IDRAM */ port0Data= (data+i)->port0Data; port1Data= (data+i)->port1Data; /* port0Data= *(stream[0]+i); port1Data= *(stream[1]+i); */ if (i==0) { /* Start data capture into input memories - RRIF command register 1 */ if(capture) { writeRegister(RRIF_CMND_1, 1, CONFIGURATION_READBACK_O, 1); } *dataTranReg0= 0; /* preload port 0 */ /* adjust latency between port0 and port1 to 0 */ asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 9"); asm(" nop 5"); } /* test that port 0 and 1 need data */ while ((!(*spcrReg0 & 0x00020000))||(!(*spcrReg1 & 0x00020000))) { /* do nothing - serial ports are not empty */; ++k; } /* transmit */ *dataTranReg0= port0Data; *dataTranReg1= port1Data; ++i; } /* set last word to 0 !!!! */ while((!(*spcrReg0 & 0x00020000))||(!(*spcrReg1 & 0x00020000))) { /* do nothing - serial ports are not empty */; } *dataTranReg0= 0; *dataTranReg1= 0; if (GET_RBIT(DIAGNOSTIC_REG, DR_DISP_SERIAL_LOOPS)) { sprintf(genStr, "number of sets= 0x%X, waiting count= 0x%X\n", streamLen[0], k); newInformation(__FILE__, __LINE__, genStr); } /* Reset interrupts to previous values: for SWI-- just re-enable, HWI-- restore the stored value of the Control Status Register */ SWI_enable(); HWI_restore(oldCSR); } #endif /************************************************************************************ * initCmdBuffer * * synopsis: Initializes (resets) one of the master DSP's two command stream * buffers. * * modifications/bugs: * - use DMA to clear buffer contents. 03.07.02 dpsf ************************************************************************************/ void initCmdBuffer(UINT8 sp) { UINT32 status; UINT8 i, spi, spf; if (sp == SP_BOTH) {spi= 0; spf= SP_BOTH; } else {spi= sp; spf= sp +1; } for (i=spi; iport= sp; cmd->data= data[0]; cmd->data1= data[1]; cmd->ilBuff= ilBuff; cmd->bufferSizeWords= size; cmd->bitIndex= cmd->bitIndex1= 0; if (cmd->data) status= setMem(cmd->data, size, 0); if (cmd->data1) status= setMem(cmd->data1, size, 0); if (cmd->ilBuff) status= setMem(cmd->ilBuff, 2*size, 0); spEnable[0]= ((sp == SP0) || (sp == SP_BOTH)); spEnable[1]= ((sp == SP1) || (sp == SP_BOTH)); for (i=0; i<2; ++i) for (j=0; j<2; ++j) cmd->cmdMask[i][j]= 0; for (i=0; i<2; ++i) { if ((spEnable[i]) && (module[i] < N_TOTMODULES)) { cmd->setCmdMask= TRUE; v= moduleMaskData[module[i]].cmdLine; if (v < 32) cmd->cmdMask[i][0] |= 1<cmdMask[i][1] |= 1<<(v-32); } } } /************************************************************************************ * makeStreamSet * * synopsis: Creates an interleaved serial stream from the input command lists; * if either is NULL, its stream is all zeros. The chip and fibre * variables are for configuration-type lists with data or slow commands; for the * SCT the calibration pulse command also takes a chip address, which is usually * ALL_CHIPS. Some commands, such as the SCT mask command and several Pixel * commands, take more data. In these cases the data is stored in the data array; * dataLen is *in bits*. If interleaving is requested, makeStreamSet interleaves * both serial streams together and passes back the interleaved set pointer * (ptr) and the total number of sets (nSets), for a subsequent call to * serialStreamOut. * * author: Douglas Ferguson * * modifications/bugs: * - Re-written to serve as the engine for the stream building primitive as * well. 14.03.03 dpsf ************************************************************************************/ INT32 makeStreamSet(struct CmdList *cmdList0, struct CmdList *cmdList1, UINT8 init, UINT8 chip, UINT8 fibre, UINT32 dataLen, UINT32 *data, UINT32 **ptr, UINT32 *nSets, UINT8 doInterleave) { INT32 returnCode= SUCCESS, errorCode; UINT32 *stream[2], streamLen[2]; UINT8 sp, i, chipIdx, chipMax, addr; #if defined(SCT_ROD) UINT8 addr30[N_CHIPS]= {M0_CHIP, S1_CHIP, S2_CHIP, S3_CHIP, S4_CHIP, E5_CHIP, M8_CHIP, S9_CHIP, S10_CHIP, S11_CHIP, S12_CHIP, E13_CHIP}; #elif defined(PIXEL_ROD) UINT8 addr30[N_CHIPS]= {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; #endif struct CmdList *cmdList; for (sp= 0; sp< SP_BOTH; ++sp) { stream[sp]= NULL; streamLen[sp]= 0; if (sp == SP0) cmdList= cmdList0; else if (sp == SP1) cmdList= cmdList1; if (cmdList == NULL) continue; if (init) initCmdBuffer(sp); for (i=0; icmd[i] == NO_CMD) continue; if (chip == CHIP_ADDR_LOOP) { chipMax= N_CHIPS; } else { chipMax= 1; } if ( (cmdList->cmd[i] == L1_TRIGGER) || (cmdList->cmd[i] == SOFT_RESET) || (cmdList->cmd[i] == BC_RESET) || (cmdList->cmd[i] == DELAY) ) { chipMax= 1; } //No address. for (chipIdx= 0; chipIdx< chipMax; ++chipIdx) { if (chip == CHIP_ADDR_LOOP) { addr= CHIP_ADDRESS(fibre, (addr30[chipIdx] & 0xF)); } else if (chip == ALL_CHIPS) { addr= chip; /* SCT == 0x3f; 0x2f for primary fibre doesn't work. */ /* Pixel == 0x10 */ } else { addr= CHIP_ADDRESS(fibre, (chip & 0xF)); } if (cmdList->cmd[i] == MASK) { errorCode= addCommand(&cmdBuffer[sp], cmdList->cmd[i], addr, data, dataLen, fibre); } else { errorCode= addCommand(&cmdBuffer[sp], cmdList->cmd[i], addr, &cmdList->data[i], 32, fibre); } if (errorCode != SUCCESS) { addError(&returnCode, errorCode, "makeStreamSet", "addCommand", __FILE__, __LINE__); return returnCode; } } /* loop over chips if enabled */ } /* loop over commands in list */ stream[sp]= cmdBuffer[sp].data; streamLen[sp]= WORD_INDEX(cmdBuffer[sp].bitIndex +31); } /* loop over serial ports */ if (doInterleave) interleave(streamLen, stream, &(*ptr), &(*nSets)); return returnCode; }