diff --git a/src/include/drv/daqLib.c b/src/include/drv/daqLib.c index 86dbf20d5f44acaa503c55ba8cc1c22b732f2eec..001c14ecb87fde2401de7d316664fb3a4a258d6b 100644 --- a/src/include/drv/daqLib.c +++ b/src/include/drv/daqLib.c @@ -7,6 +7,7 @@ volatile DAQ_INFO_BLOCK *pInfo; ///< Ptr to DAQ config in shmem. extern volatile char *_epics_shm; ///< Ptr to EPICS shmem block extern long daqBuffer; ///< Address of daqLib swing buffers. extern char *_daq_shm; ///< Pointer to DAQ base address in shared memory. +extern char *_gds_shm; ///< Pointer to GDS shared memory for ZMQ xmission. struct rmIpcStr *dipc; ///< Pointer to DAQ IPC data in shared memory. struct cdsDaqNetGdsTpNum *tpPtr; ///< Pointer to TP table in shared memory. char *daqShmPtr; ///< Pointer to DAQ data in shared memory. @@ -20,8 +21,10 @@ float *pEpicsFloat; // Pointer to current DAQ data in shared memory. double *pEpicsDblData1; int daqConfig(struct DAQ_INFO_BLOCK *, struct DAQ_INFO_BLOCK *, char *); +int gdsConfig(GDS_INFO_BLOCK *, GDS_INFO_BLOCK *); int loadLocalTable(DAQ_XFER_INFO *, DAQ_LKUP_TABLE [], int , DAQ_INFO_BLOCK *, DAQ_RANGE *); int daqWrite(int,int,struct DAQ_RANGE,int,double *[],struct FILT_MOD *,int,int [],double [],char *); +int totaltp; // Total number of TP available in a control model based on reading tpchn file inline double htond(double in) { @@ -42,6 +45,9 @@ double htond(double in) { } + + + /* ******************************************************************** */ /* Routine to connect and write to LIGO DAQ system */ /* ******************************************************************** */ @@ -114,6 +120,14 @@ int num_tps; unsigned int tpnum[DAQ_GDS_MAX_TP_ALLOWED]; // Current TP nums unsigned int excnum[DAQ_GDS_MAX_TP_ALLOWED]; // Current EXC nums double mydouble; +static GDS_INFO_BLOCK gdsInfo; +static volatile GDS_INFO_BLOCK *gdsInfoPtr; +// Added channels to send GDS via separate shmem area to ZMQ software +static volatile char *gdsDataPtr; +static volatile char *gdsHdrPtr; +static GDS_DATA_HEADER *gdsHdrInfo; +static GDS_STATUS *gdsStatus; +static float *gdsOffset; #ifdef CORE_BIQUAD // BIQUAD Decimation filter coefficient definitions. @@ -248,12 +262,20 @@ static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY]; daqShmPtr = _daq_shm + CDS_DAQ_NET_DATA_OFFSET; buf_size = DAQ_DCU_BLOCK_SIZE*2; pWriteBuffer = (volatile char *)daqShmPtr; - pWriteBuffer += buf_size * 15; + pWriteBuffer += buf_size * 15; /// ---- Setup Ptr to interprocess comms with network driver dipc = (struct rmIpcStr *)(_daq_shm + CDS_DAQ_NET_IPC_OFFSET); /// ---- Setup Ptr to awgtpman shared memory (TP number table) tpPtr = (struct cdsDaqNetGdsTpNum *)(_daq_shm + CDS_DAQ_NET_GDS_TP_TABLE_OFFSET); + gdsInfoPtr = (GDS_INFO_BLOCK *)(_gds_shm); + gdsHdrPtr = (char *)(_gds_shm + GDS_DATA_OFFSET); + gdsStatus = (GDS_STATUS *) (_gds_shm + GDS_DATA_OFFSET - sizeof(GDS_STATUS)); + gdsStatus->valsperchan = sysRate; + gdsHdrPtr += GDS_BUFF_SIZE * 15; + gdsHdrInfo = (GDS_DATA_HEADER *)gdsHdrPtr; + gdsDataPtr = (char *)(gdsHdrPtr + sizeof(GDS_DATA_HEADER)); + /// ---- Set up pointer to DAQ configuration information in shmem */ pInfo = (DAQ_INFO_BLOCK *)(_epics_shm + DAQ_INFO_ADDRESS); /// ---- Set pointer to shared mem to pass GDS info to DAQ @@ -280,6 +302,9 @@ static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY]; /// \> Load local table information with channel info if((status = loadLocalTable(&xferInfo,localTable,sysRate,&dataInfo,&daqRange)) == -1) return(-1); + /// \> Load GDS channel name and count information. + totaltp = gdsConfig(&gdsInfo, gdsInfoPtr); + // Set the start of TP data after DAQ data. tpStart = xferInfo.offsetAccum; totalChans = dataInfo.numChans; @@ -310,6 +335,8 @@ static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY]; { /// \> Calc data offset into current write swing buffer daqSlot = (daqSlot + 1) % sysRate; + gdsOffset = (float *) gdsDataPtr;; + gdsOffset += daqSlot; #if 0 /// \> At start of 1/16 sec. data block, reset the xfer sizes and done bit */ @@ -336,6 +363,7 @@ static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY]; { dWord = 0; + if(localTable[ii].type == DAQ_SRC_NOOP) continue; /// \> Read data to a local variable, either from a FM TP or other TP */ if(localTable[ii].type == DAQ_SRC_FM_TP) /* Data if from filter module testpoint */ @@ -413,7 +441,14 @@ static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY]; break; default: // Write a 32-bit float (downcast from the double passed) - ((float *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor] = (float)dWord; + if(ii >= dataInfo.numChans) { + if(localTable[ii].type != DAQ_SRC_NOOP) { + *gdsOffset = (float)dWord; + gdsOffset += sysRate; + } + } else { + ((float *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor] = (float)dWord; + } break; } } else if (dataInfo.tp[ii].dataType == DAQ_DATATYPE_32BIT_UINT) { @@ -565,6 +600,22 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) // Frame builder is looking for cycle change /// - ------ Write IPC cycle number. This will trigger DAQ network driver to send data to DAQ dipc->cycle =daqXmitBlockNum; // Ready cycle (16 Hz) + // + // Write GDS Data Information + // Write the channel names to header + jj = 0; + for(ii=dataInfo.numChans;ii<totalChans;ii++) { + if(localTable[ii].type != DAQ_SRC_NOOP) { + sprintf(gdsHdrInfo->chan_name[jj],"%s",localTable[ii].chname); + jj ++; + } + } + // Write GDS channel count and timing information + gdsHdrInfo->chan_count = jj; + gdsHdrInfo->timesec = cycle_gps_time; + gdsHdrInfo->timensec = daqXmitBlockNum;; + // Write cycle count to trigger ZMQ GDS data transmission code + gdsStatus->cycle = daqXmitBlockNum; /// - -- Increment the 1/16 sec block counter daqBlockNum = (daqBlockNum + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; @@ -574,6 +625,12 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) pWriteBuffer = (char *)daqShmPtr; pWriteBuffer += buf_size * daqXmitBlockNum; + // Advance GDS Data Pointers + gdsHdrPtr = (char *)(_gds_shm + GDS_DATA_OFFSET); + gdsHdrPtr += GDS_BUFF_SIZE * daqXmitBlockNum; + gdsHdrInfo = (GDS_DATA_HEADER *)gdsHdrPtr; + gdsDataPtr = (char *)(gdsHdrPtr + sizeof(GDS_DATA_HEADER)); + // - -- Check for reconfig request at start of each second if((pInfo->reconfig == 1) && (daqBlockNum == 0)) { @@ -594,6 +651,8 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) totalChans = dataInfo.numChans; } + /// \> Load GDS channel name and count information. + totaltp = gdsConfig(&gdsInfo, gdsInfoPtr); } /// - -- If last cycle of 1 sec time frame, check for new TP and load info. // This will cause new TP to be written to local memory at start of 1 sec block. @@ -627,6 +686,19 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) } return -1; } + // Function to locate TP channel names from tp number + inline int findTpName(int tpn, int slot) { + int ii; + + for(ii=0;ii<totaltp;ii++) { + if(gdsInfo.tpinfo[ii].tpnumber == tpn) { + sprintf(localTable[slot].chname,"%s", gdsInfo.tpinfo[ii].tpname); + // printf("Found tpname = %s\n",localTable[slot].chname); + return(0); + } + } + return(-1); + } // Copy TP/EXC tables into my local memory memcpy(excnum, (const void *)(gdsPtr->tp[_2k_sys_offs][0]), sizeof(excnum)); @@ -649,7 +721,7 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) excTable[i].sigNum = 0; } - localTable[ltSlot].type = 0; + localTable[ltSlot].type = DAQ_SRC_NOOP; localTable[ltSlot].sysNum = 0; localTable[ltSlot].fmNum = 0; localTable[ltSlot].sigNum = 0; @@ -657,6 +729,7 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; } } + validTpNet = 0; // tpnum and excnum lists now have only the new test points // Insert these new numbers into empty localTable slots @@ -686,6 +759,8 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) // Populate the slot with the information if (!exc) { if (tpn >= daqRange.filtTpMin && tpn < daqRange.filtTpMax) { + findTpName(tpn,ltSlot); + validTpNet ++; jj = tpn - daqRange.filtTpMin; localTable[ltSlot].type = DAQ_SRC_FM_TP; localTable[ltSlot].sysNum = jj / daqRange.filtTpSize; @@ -700,6 +775,8 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) tpNum[slot] = tpn; } else if (tpn >= daqRange.xTpMin && tpn < daqRange.xTpMax) { + findTpName(tpn,ltSlot); + validTpNet ++; jj = tpn - daqRange.xTpMin; localTable[ltSlot].type = DAQ_SRC_NFM_TP; localTable[ltSlot].sigNum = jj; @@ -712,6 +789,8 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) } else { if (tpn >= daqRange.filtExMin && tpn < daqRange.filtExMax) { + findTpName(tpn,ltSlot); + validTpNet ++; jj = tpn - daqRange.filtExMin; localTable[ltSlot].type = DAQ_SRC_FM_EXC; localTable[ltSlot].sysNum = jj / daqRange.filtExSize; // filtExSize = MAX_MODULES @@ -731,6 +810,8 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) tpNum[slot] = tpn; } else if (tpn >= daqRange.xExMin && tpn < daqRange.xExMax) { + findTpName(tpn,ltSlot); + validTpNet ++; jj = tpn - daqRange.xExMin; localTable[ltSlot].type = DAQ_SRC_NFM_EXC; localTable[ltSlot].sysNum = 0; // filtExSize = MAX_MODULES @@ -786,10 +867,12 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) // Network write is one cycle behind memory write, so now update tp nums for FB xmission if(daqBlockNum == 0) { - for(ii=0;ii<validTp;ii++) + for(ii=0;ii<validTp;ii++) { tpNumNet[ii] = tpNum[ii]; - validTpNet = validTp; - xferInfo.totalSizeNet = xferInfo.totalSize; + // if(tpNum[ii] != 0) validTpNet ++; + } + // validTpNet = validTp; + xferInfo.totalSizeNet = xferInfo.crcLength; } } /* End done 16Hz Cycle */ @@ -801,6 +884,22 @@ if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) } +// ************************************************************************************** +// New routine to get GDS TP channel names via GDS shmem +// ************************************************************************************** +int gdsConfig(GDS_INFO_BLOCK *localtable, GDS_INFO_BLOCK *shmtable) { + int ii; + int tpcount = shmtable->totalchans; + printf(" ********** GDS total chans = %d ****************\n",tpcount); + for(ii=0;ii<tpcount;ii++) { + strcpy(localtable->tpinfo[ii].tpname,shmtable->tpinfo[ii].tpname); + localtable->tpinfo[ii].tpnumber = shmtable->tpinfo[ii].tpnumber; + // if(ii<10) printf("\t name = %s \tnumber = %d\n",localtable->tpinfo[ii].tpname,localtable->tpinfo[ii].tpnumber); + } + return(tpcount); + +} + // ************************************************************************************** /// @author R.Bork\n /// @brief This function updates the DAQ configuration from information @@ -902,6 +1001,7 @@ int mydatatype; /// \> Get the DAQ configuration information for all fast DAQ channels and calc a crc checksum length for(ii=0;ii<dataInfo->numChans;ii++) { + strcpy(dataInfo->tp[ii].channel_name,pInfo->tp[ii].channel_name); dataInfo->tp[ii].tpnum = pInfo->tp[ii].tpnum; dataInfo->tp[ii].dataType = pInfo->tp[ii].dataType; dataInfo->tp[ii].dataRate = pInfo->tp[ii].dataRate; @@ -966,6 +1066,9 @@ int mydatatype; /// - (This is based on decimation factors and data size.) for(ii=0;ii<dataInfo->numChans;ii++) { + // New feature to load channel names with DAQ info + // Not presently used, but may be in later versions for live data requests. + strcpy(localTable[ii].chname, dataInfo->tp[ii].channel_name); if ((dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS) > sysRate) { /* Channel data rate is greater than system rate */ printf("Channels %d has bad data rate %d\n", ii, dataInfo->tp[ii].dataRate); @@ -974,6 +1077,7 @@ for(ii=0;ii<dataInfo->numChans;ii++) /// - ---- Load decimation factor localTable[ii].decFactor = sysRate/(dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS); } + // printf("local table %d is %d name %s\n",ii,dataInfo->tp[ii].dataRate,localTable[ii].chname); /// - ---- Calc offset into swing buffer for writing data mydatatype = dataInfo->tp[ii].dataType;