From 1f6c08f75905eaee0fa88b74efaad38a2ae49306 Mon Sep 17 00:00:00 2001 From: Rolf Bork <rbork@caltech.edu> Date: Fri, 22 Nov 2019 10:00:43 -0600 Subject: [PATCH] Ran clang-format on all FE code in src/fe and src/include/drv directories. No other changes. --- src/fe/commData3.c | 32 +- src/fe/controllerApp.c | 1075 ++++++------ src/fe/controllerAppUser.c | 1498 +++++++++-------- src/fe/controllerIop.c | 1765 +++++++++++--------- src/fe/controllerIopUser.c | 1647 ++++++++++--------- src/fe/controllerLR.c | 1932 ++++++++++++---------- src/fe/dolphin.c | 297 ++-- src/fe/map.c | 791 +++++---- src/fe/moduleLoadApp.c | 709 ++++---- src/fe/moduleLoadCommon.c | 234 +-- src/fe/moduleLoadTS.c | 2234 ++++++++++++++----------- src/fe/moduleLoadVirtual.c | 423 ++--- src/fe/rcguser.c | 670 ++++---- src/fe/rcguserIop.c | 770 +++++---- src/fe/timing.c | 168 +- src/include/drv/accesDio24.c | 86 +- src/include/drv/accesIIRO16.c | 92 +- src/include/drv/accesIIRO8.c | 95 +- src/include/drv/adc_info.c | 73 +- src/include/drv/app_adc_read.c | 181 +- src/include/drv/app_dac_functions.c | 327 ++-- src/include/drv/app_dio_routines.c | 210 ++- src/include/drv/contec1616.c | 106 +- src/include/drv/contec32o.c | 63 +- src/include/drv/contec6464.c | 124 +- src/include/drv/dac_info.c | 65 +- src/include/drv/daqLib.c | 2316 ++++++++++++++------------ src/include/drv/daqLibZmq.c | 2355 +++++++++++++++------------ src/include/drv/epicsXfer.c | 189 ++- src/include/drv/fm10Gen.c | 1811 +++++++++++--------- src/include/drv/gsc16ai64.c | 358 ++-- src/include/drv/gsc16ao16.c | 236 +-- src/include/drv/gsc18ai32.c | 320 ++-- src/include/drv/gsc18ai6.c | 140 +- src/include/drv/gsc18ao8.c | 245 +-- src/include/drv/gsc20ao8.c | 298 ++-- src/include/drv/iop_adc_functions.c | 2 +- src/include/drv/iop_dac_functions.c | 598 ++++--- src/include/drv/seiwd.c | 234 +-- src/include/drv/spectracomGPS.c | 372 +++-- src/include/drv/symmetricomGps.c | 259 +-- src/include/drv/tRamp.c | 214 +-- src/include/drv/time_slave_io.c | 4 +- src/include/drv/vmic5565.c | 201 +-- 44 files changed, 14246 insertions(+), 11573 deletions(-) diff --git a/src/fe/commData3.c b/src/fe/commData3.c index 146e25dfa..983643bca 100644 --- a/src/fe/commData3.c +++ b/src/fe/commData3.c @@ -1,6 +1,6 @@ /// @file commData3.c /// @brief This is the generic software for communicating realtime data -///between CDS applications. +/// between CDS applications. /// @detail This software supports data communication via: \n /// 1) Shared memory, between two processes on the same computer \n /// 2) GE Fanuc 5565 Reflected Memory PCIe hardware \n @@ -29,7 +29,7 @@ #endif /// This function is called from the user application to initialize -///communications structures and pointers. +/// communications structures and pointers. /// @param[in] connects = total number of IPC connections in the application /// @param[in] rate = Sample rate of the calling application eg 2048 /// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC @@ -233,12 +233,12 @@ commData3Init( // ************************************************************************************************* /// This function is called from the user application to send data via IPC -///connections. +/// connections. /// @param[in] connects = total number of IPC connections in the application /// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC /// @param[in] timeSec = Present GPS time in GPS seconds /// @param[in] cycle = Present cycle of the user application making this -///call. +/// call. INLINE void commData3Send( int connects, // Total number of IPC connections in the application CDS_IPC_INFO ipcInfo[], // IPC information structure @@ -322,10 +322,10 @@ INLINE void commData3Send( if ( lastPcie >= 0 ) { clflush_cache_range( - (void *)&( ipcInfo[ lastPcie ] - .pIpcDataWrite[ 0 ] - ->dBlock[ sendBlock ][ ipcInfo[ lastPcie ].ipcNum ] - .data ), + (void*)&( ipcInfo[ lastPcie ] + .pIpcDataWrite[ 0 ] + ->dBlock[ sendBlock ][ ipcInfo[ lastPcie ].ipcNum ] + .data ), 16 ); } lastPcie = -1; @@ -381,22 +381,22 @@ INLINE void commData3Send( if ( lastPcie >= 0 ) { clflush_cache_range( - (void *)&( ipcInfo[ lastPcie ] - .pIpcDataWrite[ 0 ] - ->dBlock[ sendBlock ][ ipcInfo[ lastPcie ].ipcNum ] - .data ), + (void*)&( ipcInfo[ lastPcie ] + .pIpcDataWrite[ 0 ] + ->dBlock[ sendBlock ][ ipcInfo[ lastPcie ].ipcNum ] + .data ), 16 ); } } // ************************************************************************************************* /// This function is called from the user application to receive data via -///IPC connections. +/// IPC connections. /// @param[in] connects = total number of IPC connections in the application /// @param[in,out] ipcInfo[] = Stucture to hold information about each IPC /// @param[in] timeSec = Present GPS time in GPS seconds /// @param[in] cycle = Present cycle of the user application making this -///call. +/// call. INLINE void commData3Receive( int connects, // Total number of IPC connections in the application CDS_IPC_INFO ipcInfo[], // IPC information structure @@ -417,8 +417,8 @@ INLINE void commData3Receive( int rcvBlock; // Which of the IPC_BLOCKS IPC data blocks to read from double tmp; // Temp location for data for checking NaN // static unsigned long ptim = 0; // last printing time - // static unsigned long nskipped = 0; // number of skipped error messages - // (couldn't print that fast) + // static unsigned long nskipped = 0; // number of skipped error + // messages (couldn't print that fast) // Determine which block to read, based on present code cycle rcvBlock = ( ( cycle ) * ( IPC_MAX_RATE / IPC_RATE ) ) % IPC_BLOCKS; diff --git a/src/fe/controllerApp.c b/src/fe/controllerApp.c index 5046e0701..2fc872e65 100644 --- a/src/fe/controllerApp.c +++ b/src/fe/controllerApp.c @@ -14,19 +14,21 @@ /// @file controllerApp.c /// @brief Main scheduler program for compiled real-time kernal object. \n /// @detail More information can be found in the following DCC document: -///< <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 CDS RT Sequencer Software</a> +///< <a +///<href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 +///<CDS RT Sequencer Software</a> /// @author R.Bork, A.Ivanov /// @copyright Copyright (C) 2014 LIGO Project \n ///< California Institute of Technology \n ///< Massachusetts Institute of Technology \n\n -/// @license This program is free software: you can redistribute it and/or modify +/// @license This program is free software: you can redistribute it and/or +/// modify ///< it under the terms of the GNU General Public License as published by -///< the Free Software Foundation, version 3 of the License. \n -///< This program is distributed in the hope that it will be useful, -///< but WITHOUT ANY WARRANTY; without even the implied warranty of -///< MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -///< GNU General Public License for more details. - +///< the Free Software Foundation, version 3 of the License. \n This program +///< is distributed in the hope that it will be useful, but WITHOUT ANY +///< WARRANTY; without even the implied warranty of MERCHANTABILITY or +///< FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +///< for more details. #include "controllerko.h" @@ -37,559 +39,658 @@ #include <drv/app_dac_functions.c> #include <drv/app_dio_routines.c> - int startGpsTime = 0; -int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); +int getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec ); int killipc = 0; - // Clear DAC channel shared memory map, // used to keep track of non-overlapping DAC channels among slave models // -void deallocate_dac_channels(void) { - int ii, jj; - for (ii = 0; ii < MAX_DAC_MODULES; ii++) { - int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; - for (jj = 0; jj < 16; jj++) - if (dacOutUsed[ii][jj]) - ioMemData->dacOutUsed[pd][jj] = 0; - } +void +deallocate_dac_channels( void ) +{ + int ii, jj; + for ( ii = 0; ii < MAX_DAC_MODULES; ii++ ) + { + int pd = cdsPciModules.dacConfig[ ii ] - ioMemData->adcCount; + for ( jj = 0; jj < 16; jj++ ) + if ( dacOutUsed[ ii ][ jj ] ) + ioMemData->dacOutUsed[ pd ][ jj ] = 0; + } } //*********************************************************************** -// TASK: fe_start_app() -// This routine is the skeleton for all front end code +// TASK: fe_start_app() +// This routine is the skeleton for all front end code //*********************************************************************** -/// This function is the main real-time sequencer or scheduler for all code built -/// using the RCG. \n -/// There are two primary modes of operation, based on two compile options: \n -/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). +/// This function is the main real-time sequencer or scheduler for all code +/// built using the RCG. \n There are two primary modes of operation, based on +/// two compile options: \n +/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). /// - ADC_SLAVE: Normal user control process. -/// This code runs in a continuous loop at the rate specified in the RCG model. The -/// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn -/// is triggered to sample by the 64KHz clock provided by the Timing Distribution System. -/// - -void *fe_start_app(void *arg) +/// This code runs in a continuous loop at the rate specified in the RCG model. +/// The loop is synchronized and triggered by the arrival of ADC data, the ADC +/// module in turn is triggered to sample by the 64KHz clock provided by the +/// Timing Distribution System. +/// - +void* +fe_start_app( void* arg ) { - int ii,jj,kk,ll; // Dummy loop counter variables - static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) - static int cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables - - - static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code - ///< Code runs longer for first few cycles on startup as it settles in, - ///< so this helps prevent long cycles during that time. - int dkiTrip = 0; - RFM_FE_COMMS *pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared memory space - int myGmError2 = 0; /// @param myGmError2 Myrinet error variable - int status; /// @param status Typical function return value - int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check + int ii, jj, kk, ll; // Dummy loop counter variables + static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) + static int cpuClock[ CPU_TIMER_CNT ]; /// @param cpuClock[] Code timing + /// diag variables + + static int dacWriteEnable = + 0; /// @param dacWriteEnable No DAC outputs until >4 times through code + ///< Code runs longer for first few cycles on startup as it settles + ///< in, so this helps prevent long cycles during that time. + int dkiTrip = 0; + RFM_FE_COMMS* pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared + /// memory space + int myGmError2 = 0; /// @param myGmError2 Myrinet error variable + int status; /// @param status Typical function return value + int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check #ifdef DIAG_TEST - float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for diagnostics - int onePpsHiTest[10]; /// @param onePpsHiTest[] One PPS diagnostic check - int onePpsTimeTest[10]; /// @param onePpsTimeTest[] One PPS diagnostic check + float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for + /// diagnostics + int onePpsHiTest[ 10 ]; /// @param onePpsHiTest[] One PPS diagnostic check + int onePpsTimeTest[ 10 ]; /// @param onePpsTimeTest[] One PPS diagnostic + /// check #endif - int dcuId; /// @param dcuId DAQ ID number for this process - int diagWord = 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS - int system = 0; - int sampleCount = 1; /// @param sampleCount Number of ADC samples to take per code cycle - int syncSource = SYNC_SRC_MASTER; /// @param syncSource Code startup synchronization source - int mxStat = 0; /// @param mxStat Net diags when myrinet express is used - int mxDiag = 0; - int mxDiagR = 0; -// ****** Share data - int ioClockDac = DAC_PRELOAD_CNT; - int ioMemCntr = 0; - int ioMemCntrDac = DAC_PRELOAD_CNT; - int ioClock = 0; - - int feStatus = 0; - - - unsigned long cpc; - -/// **********************************************************************************************\n -/// Start Initialization Process \n -/// **********************************************************************************************\n - - /// \> Flush L1 cache - memset (fp, 0, 64*1024); - memset (fp, 1, 64*1024); - clflush_cache_range ((void *)fp, 64*1024); - - fz_daz(); /// \> Kill the denorms! - - /// \> Init comms with EPICS processor */ - pEpicsComms = (RFM_FE_COMMS *)_epics_shm; - pLocalEpics = (CDS_EPICS *)&pEpicsComms->epicsSpace; - pEpicsDaq = (char *)&(pLocalEpics->epicsOutput); + int dcuId; /// @param dcuId DAQ ID number for this process + int diagWord = + 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS + int system = 0; + int sampleCount = + 1; /// @param sampleCount Number of ADC samples to take per code cycle + int syncSource = SYNC_SRC_MASTER; /// @param syncSource Code startup + /// synchronization source + int mxStat = 0; /// @param mxStat Net diags when myrinet express is used + int mxDiag = 0; + int mxDiagR = 0; + // ****** Share data + int ioClockDac = DAC_PRELOAD_CNT; + int ioMemCntr = 0; + int ioMemCntrDac = DAC_PRELOAD_CNT; + int ioClock = 0; + + int feStatus = 0; + + unsigned long cpc; + + /// **********************************************************************************************\n + /// Start Initialization Process \n + /// **********************************************************************************************\n + + /// \> Flush L1 cache + memset( fp, 0, 64 * 1024 ); + memset( fp, 1, 64 * 1024 ); + clflush_cache_range( (void*)fp, 64 * 1024 ); + + fz_daz( ); /// \> Kill the denorms! + + /// \> Init comms with EPICS processor */ + pEpicsComms = (RFM_FE_COMMS*)_epics_shm; + pLocalEpics = (CDS_EPICS*)&pEpicsComms->epicsSpace; + pEpicsDaq = (char*)&( pLocalEpics->epicsOutput ); #ifdef OVERSAMPLE - /// \> Zero out filter histories - memset(dHistory, 0, sizeof(dHistory)); - memset(dDacHistory, 0, sizeof(dDacHistory)); + /// \> Zero out filter histories + memset( dHistory, 0, sizeof( dHistory ) ); + memset( dDacHistory, 0, sizeof( dDacHistory ) ); #endif - /// \> Zero out DAC outputs - for (ii = 0; ii < MAX_DAC_MODULES; ii++) - { - for (jj = 0; jj < 16; jj++) { - dacOut[ii][jj] = 0.0; - dacOutUsed[ii][jj] = 0; + /// \> Zero out DAC outputs + for ( ii = 0; ii < MAX_DAC_MODULES; ii++ ) + { + for ( jj = 0; jj < 16; jj++ ) + { + dacOut[ ii ][ jj ] = 0.0; + dacOutUsed[ ii ][ jj ] = 0; + } } - } - /// \> Set pointers to filter module data buffers. \n - /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n - /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n - /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n - /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n - pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace); - dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - - /// \> Clear the FE reset which comes from Epics - pLocalEpics->epicsInput.vmeReset = 0; + /// \> Set pointers to filter module data buffers. \n + /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD + /// data.\n + /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done + /// to: \n + /// - -------- Allow daqLib.c to retrieve filter module data directly from + /// shared memory. \n + /// - -------- Avoid copy of filter module data between to memory locations, + /// which was slow. \n + pDsp[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + pCoeff[ system ] = (VME_COEF*)( &pEpicsComms->coeffSpace ); + dspPtr[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + + /// \> Clear the FE reset which comes from Epics + pLocalEpics->epicsInput.vmeReset = 0; + + // Clear input masks + pLocalEpics->epicsInput.burtRestore_mask = 0; + pLocalEpics->epicsInput.dacDuoSet_mask = 0; + + /// < Read in all Filter Module EPICS coeff settings + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + checkFiltReset( ii, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); + } - // Clear input masks - pLocalEpics->epicsInput.burtRestore_mask = 0; - pLocalEpics->epicsInput.dacDuoSet_mask = 0; + // Need this FE dcuId to make connection to FB + dcuId = pLocalEpics->epicsInput.dcuId; + pLocalEpics->epicsOutput.dcuId = dcuId; + // Reset timing diagnostics + pLocalEpics->epicsOutput.diagWord = 0; + pLocalEpics->epicsOutput.timeDiag = 0; + pLocalEpics->epicsOutput.timeErr = syncSource; -/// < Read in all Filter Module EPICS coeff settings - for(ii=0;ii<MAX_MODULES;ii++) + /// \> Init IIR filter banks + // Initialize filter banks ********************************************* + for ( system = 0; system < NUM_SYSTEMS; system++ ) { - checkFiltReset(ii, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - } - - // Need this FE dcuId to make connection to FB - dcuId = pLocalEpics->epicsInput.dcuId; - pLocalEpics->epicsOutput.dcuId = dcuId; - - // Reset timing diagnostics - pLocalEpics->epicsOutput.diagWord = 0; - pLocalEpics->epicsOutput.timeDiag = 0; - pLocalEpics->epicsOutput.timeErr = syncSource; - -/// \> Init IIR filter banks -// Initialize filter banks ********************************************* - for (system = 0; system < NUM_SYSTEMS; system++) { - for(ii=0;ii<MAX_MODULES;ii++){ - for(jj=0;jj<FILTERS;jj++){ - for(kk=0;kk<MAX_COEFFS;kk++){ - dspCoeff[system].coeffs[ii].filtCoeff[jj][kk] = 0.0; + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + for ( jj = 0; jj < FILTERS; jj++ ) + { + for ( kk = 0; kk < MAX_COEFFS; kk++ ) + { + dspCoeff[ system ].coeffs[ ii ].filtCoeff[ jj ][ kk ] = 0.0; + } + dspCoeff[ system ].coeffs[ ii ].filtSections[ jj ] = 0; + } } - dspCoeff[system].coeffs[ii].filtSections[jj] = 0; - } } - } - /// \> Initialize all filter module excitation signals to zero - for (system = 0; system < NUM_SYSTEMS; system++) - for(ii=0;ii<MAX_MODULES;ii++) - // dsp[system].data[ii].exciteInput = 0.0; - pDsp[0]->data[ii].exciteInput = 0.0; + /// \> Initialize all filter module excitation signals to zero + for ( system = 0; system < NUM_SYSTEMS; system++ ) + for ( ii = 0; ii < MAX_MODULES; ii++ ) + // dsp[system].data[ii].exciteInput = 0.0; + pDsp[ 0 ]->data[ ii ].exciteInput = 0.0; - - /// \> Initialize IIR filter bank values - if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) { - pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR; - return 0; + /// \> Initialize IIR filter bank values + if ( initVars( pDsp[ 0 ], pDsp[ 0 ], dspCoeff, MAX_MODULES, pCoeff[ 0 ] ) ) + { + pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR; + return 0; } + udelay( 1000 ); -udelay(1000); - -/// \> Initialize DAQ variable/software -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Set data range limits for daqLib routine -#if defined(SERVO2K) || defined(SERVO4K) - daq.filtExMin = GDS_2K_EXC_MIN; - daq.filtTpMin = GDS_2K_TP_MIN; +/// \> Initialize DAQ variable/software +#if !defined( NO_DAQ ) && !defined( IOP_TASK ) + /// - ---- Set data range limits for daqLib routine +#if defined( SERVO2K ) || defined( SERVO4K ) + daq.filtExMin = GDS_2K_EXC_MIN; + daq.filtTpMin = GDS_2K_TP_MIN; #else - daq.filtExMin = GDS_16K_EXC_MIN; - daq.filtTpMin = GDS_16K_TP_MIN; + daq.filtExMin = GDS_16K_EXC_MIN; + daq.filtTpMin = GDS_16K_TP_MIN; #endif - daq.filtExMax = daq.filtExMin + MAX_MODULES; - daq.filtExSize = MAX_MODULES; - daq.xExMin = daq.filtExMax; - daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; - daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; - daq.filtTpSize = MAX_MODULES * 3; - daq.xTpMin = daq.filtTpMax; - daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; - - /// - ---- Initialize DAQ function - status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - if(status == -1) - { - pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR; - vmeDone = 1; - return(0); - } + daq.filtExMax = daq.filtExMin + MAX_MODULES; + daq.filtExSize = MAX_MODULES; + daq.xExMin = daq.filtExMax; + daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; + daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; + daq.filtTpSize = MAX_MODULES * 3; + daq.xTpMin = daq.filtTpMax; + daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; + + /// - ---- Initialize DAQ function + status = daqWrite( 0, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + 0, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + if ( status == -1 ) + { + pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR; + vmeDone = 1; + return ( 0 ); + } #endif - /// - ---- Assign DAC testpoint pointers - for (ii = 0; ii < cdsPciModules.dacCount; ii++) - for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) // 16 per DAC regardless of the actual - testpoint[MAX_DAC_CHN_PER_MOD * ii + jj] = floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; - - // Zero out storage - memset(floatDacOut, 0, sizeof(floatDacOut)); - - pLocalEpics->epicsOutput.ipcStat = 0; - pLocalEpics->epicsOutput.fbNetStat = 0; - pLocalEpics->epicsOutput.tpCnt = 0; - - - /// \> Read Dio card initial values - /// - ---- SLAVE units read/write their own DIO \n - /// - ---- MASTER units ignore DIO for speed reasons \n - status = app_dio_init(); - - - // Clear the code exit flag - vmeDone = 0; - - /// \> Call user application software initialization routine. - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); - -// Initialize timing info variables - initializeTimingDiags(&timeinfo); - - pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; - /// \> Initialize DAC channels. - status = app_dac_init(); - if (status) { - pLocalEpics->epicsOutput.fe_status = DAC_INIT_ERROR; - return(0); - } + /// - ---- Assign DAC testpoint pointers + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + for ( jj = 0; jj < MAX_DAC_CHN_PER_MOD; + jj++ ) // 16 per DAC regardless of the actual + testpoint[ MAX_DAC_CHN_PER_MOD * ii + jj ] = + floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; + + // Zero out storage + memset( floatDacOut, 0, sizeof( floatDacOut ) ); + + pLocalEpics->epicsOutput.ipcStat = 0; + pLocalEpics->epicsOutput.fbNetStat = 0; + pLocalEpics->epicsOutput.tpCnt = 0; + + /// \> Read Dio card initial values + /// - ---- SLAVE units read/write their own DIO \n + /// - ---- MASTER units ignore DIO for speed reasons \n + status = app_dio_init( ); + + // Clear the code exit flag + vmeDone = 0; + + /// \> Call user application software initialization routine. + iopDacEnable = feCode( cycleNum, + dWord, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 1 ); + + // Initialize timing info variables + initializeTimingDiags( &timeinfo ); + + pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; + /// \> Initialize DAC channels. + status = app_dac_init( ); + if ( status ) + { + pLocalEpics->epicsOutput.fe_status = DAC_INIT_ERROR; + return ( 0 ); + } - /// \> Initialize the ADC status - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - pLocalEpics->epicsOutput.statAdc[jj] = 1; - } + /// \> Initialize the ADC status + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] = 1; + } - // SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc memory - // Find memory buffer of first ADC to be used in SLAVE application. - ll = cdsPciModules.adcConfig[0]; - cpuClock[CPU_TIME_CYCLE_START] = rdtsc_ordered(); + // SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc + // memory Find memory buffer of first ADC to be used in SLAVE application. + ll = cdsPciModules.adcConfig[ 0 ]; + cpuClock[ CPU_TIME_CYCLE_START ] = rdtsc_ordered( ); - pLocalEpics->epicsOutput.fe_status = INIT_SYNC; + pLocalEpics->epicsOutput.fe_status = INIT_SYNC; // Spin until cycle 0 detected in first ADC buffer location. - do { - udelay(1); - } while(ioMemData->iodata[ll][0].cycle != 0); - pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; - - timeSec = ioMemData->iodata[ll][0].timeSec; - cpuClock[CPU_TIME_CYCLE_END] = rdtsc_ordered(); - timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - // Get GPS seconds from MASTER - timeSec = ioMemData->gpsSecond; - pLocalEpics->epicsOutput.timeDiag = timeSec; - // Decrement GPS seconds as it will be incremented on first read cycle. - timeSec --; - - onePpsTime = cycleNum; + do + { + udelay( 1 ); + } while ( ioMemData->iodata[ ll ][ 0 ].cycle != 0 ); + pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; + + timeSec = ioMemData->iodata[ ll ][ 0 ].timeSec; + cpuClock[ CPU_TIME_CYCLE_END ] = rdtsc_ordered( ); + timeinfo.cycleTime = + ( cpuClock[ CPU_TIME_CYCLE_END ] - cpuClock[ CPU_TIME_CYCLE_START ] ) / + CPURATE; + // Get GPS seconds from MASTER + timeSec = ioMemData->gpsSecond; + pLocalEpics->epicsOutput.timeDiag = timeSec; + // Decrement GPS seconds as it will be incremented on first read cycle. + timeSec--; + + onePpsTime = cycleNum; #ifdef REMOTE_GPS - timeSec = remote_time((struct CDS_EPICS *)pLocalEpics); + timeSec = remote_time( (struct CDS_EPICS*)pLocalEpics ); #else - timeSec = current_time_fe() -1; + timeSec = current_time_fe( ) - 1; #endif - adcinfo.adcTime = rdtsc_ordered(); - - /// ******************************************************************************\n - /// Enter the infinite FE control loop ******************************************\n + adcinfo.adcTime = rdtsc_ordered( ); - /// ******************************************************************************\n - // Calculate how many CPU cycles per code cycle - cpc = cpu_khz * 1000; - cpc /= CYCLE_PER_SECOND; + /// ******************************************************************************\n + /// Enter the infinite FE control loop + /// ******************************************\n + /// ******************************************************************************\n + // Calculate how many CPU cycles per code cycle + cpc = cpu_khz * 1000; + cpc /= CYCLE_PER_SECOND; - // ******************************************************************************* - // NORMAL OPERATION -- Wait for ADC data ready - // On startup, only want to read one sample such that first cycle - // coincides with GPS 1PPS. Thereafter, sampleCount will be - // increased to appropriate number of 65536 s/sec to match desired - // code rate eg 32 samples each time thru before proceeding to match 2048 system. - // ******************************************************************************* + // ******************************************************************************* + // NORMAL OPERATION -- Wait for ADC data ready + // On startup, only want to read one sample such that first cycle + // coincides with GPS 1PPS. Thereafter, sampleCount will be + // increased to appropriate number of 65536 s/sec to match desired + // code rate eg 32 samples each time thru before proceeding to match 2048 + // system. + // ******************************************************************************* #ifdef NO_CPU_SHUTDOWN - while(!kthread_should_stop()){ + while ( !kthread_should_stop( ) ) + { #else - while(!vmeDone){ // Run forever until user hits reset + while ( !vmeDone ) + { // Run forever until user hits reset #endif -/// \> On 1PPS mark \n - if(cycleNum == 0) - { - /// - ---- Check awgtpman status. - pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); - if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG; - /// - ---- Check if DAC outputs are enabled, report error. - if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE; - - } + /// \> On 1PPS mark \n + if ( cycleNum == 0 ) + { + /// - ---- Check awgtpman status. + pLocalEpics->epicsOutput.awgStat = + ( pEpicsComms->padSpace.awgtpman_gps != timeSec ); + if ( pLocalEpics->epicsOutput.awgStat ) + feStatus |= FE_ERROR_AWG; + /// - ---- Check if DAC outputs are enabled, report error. + if ( !iopDacEnable || dkiTrip ) + feStatus |= FE_ERROR_DAC_ENABLE; + } #ifdef NO_CPU_SHUTDOWN - if(vmeDone)usleep_range(2,4); + if ( vmeDone ) + usleep_range( 2, 4 ); #endif - for(ll=0;ll<sampleCount;ll++) - { - status = app_adc_read(ioMemCntr,ioClock,&adcinfo,cpuClock); - - // Return of non zero = ADC timeout error. - if(status) + for ( ll = 0; ll < sampleCount; ll++ ) { - pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; - pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR; - pLocalEpics->epicsOutput.fe_status = ADC_TO_ERROR; - deallocate_dac_channels(); - return (void *)-1; + status = app_adc_read( ioMemCntr, ioClock, &adcinfo, cpuClock ); + + // Return of non zero = ADC timeout error. + if ( status ) + { + pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; + pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR; + pLocalEpics->epicsOutput.fe_status = ADC_TO_ERROR; + deallocate_dac_channels( ); + return (void*)-1; + } + + /// \> Set counters for next read from ipc memory + ioClock = ( ioClock + 1 ) % IOP_IO_RATE; + ioMemCntr = ( ioMemCntr + 1 ) % IO_MEMORY_SLOTS; + cpuClock[ CPU_TIME_CYCLE_START ] = rdtsc_ordered( ); } - /// \> Set counters for next read from ipc memory - ioClock = (ioClock + 1) % IOP_IO_RATE; - ioMemCntr = (ioMemCntr + 1) % IO_MEMORY_SLOTS; - cpuClock[CPU_TIME_CYCLE_START] = rdtsc_ordered(); - - } - - - // After first synced ADC read, must set code to read number samples/cycle - sampleCount = OVERSAMPLE_TIMES; - - -/// \> Call the front end specific application ******************\n -/// - -- This is where the user application produced by RCG gets called and executed. \n\n - cpuClock[CPU_TIME_USR_START] = rdtsc_ordered(); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0); - cpuClock[CPU_TIME_USR_END] = rdtsc_ordered(); - odcStateWord = 0; - - -// ********************************************************************** -/// START OF USER APP DAC WRITE ***************************************** - // Write out data to DAC modules -// ********************************************************************** - status = app_dac_write(ioMemCntrDac,ioClockDac, &dacinfo); - /// \> Increment DAC memory block pointers for next cycle - ioClockDac = (ioClockDac + OVERSAMPLE_TIMES) % IOP_IO_RATE; - ioMemCntrDac = (ioMemCntrDac + OVERSAMPLE_TIMES) % IO_MEMORY_SLOTS; - if(dacWriteEnable < 10) dacWriteEnable ++; -/// END OF USER APP DAC WRITE ************************************************* - - -// ********************************************************************** -/// BEGIN HOUSEKEEPING ************************************************ \n -// ********************************************************************** - - pLocalEpics->epicsOutput.cycle = cycleNum; + // After first synced ADC read, must set code to read number + // samples/cycle + sampleCount = OVERSAMPLE_TIMES; + + /// \> Call the front end specific application ******************\n + /// - -- This is where the user application produced by RCG gets called + /// and executed. \n\n + cpuClock[ CPU_TIME_USR_START ] = rdtsc_ordered( ); + iopDacEnable = feCode( cycleNum, + dWord, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 0 ); + cpuClock[ CPU_TIME_USR_END ] = rdtsc_ordered( ); + odcStateWord = 0; + + // ********************************************************************** + /// START OF USER APP DAC WRITE + /// ***************************************** + // Write out data to DAC modules + // ********************************************************************** + status = app_dac_write( ioMemCntrDac, ioClockDac, &dacinfo ); + /// \> Increment DAC memory block pointers for next cycle + ioClockDac = ( ioClockDac + OVERSAMPLE_TIMES ) % IOP_IO_RATE; + ioMemCntrDac = ( ioMemCntrDac + OVERSAMPLE_TIMES ) % IO_MEMORY_SLOTS; + if ( dacWriteEnable < 10 ) + dacWriteEnable++; + /// END OF USER APP DAC WRITE + /// ************************************************* + + // ********************************************************************** + /// BEGIN HOUSEKEEPING ************************************************ + /// \n + // ********************************************************************** + + pLocalEpics->epicsOutput.cycle = cycleNum; #ifdef NO_CPU_SHUTDOWN - if((cycleNum % 2048) == 0) { - usleep_range(1,3); - printk("cycleNum = %d\n",cycleNum); - } + if ( ( cycleNum % 2048 ) == 0 ) + { + usleep_range( 1, 3 ); + printk( "cycleNum = %d\n", cycleNum ); + } #endif -// ********************************************************************** -/// \> Cycle 18, Send timing info to EPICS at 1Hz -// ********************************************************************** - if(cycleNum ==HKP_TIMING_UPDATES) - { - sendTimingDiags2Epics(pLocalEpics, &timeinfo, &adcinfo); - - if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) - { - diagWord |= FE_ADC_HOLD_ERR; - feStatus |= FE_ERROR_TIMING; - } - if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) - { - diagWord |= FE_PROC_TIME_ERR; - feStatus |= FE_ERROR_TIMING; - } - pLocalEpics->epicsOutput.stateWord = feStatus; - feStatus = 0; - if(pLocalEpics->epicsInput.diagReset || initialDiagReset) - { - initialDiagReset = 0; - pLocalEpics->epicsInput.diagReset = 0; - pLocalEpics->epicsInput.ipcDiagReset = 1; - timeinfo.timeHoldMax = 0; - diagWord = 0; - ipcErrBits = 0; - - } - pLocalEpics->epicsOutput.diagWord = diagWord; - } - -// ***************************************************************** -/// \> Check for requests for filter module clear history requests. This is spread out over a number of cycles. - // Spread out filter coeff update, but keep updates at 16 Hz - // here we are rounding up: - // x/y rounded up equals (x + y - 1) / y - // -// ***************************************************************** - static const unsigned int mpc = (MAX_MODULES + (FE_RATE / 16) - 1) / (FE_RATE / 16); // Modules per cycle - unsigned int smpc = mpc * subcycle; // Start module counter - unsigned int empc = smpc + mpc; // End module counter - unsigned int i; - for (i = smpc; i < MAX_MODULES && i < empc ; i++) - checkFiltReset(i, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - -// ***************************************************************** - /// \> Check if code exit is requested - if(cycleNum == MAX_MODULES) - vmeDone = stop_working_threads | checkEpicsReset(cycleNum, (struct CDS_EPICS *)pLocalEpics); -// ***************************************************************** - -// ***************************************************************** -/// \> Cycle 10 to number of BIO cards:\n - /// - ---- Read Dio cards once per second \n -// ***************************************************************** + // ********************************************************************** + /// \> Cycle 18, Send timing info to EPICS at 1Hz + // ********************************************************************** + if ( cycleNum == HKP_TIMING_UPDATES ) + { + sendTimingDiags2Epics( pLocalEpics, &timeinfo, &adcinfo ); + + if ( ( adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI ) || + ( adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO ) ) + { + diagWord |= FE_ADC_HOLD_ERR; + feStatus |= FE_ERROR_TIMING; + } + if ( timeinfo.timeHoldMax > CYCLE_TIME_ALRM ) + { + diagWord |= FE_PROC_TIME_ERR; + feStatus |= FE_ERROR_TIMING; + } + pLocalEpics->epicsOutput.stateWord = feStatus; + feStatus = 0; + if ( pLocalEpics->epicsInput.diagReset || initialDiagReset ) + { + initialDiagReset = 0; + pLocalEpics->epicsInput.diagReset = 0; + pLocalEpics->epicsInput.ipcDiagReset = 1; + timeinfo.timeHoldMax = 0; + diagWord = 0; + ipcErrBits = 0; + } + pLocalEpics->epicsOutput.diagWord = diagWord; + } - status = app_dio_read_write(); + // ***************************************************************** + /// \> Check for requests for filter module clear history requests. This + /// is spread out over a number of cycles. + // Spread out filter coeff update, but keep updates at 16 Hz + // here we are rounding up: + // x/y rounded up equals (x + y - 1) / y + // + // ***************************************************************** + static const unsigned int mpc = ( MAX_MODULES + ( FE_RATE / 16 ) - 1 ) / + ( FE_RATE / 16 ); // Modules per cycle + unsigned int smpc = mpc * subcycle; // Start module counter + unsigned int empc = smpc + mpc; // End module counter + unsigned int i; + for ( i = smpc; i < MAX_MODULES && i < empc; i++ ) + checkFiltReset( i, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); + + // ***************************************************************** + /// \> Check if code exit is requested + if ( cycleNum == MAX_MODULES ) + vmeDone = stop_working_threads | + checkEpicsReset( cycleNum, (struct CDS_EPICS*)pLocalEpics ); + // ***************************************************************** + + // ***************************************************************** + /// \> Cycle 10 to number of BIO cards:\n + /// - ---- Read Dio cards once per second \n + // ***************************************************************** + + status = app_dio_read_write( ); // ***************************************************************** /// \> Write data to DAQ. // ***************************************************************** #ifndef NO_DAQ - - // Call daqLib - pLocalEpics->epicsOutput.daqByteCnt = - daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - // Send the current DAQ block size to the awgtpman for TP number checking - pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; - pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; - feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); - if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; - else odcStateWord &= ~(ODC_EXC_SET); - if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) - feStatus |= FE_ERROR_DAQ; + + // Call daqLib + pLocalEpics->epicsOutput.daqByteCnt = + daqWrite( 1, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + myGmError2, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + // Send the current DAQ block size to the awgtpman for TP number + // checking + pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; + pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; + feStatus |= ( FE_ERROR_EXC_SET & tpPtr->count ); + if ( FE_ERROR_EXC_SET & tpPtr->count ) + odcStateWord |= ODC_EXC_SET; + else + odcStateWord &= ~( ODC_EXC_SET ); + if ( pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING ) + feStatus |= FE_ERROR_DAQ; #endif -// ***************************************************************** -/// \> Cycle 19, write updated diag info to EPICS -// ***************************************************************** - if(cycleNum == HKP_DIAG_UPDATES) - { - pLocalEpics->epicsOutput.ipcStat = ipcErrBits; - if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; - // Create FB status word for return to EPICS - mxStat = 0; - mxDiagR = daqPtr->reqAck; - if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; - if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; + // ***************************************************************** + /// \> Cycle 19, write updated diag info to EPICS + // ***************************************************************** + if ( cycleNum == HKP_DIAG_UPDATES ) + { + pLocalEpics->epicsOutput.ipcStat = ipcErrBits; + if ( ipcErrBits & 0xf ) + feStatus |= FE_ERROR_IPC; + // Create FB status word for return to EPICS + mxStat = 0; + mxDiagR = daqPtr->reqAck; + if ( ( mxDiag & 1 ) != ( mxDiagR & 1 ) ) + mxStat = 1; + if ( ( mxDiag & 2 ) != ( mxDiagR & 2 ) ) + mxStat += 2; #ifdef DUAL_DAQ_DC - if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; - if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; + if ( ( mxDiag & 4 ) != ( mxDiagR & 4 ) ) + mxStat += 4; + if ( ( mxDiag & 8 ) != ( mxDiagR & 8 ) ) + mxStat += 8; #endif - pLocalEpics->epicsOutput.fbNetStat = mxStat; - mxDiag = mxDiagR; - if(mxStat != MX_OK) feStatus |= FE_ERROR_DAQ;; - if(pLocalEpics->epicsInput.overflowReset) - { - if (pLocalEpics->epicsInput.overflowReset) { - for (ii = 0; ii < 16; ii++) { - for (jj = 0; jj < cdsPciModules.adcCount; jj++) { - adcinfo.overflowAdc[jj][ii] = 0; - adcinfo.overflowAdc[jj][ii + 16] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; - } - for (jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; - } - } - } - } - if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) - { - pLocalEpics->epicsInput.overflowReset = 0; - pLocalEpics->epicsOutput.ovAccum = 0; - overflowAcc = 0; - } - } - - if(cycleNum == 1) - { - pLocalEpics->epicsOutput.timeDiag = timeSec; - } + pLocalEpics->epicsOutput.fbNetStat = mxStat; + mxDiag = mxDiagR; + if ( mxStat != MX_OK ) + feStatus |= FE_ERROR_DAQ; + ; + if ( pLocalEpics->epicsInput.overflowReset ) + { + if ( pLocalEpics->epicsInput.overflowReset ) + { + for ( ii = 0; ii < 16; ii++ ) + { + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + adcinfo.overflowAdc[ jj ][ ii ] = 0; + adcinfo.overflowAdc[ jj ][ ii + 16 ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii + 16 ] = 0; + } + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + pLocalEpics->epicsOutput + .overflowDacAcc[ jj ][ ii ] = 0; + } + } + } + } + if ( ( pLocalEpics->epicsInput.overflowReset ) || + ( overflowAcc > OVERFLOW_CNTR_LIMIT ) ) + { + pLocalEpics->epicsInput.overflowReset = 0; + pLocalEpics->epicsOutput.ovAccum = 0; + overflowAcc = 0; + } + } -// ***************************************************************** -/// \> Cycle 20, Update latest DAC output values to EPICS -// ***************************************************************** - if(subcycle == HKP_DAC_EPICS_UPDATES) - { - // Send DAC output values at 16Hzfb - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacinfo.dacOutEpics[jj][ii]; - } - } - } + if ( cycleNum == 1 ) + { + pLocalEpics->epicsOutput.timeDiag = timeSec; + } -// ***************************************************************** -/// \> Cycle 21, Update ADC/DAC status to EPICS. -// ***************************************************************** - if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) - { - pLocalEpics->epicsOutput.ovAccum = overflowAcc; - feStatus |= app_adc_status_update(&adcinfo); - feStatus |= app_dac_status_update(&dacinfo); - } - - // ***************************************************************** - // // Update end of cycle information - // // ***************************************************************** - // Capture end of cycle time. - cpuClock[CPU_TIME_CYCLE_END] = rdtsc_ordered(); - - captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo); - - /// \> Compute code cycle time diag information. - timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - - adcinfo.adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcinfo.adcTime)/CPURATE; - adcinfo.adcTime = cpuClock[CPU_TIME_CYCLE_START]; - // Calc the max time of one cycle of the user code - timeinfo.usrTime = (cpuClock[CPU_TIME_USR_END] - cpuClock[CPU_TIME_USR_START])/CPURATE; - if(timeinfo.usrTime > timeinfo.usrHoldTime) timeinfo.usrHoldTime = timeinfo.usrTime; - - /// \> Update internal cycle counters - cycleNum += 1; - cycleNum %= CYCLE_PER_SECOND; - clock1Min += 1; - clock1Min %= CYCLE_PER_MINUTE; - if(subcycle == DAQ_CYCLE_CHANGE) - { - daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle; - } - if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ - { - /* Reset the data cycle counter */ - subcycle = 0; - } - else{ - /* Increment the internal cycle counter */ - subcycle ++; - } + // ***************************************************************** + /// \> Cycle 20, Update latest DAC output values to EPICS + // ***************************************************************** + if ( subcycle == HKP_DAC_EPICS_UPDATES ) + { + // Send DAC output values at 16Hzfb + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { + pLocalEpics->epicsOutput.dacValue[ jj ][ ii ] = + dacinfo.dacOutEpics[ jj ][ ii ]; + } + } + } + + // ***************************************************************** + /// \> Cycle 21, Update ADC/DAC status to EPICS. + // ***************************************************************** + if ( cycleNum == HKP_ADC_DAC_STAT_UPDATES ) + { + pLocalEpics->epicsOutput.ovAccum = overflowAcc; + feStatus |= app_adc_status_update( &adcinfo ); + feStatus |= app_dac_status_update( &dacinfo ); + } + + // ***************************************************************** + // // Update end of cycle information + // // ***************************************************************** + // Capture end of cycle time. + cpuClock[ CPU_TIME_CYCLE_END ] = rdtsc_ordered( ); + + captureEocTiming( cycleNum, cycle_gps_time, &timeinfo, &adcinfo ); + + /// \> Compute code cycle time diag information. + timeinfo.cycleTime = ( cpuClock[ CPU_TIME_CYCLE_END ] - + cpuClock[ CPU_TIME_CYCLE_START ] ) / + CPURATE; + + adcinfo.adcHoldTime = + ( cpuClock[ CPU_TIME_CYCLE_START ] - adcinfo.adcTime ) / CPURATE; + adcinfo.adcTime = cpuClock[ CPU_TIME_CYCLE_START ]; + // Calc the max time of one cycle of the user code + timeinfo.usrTime = + ( cpuClock[ CPU_TIME_USR_END ] - cpuClock[ CPU_TIME_USR_START ] ) / + CPURATE; + if ( timeinfo.usrTime > timeinfo.usrHoldTime ) + timeinfo.usrHoldTime = timeinfo.usrTime; + + /// \> Update internal cycle counters + cycleNum += 1; + cycleNum %= CYCLE_PER_SECOND; + clock1Min += 1; + clock1Min %= CYCLE_PER_MINUTE; + if ( subcycle == DAQ_CYCLE_CHANGE ) + { + daqCycle = ( daqCycle + 1 ) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; + if ( !( daqCycle % 2 ) ) + pLocalEpics->epicsOutput.epicsSync = daqCycle; + } + if ( subcycle == + END_OF_DAQ_BLOCK ) /*we have reached the 16Hz second barrier*/ + { + /* Reset the data cycle counter */ + subcycle = 0; + } + else + { + /* Increment the internal cycle counter */ + subcycle++; + } -/// \> If not exit request, then continue INFINITE LOOP ******* - } + /// \> If not exit request, then continue INFINITE LOOP ******* + } - pLocalEpics->epicsOutput.cpuMeter = 0; + pLocalEpics->epicsOutput.cpuMeter = 0; - deallocate_dac_channels(); + deallocate_dac_channels( ); - /* System reset command received */ - return (void *)-1; + /* System reset command received */ + return (void*)-1; } diff --git a/src/fe/controllerAppUser.c b/src/fe/controllerAppUser.c index bf31d5830..04095b3cf 100644 --- a/src/fe/controllerAppUser.c +++ b/src/fe/controllerAppUser.c @@ -12,22 +12,24 @@ /*----------------------------------------------------------------------*/ /// @file controllerAppUser.c -/// @brief Main scheduler program for compiled real-time user space object. \n +/// @brief Main scheduler program for compiled real-time user space object. +///\n /// @detail More information can be found in the following DCC document: -///< <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 CDS RT Sequencer Software</a> +///< <a +///<href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 +///<CDS RT Sequencer Software</a> /// @author R.Bork, A.Ivanov /// @copyright Copyright (C) 2014 LIGO Project \n ///< California Institute of Technology \n ///< Massachusetts Institute of Technology \n\n -/// @license This program is free software: you can redistribute it and/or modify +/// @license This program is free software: you can redistribute it and/or +/// modify ///< it under the terms of the GNU General Public License as published by -///< the Free Software Foundation, version 3 of the License. \n -///< This program is distributed in the hope that it will be useful, -///< but WITHOUT ANY WARRANTY; without even the implied warranty of -///< MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -///< GNU General Public License for more details. - - +///< the Free Software Foundation, version 3 of the License. \n This program +///< is distributed in the hope that it will be useful, but WITHOUT ANY +///< WARRANTY; without even the implied warranty of MERCHANTABILITY or +///< FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +///< for more details. /// Can't use printf in kernel module so redefine to use Linux printk function #include <linux/version.h> @@ -37,25 +39,24 @@ #include <drv/cdsHardware.h> #include "inlineMath.h" - -#include "fm10Gen.h" // CDS filter module defs and C code -#include "feComms.h" // Lvea control RFM network defs. -#include "daqmap.h" // DAQ network layout +#include "fm10Gen.h" // CDS filter module defs and C code +#include "feComms.h" // Lvea control RFM network defs. +#include "daqmap.h" // DAQ network layout #include "cds_types.h" #include "controller.h" #ifndef NO_DAQ #include "drv/fb.h" -#include "drv/daqLib.c" // DAQ/GDS connection software +#include "drv/daqLib.c" // DAQ/GDS connection software #endif -#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function +#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function #include "drv/mapuser.h" -#include "timing.c" // timing module / IRIG-B functions +#include "timing.c" // timing module / IRIG-B functions -int dacOF[MAX_DAC_MODULES]; -#include "drv/inputFilterModule.h" -#include "drv/inputFilterModule1.h" +int dacOF[ MAX_DAC_MODULES ]; +#include "drv/inputFilterModule.h" +#include "drv/inputFilterModule1.h" #include <drv/app_dac_functions.c> #ifdef DOLPHIN_TEST @@ -66,734 +67,895 @@ int dacOF[MAX_DAC_MODULES]; // Contec 64 input bits plus 64 output bits (Standard for aLIGO) // /// Contec6464 input register values -unsigned int CDIO6464InputInput[MAX_DIO_MODULES]; // Binary input bits +unsigned int CDIO6464InputInput[ MAX_DIO_MODULES ]; // Binary input bits // /// Contec6464 - Last output request sent to module. -unsigned int CDIO6464LastOutState[MAX_DIO_MODULES]; // Current requested value of the BO bits +unsigned int CDIO6464LastOutState[ MAX_DIO_MODULES ]; // Current requested value + // of the BO bits // /// Contec6464 values to be written to the output register -unsigned int CDIO6464Output[MAX_DIO_MODULES]; // Binary output bits +unsigned int CDIO6464Output[ MAX_DIO_MODULES ]; // Binary output bits // -// // This Contect 16 input / 16 output DIO card is used to control timing slave by IOP +// // This Contect 16 input / 16 output DIO card is used to control timing slave +// by IOP // /// Contec1616 input register values -unsigned int CDIO1616InputInput[MAX_DIO_MODULES]; // Binary input bits +unsigned int CDIO1616InputInput[ MAX_DIO_MODULES ]; // Binary input bits // /// Contec1616 output register values read back from the module -unsigned int CDIO1616Input[MAX_DIO_MODULES]; // Current value of the BO bits +unsigned int CDIO1616Input[ MAX_DIO_MODULES ]; // Current value of the BO bits // /// Contec1616 values to be written to the output register -unsigned int CDIO1616Output[MAX_DIO_MODULES]; // Binary output bits +unsigned int CDIO1616Output[ MAX_DIO_MODULES ]; // Binary output bits // /// Holds ID number of Contec1616 DIO card(s) used for timing control. // Include C code modules #include "rcguser.c" -int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); -struct timespec adcTime; ///< Used in code cycle timing -int timeHoldHold = 0; ///< Max code cycle time within 1 sec period; hold for another sec -struct timespec myTimer[2]; ///< Used in code cycle timing +int getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec ); +struct timespec adcTime; ///< Used in code cycle timing +int timeHoldHold = + 0; ///< Max code cycle time within 1 sec period; hold for another sec +struct timespec myTimer[ 2 ]; ///< Used in code cycle timing // Clear DAC channel shared memory map, // used to keep track of non-overlapping DAC channels among slave models // -void deallocate_dac_channels(void) { - int ii, jj; - for (ii = 0; ii < MAX_DAC_MODULES; ii++) { - int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; - for (jj = 0; jj < 16; jj++) - if (dacOutUsed[ii][jj]) - ioMemData->dacOutUsed[pd][jj] = 0; - } +void +deallocate_dac_channels( void ) +{ + int ii, jj; + for ( ii = 0; ii < MAX_DAC_MODULES; ii++ ) + { + int pd = cdsPciModules.dacConfig[ ii ] - ioMemData->adcCount; + for ( jj = 0; jj < 16; jj++ ) + if ( dacOutUsed[ ii ][ jj ] ) + ioMemData->dacOutUsed[ pd ][ jj ] = 0; + } } -unsigned int getGpsTimeProc() { - FILE *timef; - char line[100]; - int status; - unsigned int mytime; - - timef = fopen("/sys/kernel/gpstime/time","r"); - if(!timef) { - printf("Cannot find GPS time \n"); - return(0); - } - fgets(line,100,timef); - mytime = atoi(line); - printf("GPS TIME is %d\n",mytime); - fclose(timef); - return (mytime); +unsigned int +getGpsTimeProc( ) +{ + FILE* timef; + char line[ 100 ]; + int status; + unsigned int mytime; + + timef = fopen( "/sys/kernel/gpstime/time", "r" ); + if ( !timef ) + { + printf( "Cannot find GPS time \n" ); + return ( 0 ); + } + fgets( line, 100, timef ); + mytime = atoi( line ); + printf( "GPS TIME is %d\n", mytime ); + fclose( timef ); + return ( mytime ); } //*********************************************************************** -// TASK: fe_start_app_user() -// This routine is the skeleton for all front end code +// TASK: fe_start_app_user() +// This routine is the skeleton for all front end code //*********************************************************************** -/// This function is the main real-time sequencer or scheduler for all code built -/// using the RCG. \n -/// There are two primary modes of operation, based on two compile options: \n -/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). +/// This function is the main real-time sequencer or scheduler for all code +/// built using the RCG. \n There are two primary modes of operation, based on +/// two compile options: \n +/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). /// - ADC_SLAVE: Normal user control process. -/// This code runs in a continuous loop at the rate specified in the RCG model. The -/// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn -/// is triggered to sample by the 64KHz clock provided by the Timing Distribution System. -/// - -int fe_start_app_user() +/// This code runs in a continuous loop at the rate specified in the RCG model. +/// The loop is synchronized and triggered by the arrival of ADC data, the ADC +/// module in turn is triggered to sample by the 64KHz clock provided by the +/// Timing Distribution System. +/// - +int +fe_start_app_user( ) { - int longestWrite2 = 0; - int tempClock[4]; - int ii,jj,kk,ll,mm; // Dummy loop counter variables - static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) - struct timespec tp; - static struct timespec cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables - // int dacOF[MAX_DAC_MODULES]; - - adcInfo_t adcInfo; - dacInfo_t dacInfo; - - static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code - ///< Code runs longer for first few cycles on startup as it settles in, - ///< so this helps prevent long cycles during that time. - int limit = OVERFLOW_LIMIT_16BIT; /// @param limit ADC/DAC overflow test value - int mask = GSAI_DATA_MASK; /// @param mask Bit mask for ADC/DAC read/writes - int num_outs = MAX_DAC_CHN_PER_MOD; /// @param num_outs Number of DAC channels variable - int dkiTrip = 0; - RFM_FE_COMMS *pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared memory space - // int timeHoldMax = 0; /// @param timeHoldMax Max code cycle time since last diag reset - int myGmError2 = 0; /// @param myGmError2 Myrinet error variable - int status; /// @param status Typical function return value - float onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics - int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check - int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check + int longestWrite2 = 0; + int tempClock[ 4 ]; + int ii, jj, kk, ll, mm; // Dummy loop counter variables + static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) + struct timespec tp; + static struct timespec + cpuClock[ CPU_TIMER_CNT ]; /// @param cpuClock[] Code timing diag + /// variables + // int dacOF[MAX_DAC_MODULES]; + + adcInfo_t adcInfo; + dacInfo_t dacInfo; + + static int dacWriteEnable = + 0; /// @param dacWriteEnable No DAC outputs until >4 times through code + ///< Code runs longer for first few cycles on startup as it settles + ///< in, so this helps prevent long cycles during that time. + int limit = + OVERFLOW_LIMIT_16BIT; /// @param limit ADC/DAC overflow test value + int mask = GSAI_DATA_MASK; /// @param mask Bit mask for ADC/DAC read/writes + int num_outs = + MAX_DAC_CHN_PER_MOD; /// @param num_outs Number of DAC channels variable + int dkiTrip = 0; + RFM_FE_COMMS* pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared + /// memory space + // int timeHoldMax = 0; /// @param timeHoldMax Max code cycle time since + // last diag reset + int myGmError2 = 0; /// @param myGmError2 Myrinet error variable + int status; /// @param status Typical function return value + float + onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics + int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check + int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check #ifdef DIAG_TEST - float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for diagnostics - int onePpsHiTest[10]; /// @param onePpsHiTest[] One PPS diagnostic check - int onePpsTimeTest[10]; /// @param onePpsTimeTest[] One PPS diagnostic check + float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for + /// diagnostics + int onePpsHiTest[ 10 ]; /// @param onePpsHiTest[] One PPS diagnostic check + int onePpsTimeTest[ 10 ]; /// @param onePpsTimeTest[] One PPS diagnostic + /// check #endif - int dcuId; /// @param dcuId DAQ ID number for this process - int diagWord = 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS - int system = 0; - int sampleCount = 1; /// @param sampleCount Number of ADC samples to take per code cycle - int sync21pps = 0; /// @param sync21pps Code startup sync to 1PPS flag - int syncSource = SYNC_SRC_MASTER; /// @param syncSource Code startup synchronization source - int mxStat = 0; /// @param mxStat Net diags when myrinet express is used - int mxDiag = 0; - int mxDiagR = 0; -// ****** Share data - int ioClockDac = DAC_PRELOAD_CNT; - int ioMemCntr = 0; - int ioMemCntrDac = DAC_PRELOAD_CNT; - int memCtr = 0; - int ioClock = 0; - double dac_in = 0.0; /// @param dac_in DAC value after upsample filtering - int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO - - int feStatus = 0; - - int clk, clk1; // Used only when run on timer enabled (test mode) - - - int cnt = 0; - unsigned long cpc; - -/// **********************************************************************************************\n -/// Start Initialization Process \n -/// **********************************************************************************************\n - memset (tempClock, 0, sizeof(tempClock)); - - /// \> Flush L1 cache - memset (fp, 0, 64*1024); - memset (fp, 1, 64*1024); - - fz_daz(); /// \> Kill the denorms! - - /// \> Init comms with EPICS processor */ - pEpicsComms = (RFM_FE_COMMS *)_epics_shm; - pLocalEpics = (CDS_EPICS *)&pEpicsComms->epicsSpace; - pEpicsDaq = (char *)&(pLocalEpics->epicsOutput); -// printf("Epics at 0x%x and DAQ at 0x%x size = %d \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN)); + int dcuId; /// @param dcuId DAQ ID number for this process + int diagWord = + 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS + int system = 0; + int sampleCount = + 1; /// @param sampleCount Number of ADC samples to take per code cycle + int sync21pps = 0; /// @param sync21pps Code startup sync to 1PPS flag + int syncSource = SYNC_SRC_MASTER; /// @param syncSource Code startup + /// synchronization source + int mxStat = 0; /// @param mxStat Net diags when myrinet express is used + int mxDiag = 0; + int mxDiagR = 0; + // ****** Share data + int ioClockDac = DAC_PRELOAD_CNT; + int ioMemCntr = 0; + int ioMemCntrDac = DAC_PRELOAD_CNT; + int memCtr = 0; + int ioClock = 0; + double dac_in = 0.0; /// @param dac_in DAC value after upsample filtering + int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO + + int feStatus = 0; + + int clk, clk1; // Used only when run on timer enabled (test mode) + + int cnt = 0; + unsigned long cpc; + + /// **********************************************************************************************\n + /// Start Initialization Process \n + /// **********************************************************************************************\n + memset( tempClock, 0, sizeof( tempClock ) ); + + /// \> Flush L1 cache + memset( fp, 0, 64 * 1024 ); + memset( fp, 1, 64 * 1024 ); + + fz_daz( ); /// \> Kill the denorms! + + /// \> Init comms with EPICS processor */ + pEpicsComms = (RFM_FE_COMMS*)_epics_shm; + pLocalEpics = (CDS_EPICS*)&pEpicsComms->epicsSpace; + pEpicsDaq = (char*)&( pLocalEpics->epicsOutput ); + // printf("Epics at 0x%x and DAQ at 0x%x size = %d + // \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN)); #ifdef OVERSAMPLE - /// \> Zero out filter histories - memset(dHistory, 0, sizeof(dHistory)); - memset(dDacHistory, 0, sizeof(dDacHistory)); + /// \> Zero out filter histories + memset( dHistory, 0, sizeof( dHistory ) ); + memset( dDacHistory, 0, sizeof( dDacHistory ) ); #endif - /// \> Zero out DAC outputs - for (ii = 0; ii < MAX_DAC_MODULES; ii++) - { - for (jj = 0; jj < 16; jj++) { - dacOut[ii][jj] = 0.0; - dacOutUsed[ii][jj] = 0; + /// \> Zero out DAC outputs + for ( ii = 0; ii < MAX_DAC_MODULES; ii++ ) + { + for ( jj = 0; jj < 16; jj++ ) + { + dacOut[ ii ][ jj ] = 0.0; + dacOutUsed[ ii ][ jj ] = 0; + } } - } - - /// \> Set pointers to filter module data buffers. \n - /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n - /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n - /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n - /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n - pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace); - dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - /// \> Clear the FE reset which comes from Epics - pLocalEpics->epicsInput.vmeReset = 0; + /// \> Set pointers to filter module data buffers. \n + /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD + /// data.\n + /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done + /// to: \n + /// - -------- Allow daqLib.c to retrieve filter module data directly from + /// shared memory. \n + /// - -------- Avoid copy of filter module data between to memory locations, + /// which was slow. \n + pDsp[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + pCoeff[ system ] = (VME_COEF*)( &pEpicsComms->coeffSpace ); + dspPtr[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + + /// \> Clear the FE reset which comes from Epics + pLocalEpics->epicsInput.vmeReset = 0; + + // Clear input masks + pLocalEpics->epicsInput.burtRestore_mask = 0; + pLocalEpics->epicsInput.dacDuoSet_mask = 0; + + /// < Read in all Filter Module EPICS coeff settings + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + checkFiltReset( ii, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); + } - // Clear input masks - pLocalEpics->epicsInput.burtRestore_mask = 0; - pLocalEpics->epicsInput.dacDuoSet_mask = 0; + // Need this FE dcuId to make connection to FB + dcuId = pLocalEpics->epicsInput.dcuId; + pLocalEpics->epicsOutput.dcuId = dcuId; + // Reset timing diagnostics + pLocalEpics->epicsOutput.diagWord = 0; + pLocalEpics->epicsOutput.timeDiag = 0; + pLocalEpics->epicsOutput.timeErr = syncSource; -/// < Read in all Filter Module EPICS coeff settings - for(ii=0;ii<MAX_MODULES;ii++) + /// \> Init IIR filter banks + // Initialize filter banks ********************************************* + for ( system = 0; system < NUM_SYSTEMS; system++ ) { - checkFiltReset(ii, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - } - - // Need this FE dcuId to make connection to FB - dcuId = pLocalEpics->epicsInput.dcuId; - pLocalEpics->epicsOutput.dcuId = dcuId; - - // Reset timing diagnostics - pLocalEpics->epicsOutput.diagWord = 0; - pLocalEpics->epicsOutput.timeDiag = 0; - pLocalEpics->epicsOutput.timeErr = syncSource; - -/// \> Init IIR filter banks -// Initialize filter banks ********************************************* - for (system = 0; system < NUM_SYSTEMS; system++) { - for(ii=0;ii<MAX_MODULES;ii++){ - for(jj=0;jj<FILTERS;jj++){ - for(kk=0;kk<MAX_COEFFS;kk++){ - dspCoeff[system].coeffs[ii].filtCoeff[jj][kk] = 0.0; + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + for ( jj = 0; jj < FILTERS; jj++ ) + { + for ( kk = 0; kk < MAX_COEFFS; kk++ ) + { + dspCoeff[ system ].coeffs[ ii ].filtCoeff[ jj ][ kk ] = 0.0; + } + dspCoeff[ system ].coeffs[ ii ].filtSections[ jj ] = 0; + } } - dspCoeff[system].coeffs[ii].filtSections[jj] = 0; - } } - } - /// \> Initialize all filter module excitation signals to zero - for (system = 0; system < NUM_SYSTEMS; system++) - for(ii=0;ii<MAX_MODULES;ii++) - // dsp[system].data[ii].exciteInput = 0.0; - pDsp[0]->data[ii].exciteInput = 0.0; + /// \> Initialize all filter module excitation signals to zero + for ( system = 0; system < NUM_SYSTEMS; system++ ) + for ( ii = 0; ii < MAX_MODULES; ii++ ) + // dsp[system].data[ii].exciteInput = 0.0; + pDsp[ 0 ]->data[ ii ].exciteInput = 0.0; - - /// \> Initialize IIR filter bank values - if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) { - printf("Filter module init failed, exiting\n"); - return 0; + /// \> Initialize IIR filter bank values + if ( initVars( pDsp[ 0 ], pDsp[ 0 ], dspCoeff, MAX_MODULES, pCoeff[ 0 ] ) ) + { + printf( "Filter module init failed, exiting\n" ); + return 0; } - printf("Initialized servo control parameters.\n"); + printf( "Initialized servo control parameters.\n" ); -usleep(1000); + usleep( 1000 ); -/// \> Initialize DAQ variable/software -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Set data range limits for daqLib routine -#if defined(SERVO2K) || defined(SERVO4K) - daq.filtExMin = GDS_2K_EXC_MIN; - daq.filtTpMin = GDS_2K_TP_MIN; +/// \> Initialize DAQ variable/software +#if !defined( NO_DAQ ) && !defined( IOP_TASK ) + /// - ---- Set data range limits for daqLib routine +#if defined( SERVO2K ) || defined( SERVO4K ) + daq.filtExMin = GDS_2K_EXC_MIN; + daq.filtTpMin = GDS_2K_TP_MIN; #else - daq.filtExMin = GDS_16K_EXC_MIN; - daq.filtTpMin = GDS_16K_TP_MIN; + daq.filtExMin = GDS_16K_EXC_MIN; + daq.filtTpMin = GDS_16K_TP_MIN; #endif - daq.filtExMax = daq.filtExMin + MAX_MODULES; - daq.filtExSize = MAX_MODULES; - daq.xExMin = daq.filtExMax; - daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; - daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; - daq.filtTpSize = MAX_MODULES * 3; - daq.xTpMin = daq.filtTpMax; - daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; - - printf("DAQ Ex Min/Max = %d %d\n",daq.filtExMin,daq.filtExMax); - printf("DAQ XEx Min/Max = %d %d\n",daq.xExMin,daq.xExMax); - printf("DAQ Tp Min/Max = %d %d\n",daq.filtTpMin,daq.filtTpMax); - printf("DAQ XTp Min/Max = %d %d\n",daq.xTpMin,daq.xTpMax); - - /// - ---- Assign DAC testpoint pointers - for (ii = 0; ii < cdsPciModules.dacCount; ii++) - for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) // 16 per DAC regardless of the actual - testpoint[MAX_DAC_CHN_PER_MOD * ii + jj] = floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; - - // Zero out storage - memset(floatDacOut, 0, sizeof(floatDacOut)); + daq.filtExMax = daq.filtExMin + MAX_MODULES; + daq.filtExSize = MAX_MODULES; + daq.xExMin = daq.filtExMax; + daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; + daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; + daq.filtTpSize = MAX_MODULES * 3; + daq.xTpMin = daq.filtTpMax; + daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; + + printf( "DAQ Ex Min/Max = %d %d\n", daq.filtExMin, daq.filtExMax ); + printf( "DAQ XEx Min/Max = %d %d\n", daq.xExMin, daq.xExMax ); + printf( "DAQ Tp Min/Max = %d %d\n", daq.filtTpMin, daq.filtTpMax ); + printf( "DAQ XTp Min/Max = %d %d\n", daq.xTpMin, daq.xTpMax ); + + /// - ---- Assign DAC testpoint pointers + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + for ( jj = 0; jj < MAX_DAC_CHN_PER_MOD; + jj++ ) // 16 per DAC regardless of the actual + testpoint[ MAX_DAC_CHN_PER_MOD * ii + jj ] = + floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; + + // Zero out storage + memset( floatDacOut, 0, sizeof( floatDacOut ) ); #endif - pLocalEpics->epicsOutput.ipcStat = 0; - pLocalEpics->epicsOutput.fbNetStat = 0; - pLocalEpics->epicsOutput.tpCnt = 0; - -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Initialize DAQ function - status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - if(status == -1) - { - printf("DAQ init failed -- exiting\n"); - vmeDone = 1; - return(0); - } + pLocalEpics->epicsOutput.ipcStat = 0; + pLocalEpics->epicsOutput.fbNetStat = 0; + pLocalEpics->epicsOutput.tpCnt = 0; + +#if !defined( NO_DAQ ) && !defined( IOP_TASK ) + /// - ---- Initialize DAQ function + status = daqWrite( 0, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + 0, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + if ( status == -1 ) + { + printf( "DAQ init failed -- exiting\n" ); + vmeDone = 1; + return ( 0 ); + } #endif - - // Clear the code exit flag - vmeDone = 0; - - /// \> Call user application software initialization routine. - printf("Calling feCode() to initialize\n"); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); - -/// \> Verify DAC channels defined for this app are not already in use. \n -/// - ---- User apps are allowed to share DAC modules but not DAC channels. - // See if my DAC channel map overlaps with already running models - for (ii = 0; ii < cdsPciModules.dacCount; ii++) { - int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number - for (jj = 0; jj < 16; jj++) { - if (dacOutUsed[ii][jj]) { - if (ioMemData->dacOutUsed[pd][jj]) { - // vmeDone = 1; - printf("Failed to allocate DAC channel.\n"); - printf("DAC local %d global %d channel %d is already allocated.\n", ii, pd, jj); - } - } + // Clear the code exit flag + vmeDone = 0; + + /// \> Call user application software initialization routine. + printf( "Calling feCode() to initialize\n" ); + iopDacEnable = feCode( cycleNum, + dWord, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 1 ); + + /// \> Verify DAC channels defined for this app are not already in use. \n + /// - ---- User apps are allowed to share DAC modules but not DAC channels. + // See if my DAC channel map overlaps with already running models + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + { + int pd = cdsPciModules.dacConfig[ ii ] - + ioMemData->adcCount; // physical DAC number + for ( jj = 0; jj < 16; jj++ ) + { + if ( dacOutUsed[ ii ][ jj ] ) + { + if ( ioMemData->dacOutUsed[ pd ][ jj ] ) + { + // vmeDone = 1; + printf( "Failed to allocate DAC channel.\n" ); + printf( "DAC local %d global %d channel %d is already " + "allocated.\n", + ii, + pd, + jj ); + } + } + } } - } - if (vmeDone) { - return(0); - } else { - for (ii = 0; ii < cdsPciModules.dacCount; ii++) { - int pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number - for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) { - if (dacOutUsed[ii][jj]) { - ioMemData->dacOutUsed[pd][jj] = 1; - printf("Setting card local=%d global = %d channel=%d dac usage\n", ii, pd, jj); - } - } + if ( vmeDone ) + { + return ( 0 ); + } + else + { + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + { + int pd = cdsPciModules.dacConfig[ ii ] - + ioMemData->adcCount; // physical DAC number + for ( jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++ ) + { + if ( dacOutUsed[ ii ][ jj ] ) + { + ioMemData->dacOutUsed[ pd ][ jj ] = 1; + printf( "Setting card local=%d global = %d channel=%d dac " + "usage\n", + ii, + pd, + jj ); + } + } + } } - } - -// Initialize ADC status - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - pLocalEpics->epicsOutput.statAdc[jj] = 1; - } + // Initialize ADC status + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] = 1; + } - // SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc memory - // Find memory buffer of first ADC to be used in SLAVE application. + // SLAVE needs to sync with MASTER by looking for cycle 0 count in ipc + // memory Find memory buffer of first ADC to be used in SLAVE application. pLocalEpics->epicsOutput.fe_status = INIT_SYNC; - ll = cdsPciModules.adcConfig[0]; - printf("waiting to sync %d\n",ioMemData->iodata[ll][0].cycle); - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_START]); - - // Spin until cycle 0 detected in first ADC buffer location. - do { - usleep(1); - } while(ioMemData->iodata[ll][0].cycle != 0); - timeSec = ioMemData->iodata[ll][0].timeSec; - - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_END]); - timeinfo.cycleTime = BILLION * (cpuClock[CPU_TIME_CYCLE_END].tv_sec - cpuClock[CPU_TIME_CYCLE_START].tv_sec) + - cpuClock[CPU_TIME_CYCLE_END].tv_nsec - cpuClock[CPU_TIME_CYCLE_START].tv_nsec; - timeinfo.cycleTime /= 1000; - printf("Synched %d\n",timeinfo.cycleTime); - // Need to set sync21pps so code will not try to sync with 1pps pulse later. - sync21pps=1; - // Get GPS seconds from MASTER - timeSec = ioMemData->gpsSecond; - pLocalEpics->epicsOutput.timeDiag = timeSec; - // Decrement GPS seconds as it will be incremented on first read cycle. - timeSec --; - - onePpsTime = cycleNum; - // timeSec = current_time() -1; - timeSec = ioMemData->gpsSecond; - // timeSec = ioMemData->iodata[0][0].timeSec; - printf ("Using local GPS time %d \n",timeSec); - pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; - - clock_gettime(CLOCK_MONOTONIC, &adcTime); - - /// ******************************************************************************\n - /// Enter the infinite FE control loop ******************************************\n - - /// ******************************************************************************\n - // Calculate how many CPU cycles per code cycle - // cpc = cpu_khz * 1000; - // cpc /= CYCLE_PER_SECOND; - - - while(!vmeDone){ // Run forever until user hits reset - // ********************************************************************************************************** - // NORMAL OPERATION -- Wait for ADC data ready - // On startup, only want to read one sample such that first cycle - // coincides with GPS 1PPS. Thereafter, sampleCount will be - // increased to appropriate number of 65536 s/sec to match desired - // code rate eg 32 samples each time thru before proceeding to match 2048 system. - // ********************************************************************************************************** - -/// \> On 1PPS mark \n - if(cycleNum == 0) - { - /// - ---- Check awgtpman status. - //printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec); - pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); - if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG; - /// - ---- Check if DAC outputs are enabled, report error. - if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE; - - } - for(ll=0;ll<sampleCount;ll++) + ll = cdsPciModules.adcConfig[ 0 ]; + printf( "waiting to sync %d\n", ioMemData->iodata[ ll ][ 0 ].cycle ); + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_CYCLE_START ] ); + + // Spin until cycle 0 detected in first ADC buffer location. + do { - /// \> SLAVE gets its adc data from MASTER via ipc shared memory\n - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - mm = cdsPciModules.adcConfig[jj]; - kk = 0; - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_RDY_ADC]); - /// - ---- Wait for proper timestamp in shared memory, indicating data ready. - do{ - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_ADC_WAIT]); - adcInfo.adcWait = BILLION * - (cpuClock[CPU_TIME_ADC_WAIT].tv_sec - cpuClock[CPU_TIME_RDY_ADC].tv_sec) + - cpuClock[CPU_TIME_ADC_WAIT].tv_nsec - cpuClock[CPU_TIME_RDY_ADC].tv_nsec; - adcInfo.adcWait /= 1000; - }while((ioMemData->iodata[mm][ioMemCntr].cycle != ioClock) && (adcInfo.adcWait < MAX_ADC_WAIT_SLAVE)); - timeSec = ioMemData->iodata[mm][ioMemCntr].timeSec; - if (cycle_gps_time == 0) { - timeinfo.startGpsTime = timeSec; - pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime; - } - cycle_gps_time = timeSec; - - /// - --------- If data not ready in time, set error, release DAC channel reservation and exit the code. - if(adcInfo.adcWait >= MAX_ADC_WAIT_SLAVE) - { - printf ("ADC TIMEOUT %d %d %d %d\n",mm,ioMemData->iodata[mm][ioMemCntr].cycle, ioMemCntr,ioClock); - pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; - pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR; - deallocate_dac_channels(); - return (void *)-1; - } - for(ii=0;ii<MAX_ADC_CHN_PER_MOD;ii++) + usleep( 1 ); + } while ( ioMemData->iodata[ ll ][ 0 ].cycle != 0 ); + timeSec = ioMemData->iodata[ ll ][ 0 ].timeSec; + + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_CYCLE_END ] ); + timeinfo.cycleTime = BILLION * + ( cpuClock[ CPU_TIME_CYCLE_END ].tv_sec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_sec ) + + cpuClock[ CPU_TIME_CYCLE_END ].tv_nsec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_nsec; + timeinfo.cycleTime /= 1000; + printf( "Synched %d\n", timeinfo.cycleTime ); + // Need to set sync21pps so code will not try to sync with 1pps pulse later. + sync21pps = 1; + // Get GPS seconds from MASTER + timeSec = ioMemData->gpsSecond; + pLocalEpics->epicsOutput.timeDiag = timeSec; + // Decrement GPS seconds as it will be incremented on first read cycle. + timeSec--; + + onePpsTime = cycleNum; + // timeSec = current_time() -1; + timeSec = ioMemData->gpsSecond; + // timeSec = ioMemData->iodata[0][0].timeSec; + printf( "Using local GPS time %d \n", timeSec ); + pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; + + clock_gettime( CLOCK_MONOTONIC, &adcTime ); + + /// ******************************************************************************\n + /// Enter the infinite FE control loop + /// ******************************************\n + + /// ******************************************************************************\n + // Calculate how many CPU cycles per code cycle + // cpc = cpu_khz * 1000; + // cpc /= CYCLE_PER_SECOND; + + while ( !vmeDone ) + { // Run forever until user hits reset + // ********************************************************************************************************** + // NORMAL OPERATION -- Wait for ADC data ready + // On startup, only want to read one sample such that first cycle + // coincides with GPS 1PPS. Thereafter, sampleCount will be + // increased to appropriate number of 65536 s/sec to match desired + // code rate eg 32 samples each time thru before proceeding to match + // 2048 system. + // ********************************************************************************************************** + + /// \> On 1PPS mark \n + if ( cycleNum == 0 ) + { + /// - ---- Check awgtpman status. + // printf("awgtpman gps = %d local = %d\n", + // pEpicsComms->padSpace.awgtpman_gps, timeSec); + pLocalEpics->epicsOutput.awgStat = + ( pEpicsComms->padSpace.awgtpman_gps != timeSec ); + if ( pLocalEpics->epicsOutput.awgStat ) + feStatus |= FE_ERROR_AWG; + /// - ---- Check if DAC outputs are enabled, report error. + if ( !iopDacEnable || dkiTrip ) + feStatus |= FE_ERROR_DAC_ENABLE; + } + for ( ll = 0; ll < sampleCount; ll++ ) + { + /// \> SLAVE gets its adc data from MASTER via ipc shared memory\n + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) { - /// - ---- Read data from shared memory. - adcInfo.adcData[jj][ii] = ioMemData->iodata[mm][ioMemCntr].data[ii]; + mm = cdsPciModules.adcConfig[ jj ]; + kk = 0; + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_RDY_ADC ] ); + /// - ---- Wait for proper timestamp in shared memory, + /// indicating data ready. + do + { + clock_gettime( CLOCK_MONOTONIC, + &cpuClock[ CPU_TIME_ADC_WAIT ] ); + adcInfo.adcWait = BILLION * + ( cpuClock[ CPU_TIME_ADC_WAIT ].tv_sec - + cpuClock[ CPU_TIME_RDY_ADC ].tv_sec ) + + cpuClock[ CPU_TIME_ADC_WAIT ].tv_nsec - + cpuClock[ CPU_TIME_RDY_ADC ].tv_nsec; + adcInfo.adcWait /= 1000; + } while ( + ( ioMemData->iodata[ mm ][ ioMemCntr ].cycle != ioClock ) && + ( adcInfo.adcWait < MAX_ADC_WAIT_SLAVE ) ); + timeSec = ioMemData->iodata[ mm ][ ioMemCntr ].timeSec; + if ( cycle_gps_time == 0 ) + { + timeinfo.startGpsTime = timeSec; + pLocalEpics->epicsOutput.startgpstime = + timeinfo.startGpsTime; + } + cycle_gps_time = timeSec; + + /// - --------- If data not ready in time, set error, release + /// DAC channel reservation and exit the code. + if ( adcInfo.adcWait >= MAX_ADC_WAIT_SLAVE ) + { + printf( "ADC TIMEOUT %d %d %d %d\n", + mm, + ioMemData->iodata[ mm ][ ioMemCntr ].cycle, + ioMemCntr, + ioClock ); + pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; + pLocalEpics->epicsOutput.diagWord |= ADC_TIMEOUT_ERR; + deallocate_dac_channels( ); + return (void*)-1; + } + for ( ii = 0; ii < MAX_ADC_CHN_PER_MOD; ii++ ) + { + /// - ---- Read data from shared memory. + adcInfo.adcData[ jj ][ ii ] = + ioMemData->iodata[ mm ][ ioMemCntr ].data[ ii ]; #ifdef FLIP_SIGNALS - adcInfo.adcData[jj][ii] *= -1; + adcInfo.adcData[ jj ][ ii ] *= -1; #endif - dWord[jj][ii] = adcInfo.adcData[jj][ii]; + dWord[ jj ][ ii ] = adcInfo.adcData[ jj ][ ii ]; #ifdef OVERSAMPLE - /// - ---- Downsample ADC data from 64K to rate of user application - if (dWordUsed[jj][ii]) { - dWord[jj][ii] = iir_filter_biquad(dWord[jj][ii],FE_OVERSAMPLE_COEFF,2,&dHistory[ii+jj*32][0]); - } - /// - ---- Check for ADC data over/under range - if((adcInfo.adcData[jj][ii] > limit) || (adcInfo.adcData[jj][ii] < -limit)) - { - adcInfo.overflowAdc[jj][ii] ++; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++; - overflowAcc ++; - adcInfo.adcOF[jj] = 1; - odcStateWord |= ODC_ADC_OVF; - } + /// - ---- Downsample ADC data from 64K to rate of user + /// application + if ( dWordUsed[ jj ][ ii ] ) + { + dWord[ jj ][ ii ] = + iir_filter_biquad( dWord[ jj ][ ii ], + FE_OVERSAMPLE_COEFF, + 2, + &dHistory[ ii + jj * 32 ][ 0 ] ); + } + /// - ---- Check for ADC data over/under range + if ( ( adcInfo.adcData[ jj ][ ii ] > limit ) || + ( adcInfo.adcData[ jj ][ ii ] < -limit ) ) + { + adcInfo.overflowAdc[ jj ][ ii ]++; + pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ]++; + overflowAcc++; + adcInfo.adcOF[ jj ] = 1; + odcStateWord |= ODC_ADC_OVF; + } #endif - // No filter dWord[kk][ll] = adcData[kk][ll]; + // No filter dWord[kk][ll] = adcData[kk][ll]; + } } + /// \> Set counters for next read from ipc memory + ioClock = ( ioClock + 1 ) % IOP_IO_RATE; + ioMemCntr = ( ioMemCntr + 1 ) % IO_MEMORY_SLOTS; + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_CYCLE_START ] ); } - /// \> Set counters for next read from ipc memory - ioClock = (ioClock + 1) % IOP_IO_RATE; - ioMemCntr = (ioMemCntr + 1) % IO_MEMORY_SLOTS; - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_START]); - - } - - // After first synced ADC read, must set to code to read number samples/cycle - sampleCount = OVERSAMPLE_TIMES; -/// End of ADC Read ************************************************************************************** - - - -/// \> Call the front end specific application ******************\n -/// - -- This is where the user application produced by RCG gets called and executed. \n\n - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_START]); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0); - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_END]); - - odcStateWord = 0; -/// WRITE DAC OUTPUTS ***************************************** \n - -/// Writing of DAC outputs is dependent on code compile option: \n -/// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user apps and writes to DAC hardware. \n -/// - -- USER APP (ADC_SLAVE) sends output values to memory shared with IOP. \n - -/// START OF USER APP DAC WRITE ***************************************** - // Write out data to DAC modules - /// \> Loop thru all DAC modules - status = app_dac_write(ioMemCntrDac,ioClockDac, &dacinfo); - /// \> Increment DAC memory block pointers for next cycle - ioClockDac = (ioClockDac + OVERSAMPLE_TIMES) % IOP_IO_RATE; - ioMemCntrDac = (ioMemCntrDac + OVERSAMPLE_TIMES) % IO_MEMORY_SLOTS; - if(dacWriteEnable < 10) dacWriteEnable ++; - -/// END OF DAC WRITE ************************************************* - - -/// BEGIN HOUSEKEEPING ************************************************ \n - - pLocalEpics->epicsOutput.cycle = cycleNum; - -// ******************************************************************* -/// \> Cycle 18, Send timing info to EPICS at 1Hz -// ******************************************************************* - if(cycleNum ==HKP_TIMING_UPDATES) - { - sendTimingDiags2Epics(pLocalEpics, &timeinfo, &adcinfo); - - - if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) - { - diagWord |= FE_ADC_HOLD_ERR; - feStatus |= FE_ERROR_TIMING; - - } - if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) - { - diagWord |= FE_PROC_TIME_ERR; - feStatus |= FE_ERROR_TIMING; - } - pLocalEpics->epicsOutput.stateWord = feStatus; - feStatus = 0; - if(pLocalEpics->epicsInput.diagReset || initialDiagReset) - { - initialDiagReset = 0; - pLocalEpics->epicsInput.diagReset = 0; - pLocalEpics->epicsInput.ipcDiagReset = 1; - // pLocalEpics->epicsOutput.diags[1] = 0; - timeinfo.timeHoldMax = 0; - diagWord = 0; - ipcErrBits = 0; - - // feStatus = 0; - } - // Flip the onePPS various once/sec as a watchdog monitor. - // pLocalEpics->epicsOutput.onePps ^= 1; - pLocalEpics->epicsOutput.diagWord = diagWord; - } + // After first synced ADC read, must set to code to read number + // samples/cycle + sampleCount = OVERSAMPLE_TIMES; + /// End of ADC Read + /// ************************************************************************************** + + /// \> Call the front end specific application ******************\n + /// - -- This is where the user application produced by RCG gets called + /// and executed. \n\n + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_USR_START ] ); + iopDacEnable = feCode( cycleNum, + dWord, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 0 ); + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_USR_END ] ); + + odcStateWord = 0; + /// WRITE DAC OUTPUTS ***************************************** \n + + /// Writing of DAC outputs is dependent on code compile option: \n + /// - -- IOP (ADC_MASTER) reads DAC output values from memory shared + /// with user apps and writes to DAC hardware. \n + /// - -- USER APP (ADC_SLAVE) sends output values to memory shared with + /// IOP. \n + + /// START OF USER APP DAC WRITE + /// ***************************************** + // Write out data to DAC modules + /// \> Loop thru all DAC modules + status = app_dac_write( ioMemCntrDac, ioClockDac, &dacinfo ); + /// \> Increment DAC memory block pointers for next cycle + ioClockDac = ( ioClockDac + OVERSAMPLE_TIMES ) % IOP_IO_RATE; + ioMemCntrDac = ( ioMemCntrDac + OVERSAMPLE_TIMES ) % IO_MEMORY_SLOTS; + if ( dacWriteEnable < 10 ) + dacWriteEnable++; + + /// END OF DAC WRITE ************************************************* + + /// BEGIN HOUSEKEEPING ************************************************ + /// \n + + pLocalEpics->epicsOutput.cycle = cycleNum; + + // ******************************************************************* + /// \> Cycle 18, Send timing info to EPICS at 1Hz + // ******************************************************************* + if ( cycleNum == HKP_TIMING_UPDATES ) + { + sendTimingDiags2Epics( pLocalEpics, &timeinfo, &adcinfo ); -/// \> Check for requests for filter module clear history requests. This is spread out over a number of cycles. - // Spread out filter coeff update, but keep updates at 16 Hz - // here we are rounding up: - // x/y rounded up equals (x + y - 1) / y - // - static const unsigned int mpc = (MAX_MODULES + (FE_RATE / 16) - 1) / (FE_RATE / 16); // Modules per cycle - unsigned int smpc = mpc * subcycle; // Start module counter - unsigned int empc = smpc + mpc; // End module counter - unsigned int i; - for (i = smpc; i < MAX_MODULES && i < empc ; i++) - checkFiltReset(i, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); + if ( ( adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI ) || + ( adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO ) ) + { + diagWord |= FE_ADC_HOLD_ERR; + feStatus |= FE_ERROR_TIMING; + } + if ( timeinfo.timeHoldMax > CYCLE_TIME_ALRM ) + { + diagWord |= FE_PROC_TIME_ERR; + feStatus |= FE_ERROR_TIMING; + } + pLocalEpics->epicsOutput.stateWord = feStatus; + feStatus = 0; + if ( pLocalEpics->epicsInput.diagReset || initialDiagReset ) + { + initialDiagReset = 0; + pLocalEpics->epicsInput.diagReset = 0; + pLocalEpics->epicsInput.ipcDiagReset = 1; + // pLocalEpics->epicsOutput.diags[1] = 0; + timeinfo.timeHoldMax = 0; + diagWord = 0; + ipcErrBits = 0; + + // feStatus = 0; + } + // Flip the onePPS various once/sec as a watchdog monitor. + // pLocalEpics->epicsOutput.onePps ^= 1; + pLocalEpics->epicsOutput.diagWord = diagWord; + } -/// \> Check if code exit is requested - if(cycleNum == MAX_MODULES) - vmeDone = stop_working_threads | checkEpicsReset(cycleNum, (struct CDS_EPICS *)pLocalEpics); + /// \> Check for requests for filter module clear history requests. This + /// is spread out over a number of cycles. + // Spread out filter coeff update, but keep updates at 16 Hz + // here we are rounding up: + // x/y rounded up equals (x + y - 1) / y + // + static const unsigned int mpc = ( MAX_MODULES + ( FE_RATE / 16 ) - 1 ) / + ( FE_RATE / 16 ); // Modules per cycle + unsigned int smpc = mpc * subcycle; // Start module counter + unsigned int empc = smpc + mpc; // End module counter + unsigned int i; + for ( i = smpc; i < MAX_MODULES && i < empc; i++ ) + checkFiltReset( i, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); + + /// \> Check if code exit is requested + if ( cycleNum == MAX_MODULES ) + vmeDone = stop_working_threads | + checkEpicsReset( cycleNum, (struct CDS_EPICS*)pLocalEpics ); /// \> Write data to DAQ. #ifndef NO_DAQ - - // Call daqLib - pLocalEpics->epicsOutput.daqByteCnt = - daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - // Send the current DAQ block size to the awgtpman for TP number checking - pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; - pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; - feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); - if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; - else odcStateWord &= ~(ODC_EXC_SET); - if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) - feStatus |= FE_ERROR_DAQ; + + // Call daqLib + pLocalEpics->epicsOutput.daqByteCnt = + daqWrite( 1, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + myGmError2, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + // Send the current DAQ block size to the awgtpman for TP number + // checking + pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; + pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; + feStatus |= ( FE_ERROR_EXC_SET & tpPtr->count ); + if ( FE_ERROR_EXC_SET & tpPtr->count ) + odcStateWord |= ODC_EXC_SET; + else + odcStateWord &= ~( ODC_EXC_SET ); + if ( pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING ) + feStatus |= FE_ERROR_DAQ; #endif -// ******************************************************************* -/// \> Cycle 19, write updated diag info to EPICS -// ******************************************************************* - if(cycleNum == HKP_DIAG_UPDATES) - { - pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime; - pLocalEpics->epicsOutput.ipcStat = ipcErrBits; - if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; - // Create FB status word for return to EPICS - mxStat = 0; - mxDiagR = daqPtr->reqAck; - if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; - if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; + // ******************************************************************* + /// \> Cycle 19, write updated diag info to EPICS + // ******************************************************************* + if ( cycleNum == HKP_DIAG_UPDATES ) + { + pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime; + pLocalEpics->epicsOutput.ipcStat = ipcErrBits; + if ( ipcErrBits & 0xf ) + feStatus |= FE_ERROR_IPC; + // Create FB status word for return to EPICS + mxStat = 0; + mxDiagR = daqPtr->reqAck; + if ( ( mxDiag & 1 ) != ( mxDiagR & 1 ) ) + mxStat = 1; + if ( ( mxDiag & 2 ) != ( mxDiagR & 2 ) ) + mxStat += 2; #ifdef DUAL_DAQ_DC - if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; - if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; + if ( ( mxDiag & 4 ) != ( mxDiagR & 4 ) ) + mxStat += 4; + if ( ( mxDiag & 8 ) != ( mxDiagR & 8 ) ) + mxStat += 8; #endif - pLocalEpics->epicsOutput.fbNetStat = mxStat; - mxDiag = mxDiagR; - if(mxStat != MX_OK) - feStatus |= FE_ERROR_DAQ;; - timeinfo.usrHoldTime = 0; - if(pLocalEpics->epicsInput.overflowReset) - { - for (ii = 0; ii < 16; ii++) { - for (jj = 0; jj < cdsPciModules.adcCount; jj++) { - adcInfo.overflowAdc[jj][ii] = 0; - adcInfo.overflowAdc[jj][ii + 16] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; + pLocalEpics->epicsOutput.fbNetStat = mxStat; + mxDiag = mxDiagR; + if ( mxStat != MX_OK ) + feStatus |= FE_ERROR_DAQ; + ; + timeinfo.usrHoldTime = 0; + if ( pLocalEpics->epicsInput.overflowReset ) + { + for ( ii = 0; ii < 16; ii++ ) + { + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + adcInfo.overflowAdc[ jj ][ ii ] = 0; + adcInfo.overflowAdc[ jj ][ ii + 16 ] = 0; + pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii + 16 ] = 0; + } + + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] = 0; + } } + } + if ( ( pLocalEpics->epicsInput.overflowReset ) || + ( overflowAcc > OVERFLOW_CNTR_LIMIT ) ) + { + pLocalEpics->epicsInput.overflowReset = 0; + pLocalEpics->epicsOutput.ovAccum = 0; + overflowAcc = 0; + } + } - for (jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; + // ******************************************************************* + // ******************************************************************* + if ( cycleNum == 1 ) + { + pLocalEpics->epicsOutput.timeDiag = timeSec; + } + // ******************************************************************* + /// \> Cycle 20, Update latest DAC output values to EPICS + // ******************************************************************* + if ( subcycle == HKP_DAC_EPICS_UPDATES ) + { + // Send DAC output values at 16Hzfb + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { + pLocalEpics->epicsOutput.dacValue[ jj ][ ii ] = + dacInfo.dacOutEpics[ jj ][ ii ]; } } - } - if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) - { - pLocalEpics->epicsInput.overflowReset = 0; - pLocalEpics->epicsOutput.ovAccum = 0; - overflowAcc = 0; - } - } + } -// ******************************************************************* -// ******************************************************************* - if(cycleNum == 1) - { - pLocalEpics->epicsOutput.timeDiag = timeSec; - } -// ******************************************************************* -/// \> Cycle 20, Update latest DAC output values to EPICS -// ******************************************************************* - if(subcycle == HKP_DAC_EPICS_UPDATES) - { - // Send DAC output values at 16Hzfb - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacInfo.dacOutEpics[jj][ii]; - } - } - } - -// ******************************************************************* -/// \> Cycle 21, Update ADC/DAC status to EPICS. -// ******************************************************************* - if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) - { - pLocalEpics->epicsOutput.ovAccum = overflowAcc; - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - // SET/CLR Channel Hopping Error - if(adcInfo.adcChanErr[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(2); - feStatus |= FE_ERROR_ADC;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 2; - adcInfo.adcChanErr[jj] = 0; - // SET/CLR Overflow Error - if(adcInfo.adcOF[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(4); - feStatus |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 4; - adcInfo.adcOF[jj] = 0; - for(ii=0;ii<32;ii++) - { - if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; + // ******************************************************************* + /// \> Cycle 21, Update ADC/DAC status to EPICS. + // ******************************************************************* + if ( cycleNum == HKP_ADC_DAC_STAT_UPDATES ) + { + pLocalEpics->epicsOutput.ovAccum = overflowAcc; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + // SET/CLR Channel Hopping Error + if ( adcInfo.adcChanErr[ jj ] ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] &= ~( 2 ); + feStatus |= FE_ERROR_ADC; + ; + } + else + pLocalEpics->epicsOutput.statAdc[ jj ] |= 2; + adcInfo.adcChanErr[ jj ] = 0; + // SET/CLR Overflow Error + if ( adcInfo.adcOF[ jj ] ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] &= ~( 4 ); + feStatus |= FE_ERROR_OVERFLOW; + ; + } + else + pLocalEpics->epicsOutput.statAdc[ jj ] |= 4; + adcInfo.adcOF[ jj ] = 0; + for ( ii = 0; ii < 32; ii++ ) + { + if ( pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] > + OVERFLOW_CNTR_LIMIT ) + { + pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] = 0; + } + pLocalEpics->epicsOutput.overflowAdc[ jj ][ ii ] = + adcInfo.overflowAdc[ jj ][ ii ]; + adcInfo.overflowAdc[ jj ][ ii ] = 0; + } + } + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + if ( dacOF[ jj ] ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= + ~( DAC_OVERFLOW_BIT ); + feStatus |= FE_ERROR_OVERFLOW; + ; + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_OVERFLOW_BIT; + dacOF[ jj ] = 0; + if ( dacChanErr[ jj ] ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= + ~( DAC_TIMING_BIT ); + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_TIMING_BIT; + dacChanErr[ jj ] = 0; + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { + if ( pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] > + OVERFLOW_CNTR_LIMIT ) + { + pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] = 0; + } + pLocalEpics->epicsOutput.overflowDac[ jj ][ ii ] = + dacInfo.overflowDac[ jj ][ ii ]; + dacInfo.overflowDac[ jj ][ ii ] = 0; } - pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcInfo.overflowAdc[jj][ii]; - adcInfo.overflowAdc[jj][ii] = 0; - } - } - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(dacOF[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT); - feStatus |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT; - dacOF[jj] = 0; - if(dacChanErr[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT); - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT; - dacChanErr[jj] = 0; - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; } - pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacInfo.overflowDac[jj][ii]; - dacInfo.overflowDac[jj][ii] = 0; - } } - } - // ********************************************************************* - // Capture end of cycle time. - // ********************************************************************* - - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_END]); - /// \> Compute code cycle time diag information. - timeinfo.cycleTime = BILLION * - (cpuClock[CPU_TIME_CYCLE_END].tv_sec - - cpuClock[CPU_TIME_CYCLE_START].tv_sec) + - cpuClock[CPU_TIME_CYCLE_END].tv_nsec - - cpuClock[CPU_TIME_CYCLE_START].tv_nsec; - timeinfo.cycleTime /= 1000; - // BILLION - adcinfo.adcHoldTime = BILLION * - (cpuClock[CPU_TIME_CYCLE_START].tv_sec - adcTime.tv_sec) + - cpuClock[CPU_TIME_CYCLE_START].tv_nsec - adcTime.tv_nsec; - adcinfo.adcHoldTime /= 1000; - // Calc the max time of one cycle of the user code - timeinfo.usrTime = BILLION * - (cpuClock[CPU_TIME_USR_END].tv_sec - - cpuClock[CPU_TIME_CYCLE_START].tv_sec) + - cpuClock[CPU_TIME_USR_END].tv_nsec - - cpuClock[CPU_TIME_CYCLE_START].tv_nsec; - timeinfo.usrTime /= 1000; - - // Calculate timing max/mins/etc. - captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo); - - pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime; - adcTime.tv_sec = cpuClock[CPU_TIME_CYCLE_START].tv_sec; - adcTime.tv_nsec = cpuClock[CPU_TIME_CYCLE_START].tv_nsec; - - /// \> Update internal cycle counters - cycleNum += 1; - cycleNum %= CYCLE_PER_SECOND; - clock1Min += 1; - clock1Min %= CYCLE_PER_MINUTE; - if(subcycle == DAQ_CYCLE_CHANGE) - { - daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle; - } - if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ - { - /* Reset the data cycle counter */ - subcycle = 0; - } - else{ - /* Increment the internal cycle counter */ - subcycle ++; - } + // ********************************************************************* + // Capture end of cycle time. + // ********************************************************************* + + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_CYCLE_END ] ); + /// \> Compute code cycle time diag information. + timeinfo.cycleTime = BILLION * + ( cpuClock[ CPU_TIME_CYCLE_END ].tv_sec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_sec ) + + cpuClock[ CPU_TIME_CYCLE_END ].tv_nsec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_nsec; + timeinfo.cycleTime /= 1000; + // BILLION + adcinfo.adcHoldTime = BILLION * + ( cpuClock[ CPU_TIME_CYCLE_START ].tv_sec - adcTime.tv_sec ) + + cpuClock[ CPU_TIME_CYCLE_START ].tv_nsec - adcTime.tv_nsec; + adcinfo.adcHoldTime /= 1000; + // Calc the max time of one cycle of the user code + timeinfo.usrTime = BILLION * + ( cpuClock[ CPU_TIME_USR_END ].tv_sec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_sec ) + + cpuClock[ CPU_TIME_USR_END ].tv_nsec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_nsec; + timeinfo.usrTime /= 1000; + + // Calculate timing max/mins/etc. + captureEocTiming( cycleNum, cycle_gps_time, &timeinfo, &adcinfo ); + + pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime; + adcTime.tv_sec = cpuClock[ CPU_TIME_CYCLE_START ].tv_sec; + adcTime.tv_nsec = cpuClock[ CPU_TIME_CYCLE_START ].tv_nsec; + + /// \> Update internal cycle counters + cycleNum += 1; + cycleNum %= CYCLE_PER_SECOND; + clock1Min += 1; + clock1Min %= CYCLE_PER_MINUTE; + if ( subcycle == DAQ_CYCLE_CHANGE ) + { + daqCycle = ( daqCycle + 1 ) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; + if ( !( daqCycle % 2 ) ) + pLocalEpics->epicsOutput.epicsSync = daqCycle; + } + if ( subcycle == + END_OF_DAQ_BLOCK ) /*we have reached the 16Hz second barrier*/ + { + /* Reset the data cycle counter */ + subcycle = 0; + } + else + { + /* Increment the internal cycle counter */ + subcycle++; + } -/// \> If not exit request, then continue INFINITE LOOP ******* - } + /// \> If not exit request, then continue INFINITE LOOP ******* + } - printf("exiting from fe_code()\n"); - pLocalEpics->epicsOutput.cpuMeter = 0; + printf( "exiting from fe_code()\n" ); + pLocalEpics->epicsOutput.cpuMeter = 0; - deallocate_dac_channels(); + deallocate_dac_channels( ); - /* System reset command received */ - return (void *)-1; + /* System reset command received */ + return (void*)-1; } diff --git a/src/fe/controllerIop.c b/src/fe/controllerIop.c index 737cfef5f..c31a24fcd 100644 --- a/src/fe/controllerIop.c +++ b/src/fe/controllerIop.c @@ -14,34 +14,32 @@ /// @file controllerIop.c /// @brief Main scheduler program for compiled real-time kernal object. \n /// @detail More information can be found in the following DCC document: -///< <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 CDS RT Sequencer Software</a> +///< <a +///<href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 +///<CDS RT Sequencer Software</a> /// @author R.Bork, A.Ivanov /// @copyright Copyright (C) 2014 LIGO Project \n ///< California Institute of Technology \n ///< Massachusetts Institute of Technology \n\n -/// @license This program is free software: you can redistribute it and/or modify +/// @license This program is free software: you can redistribute it and/or +/// modify ///< it under the terms of the GNU General Public License as published by -///< the Free Software Foundation, version 3 of the License. \n -///< This program is distributed in the hope that it will be useful, -///< but WITHOUT ANY WARRANTY; without even the implied warranty of -///< MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -///< GNU General Public License for more details. - +///< the Free Software Foundation, version 3 of the License. \n This program +///< is distributed in the hope that it will be useful, but WITHOUT ANY +///< WARRANTY; without even the implied warranty of MERCHANTABILITY or +///< FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +///< for more details. #include "controllerko.h" - #ifdef DOLPHIN_TEST #include "dolphin.c" #endif - -#if defined (TIME_MASTER) || defined (TIME_SLAVE) -volatile TIMING_SIGNAL *pcieTimer; +#if defined( TIME_MASTER ) || defined( TIME_SLAVE ) +volatile TIMING_SIGNAL* pcieTimer; #endif - - // Duotone diags struct duotone_diag_t dt_diag; @@ -53,15 +51,16 @@ int ioClockDac = DAC_PRELOAD_CNT; int ioMemCntrDac = DAC_PRELOAD_CNT; // DAC variable int dacEnable = 0; -int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code -int dacTimingErrorPending[MAX_DAC_MODULES]; +int dacWriteEnable = + 0; /// @param dacWriteEnable No DAC outputs until >4 times through code +int dacTimingErrorPending[ MAX_DAC_MODULES ]; static int dacTimingError = 0; -int dacWatchDog = 0; -int dac_out = 0; +int dacWatchDog = 0; +int dac_out = 0; -int pBits[9] = {1,2,4,8,16,32,64,128,256}; +int pBits[ 9 ] = { 1, 2, 4, 8, 16, 32, 64, 128, 256 }; -int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); +int getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec ); // Include C code modules #include "moduleLoadIop.c" @@ -79,871 +78,1075 @@ int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); #include <drv/adc_info.c> //*********************************************************************** -// TASK: fe_start_iop() -// This routine is the skeleton for all front end code +// TASK: fe_start_iop() +// This routine is the skeleton for all front end code //*********************************************************************** -/// This function is the main real-time sequencer or scheduler for all code built -/// using the RCG. \n -/// There are two primary modes of operation, based on two compile options: \n -/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). +/// This function is the main real-time sequencer or scheduler for all code +/// built using the RCG. \n There are two primary modes of operation, based on +/// two compile options: \n +/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). /// - ADC_SLAVE: Normal user control process. -/// This code runs in a continuous loop at the rate specified in the RCG model. The -/// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn -/// is triggered to sample by the 64KHz clock provided by the Timing Distribution System. -/// - -void *fe_start_iop(void *arg) +/// This code runs in a continuous loop at the rate specified in the RCG model. +/// The loop is synchronized and triggered by the arrival of ADC data, the ADC +/// module in turn is triggered to sample by the 64KHz clock provided by the +/// Timing Distribution System. +/// - +void* +fe_start_iop( void* arg ) { - int ii,jj,kk,ll; // Dummy loop counter variables - static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) - static int cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables - - int sync21ppsCycles = 0; /// @param sync32ppsCycles Number of attempts to sync to 1PPS - volatile RFM_FE_COMMS *pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared memory space - int status; /// @param status Typical function return value - float onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics - int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check - int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check + int ii, jj, kk, ll; // Dummy loop counter variables + static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) + static int cpuClock[ CPU_TIMER_CNT ]; /// @param cpuClock[] Code timing + /// diag variables + + int sync21ppsCycles = + 0; /// @param sync32ppsCycles Number of attempts to sync to 1PPS + volatile RFM_FE_COMMS* pEpicsComms; /// @param *pEpicsComms Pointer to EPICS + /// shared memory space + int status; /// @param status Typical function return value + float + onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics + int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check + int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check #ifdef DIAG_TEST - float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for diagnostics - int onePpsHiTest[10]; /// @param onePpsHiTest[] One PPS diagnostic check - int onePpsTimeTest[10]; /// @param onePpsTimeTest[] One PPS diagnostic check + float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for + /// diagnostics + int onePpsHiTest[ 10 ]; /// @param onePpsHiTest[] One PPS diagnostic check + int onePpsTimeTest[ 10 ]; /// @param onePpsTimeTest[] One PPS diagnostic + /// check #endif - int dcuId; /// @param dcuId DAQ ID number for this process - static int missedCycle = 0; /// @param missedCycle Incremented error counter when too many values in ADC FIFO - int diagWord = 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS - int system = 0; - int sync21pps = 0; /// @param sync21pps Code startup sync to 1PPS flag - int syncSource = SYNC_SRC_NONE; /// @param syncSource Code startup synchronization source - int mxStat = 0; /// @param mxStat Net diags when myrinet express is used - int mxDiag = 0; - int mxDiagR = 0; - - int feStatus = 0; - int dkiTrip = 0; - - unsigned int usec = 0; - unsigned long cpc; - float duotoneTimeDac; - float duotoneTime; - - int usloop=1; - double adcval[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD]; - adcInfo_t *padcinfo; - - - - -/// **********************************************************************************************\n -/// Start Initialization Process \n -/// **********************************************************************************************\n - -/// \> Flush L1 cache - memset (fp, 0, 64*1024); - memset (fp, 1, 64*1024); - clflush_cache_range ((void *)fp, 64*1024); - - fz_daz(); /// \> Kill the denorms! - - /// \> Init comms with EPICS processor */ - pEpicsComms = (volatile RFM_FE_COMMS *)_epics_shm; - pLocalEpics = (volatile CDS_EPICS *)&pEpicsComms->epicsSpace; - pEpicsDaq = (volatile char *)&(pLocalEpics->epicsOutput); - - padcinfo = (adcInfo_t *)&adcinfo; + int dcuId; /// @param dcuId DAQ ID number for this process + static int missedCycle = 0; /// @param missedCycle Incremented error counter + /// when too many values in ADC FIFO + int diagWord = + 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS + int system = 0; + int sync21pps = 0; /// @param sync21pps Code startup sync to 1PPS flag + int syncSource = + SYNC_SRC_NONE; /// @param syncSource Code startup synchronization source + int mxStat = 0; /// @param mxStat Net diags when myrinet express is used + int mxDiag = 0; + int mxDiagR = 0; + + int feStatus = 0; + int dkiTrip = 0; + + unsigned int usec = 0; + unsigned long cpc; + float duotoneTimeDac; + float duotoneTime; + + int usloop = 1; + double adcval[ MAX_ADC_MODULES ][ MAX_ADC_CHN_PER_MOD ]; + adcInfo_t* padcinfo; + + /// **********************************************************************************************\n + /// Start Initialization Process \n + /// **********************************************************************************************\n + + /// \> Flush L1 cache + memset( fp, 0, 64 * 1024 ); + memset( fp, 1, 64 * 1024 ); + clflush_cache_range( (void*)fp, 64 * 1024 ); + + fz_daz( ); /// \> Kill the denorms! + + /// \> Init comms with EPICS processor */ + pEpicsComms = (volatile RFM_FE_COMMS*)_epics_shm; + pLocalEpics = (volatile CDS_EPICS*)&pEpicsComms->epicsSpace; + pEpicsDaq = (volatile char*)&( pLocalEpics->epicsOutput ); + + padcinfo = (adcInfo_t*)&adcinfo; #ifdef OVERSAMPLE - /// \> Zero out filter histories - memset(dHistory, 0, sizeof(dHistory)); - memset(dDacHistory, 0, sizeof(dDacHistory)); + /// \> Zero out filter histories + memset( dHistory, 0, sizeof( dHistory ) ); + memset( dDacHistory, 0, sizeof( dDacHistory ) ); #endif - /// \> Set pointers to filter module data buffers. \n - /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n - /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n - /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n - /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n - pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace); - dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - - /// \> Clear the FE reset which comes from Epics - pLocalEpics->epicsInput.vmeReset = 0; - - // Clear input masks - pLocalEpics->epicsInput.burtRestore_mask = 0; - pLocalEpics->epicsInput.dacDuoSet_mask = 0; - -/// \> Init code synchronization source. - // Look for DIO card or IRIG-B Card - // if Contec 1616 BIO present, TDS slave will be used for timing. - if(cdsPciModules.cDio1616lCount) syncSource = SYNC_SRC_TDS; - else syncSource = SYNC_SRC_1PPS; + /// \> Set pointers to filter module data buffers. \n + /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD + /// data.\n + /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done + /// to: \n + /// - -------- Allow daqLib.c to retrieve filter module data directly from + /// shared memory. \n + /// - -------- Avoid copy of filter module data between to memory locations, + /// which was slow. \n + pDsp[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + pCoeff[ system ] = (VME_COEF*)( &pEpicsComms->coeffSpace ); + dspPtr[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + + /// \> Clear the FE reset which comes from Epics + pLocalEpics->epicsInput.vmeReset = 0; + + // Clear input masks + pLocalEpics->epicsInput.burtRestore_mask = 0; + pLocalEpics->epicsInput.dacDuoSet_mask = 0; + + /// \> Init code synchronization source. + // Look for DIO card or IRIG-B Card + // if Contec 1616 BIO present, TDS slave will be used for timing. + if ( cdsPciModules.cDio1616lCount ) + syncSource = SYNC_SRC_TDS; + else + syncSource = SYNC_SRC_1PPS; #ifdef NO_SYNC - syncSource = SYNC_SRC_NONE; + syncSource = SYNC_SRC_NONE; #endif - -#ifdef TIME_MASTER - pcieTimer = (volatile TIMING_SIGNAL *) ((volatile char *)(cdsPciModules.dolphinWrite[0]) + IPC_PCIE_TIME_OFFSET); +#ifdef TIME_MASTER + pcieTimer = + (volatile TIMING_SIGNAL*)( (volatile char*)( cdsPciModules + .dolphinWrite[ 0 ] ) + + IPC_PCIE_TIME_OFFSET ); #endif -#ifdef TIME_SLAVE - pcieTimer = (volatile TIMING_SIGNAL *) ((volatile char *)(cdsPciModules.dolphinRead[0]) + IPC_PCIE_TIME_OFFSET); -syncSource = SYNC_SRC_DOLPHIN; +#ifdef TIME_SLAVE + pcieTimer = + (volatile TIMING_SIGNAL*)( (volatile char*)( cdsPciModules + .dolphinRead[ 0 ] ) + + IPC_PCIE_TIME_OFFSET ); + syncSource = SYNC_SRC_DOLPHIN; #endif -/// < Read in all Filter Module EPICS coeff settings - for(ii=0;ii<MAX_MODULES;ii++) - { - checkFiltReset(ii, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - } - - // Need this FE dcuId to make connection to FB - dcuId = pLocalEpics->epicsInput.dcuId; - pLocalEpics->epicsOutput.dcuId = dcuId; - - // Reset timing diagnostics - pLocalEpics->epicsOutput.diagWord = 0; - pLocalEpics->epicsOutput.timeDiag = 0; - pLocalEpics->epicsOutput.timeErr = syncSource; - -/// \> Init IIR filter banks -// Initialize filter banks ********************************************* - for (system = 0; system < NUM_SYSTEMS; system++) { - for(ii=0;ii<MAX_MODULES;ii++){ - for(jj=0;jj<FILTERS;jj++){ - for(kk=0;kk<MAX_COEFFS;kk++){ - dspCoeff[system].coeffs[ii].filtCoeff[jj][kk] = 0.0; - } - dspCoeff[system].coeffs[ii].filtSections[jj] = 0; - } + /// < Read in all Filter Module EPICS coeff settings + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + checkFiltReset( ii, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); } - } - - /// \> Initialize all filter module excitation signals to zero - for (system = 0; system < NUM_SYSTEMS; system++) - for(ii=0;ii<MAX_MODULES;ii++) - pDsp[0]->data[ii].exciteInput = 0.0; - - - /// \> Initialize IIR filter bank values - if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) { - pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR; - return 0; - } - - - udelay(1000); - -/// \> Initialize DAQ variable/software -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Set data range limits for daqLib routine - daq.filtExMin = GDS_16K_EXC_MIN; - daq.filtTpMin = GDS_16K_TP_MIN; - daq.filtExMax = daq.filtExMin + MAX_MODULES; - daq.filtExSize = MAX_MODULES; - daq.xExMin = daq.filtExMax; - daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; - daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; - daq.filtTpSize = MAX_MODULES * 3; - daq.xTpMin = daq.filtTpMax; - daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; - - /// - ---- Initialize DAQ function - status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - if(status == -1) - { - pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR; - vmeDone = 1; - return(0); - } -#endif + // Need this FE dcuId to make connection to FB + dcuId = pLocalEpics->epicsInput.dcuId; + pLocalEpics->epicsOutput.dcuId = dcuId; - /// - ---- Assign DAC testpoint pointers - for (ii = 0; ii < cdsPciModules.dacCount; ii++) - for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) // 16 per DAC regardless of the actual - testpoint[MAX_DAC_CHN_PER_MOD * ii + jj] = floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; + // Reset timing diagnostics + pLocalEpics->epicsOutput.diagWord = 0; + pLocalEpics->epicsOutput.timeDiag = 0; + pLocalEpics->epicsOutput.timeErr = syncSource; - // Zero out storage - memset(floatDacOut, 0, sizeof(floatDacOut)); - - pLocalEpics->epicsOutput.ipcStat = 0; - pLocalEpics->epicsOutput.fbNetStat = 0; - pLocalEpics->epicsOutput.tpCnt = 0; - - // Clear the code exit flag - vmeDone = 0; - - /// \> Call user application software initialization routine. - iopDacEnable = feCode(cycleNum,adcval,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); - - // Initialize timing info variables - initializeTimingDiags(&timeinfo); - missedCycle = 0; + /// \> Init IIR filter banks + // Initialize filter banks ********************************************* + for ( system = 0; system < NUM_SYSTEMS; system++ ) + { + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + for ( jj = 0; jj < FILTERS; jj++ ) + { + for ( kk = 0; kk < MAX_COEFFS; kk++ ) + { + dspCoeff[ system ].coeffs[ ii ].filtCoeff[ jj ][ kk ] = 0.0; + } + dspCoeff[ system ].coeffs[ ii ].filtSections[ jj ] = 0; + } + } + } - // Initialize duotone measurement signals - initializeDuotoneDiags(&dt_diag); + /// \> Initialize all filter module excitation signals to zero + for ( system = 0; system < NUM_SYSTEMS; system++ ) + for ( ii = 0; ii < MAX_MODULES; ii++ ) + pDsp[ 0 ]->data[ ii ].exciteInput = 0.0; - /// \> Initialize the ADC modules ************************************* - pLocalEpics->epicsOutput.fe_status = INIT_ADC_MODS; - status = iop_adc_init(padcinfo); + /// \> Initialize IIR filter bank values + if ( initVars( pDsp[ 0 ], pDsp[ 0 ], dspCoeff, MAX_MODULES, pCoeff[ 0 ] ) ) + { + pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR; + return 0; + } - /// \> Initialize the DAC module variables ********************************** - pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; - status = iop_dac_init(dacTimingErrorPending); + udelay( 1000 ); + +/// \> Initialize DAQ variable/software +#if !defined( NO_DAQ ) && !defined( IOP_TASK ) + /// - ---- Set data range limits for daqLib routine + daq.filtExMin = GDS_16K_EXC_MIN; + daq.filtTpMin = GDS_16K_TP_MIN; + daq.filtExMax = daq.filtExMin + MAX_MODULES; + daq.filtExSize = MAX_MODULES; + daq.xExMin = daq.filtExMax; + daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; + daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; + daq.filtTpSize = MAX_MODULES * 3; + daq.xTpMin = daq.filtTpMax; + daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; + + /// - ---- Initialize DAQ function + status = daqWrite( 0, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + 0, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + if ( status == -1 ) + { + pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR; + vmeDone = 1; + return ( 0 ); + } - pLocalEpics->epicsOutput.fe_status = INIT_SYNC; +#endif -/// \> Find the code syncrhonization source. \n -/// - Standard aLIGO Sync source is the Timing Distribution System (TDS) (SYNC_SRC_TDS). - switch(syncSource) - { - /// \>\> For SYNC_SRC_TDS, initialize system for synchronous start on 1PPS mark: + /// - ---- Assign DAC testpoint pointers + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + for ( jj = 0; jj < MAX_DAC_CHN_PER_MOD; + jj++ ) // 16 per DAC regardless of the actual + testpoint[ MAX_DAC_CHN_PER_MOD * ii + jj ] = + floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; + + // Zero out storage + memset( floatDacOut, 0, sizeof( floatDacOut ) ); + + pLocalEpics->epicsOutput.ipcStat = 0; + pLocalEpics->epicsOutput.fbNetStat = 0; + pLocalEpics->epicsOutput.tpCnt = 0; + + // Clear the code exit flag + vmeDone = 0; + + /// \> Call user application software initialization routine. + iopDacEnable = feCode( cycleNum, + adcval, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 1 ); + + // Initialize timing info variables + initializeTimingDiags( &timeinfo ); + missedCycle = 0; + + // Initialize duotone measurement signals + initializeDuotoneDiags( &dt_diag ); + + /// \> Initialize the ADC modules ************************************* + pLocalEpics->epicsOutput.fe_status = INIT_ADC_MODS; + status = iop_adc_init( padcinfo ); + + /// \> Initialize the DAC module variables + /// ********************************** + pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; + status = iop_dac_init( dacTimingErrorPending ); + + pLocalEpics->epicsOutput.fe_status = INIT_SYNC; + + /// \> Find the code syncrhonization source. \n + /// - Standard aLIGO Sync source is the Timing Distribution System (TDS) + /// (SYNC_SRC_TDS). + switch ( syncSource ) + { + /// \>\> For SYNC_SRC_TDS, initialize system for synchronous start on 1PPS + /// mark: case SYNC_SRC_TDS: - /// - ---- Turn off TDS slave unit timing clocks, in turn removing clocks from ADC/DAC modules. - for(ii=0;ii<tdsCount;ii++) - { - CDIO1616Output[ii] = TDS_STOP_CLOCKS; - CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]); - } - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - /// - ---- Arm ADC modules - gsc16ai64Enable(&cdsPciModules); - gsc18ai32Enable(&cdsPciModules); - /// - ---- Arm DAC outputs - gsc18ao8Enable(&cdsPciModules); - gsc20ao8Enable(&cdsPciModules); - gsc16ao16Enable(&cdsPciModules); - // Set synched flag so later code will not check for 1PPS - sync21pps = 1; - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - /// - ---- Preload DAC FIFOS\n - /// - --------- Code runs intrinsically slower first few cycle after startup, so new DAC - /// values not written until a few cycle into run. \n - /// - --------- DAC timing diags will later check FIFO sizes to verify synchrounous timing. - // #ifndef NO_DAC_PRELOAD -#if !defined (NO_DAC_PRELOAD) && !defined (TIME_SLAVE) - status = iop_dac_preload(dacPtr); + /// - ---- Turn off TDS slave unit timing clocks, in turn removing + /// clocks from ADC/DAC modules. + for ( ii = 0; ii < tdsCount; ii++ ) + { + CDIO1616Output[ ii ] = TDS_STOP_CLOCKS; + CDIO1616Input[ ii ] = contec1616WriteOutputRegister( + &cdsPciModules, tdsControl[ ii ], CDIO1616Output[ ii ] ); + } + udelay( MAX_UDELAY ); + udelay( MAX_UDELAY ); + /// - ---- Arm ADC modules + gsc16ai64Enable( &cdsPciModules ); + gsc18ai32Enable( &cdsPciModules ); + /// - ---- Arm DAC outputs + gsc18ao8Enable( &cdsPciModules ); + gsc20ao8Enable( &cdsPciModules ); + gsc16ao16Enable( &cdsPciModules ); + // Set synched flag so later code will not check for 1PPS + sync21pps = 1; + udelay( MAX_UDELAY ); + udelay( MAX_UDELAY ); + /// - ---- Preload DAC FIFOS\n + /// - --------- Code runs intrinsically slower first few cycle after + /// startup, so new DAC values not written until a few cycle into run. + /// \n + /// - --------- DAC timing diags will later check FIFO sizes to verify + /// synchrounous timing. + // #ifndef NO_DAC_PRELOAD +#if !defined( NO_DAC_PRELOAD ) && !defined( TIME_SLAVE ) + status = iop_dac_preload( dacPtr ); #endif - /// - ---- Start the timing clocks\n - /// - --------- Send start command to TDS slave.\n - /// - --------- TDS slave will begin sending 64KHz clocks synchronous to next 1PPS mark. - // CDIO1616Output[tdsControl] = 0x7B00000; - for(ii=0;ii<tdsCount;ii++) - { - // CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS; - CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; - CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]); - } - break; + /// - ---- Start the timing clocks\n + /// - --------- Send start command to TDS slave.\n + /// - --------- TDS slave will begin sending 64KHz clocks synchronous to + /// next 1PPS mark. + // CDIO1616Output[tdsControl] = 0x7B00000; + for ( ii = 0; ii < tdsCount; ii++ ) + { + // CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS; + CDIO1616Output[ ii ] = + TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; + CDIO1616Input[ ii ] = contec1616WriteOutputRegister( + &cdsPciModules, tdsControl[ ii ], CDIO1616Output[ ii ] ); + } + break; case SYNC_SRC_1PPS: // #ifndef NO_DAC_PRELOAD -#if !defined (NO_DAC_PRELOAD) && !defined (TIME_SLAVE) - gsc16ai64Enable(&cdsPciModules); - status = iop_dac_preload(dacPtr); +#if !defined( NO_DAC_PRELOAD ) && !defined( TIME_SLAVE ) + gsc16ai64Enable( &cdsPciModules ); + status = iop_dac_preload( dacPtr ); #endif - // Arm ADC modules - // This has to be done sequentially, one at a time. - status = sync_adc_2_1pps(); - break; + // Arm ADC modules + // This has to be done sequentially, one at a time. + status = sync_adc_2_1pps( ); + break; case SYNC_SRC_NONE: - gsc16ai64Enable(&cdsPciModules); - gsc18ai32Enable(&cdsPciModules); - sync21pps = 1; - break; + gsc16ai64Enable( &cdsPciModules ); + gsc18ai32Enable( &cdsPciModules ); + sync21pps = 1; + break; case SYNC_SRC_DOLPHIN: - sync21pps = 1; - break; - default: { - // IRIG-B card not found, so use CPU time to get close to 1PPS on startup - // Pause until this second ends - gsc16ai64Enable(&cdsPciModules); - gsc18ai32Enable(&cdsPciModules); - sync21pps = 1; - break; + sync21pps = 1; + break; + default: + { + // IRIG-B card not found, so use CPU time to get close to 1PPS on + // startup Pause until this second ends + gsc16ai64Enable( &cdsPciModules ); + gsc18ai32Enable( &cdsPciModules ); + sync21pps = 1; + break; + } } - } -// for(jj=0;jj<cdsPciModules.adcCount;jj++) gsc18ai32DmaEnable(jj); - pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; + // for(jj=0;jj<cdsPciModules.adcCount;jj++) gsc18ai32DmaEnable(jj); + pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; - onePpsTime = cycleNum; + onePpsTime = cycleNum; #ifdef REMOTE_GPS - timeSec = remote_time((struct CDS_EPICS *)pLocalEpics); + timeSec = remote_time( (struct CDS_EPICS*)pLocalEpics ); #elif TIME_SLAVE - timeSec = sync2master(pcieTimer); - sync21pps = 1; + timeSec = sync2master( pcieTimer ); + sync21pps = 1; #else - timeSec = current_time_fe() -1; + timeSec = current_time_fe( ) - 1; #endif - adcinfo.adcTime = rdtsc_ordered(); - - /// ******************************************************************************\n - /// Enter the infinite FE control loop ******************************************\n + adcinfo.adcTime = rdtsc_ordered( ); - /// ******************************************************************************\n - // Calculate how many CPU cycles per code cycle - cpc = cpu_khz * 1000; - cpc /= CYCLE_PER_SECOND; + /// ******************************************************************************\n + /// Enter the infinite FE control loop + /// ******************************************\n + /// ******************************************************************************\n + // Calculate how many CPU cycles per code cycle + cpc = cpu_khz * 1000; + cpc /= CYCLE_PER_SECOND; #ifdef NO_CPU_SHUTDOWN - while(!kthread_should_stop() && !vmeDone){ + while ( !kthread_should_stop( ) && !vmeDone ) + { #else - while(!vmeDone){ // Run forever until user hits reset + while ( !vmeDone ) + { // Run forever until user hits reset #endif // ***************************************************************************************** // NORMAL OPERATION -- Wait for ADC data ready // ***************************************************************************************** #ifndef RFM_DIRECT_READ -/// \> If IOP and RFM DMA selected, block transfer data from GeFanuc RFM cards. -// Used in block transfers of data from GEFANUC RFM -/// - ---- Want to start the DMA ASAP, before ADC data starts coming in. -/// - ---- Note that data only xferred every 4th cycle of IOP, so max data rate on RFM is 16K. - if((cycleNum % 4) == 0) - { - if (cdsPciModules.pci_rfm[0]) vmic5565DMA(&cdsPciModules,0,(cycleNum % IPC_BLOCKS)); - if (cdsPciModules.pci_rfm[1]) vmic5565DMA(&cdsPciModules,1,(cycleNum % IPC_BLOCKS)); - } -#endif - -/// \> On 1PPS mark \n - if(cycleNum == 0) - { - /// - ---- Check awgtpman status. - pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); - if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG; - /// - ---- Check if DAC outputs are enabled, report error. - if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE; - - /// - ---- If IOP, Increment GPS second - timeSec ++; - pLocalEpics->epicsOutput.timeDiag = timeSec; - if (cycle_gps_time == 0) { - timeinfo.startGpsTime = timeSec; - pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime; - } - cycle_gps_time = timeSec; - } -#ifdef NO_CPU_SHUTDOWN - if((cycleNum % 2048) == 0) { - usleep_range(1,3); - } -#endif -// Start of ADC Read ********************************************************************** - // Read ADC data - status = iop_adc_read (padcinfo, cpuClock); - // Try synching to 1PPS on ADC[0][31] if not using IRIG-B or TDS - // Only try for 1 sec. - if(!sync21pps) - { - // 1PPS signal should rise above 4000 ADC counts if present. - if((adcinfo.adcData[0][31] < ONE_PPS_THRESH) && (sync21ppsCycles < (CYCLE_PER_SECOND*OVERSAMPLE_TIMES))) - { - ll = -1; - sync21ppsCycles ++; - }else { - // Need to start clocking the DAC outputs. - gsc18ao8Enable(&cdsPciModules); - gsc16ao16Enable(&cdsPciModules); - sync21pps = 1; - // 1PPS never found, so indicate NO SYNC to user - if(sync21ppsCycles >= (CYCLE_PER_SECOND*OVERSAMPLE_TIMES)) - { - syncSource = SYNC_SRC_NONE; - } else { - // 1PPS found and synched to - syncSource = SYNC_SRC_1PPS; + /// \> If IOP and RFM DMA selected, block transfer data from GeFanuc RFM + /// cards. + // Used in block transfers of data from GEFANUC RFM + /// - ---- Want to start the DMA ASAP, before ADC data starts coming in. + /// - ---- Note that data only xferred every 4th cycle of IOP, so max + /// data rate on RFM is 16K. + if ( ( cycleNum % 4 ) == 0 ) + { + if ( cdsPciModules.pci_rfm[ 0 ] ) + vmic5565DMA( &cdsPciModules, 0, ( cycleNum % IPC_BLOCKS ) ); + if ( cdsPciModules.pci_rfm[ 1 ] ) + vmic5565DMA( &cdsPciModules, 1, ( cycleNum % IPC_BLOCKS ) ); } - pLocalEpics->epicsOutput.timeErr = syncSource; - } - } - - -for(usloop=0;usloop<UNDERSAMPLE;usloop++) -{ +#endif -// ************************************************************************************** -/// \> Call the front end specific application ******************\n -/// - -- This is where the user application produced by RCG gets called and executed. \n\n - // - for(ii=0;ii<cdsPciModules.adcCount;ii++) - { - if (cdsPciModules.adcType[ii] == GSC_18AI32SSC1M) { - for(jj=0;jj<32;jj++) + /// \> On 1PPS mark \n + if ( cycleNum == 0 ) { - adcval[ii][jj] = dWord[ii][jj][usloop]; + /// - ---- Check awgtpman status. + pLocalEpics->epicsOutput.awgStat = + ( pEpicsComms->padSpace.awgtpman_gps != timeSec ); + if ( pLocalEpics->epicsOutput.awgStat ) + feStatus |= FE_ERROR_AWG; + /// - ---- Check if DAC outputs are enabled, report error. + if ( !iopDacEnable || dkiTrip ) + feStatus |= FE_ERROR_DAC_ENABLE; + + /// - ---- If IOP, Increment GPS second + timeSec++; + pLocalEpics->epicsOutput.timeDiag = timeSec; + if ( cycle_gps_time == 0 ) + { + timeinfo.startGpsTime = timeSec; + pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime; + } + cycle_gps_time = timeSec; } - } else { - for(jj=0;jj<32;jj++) +#ifdef NO_CPU_SHUTDOWN + if ( ( cycleNum % 2048 ) == 0 ) { - adcval[ii][jj] = dWord[ii][jj][0]; + usleep_range( 1, 3 ); } - } - } - cpuClock[CPU_TIME_USR_START] = rdtsc_ordered(); - iopDacEnable = feCode(cycleNum,adcval,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0); - cpuClock[CPU_TIME_USR_END] = rdtsc_ordered(); -// ************************************************************************************** -// -// -// ************************************************************************************** - /// - ---- Reset ADC DMA Start Flag \n - /// - --------- This allows ADC to dump next data set whenever it is ready - // for(jj=0;jj<cdsPciModules.adcCount;jj++) gsc16ai64DmaEnable(jj); - // for(jj=0;jj<cdsPciModules.adcCount;jj++) gsc18ai32DmaEnable(jj); - odcStateWord = 0; -// -// ******************************************************************** -/// WRITE DAC OUTPUTS ***************************************** \n -// ******************************************************************** - -#ifndef DAC_WD_OVERRIDE - // If a DAC module has bad timing then quit writing outputs - // COMMENT OUT NEXT LINE FOR TEST STAND w/bad DAC cards. - if(dacTimingError) iopDacEnable = 0; #endif - // Write out data to DAC modules - if(usloop == 0) dkiTrip = iop_dac_write(); - - -// *********************************************************************** -/// BEGIN HOUSEKEEPING ************************************************ \n -// *********************************************************************** - - pLocalEpics->epicsOutput.cycle = cycleNum; -// ***************************************************************** -/// \> Cycle 0: \n -/// - ---- Read IRIGB time if symmetricom card (this is not standard, but supported for earlier cards. \n -// ***************************************************************** - if(cycleNum == HKP_READ_SYMCOM_IRIGB) - { - if(cdsPciModules.gpsType == SYMCOM_RCVR) - { - // Retrieve time set in at adc read and report offset from 1PPS - gps_receiver_locked = getGpsTime(&timeSec,&usec); - pLocalEpics->epicsOutput.irigbTime = usec; - } - if((usec > MAX_IRIGB_SKEW || usec < MIN_IRIGB_SKEW) && cdsPciModules.gpsType != 0) - { - diagWord |= TIME_ERR_IRIGB;; - feStatus |= FE_ERROR_TIMING;; - } -/// - ---- Calc duotone diagnostic mean values for past second and reset. - dt_diag.meanAdc = dt_diag.totalAdc/CYCLE_PER_SECOND; - dt_diag.totalAdc = 0.0; - dt_diag.meanDac = dt_diag.totalDac/CYCLE_PER_SECOND; - dt_diag.totalDac = 0.0; - } - -// ***************************************************************** -/// \> Cycle 1 and Spectricom IRIGB (standard), get IRIG-B time information. -// ***************************************************************** - if(cycleNum == HKP_READ_TSYNC_IRIBB) - { - if(cdsPciModules.gpsType == TSYNC_RCVR) - { - gps_receiver_locked = getGpsuSecTsync(&usec); - pLocalEpics->epicsOutput.irigbTime = usec; - /// - ---- If not in acceptable range, generate error. - if((usec > MAX_IRIGB_SKEW) || (usec < MIN_IRIGB_SKEW)) + // Start of ADC Read + // ********************************************************************** + // Read ADC data + status = iop_adc_read( padcinfo, cpuClock ); + // Try synching to 1PPS on ADC[0][31] if not using IRIG-B or TDS + // Only try for 1 sec. + if ( !sync21pps ) { - feStatus |= FE_ERROR_TIMING;; - diagWord |= TIME_ERR_IRIGB;; + // 1PPS signal should rise above 4000 ADC counts if present. + if ( ( adcinfo.adcData[ 0 ][ 31 ] < ONE_PPS_THRESH ) && + ( sync21ppsCycles < ( CYCLE_PER_SECOND * OVERSAMPLE_TIMES ) ) ) + { + ll = -1; + sync21ppsCycles++; + } + else + { + // Need to start clocking the DAC outputs. + gsc18ao8Enable( &cdsPciModules ); + gsc16ao16Enable( &cdsPciModules ); + sync21pps = 1; + // 1PPS never found, so indicate NO SYNC to user + if ( sync21ppsCycles >= + ( CYCLE_PER_SECOND * OVERSAMPLE_TIMES ) ) + { + syncSource = SYNC_SRC_NONE; + } + else + { + // 1PPS found and synched to + syncSource = SYNC_SRC_1PPS; + } + pLocalEpics->epicsOutput.timeErr = syncSource; + } } - } - } -/// \> Update duotone diag information - if(syncSource == SYNC_SRC_TDS) - { - dt_diag.dac[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN][usloop]; - dt_diag.totalDac += dWord[ADC_DUOTONE_BRD][DAC_DUOTONE_CHAN][usloop]; - dt_diag.adc[(cycleNum + DT_SAMPLE_OFFSET) % CYCLE_PER_SECOND] = dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN][usloop]; - dt_diag.totalAdc += dWord[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN][usloop]; - } + for ( usloop = 0; usloop < UNDERSAMPLE; usloop++ ) + { -// ***************************************************************** -/// \> Cycle 16, perform duotone diag calcs. -// ***************************************************************** - if(cycleNum == HKP_DT_CALC && syncSource == SYNC_SRC_TDS) - { - duotoneTime = duotime(DT_SAMPLE_CNT, dt_diag.meanAdc, dt_diag.adc); - pLocalEpics->epicsOutput.dtTime = duotoneTime; - if(((duotoneTime < MIN_DT_DIAG_VAL) || (duotoneTime > MAX_DT_DIAG_VAL)) && - syncSource != SYNC_SRC_1PPS) - feStatus |= FE_ERROR_TIMING; - duotoneTimeDac = duotime(DT_SAMPLE_CNT, dt_diag.meanDac, dt_diag.dac); - pLocalEpics->epicsOutput.dacDtTime = duotoneTimeDac; - } + // ************************************************************************************** + /// \> Call the front end specific application ******************\n + /// - -- This is where the user application produced by RCG gets + /// called and executed. \n\n + // + for ( ii = 0; ii < cdsPciModules.adcCount; ii++ ) + { + if ( cdsPciModules.adcType[ ii ] == GSC_18AI32SSC1M ) + { + for ( jj = 0; jj < 32; jj++ ) + { + adcval[ ii ][ jj ] = dWord[ ii ][ jj ][ usloop ]; + } + } + else + { + for ( jj = 0; jj < 32; jj++ ) + { + adcval[ ii ][ jj ] = dWord[ ii ][ jj ][ 0 ]; + } + } + } + cpuClock[ CPU_TIME_USR_START ] = rdtsc_ordered( ); + iopDacEnable = feCode( cycleNum, + adcval, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 0 ); + cpuClock[ CPU_TIME_USR_END ] = rdtsc_ordered( ); + // ************************************************************************************** + // + // + // ************************************************************************************** + /// - ---- Reset ADC DMA Start Flag \n + /// - --------- This allows ADC to dump next data set whenever it is + /// ready + // for(jj=0;jj<cdsPciModules.adcCount;jj++) gsc16ai64DmaEnable(jj); + // for(jj=0;jj<cdsPciModules.adcCount;jj++) gsc18ai32DmaEnable(jj); + odcStateWord = 0; + // + // ******************************************************************** + /// WRITE DAC OUTPUTS ***************************************** \n + // ******************************************************************** -// ***************************************************************** -/// \> Cycle 17, set/reset DAC duotone switch if request has changed. -// ***************************************************************** - if(cycleNum == HKP_DAC_DT_SWITCH && syncSource == SYNC_SRC_TDS) - { - if(dt_diag.dacDuoEnable != pLocalEpics->epicsInput.dacDuoSet) - { - dt_diag.dacDuoEnable = pLocalEpics->epicsInput.dacDuoSet; - if(dt_diag.dacDuoEnable) - CDIO1616Output[0] = TDS_START_ADC_NEG_DAC_POS; - else CDIO1616Output[0] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; - CDIO1616Input[0] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[0], CDIO1616Output[0]); - } - } +#ifndef DAC_WD_OVERRIDE + // If a DAC module has bad timing then quit writing outputs + // COMMENT OUT NEXT LINE FOR TEST STAND w/bad DAC cards. + if ( dacTimingError ) + iopDacEnable = 0; +#endif + // Write out data to DAC modules + if ( usloop == 0 ) + dkiTrip = iop_dac_write( ); + + // *********************************************************************** + /// BEGIN HOUSEKEEPING + /// ************************************************ \n + // *********************************************************************** + + pLocalEpics->epicsOutput.cycle = cycleNum; + // ***************************************************************** + /// \> Cycle 0: \n + /// - ---- Read IRIGB time if symmetricom card (this is not + /// standard, but supported for earlier cards. \n + // ***************************************************************** + if ( cycleNum == HKP_READ_SYMCOM_IRIGB ) + { + if ( cdsPciModules.gpsType == SYMCOM_RCVR ) + { + // Retrieve time set in at adc read and report offset from + // 1PPS + gps_receiver_locked = getGpsTime( &timeSec, &usec ); + pLocalEpics->epicsOutput.irigbTime = usec; + } + if ( ( usec > MAX_IRIGB_SKEW || usec < MIN_IRIGB_SKEW ) && + cdsPciModules.gpsType != 0 ) + { + diagWord |= TIME_ERR_IRIGB; + ; + feStatus |= FE_ERROR_TIMING; + ; + } + /// - ---- Calc duotone diagnostic mean values for past second + /// and reset. + dt_diag.meanAdc = dt_diag.totalAdc / CYCLE_PER_SECOND; + dt_diag.totalAdc = 0.0; + dt_diag.meanDac = dt_diag.totalDac / CYCLE_PER_SECOND; + dt_diag.totalDac = 0.0; + } -// ***************************************************************** -/// \> Cycle 18, Send timing info to EPICS at 1Hz -// ***************************************************************** - if(cycleNum ==HKP_TIMING_UPDATES) - { - sendTimingDiags2Epics(pLocalEpics, &timeinfo, &adcinfo); - - pLocalEpics->epicsOutput.dacEnable = dacEnable; - - if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) - { - diagWord |= FE_ADC_HOLD_ERR; - feStatus |= FE_ERROR_TIMING; - } - if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) - { - diagWord |= FE_PROC_TIME_ERR; - feStatus |= FE_ERROR_TIMING; - } - pLocalEpics->epicsOutput.stateWord = feStatus; - feStatus = 0; - if(pLocalEpics->epicsInput.diagReset || initialDiagReset) - { - initialDiagReset = 0; - pLocalEpics->epicsInput.diagReset = 0; - pLocalEpics->epicsInput.ipcDiagReset = 1; - timeinfo.timeHoldMax = 0; - diagWord = 0; - ipcErrBits = 0; - for(jj=0;jj<cdsPciModules.adcCount;jj++) adcinfo.adcRdTimeMax[jj] = 0; - } - pLocalEpics->epicsOutput.diagWord = diagWord; - for(jj=0;jj<cdsPciModules.adcCount;jj++) { - if(adcinfo.adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC) - pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC; - adcinfo.adcRdTimeErr[jj] = 0; - } - } + // ***************************************************************** + /// \> Cycle 1 and Spectricom IRIGB (standard), get IRIG-B time + /// information. + // ***************************************************************** + if ( cycleNum == HKP_READ_TSYNC_IRIBB ) + { + if ( cdsPciModules.gpsType == TSYNC_RCVR ) + { + gps_receiver_locked = getGpsuSecTsync( &usec ); + pLocalEpics->epicsOutput.irigbTime = usec; + /// - ---- If not in acceptable range, generate error. + if ( ( usec > MAX_IRIGB_SKEW ) || + ( usec < MIN_IRIGB_SKEW ) ) + { + feStatus |= FE_ERROR_TIMING; + ; + diagWord |= TIME_ERR_IRIGB; + ; + } + } + } + /// \> Update duotone diag information + if ( syncSource == SYNC_SRC_TDS ) + { + dt_diag + .dac[ ( cycleNum + DT_SAMPLE_OFFSET ) % CYCLE_PER_SECOND ] = + dWord[ ADC_DUOTONE_BRD ][ DAC_DUOTONE_CHAN ][ usloop ]; + dt_diag.totalDac += + dWord[ ADC_DUOTONE_BRD ][ DAC_DUOTONE_CHAN ][ usloop ]; + dt_diag + .adc[ ( cycleNum + DT_SAMPLE_OFFSET ) % CYCLE_PER_SECOND ] = + dWord[ ADC_DUOTONE_BRD ][ ADC_DUOTONE_CHAN ][ usloop ]; + dt_diag.totalAdc += + dWord[ ADC_DUOTONE_BRD ][ ADC_DUOTONE_CHAN ][ usloop ]; + } -// ***************************************************************** -/// \> Check for requests for filter module clear history requests. -/// This is spread out over a number of cycles. -// Spread out filter coeff update, but keep updates at 16 Hz -// here we are rounding up: -// x/y rounded up equals (x + y - 1) / y -// -// ***************************************************************** - { - static const unsigned int mpc = (MAX_MODULES + (FE_RATE / 16) - 1) / (FE_RATE / 16); // Modules per cycle - unsigned int smpc = mpc * subcycle; // Start module counter - unsigned int empc = smpc + mpc; // End module counter - unsigned int i; - for (i = smpc; i < MAX_MODULES && i < empc ; i++) - checkFiltReset(i, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - } + // ***************************************************************** + /// \> Cycle 16, perform duotone diag calcs. + // ***************************************************************** + if ( cycleNum == HKP_DT_CALC && syncSource == SYNC_SRC_TDS ) + { + duotoneTime = + duotime( DT_SAMPLE_CNT, dt_diag.meanAdc, dt_diag.adc ); + pLocalEpics->epicsOutput.dtTime = duotoneTime; + if ( ( ( duotoneTime < MIN_DT_DIAG_VAL ) || + ( duotoneTime > MAX_DT_DIAG_VAL ) ) && + syncSource != SYNC_SRC_1PPS ) + feStatus |= FE_ERROR_TIMING; + duotoneTimeDac = + duotime( DT_SAMPLE_CNT, dt_diag.meanDac, dt_diag.dac ); + pLocalEpics->epicsOutput.dacDtTime = duotoneTimeDac; + } -// ***************************************************************** - /// \> Check if code exit is requested - if(cycleNum == MAX_MODULES) - vmeDone = stop_working_threads | checkEpicsReset(cycleNum, (struct CDS_EPICS *)pLocalEpics); + // ***************************************************************** + /// \> Cycle 17, set/reset DAC duotone switch if request has + /// changed. + // ***************************************************************** + if ( cycleNum == HKP_DAC_DT_SWITCH && syncSource == SYNC_SRC_TDS ) + { + if ( dt_diag.dacDuoEnable != pLocalEpics->epicsInput.dacDuoSet ) + { + dt_diag.dacDuoEnable = pLocalEpics->epicsInput.dacDuoSet; + if ( dt_diag.dacDuoEnable ) + CDIO1616Output[ 0 ] = TDS_START_ADC_NEG_DAC_POS; + else + CDIO1616Output[ 0 ] = + TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; + CDIO1616Input[ 0 ] = contec1616WriteOutputRegister( + &cdsPciModules, tdsControl[ 0 ], CDIO1616Output[ 0 ] ); + } + } -// ***************************************************************** - // If synced to 1PPS on startup, continue to check that code - // is still in sync with 1PPS. - // This is NOT normal aLIGO mode. - if(syncSource == SYNC_SRC_1PPS) - { - // Assign chan 32 to onePps - onePps = adcinfo.adcData[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN]; - if((onePps > ONE_PPS_THRESH) && (onePpsHi == 0)) - { - onePpsTime = cycleNum; - onePpsHi = 1; - } - if(onePps < ONE_PPS_THRESH) onePpsHi = 0; - - // Check if front end continues to be in sync with 1pps - // If not, set sync error flag - if(onePpsTime > 1) pLocalEpics->epicsOutput.timeErr |= TIME_ERR_1PPS; - } + // ***************************************************************** + /// \> Cycle 18, Send timing info to EPICS at 1Hz + // ***************************************************************** + if ( cycleNum == HKP_TIMING_UPDATES ) + { + sendTimingDiags2Epics( pLocalEpics, &timeinfo, &adcinfo ); + + pLocalEpics->epicsOutput.dacEnable = dacEnable; + + if ( ( adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI ) || + ( adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO ) ) + { + diagWord |= FE_ADC_HOLD_ERR; + feStatus |= FE_ERROR_TIMING; + } + if ( timeinfo.timeHoldMax > CYCLE_TIME_ALRM ) + { + diagWord |= FE_PROC_TIME_ERR; + feStatus |= FE_ERROR_TIMING; + } + pLocalEpics->epicsOutput.stateWord = feStatus; + feStatus = 0; + if ( pLocalEpics->epicsInput.diagReset || initialDiagReset ) + { + initialDiagReset = 0; + pLocalEpics->epicsInput.diagReset = 0; + pLocalEpics->epicsInput.ipcDiagReset = 1; + timeinfo.timeHoldMax = 0; + diagWord = 0; + ipcErrBits = 0; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + adcinfo.adcRdTimeMax[ jj ] = 0; + } + pLocalEpics->epicsOutput.diagWord = diagWord; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + if ( adcinfo.adcRdTimeErr[ jj ] > MAX_ADC_WAIT_ERR_SEC ) + pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC; + adcinfo.adcRdTimeErr[ jj ] = 0; + } + } + + // ***************************************************************** + /// \> Check for requests for filter module clear history requests. + /// This is spread out over a number of cycles. + // Spread out filter coeff update, but keep updates at 16 Hz + // here we are rounding up: + // x/y rounded up equals (x + y - 1) / y + // + // ***************************************************************** + { + static const unsigned int mpc = + ( MAX_MODULES + ( FE_RATE / 16 ) - 1 ) / + ( FE_RATE / 16 ); // Modules per cycle + unsigned int smpc = mpc * subcycle; // Start module counter + unsigned int empc = smpc + mpc; // End module counter + unsigned int i; + for ( i = smpc; i < MAX_MODULES && i < empc; i++ ) + checkFiltReset( i, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); + } + + // ***************************************************************** + /// \> Check if code exit is requested + if ( cycleNum == MAX_MODULES ) + vmeDone = stop_working_threads | + checkEpicsReset( cycleNum, (struct CDS_EPICS*)pLocalEpics ); + + // ***************************************************************** + // If synced to 1PPS on startup, continue to check that code + // is still in sync with 1PPS. + // This is NOT normal aLIGO mode. + if ( syncSource == SYNC_SRC_1PPS ) + { + // Assign chan 32 to onePps + onePps = adcinfo.adcData[ ADC_DUOTONE_BRD ][ ADC_DUOTONE_CHAN ]; + if ( ( onePps > ONE_PPS_THRESH ) && ( onePpsHi == 0 ) ) + { + onePpsTime = cycleNum; + onePpsHi = 1; + } + if ( onePps < ONE_PPS_THRESH ) + onePpsHi = 0; + + // Check if front end continues to be in sync with 1pps + // If not, set sync error flag + if ( onePpsTime > 1 ) + pLocalEpics->epicsOutput.timeErr |= TIME_ERR_1PPS; + } // Following is only used on automated test system #ifdef DIAG_TEST - for(ii=0;ii<10;ii++) - { - if(ii<5) onePpsTest = adcinfo.adcData[0][ii]; - else onePpsTest = adcinfo.adcData[1][(ii-5)]; - if((onePpsTest > 400) && (onePpsHiTest[ii] == 0)) - { - onePpsTimeTest[ii] = cycleNum; - onePpsHiTest[ii] = 1; - if((ii == 0) || (ii == 5)) pLocalEpics->epicsOutput.timingTest[ii] = cycleNum * 15.26; - // Slaves do not see 1pps until after IOP signal loops around and back into ADC channel 0, - // therefore, need to subtract IOP loop time. - else pLocalEpics->epicsOutput.timingTest[ii] = (cycleNum * 15.26) - pLocalEpics->epicsOutput.timingTest[0]; - } - // Reset the diagnostic for next cycle - if(cycleNum > 2000) onePpsHiTest[ii] = 0; - } + for ( ii = 0; ii < 10; ii++ ) + { + if ( ii < 5 ) + onePpsTest = adcinfo.adcData[ 0 ][ ii ]; + else + onePpsTest = adcinfo.adcData[ 1 ][ ( ii - 5 ) ]; + if ( ( onePpsTest > 400 ) && ( onePpsHiTest[ ii ] == 0 ) ) + { + onePpsTimeTest[ ii ] = cycleNum; + onePpsHiTest[ ii ] = 1; + if ( ( ii == 0 ) || ( ii == 5 ) ) + pLocalEpics->epicsOutput.timingTest[ ii ] = + cycleNum * 15.26; + // Slaves do not see 1pps until after IOP signal loops + // around and back into ADC channel 0, therefore, need to + // subtract IOP loop time. + else + pLocalEpics->epicsOutput.timingTest[ ii ] = + ( cycleNum * 15.26 ) - + pLocalEpics->epicsOutput.timingTest[ 0 ]; + } + // Reset the diagnostic for next cycle + if ( cycleNum > 2000 ) + onePpsHiTest[ ii ] = 0; + } #endif // ***************************************************************** /// \> Write data to DAQ. // ***************************************************************** #ifndef NO_DAQ - - // Call daqLib - pLocalEpics->epicsOutput.daqByteCnt = - daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - // Send the current DAQ block size to the awgtpman for TP number checking - pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; - pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; - feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); - if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; - else odcStateWord &= ~(ODC_EXC_SET); - if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) - feStatus |= FE_ERROR_DAQ; + + // Call daqLib + pLocalEpics->epicsOutput.daqByteCnt = + daqWrite( 1, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + 0, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + // Send the current DAQ block size to the awgtpman for TP number + // checking + pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; + pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; + feStatus |= ( FE_ERROR_EXC_SET & tpPtr->count ); + if ( FE_ERROR_EXC_SET & tpPtr->count ) + odcStateWord |= ODC_EXC_SET; + else + odcStateWord &= ~( ODC_EXC_SET ); + if ( pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING ) + feStatus |= FE_ERROR_DAQ; #endif -// ***************************************************************** -/// \> Cycle 19, write updated diag info to EPICS -// ***************************************************************** - if(cycleNum == HKP_DIAG_UPDATES) - { - pLocalEpics->epicsOutput.ipcStat = ipcErrBits; - if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; - // Create FB status word for return to EPICS - mxStat = 0; - mxDiagR = daqPtr->reqAck; - if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; - if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; + // ***************************************************************** + /// \> Cycle 19, write updated diag info to EPICS + // ***************************************************************** + if ( cycleNum == HKP_DIAG_UPDATES ) + { + pLocalEpics->epicsOutput.ipcStat = ipcErrBits; + if ( ipcErrBits & 0xf ) + feStatus |= FE_ERROR_IPC; + // Create FB status word for return to EPICS + mxStat = 0; + mxDiagR = daqPtr->reqAck; + if ( ( mxDiag & 1 ) != ( mxDiagR & 1 ) ) + mxStat = 1; + if ( ( mxDiag & 2 ) != ( mxDiagR & 2 ) ) + mxStat += 2; #ifdef DUAL_DAQ_DC - if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; - if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; + if ( ( mxDiag & 4 ) != ( mxDiagR & 4 ) ) + mxStat += 4; + if ( ( mxDiag & 8 ) != ( mxDiagR & 8 ) ) + mxStat += 8; #endif - pLocalEpics->epicsOutput.fbNetStat = mxStat; - mxDiag = mxDiagR; - if(mxStat != MX_OK) feStatus |= FE_ERROR_DAQ;; - if(pLocalEpics->epicsInput.overflowReset) - { - if (pLocalEpics->epicsInput.overflowReset) { - for (ii = 0; ii < 16; ii++) { - for (jj = 0; jj < cdsPciModules.adcCount; jj++) { - adcinfo.overflowAdc[jj][ii] = 0; - adcinfo.overflowAdc[jj][ii + 16] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; - } - for (jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; + pLocalEpics->epicsOutput.fbNetStat = mxStat; + mxDiag = mxDiagR; + if ( mxStat != MX_OK ) + feStatus |= FE_ERROR_DAQ; + ; + if ( pLocalEpics->epicsInput.overflowReset ) + { + if ( pLocalEpics->epicsInput.overflowReset ) + { + for ( ii = 0; ii < 16; ii++ ) + { + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + adcinfo.overflowAdc[ jj ][ ii ] = 0; + adcinfo.overflowAdc[ jj ][ ii + 16 ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii + 16 ] = 0; + } + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + pLocalEpics->epicsOutput + .overflowDacAcc[ jj ][ ii ] = 0; + } + } + } + } + if ( ( pLocalEpics->epicsInput.overflowReset ) || + ( overflowAcc > OVERFLOW_CNTR_LIMIT ) ) + { + pLocalEpics->epicsInput.overflowReset = 0; + pLocalEpics->epicsOutput.ovAccum = 0; + overflowAcc = 0; + } } - } - } - } - if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) - { - pLocalEpics->epicsInput.overflowReset = 0; - pLocalEpics->epicsOutput.ovAccum = 0; - overflowAcc = 0; - } - } -// ***************************************************************** -/// \> Cycle 20, Update latest DAC output values to EPICS -// ***************************************************************** - if(subcycle == HKP_DAC_EPICS_UPDATES) - { - // Send DAC output values at 16Hzfb - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii]; - } - } - } + // ***************************************************************** + /// \> Cycle 20, Update latest DAC output values to EPICS + // ***************************************************************** + if ( subcycle == HKP_DAC_EPICS_UPDATES ) + { + // Send DAC output values at 16Hzfb + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { + pLocalEpics->epicsOutput.dacValue[ jj ][ ii ] = + dacOutEpics[ jj ][ ii ]; + } + } + } -// ***************************************************************** -/// \> Cycle 21, Update ADC/DAC status to EPICS. -// ***************************************************************** - if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) - { - pLocalEpics->epicsOutput.ovAccum = overflowAcc; - feStatus |= adc_status_update(&adcinfo); - feStatus |= dac_status_update(&dacinfo); - // If ADC channels not where they should be, we have no option but to exit - // from the RT code ie loops would be working with wrong input data. - if (adcinfo.chanHop) { - pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; - pLocalEpics->epicsOutput.fe_status = CHAN_HOP_ERROR; - stop_working_threads = 1; - vmeDone = 1; - continue; - } else { - pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; - } - } + // ***************************************************************** + /// \> Cycle 21, Update ADC/DAC status to EPICS. + // ***************************************************************** + if ( cycleNum == HKP_ADC_DAC_STAT_UPDATES ) + { + pLocalEpics->epicsOutput.ovAccum = overflowAcc; + feStatus |= adc_status_update( &adcinfo ); + feStatus |= dac_status_update( &dacinfo ); + // If ADC channels not where they should be, we have no option + // but to exit from the RT code ie loops would be working with + // wrong input data. + if ( adcinfo.chanHop ) + { + pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; + pLocalEpics->epicsOutput.fe_status = CHAN_HOP_ERROR; + stop_working_threads = 1; + vmeDone = 1; + continue; + } + else + { + pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; + } + } -// ***************************************************************** -/// \> Cycle 300, If IOP and RFM cards, check own data diagnostics -// ***************************************************************** - // Deal with the own-data bits on the VMIC 5565 rfm cards - if (cdsPciModules.rfmCount > 0) { - if (cycleNum >= HKP_RFM_CHK_CYCLE && cycleNum < (HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount)) { - int mod = cycleNum - HKP_RFM_CHK_CYCLE; - status = vmic5565CheckOwnDataRcv(mod); - if(!status) ipcErrBits |= 4 + (mod * 4); - } - if (cycleNum >= (HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount) && cycleNum < (HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount*2)) { - int mod = cycleNum - HKP_RFM_CHK_CYCLE - cdsPciModules.rfmCount; - vmic5565ResetOwnDataLight(mod); - } - if (cycleNum >= (HKP_RFM_CHK_CYCLE + 2*cdsPciModules.rfmCount) && cycleNum < (HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount*3)) { - int mod = cycleNum - HKP_RFM_CHK_CYCLE - cdsPciModules.rfmCount*2; - // Write data out to the RFM to trigger the light - ((volatile long *)(cdsPciModules.pci_rfm[mod]))[2] = 0; - } - } + // ***************************************************************** + /// \> Cycle 300, If IOP and RFM cards, check own data diagnostics + // ***************************************************************** + // Deal with the own-data bits on the VMIC 5565 rfm cards + if ( cdsPciModules.rfmCount > 0 ) + { + if ( cycleNum >= HKP_RFM_CHK_CYCLE && + cycleNum < ( HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount ) ) + { + int mod = cycleNum - HKP_RFM_CHK_CYCLE; + status = vmic5565CheckOwnDataRcv( mod ); + if ( !status ) + ipcErrBits |= 4 + ( mod * 4 ); + } + if ( cycleNum >= + ( HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount ) && + cycleNum < + ( HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount * 2 ) ) + { + int mod = + cycleNum - HKP_RFM_CHK_CYCLE - cdsPciModules.rfmCount; + vmic5565ResetOwnDataLight( mod ); + } + if ( cycleNum >= + ( HKP_RFM_CHK_CYCLE + 2 * cdsPciModules.rfmCount ) && + cycleNum < + ( HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount * 3 ) ) + { + int mod = cycleNum - HKP_RFM_CHK_CYCLE - + cdsPciModules.rfmCount * 2; + // Write data out to the RFM to trigger the light + ( (volatile long*)( cdsPciModules.pci_rfm[ mod ] ) )[ 2 ] = + 0; + } + } -// ***************************************************************** -/// \> Cycle 400 to 400 + numDacModules, write DAC heartbeat to AI chassis (only for 18 bit DAC modules) -// DAC WD Write for 18 bit DAC modules -// Check once per second on code cycle 400 to dac count -// Only one write per code cycle to reduce time -// ***************************************************************** - if (cycleNum >= HKP_DAC_WD_CLK && cycleNum < (HKP_DAC_WD_CLK + cdsPciModules.dacCount)) - { - if (cycleNum == HKP_DAC_WD_CLK) dacWatchDog ^= 1; - jj = cycleNum - HKP_DAC_WD_CLK; - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - volatile GSA_18BIT_DAC_REG *dac18bitPtr; - dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]); - if(iopDacEnable && !dacChanErr[jj]) - dac18bitPtr->digital_io_ports = (dacWatchDog | GSAO_18BIT_DIO_RW); - } - if(cdsPciModules.dacType[jj] == GSC_20AO8) - { - volatile GSA_20BIT_DAC_REG *dac20bitPtr; - dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]); - if(iopDacEnable && !dacChanErr[jj]) - dac20bitPtr->digital_io_ports = (dacWatchDog | GSAO_20BIT_DIO_RW); - } - } + // ***************************************************************** + /// \> Cycle 400 to 400 + numDacModules, write DAC heartbeat to AI + /// chassis (only for 18 bit DAC modules) + // DAC WD Write for 18 bit DAC modules + // Check once per second on code cycle 400 to dac count + // Only one write per code cycle to reduce time + // ***************************************************************** + if ( cycleNum >= HKP_DAC_WD_CLK && + cycleNum < ( HKP_DAC_WD_CLK + cdsPciModules.dacCount ) ) + { + if ( cycleNum == HKP_DAC_WD_CLK ) + dacWatchDog ^= 1; + jj = cycleNum - HKP_DAC_WD_CLK; + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) + { + volatile GSA_18BIT_DAC_REG* dac18bitPtr; + dac18bitPtr = (volatile GSA_18BIT_DAC_REG*)( dacPtr[ jj ] ); + if ( iopDacEnable && !dacChanErr[ jj ] ) + dac18bitPtr->digital_io_ports = + ( dacWatchDog | GSAO_18BIT_DIO_RW ); + } + if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + volatile GSA_20BIT_DAC_REG* dac20bitPtr; + dac20bitPtr = (volatile GSA_20BIT_DAC_REG*)( dacPtr[ jj ] ); + if ( iopDacEnable && !dacChanErr[ jj ] ) + dac20bitPtr->digital_io_ports = + ( dacWatchDog | GSAO_20BIT_DIO_RW ); + } + } // ***************************************************************** -/// \> Cycle 500 to 500 + numDacModules, read back watchdog from AI chassis (18 bit DAC only) +/// \> Cycle 500 to 500 + numDacModules, read back watchdog from AI chassis (18 +/// bit DAC only) // AI Chassis WD CHECK for 18 bit DAC modules // Check once per second on code cycle HKP_DAC_WD_CHK to dac count // Only one read per code cycle to reduce time // ***************************************************************** #ifndef TIME_SLAVE - if (cycleNum >= HKP_DAC_WD_CHK && cycleNum < (HKP_DAC_WD_CHK + cdsPciModules.dacCount)) - { - jj = cycleNum - HKP_DAC_WD_CHK; - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - static int dacWDread = 0; - volatile GSA_18BIT_DAC_REG *dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]); - dacWDread = dac18bitPtr->digital_io_ports; - if(((dacWDread >> 8) & 1) > 0) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_WD_BIT); - } - else - pLocalEpics->epicsOutput.statDac[jj] |= DAC_WD_BIT; - } - if(cdsPciModules.dacType[jj] == GSC_20AO8) - { - static int dacWDread = 0; - volatile GSA_20BIT_DAC_REG *dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]); - dacWDread = dac20bitPtr->digital_io_ports; - if(((dacWDread >> 8) & 1) > 0) - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_WD_BIT); - else - pLocalEpics->epicsOutput.statDac[jj] |= DAC_WD_BIT; - } - } + if ( cycleNum >= HKP_DAC_WD_CHK && + cycleNum < ( HKP_DAC_WD_CHK + cdsPciModules.dacCount ) ) + { + jj = cycleNum - HKP_DAC_WD_CHK; + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) + { + static int dacWDread = 0; + volatile GSA_18BIT_DAC_REG* dac18bitPtr = + (volatile GSA_18BIT_DAC_REG*)( dacPtr[ jj ] ); + dacWDread = dac18bitPtr->digital_io_ports; + if ( ( ( dacWDread >> 8 ) & 1 ) > 0 ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= + ~( DAC_WD_BIT ); + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_WD_BIT; + } + if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + static int dacWDread = 0; + volatile GSA_20BIT_DAC_REG* dac20bitPtr = + (volatile GSA_20BIT_DAC_REG*)( dacPtr[ jj ] ); + dacWDread = dac20bitPtr->digital_io_ports; + if ( ( ( dacWDread >> 8 ) & 1 ) > 0 ) + pLocalEpics->epicsOutput.statDac[ jj ] &= + ~( DAC_WD_BIT ); + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_WD_BIT; + } + } #endif // ***************************************************************** -/// \> Cycle 600 to 600 + numDacModules, Check DAC FIFO Sizes to determine if DAC modules are synched to code -/// - ---- 18bit DAC reads out FIFO size dirrectly, but 16bit module only has a 4 bit register -/// area for FIFO empty, quarter full, etc. So, to make these bits useful in 16 bit module, -/// code must set a proper FIFO size in map.c code. +/// \> Cycle 600 to 600 + numDacModules, Check DAC FIFO Sizes to determine if +/// DAC modules are synched to code +/// - ---- 18bit DAC reads out FIFO size dirrectly, but 16bit module only has a +/// 4 bit register area for FIFO empty, quarter full, etc. So, to make these +/// bits useful in 16 bit module, code must set a proper FIFO size in map.c +/// code. // This code runs once per second. // ***************************************************************** // #ifndef NO_DAC_PRELOAD -#if !defined (NO_DAC_PRELOAD) && !defined (TIME_SLAVE) - if (cycleNum >= HKP_DAC_FIFO_CHK && cycleNum < (HKP_DAC_FIFO_CHK + cdsPciModules.dacCount)) - { - status = check_dac_buffers(cycleNum); - } - if (dacTimingError) feStatus |= FE_ERROR_DAC; +#if !defined( NO_DAC_PRELOAD ) && !defined( TIME_SLAVE ) + if ( cycleNum >= HKP_DAC_FIFO_CHK && + cycleNum < ( HKP_DAC_FIFO_CHK + cdsPciModules.dacCount ) ) + { + status = check_dac_buffers( cycleNum ); + } + if ( dacTimingError ) + feStatus |= FE_ERROR_DAC; #endif -// ***************************************************************** -// Update end of cycle information -// ***************************************************************** -if(usloop == 0) -{ - // Capture end of cycle time. - cpuClock[CPU_TIME_CYCLE_END] = rdtsc_ordered(); - - /// \> Compute code cycle time diag information. - captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo); - timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - adcinfo.adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcinfo.adcTime)/CPURATE; - adcinfo.adcTime = cpuClock[CPU_TIME_CYCLE_START]; - // Calc the max time of one cycle of the user code - // For IOP, more interested in time to get thru ADC read code and send to slave apps - timeinfo.usrTime = (cpuClock[CPU_TIME_USR_START] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - if(timeinfo.usrTime > timeinfo.usrHoldTime) timeinfo.usrHoldTime = timeinfo.usrTime; -} + // ***************************************************************** + // Update end of cycle information + // ***************************************************************** + if ( usloop == 0 ) + { + // Capture end of cycle time. + cpuClock[ CPU_TIME_CYCLE_END ] = rdtsc_ordered( ); + + /// \> Compute code cycle time diag information. + captureEocTiming( + cycleNum, cycle_gps_time, &timeinfo, &adcinfo ); + timeinfo.cycleTime = ( cpuClock[ CPU_TIME_CYCLE_END ] - + cpuClock[ CPU_TIME_CYCLE_START ] ) / + CPURATE; + adcinfo.adcHoldTime = + ( cpuClock[ CPU_TIME_CYCLE_START ] - adcinfo.adcTime ) / + CPURATE; + adcinfo.adcTime = cpuClock[ CPU_TIME_CYCLE_START ]; + // Calc the max time of one cycle of the user code + // For IOP, more interested in time to get thru ADC read code + // and send to slave apps + timeinfo.usrTime = ( cpuClock[ CPU_TIME_USR_START ] - + cpuClock[ CPU_TIME_CYCLE_START ] ) / + CPURATE; + if ( timeinfo.usrTime > timeinfo.usrHoldTime ) + timeinfo.usrHoldTime = timeinfo.usrTime; + } - /// \> Update internal cycle counters - cycleNum += 1; + /// \> Update internal cycle counters + cycleNum += 1; #ifdef DIAG_TEST - if(pLocalEpics->epicsInput.bumpCycle != 0) { - cycleNum += pLocalEpics->epicsInput.bumpCycle; - pLocalEpics->epicsInput.bumpCycle = 0; - } + if ( pLocalEpics->epicsInput.bumpCycle != 0 ) + { + cycleNum += pLocalEpics->epicsInput.bumpCycle; + pLocalEpics->epicsInput.bumpCycle = 0; + } #endif - cycleNum %= CYCLE_PER_SECOND; - clock1Min += 1; - clock1Min %= CYCLE_PER_MINUTE; - if(subcycle == DAQ_CYCLE_CHANGE) - { - daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle; - } - if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ - { - /* Reset the data cycle counter */ - subcycle = 0; - } else { - /* Increment the internal cycle counter */ - subcycle ++; - } - } - -/// \> If not exit request, then continue INFINITE LOOP ******* - } + cycleNum %= CYCLE_PER_SECOND; + clock1Min += 1; + clock1Min %= CYCLE_PER_MINUTE; + if ( subcycle == DAQ_CYCLE_CHANGE ) + { + daqCycle = ( daqCycle + 1 ) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; + if ( !( daqCycle % 2 ) ) + pLocalEpics->epicsOutput.epicsSync = daqCycle; + } + if ( subcycle == + END_OF_DAQ_BLOCK ) /*we have reached the 16Hz second barrier*/ + { + /* Reset the data cycle counter */ + subcycle = 0; + } + else + { + /* Increment the internal cycle counter */ + subcycle++; + } + } - pLocalEpics->epicsOutput.cpuMeter = 0; + /// \> If not exit request, then continue INFINITE LOOP ******* + } + pLocalEpics->epicsOutput.cpuMeter = 0; - /* System reset command received */ - return (void *)-1; + /* System reset command received */ + return (void*)-1; } diff --git a/src/fe/controllerIopUser.c b/src/fe/controllerIopUser.c index 2fd453b5e..cb0ec9688 100644 --- a/src/fe/controllerIopUser.c +++ b/src/fe/controllerIopUser.c @@ -14,20 +14,21 @@ /// @file controllerIopUser.c /// @brief Main scheduler program for compiled user space IOP object. \n /// @detail More information can be found in the following DCC document: -///< <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 CDS RT Sequencer Software</a> +///< <a +///<href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 +///<CDS RT Sequencer Software</a> /// @author R.Bork, A.Ivanov /// @copyright Copyright (C) 2014 LIGO Project \n ///< California Institute of Technology \n ///< Massachusetts Institute of Technology \n\n -/// @license This program is free software: you can redistribute it and/or modify +/// @license This program is free software: you can redistribute it and/or +/// modify ///< it under the terms of the GNU General Public License as published by -///< the Free Software Foundation, version 3 of the License. \n -///< This program is distributed in the hope that it will be useful, -///< but WITHOUT ANY WARRANTY; without even the implied warranty of -///< MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -///< GNU General Public License for more details. - - +///< the Free Software Foundation, version 3 of the License. \n This program +///< is distributed in the hope that it will be useful, but WITHOUT ANY +///< WARRANTY; without even the implied warranty of MERCHANTABILITY or +///< FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +///< for more details. /// Can't use printf in kernel module so redefine to use Linux printk function #include <linux/version.h> @@ -37,24 +38,23 @@ #include <drv/cdsHardware.h> #include "inlineMath.h" - -#include "cds_types.h" -#include "fm10Gen.h" // CDS filter module defs and C code -#include "feComms.h" // Lvea control RFM network defs. -#include "daqmap.h" // DAQ network layout +#include "cds_types.h" +#include "fm10Gen.h" // CDS filter module defs and C code +#include "feComms.h" // Lvea control RFM network defs. +#include "daqmap.h" // DAQ network layout #include "controller.h" #ifndef NO_DAQ #include "drv/fb.h" -#include "drv/daqLib.c" // DAQ/GDS connection software +#include "drv/daqLib.c" // DAQ/GDS connection software #endif -#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function +#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function #include "drv/mapuser.h" -#include "timing.c" // timing module / IRIG-B functions +#include "timing.c" // timing module / IRIG-B functions -#include "drv/inputFilterModule.h" -#include "drv/inputFilterModule1.h" +#include "drv/inputFilterModule.h" +#include "drv/inputFilterModule1.h" #ifdef DOLPHIN_TEST #include "dolphin.c" @@ -64,531 +64,639 @@ // Contec 64 input bits plus 64 output bits (Standard for aLIGO) /// Contec6464 input register values -unsigned int CDIO6464InputInput[MAX_DIO_MODULES]; // Binary input bits +unsigned int CDIO6464InputInput[ MAX_DIO_MODULES ]; // Binary input bits /// Contec6464 - Last output request sent to module. -unsigned int CDIO6464LastOutState[MAX_DIO_MODULES]; // Current requested value of the BO bits +unsigned int CDIO6464LastOutState[ MAX_DIO_MODULES ]; // Current requested value + // of the BO bits /// Contec6464 values to be written to the output register -unsigned int CDIO6464Output[MAX_DIO_MODULES]; // Binary output bits +unsigned int CDIO6464Output[ MAX_DIO_MODULES ]; // Binary output bits -// This Contect 16 input / 16 output DIO card is used to control timing slave by IOP +// This Contect 16 input / 16 output DIO card is used to control timing slave by +// IOP /// Contec1616 input register values -unsigned int CDIO1616InputInput[MAX_DIO_MODULES]; // Binary input bits +unsigned int CDIO1616InputInput[ MAX_DIO_MODULES ]; // Binary input bits /// Contec1616 output register values read back from the module -unsigned int CDIO1616Input[MAX_DIO_MODULES]; // Current value of the BO bits +unsigned int CDIO1616Input[ MAX_DIO_MODULES ]; // Current value of the BO bits /// Contec1616 values to be written to the output register -unsigned int CDIO1616Output[MAX_DIO_MODULES]; // Binary output bits +unsigned int CDIO1616Output[ MAX_DIO_MODULES ]; // Binary output bits /// Holds ID number of Contec1616 DIO card(s) used for timing control. -int tdsControl[3]; // Up to 3 timing control modules allowed in case I/O chassis are daisy chained +int tdsControl[ 3 ]; // Up to 3 timing control modules allowed in case I/O + // chassis are daisy chained /// Total number of timing control modules found on bus int tdsCount = 0; int startGpsTime; int cycleOffset = 0; -struct timespec myTimer[3]; ///< Used in code cycle timing -int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); +struct timespec myTimer[ 3 ]; ///< Used in code cycle timing +int getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec ); // Include C code modules #include "rcguserIop.c" -unsigned int getGpsTimeProc() { - FILE *timef; - char line[100]; - int status; - unsigned int mytime; - - timef = fopen("/sys/kernel/gpstime/time","r"); - if(!timef) { - printf("Cannot find GPS time \n"); - return(0); - } - fgets(line,100,timef); - mytime = atoi(line); - printf("GPS TIME is %d\n",mytime); - fclose(timef); - mytime -= 1; - return (mytime); +unsigned int +getGpsTimeProc( ) +{ + FILE* timef; + char line[ 100 ]; + int status; + unsigned int mytime; + + timef = fopen( "/sys/kernel/gpstime/time", "r" ); + if ( !timef ) + { + printf( "Cannot find GPS time \n" ); + return ( 0 ); + } + fgets( line, 100, timef ); + mytime = atoi( line ); + printf( "GPS TIME is %d\n", mytime ); + fclose( timef ); + mytime -= 1; + return ( mytime ); +} +void +initAdcModules( adcInfo_t* adcinfo ) +{ + int status; + int jj; + + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + // Set ADC Present Flag + pLocalEpics->epicsOutput.statAdc[ jj ] = 1; + adcinfo->adcRdTimeErr[ jj ] = 0; + } + printf( "ADC setup complete \n" ); +} +void +initDacModules( void ) +{ + int jj; + int status; + + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + pLocalEpics->epicsOutput.statDac[ jj ] = DAC_FOUND_BIT; + } + printf( "DAC setup complete \n" ); } - void initAdcModules(adcInfo_t *adcinfo) { - int status; - int jj; - - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - // Set ADC Present Flag - pLocalEpics->epicsOutput.statAdc[jj] = 1; - adcinfo->adcRdTimeErr[jj] = 0; - } - printf("ADC setup complete \n"); - } - void initDacModules(void) { - int jj; - int status; - - for(jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.statDac[jj] = DAC_FOUND_BIT; - } - printf("DAC setup complete \n"); - } //*********************************************************************** -// TASK: fe_start_iop_user() -// This routine is the skeleton for all front end code +// TASK: fe_start_iop_user() +// This routine is the skeleton for all front end code //*********************************************************************** -/// This function is the main real-time sequencer or scheduler for all code built -/// using the RCG. \n -/// There are two primary modes of operation, based on two compile options: \n -/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). +/// This function is the main real-time sequencer or scheduler for all code +/// built using the RCG. \n There are two primary modes of operation, based on +/// two compile options: \n +/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). /// - ADC_SLAVE: Normal user control process. -/// This code runs in a continuous loop at the rate specified in the RCG model. The -/// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn -/// is triggered to sample by the 64KHz clock provided by the Timing Distribution System. -/// - -int fe_start_iop_user() +/// This code runs in a continuous loop at the rate specified in the RCG model. +/// The loop is synchronized and triggered by the arrival of ADC data, the ADC +/// module in turn is triggered to sample by the 64KHz clock provided by the +/// Timing Distribution System. +/// - +int +fe_start_iop_user( ) { - int longestWrite2 = 0; - int tempClock[4]; - int ii,jj,kk,ll,mm; // Dummy loop counter variables - static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) - struct timespec tp; - static struct timespec cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables - static int chanHop = 0; /// @param chanHop Adc channel hopping status - int dacOF[MAX_DAC_MODULES]; - - int adcData[MAX_ADC_MODULES][MAX_ADC_CHN_PER_MOD]; /// @param adcData[][] ADC raw data - int adcChanErr[MAX_ADC_MODULES]; - // int adcWait = 0; - adcInfo_t adcInfo; - dacInfo_t dacInfo; - int adcOF[MAX_ADC_MODULES]; /// @param adcOF[] ADC overrange counters - - static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code - ///< Code runs longer for first few cycles on startup as it settles in, - ///< so this helps prevent long cycles during that time. - int limit = OVERFLOW_LIMIT_16BIT; /// @param limit ADC/DAC overflow test value - int mask = GSAI_DATA_MASK; /// @param mask Bit mask for ADC/DAC read/writes - int num_outs = MAX_DAC_CHN_PER_MOD; /// @param num_outs Number of DAC channels variable - volatile int *packedData; /// @param *packedData Pointer to ADC PCI data space - volatile unsigned int *pDacData; /// @param *pDacData Pointer to DAC PCI data space - int wtmin,wtmax; /// @param wtmin Time window for startup on IRIG-B - int dacEnable = 0; - int pBits[9] = {1,2,4,8,16,32,64,128,256}; /// @param pBits[] Lookup table for quick power of 2 calcs - int sync21ppsCycles = 0; /// @param sync32ppsCycles Number of attempts to sync to 1PPS - int dkiTrip = 0; - RFM_FE_COMMS *pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared memory space - // int timeHoldMax = 0; /// @param timeHoldMax Max code cycle time since last diag reset - int myGmError2 = 0; /// @param myGmError2 Myrinet error variable - int status; /// @param status Typical function return value - float onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics - int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check - int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check + int longestWrite2 = 0; + int tempClock[ 4 ]; + int ii, jj, kk, ll, mm; // Dummy loop counter variables + static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) + struct timespec tp; + static struct timespec + cpuClock[ CPU_TIMER_CNT ]; /// @param cpuClock[] Code timing diag + /// variables + static int chanHop = 0; /// @param chanHop Adc channel hopping status + int dacOF[ MAX_DAC_MODULES ]; + + int adcData[ MAX_ADC_MODULES ] + [ MAX_ADC_CHN_PER_MOD ]; /// @param adcData[][] ADC raw data + int adcChanErr[ MAX_ADC_MODULES ]; + // int adcWait = 0; + adcInfo_t adcInfo; + dacInfo_t dacInfo; + int adcOF[ MAX_ADC_MODULES ]; /// @param adcOF[] ADC overrange counters + + static int dacWriteEnable = + 0; /// @param dacWriteEnable No DAC outputs until >4 times through code + ///< Code runs longer for first few cycles on startup as it settles + ///< in, so this helps prevent long cycles during that time. + int limit = + OVERFLOW_LIMIT_16BIT; /// @param limit ADC/DAC overflow test value + int mask = GSAI_DATA_MASK; /// @param mask Bit mask for ADC/DAC read/writes + int num_outs = + MAX_DAC_CHN_PER_MOD; /// @param num_outs Number of DAC channels variable + volatile int* + packedData; /// @param *packedData Pointer to ADC PCI data space + volatile unsigned int* + pDacData; /// @param *pDacData Pointer to DAC PCI data space + int wtmin, wtmax; /// @param wtmin Time window for startup on IRIG-B + int dacEnable = 0; + int pBits[ 9 ] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256 + }; /// @param pBits[] Lookup table for quick power of 2 calcs + int sync21ppsCycles = + 0; /// @param sync32ppsCycles Number of attempts to sync to 1PPS + int dkiTrip = 0; + RFM_FE_COMMS* pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared + /// memory space + // int timeHoldMax = 0; /// @param timeHoldMax Max code cycle time since + // last diag reset + int myGmError2 = 0; /// @param myGmError2 Myrinet error variable + int status; /// @param status Typical function return value + float + onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics + int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check + int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check #ifdef DIAG_TEST - float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for diagnostics - int onePpsHiTest[10]; /// @param onePpsHiTest[] One PPS diagnostic check - int onePpsTimeTest[10]; /// @param onePpsTimeTest[] One PPS diagnostic check + float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for + /// diagnostics + int onePpsHiTest[ 10 ]; /// @param onePpsHiTest[] One PPS diagnostic check + int onePpsTimeTest[ 10 ]; /// @param onePpsTimeTest[] One PPS diagnostic + /// check #endif - int dcuId; /// @param dcuId DAQ ID number for this process - static int missedCycle = 0; /// @param missedCycle Incremented error counter when too many values in ADC FIFO - int diagWord = 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS - int system = 0; - int sampleCount = 1; /// @param sampleCount Number of ADC samples to take per code cycle - int sync21pps = 0; /// @param sync21pps Code startup sync to 1PPS flag - int syncSource = SYNC_SRC_NONE; /// @param syncSource Code startup synchronization source - int mxStat = 0; /// @param mxStat Net diags when myrinet express is used - int mxDiag = 0; - int mxDiagR = 0; -// ****** Share data - int ioClockDac = DAC_PRELOAD_CNT; - int ioMemCntr = 0; - int ioMemCntrDac = DAC_PRELOAD_CNT; - double dac_in = 0.0; /// @param dac_in DAC value after upsample filtering - int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO - - int feStatus = 0; - - int clk, clk1; // Used only when run on timer enabled (test mode) - - static float duotone[IOP_IO_RATE]; // Duotone timing diagnostic variables - static float duotoneDac[IOP_IO_RATE]; - float duotoneTimeDac; - float duotoneTime; - static float duotoneTotal = 0.0; - static float duotoneMean = 0.0; - static float duotoneTotalDac = 0.0; - static float duotoneMeanDac = 0.0; - static int dacDuoEnable = 0; - static int dacTimingError = 0; - static int dacTimingErrorPending[MAX_DAC_MODULES]; - - volatile GSA_18BIT_DAC_REG *dac18bitPtr; // Pointer to 16bit DAC memory area - volatile GSC_DAC_REG *dac16bitPtr; // Pointer to 18bit DAC memory area - unsigned int usec = 0; - unsigned int offset = 0; - - - int cnt = 0; - unsigned long cpc; - - static int cyclensec = 15259; - int pdiff = 0; - static int nextstep = 0; - -/// **********************************************************************************************\n -/// Start Initialization Process \n -/// **********************************************************************************************\n - memset (tempClock, 0, sizeof(tempClock)); - - /// \> Flush L1 cache - memset (fp, 0, 64*1024); - memset (fp, 1, 64*1024); - - fz_daz(); /// \> Kill the denorms! - - - /// \> Init comms with EPICS processor */ - pEpicsComms = (RFM_FE_COMMS *)_epics_shm; - pLocalEpics = (CDS_EPICS *)&pEpicsComms->epicsSpace; - pEpicsDaq = (char *)&(pLocalEpics->epicsOutput); -// printf("Epics at 0x%x and DAQ at 0x%x size = %d \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN)); - - /// \> Zero out DAC outputs - for (ii = 0; ii < MAX_DAC_MODULES; ii++) - { - dacTimingErrorPending[ii] = 0; - for (jj = 0; jj < 16; jj++) { - dacOut[ii][jj] = 0.0; - dacOutUsed[ii][jj] = 0; - dacInfo.dacOutBufSize[ii] = 0; - // Zero out DAC channel map in the shared memory - // to be used to check on slaves' channel allocation - ioMemData->dacOutUsed[ii][jj] = 0; + int dcuId; /// @param dcuId DAQ ID number for this process + static int missedCycle = 0; /// @param missedCycle Incremented error counter + /// when too many values in ADC FIFO + int diagWord = + 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS + int system = 0; + int sampleCount = + 1; /// @param sampleCount Number of ADC samples to take per code cycle + int sync21pps = 0; /// @param sync21pps Code startup sync to 1PPS flag + int syncSource = + SYNC_SRC_NONE; /// @param syncSource Code startup synchronization source + int mxStat = 0; /// @param mxStat Net diags when myrinet express is used + int mxDiag = 0; + int mxDiagR = 0; + // ****** Share data + int ioClockDac = DAC_PRELOAD_CNT; + int ioMemCntr = 0; + int ioMemCntrDac = DAC_PRELOAD_CNT; + double dac_in = 0.0; /// @param dac_in DAC value after upsample filtering + int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO + + int feStatus = 0; + + int clk, clk1; // Used only when run on timer enabled (test mode) + + static float duotone[ IOP_IO_RATE ]; // Duotone timing diagnostic variables + static float duotoneDac[ IOP_IO_RATE ]; + float duotoneTimeDac; + float duotoneTime; + static float duotoneTotal = 0.0; + static float duotoneMean = 0.0; + static float duotoneTotalDac = 0.0; + static float duotoneMeanDac = 0.0; + static int dacDuoEnable = 0; + static int dacTimingError = 0; + static int dacTimingErrorPending[ MAX_DAC_MODULES ]; + + volatile GSA_18BIT_DAC_REG* dac18bitPtr; // Pointer to 16bit DAC memory area + volatile GSC_DAC_REG* dac16bitPtr; // Pointer to 18bit DAC memory area + unsigned int usec = 0; + unsigned int offset = 0; + + int cnt = 0; + unsigned long cpc; + + static int cyclensec = 15259; + int pdiff = 0; + static int nextstep = 0; + + /// **********************************************************************************************\n + /// Start Initialization Process \n + /// **********************************************************************************************\n + memset( tempClock, 0, sizeof( tempClock ) ); + + /// \> Flush L1 cache + memset( fp, 0, 64 * 1024 ); + memset( fp, 1, 64 * 1024 ); + + fz_daz( ); /// \> Kill the denorms! + + /// \> Init comms with EPICS processor */ + pEpicsComms = (RFM_FE_COMMS*)_epics_shm; + pLocalEpics = (CDS_EPICS*)&pEpicsComms->epicsSpace; + pEpicsDaq = (char*)&( pLocalEpics->epicsOutput ); + // printf("Epics at 0x%x and DAQ at 0x%x size = %d + // \n",pLocalEpics,pEpicsDaq,sizeof(CDS_EPICS_IN)); + + /// \> Zero out DAC outputs + for ( ii = 0; ii < MAX_DAC_MODULES; ii++ ) + { + dacTimingErrorPending[ ii ] = 0; + for ( jj = 0; jj < 16; jj++ ) + { + dacOut[ ii ][ jj ] = 0.0; + dacOutUsed[ ii ][ jj ] = 0; + dacInfo.dacOutBufSize[ ii ] = 0; + // Zero out DAC channel map in the shared memory + // to be used to check on slaves' channel allocation + ioMemData->dacOutUsed[ ii ][ jj ] = 0; + } } - } - - /// \> Set pointers to filter module data buffers. \n - /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n - /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n - /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n - /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n - pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace); - dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - /// \> Clear the FE reset which comes from Epics - pLocalEpics->epicsInput.vmeReset = 0; - - // Clear input masks - pLocalEpics->epicsInput.burtRestore_mask = 0; - pLocalEpics->epicsInput.dacDuoSet_mask = 0; - -/// \> Init code synchronization source. - // Look for DIO card or IRIG-B Card - // if Contec 1616 BIO present, TDS slave will be used for timing. - syncSource = SYNC_SRC_TIMER; + /// \> Set pointers to filter module data buffers. \n + /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD + /// data.\n + /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done + /// to: \n + /// - -------- Allow daqLib.c to retrieve filter module data directly from + /// shared memory. \n + /// - -------- Avoid copy of filter module data between to memory locations, + /// which was slow. \n + pDsp[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + pCoeff[ system ] = (VME_COEF*)( &pEpicsComms->coeffSpace ); + dspPtr[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + + /// \> Clear the FE reset which comes from Epics + pLocalEpics->epicsInput.vmeReset = 0; + + // Clear input masks + pLocalEpics->epicsInput.burtRestore_mask = 0; + pLocalEpics->epicsInput.dacDuoSet_mask = 0; + + /// \> Init code synchronization source. + // Look for DIO card or IRIG-B Card + // if Contec 1616 BIO present, TDS slave will be used for timing. + syncSource = SYNC_SRC_TIMER; + + printf( "Sync source = %d\n", syncSource ); + + /// \> Wait for BURT restore.\n + /// - ---- Code will exit if BURT flag not set by EPICS sequencer. + // Do not proceed until EPICS has had a BURT restore + // ******************************* + printf( "Waiting for EPICS BURT Restore = %d\n", + pLocalEpics->epicsInput.burtRestore ); + cnt = 0; + do + { + usleep( 80000 ); + printf( "Waiting for EPICS BURT %d\n", cnt++ ); + } while ( !pLocalEpics->epicsInput.burtRestore ); -printf("Sync source = %d\n",syncSource); + printf( "BURT Restore Complete\n" ); + // BURT has completed + // ******************************************************************* -/// \> Wait for BURT restore.\n -/// - ---- Code will exit if BURT flag not set by EPICS sequencer. - // Do not proceed until EPICS has had a BURT restore ******************************* - printf("Waiting for EPICS BURT Restore = %d\n", pLocalEpics->epicsInput.burtRestore); - cnt = 0; - do{ - usleep(80000); - printf("Waiting for EPICS BURT %d\n", cnt++); - }while(!pLocalEpics->epicsInput.burtRestore); + /// < Read in all Filter Module EPICS coeff settings + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + checkFiltReset( ii, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); + } - printf("BURT Restore Complete\n"); + // Need this FE dcuId to make connection to FB + dcuId = pLocalEpics->epicsInput.dcuId; + pLocalEpics->epicsOutput.dcuId = dcuId; -// BURT has completed ******************************************************************* + // Reset timing diagnostics + pLocalEpics->epicsOutput.diagWord = 0; + pLocalEpics->epicsOutput.timeDiag = 0; + pLocalEpics->epicsOutput.timeErr = syncSource; -/// < Read in all Filter Module EPICS coeff settings - for(ii=0;ii<MAX_MODULES;ii++) + /// \> Init IIR filter banks + // Initialize filter banks ********************************************* + for ( system = 0; system < NUM_SYSTEMS; system++ ) { - checkFiltReset(ii, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - } - - // Need this FE dcuId to make connection to FB - dcuId = pLocalEpics->epicsInput.dcuId; - pLocalEpics->epicsOutput.dcuId = dcuId; - - // Reset timing diagnostics - pLocalEpics->epicsOutput.diagWord = 0; - pLocalEpics->epicsOutput.timeDiag = 0; - pLocalEpics->epicsOutput.timeErr = syncSource; - -/// \> Init IIR filter banks -// Initialize filter banks ********************************************* - for (system = 0; system < NUM_SYSTEMS; system++) { - for(ii=0;ii<MAX_MODULES;ii++){ - for(jj=0;jj<FILTERS;jj++){ - for(kk=0;kk<MAX_COEFFS;kk++){ - dspCoeff[system].coeffs[ii].filtCoeff[jj][kk] = 0.0; + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + for ( jj = 0; jj < FILTERS; jj++ ) + { + for ( kk = 0; kk < MAX_COEFFS; kk++ ) + { + dspCoeff[ system ].coeffs[ ii ].filtCoeff[ jj ][ kk ] = 0.0; + } + dspCoeff[ system ].coeffs[ ii ].filtSections[ jj ] = 0; + } } - dspCoeff[system].coeffs[ii].filtSections[jj] = 0; - } } - } - /// \> Initialize all filter module excitation signals to zero - for (system = 0; system < NUM_SYSTEMS; system++) - for(ii=0;ii<MAX_MODULES;ii++) - // dsp[system].data[ii].exciteInput = 0.0; - pDsp[0]->data[ii].exciteInput = 0.0; + /// \> Initialize all filter module excitation signals to zero + for ( system = 0; system < NUM_SYSTEMS; system++ ) + for ( ii = 0; ii < MAX_MODULES; ii++ ) + // dsp[system].data[ii].exciteInput = 0.0; + pDsp[ 0 ]->data[ ii ].exciteInput = 0.0; - - /// \> Initialize IIR filter bank values - if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) { - printf("Filter module init failed, exiting\n"); - return 0; + /// \> Initialize IIR filter bank values + if ( initVars( pDsp[ 0 ], pDsp[ 0 ], dspCoeff, MAX_MODULES, pCoeff[ 0 ] ) ) + { + printf( "Filter module init failed, exiting\n" ); + return 0; } - printf("Initialized servo control parameters.\n"); + printf( "Initialized servo control parameters.\n" ); -usleep(1000); + usleep( 1000 ); -/// \> Initialize DAQ variable/software -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Set data range limits for daqLib routine -#if defined(SERVO2K) || defined(SERVO4K) - daq.filtExMin = GDS_2K_EXC_MIN; - daq.filtTpMin = GDS_2K_TP_MIN; +/// \> Initialize DAQ variable/software +#if !defined( NO_DAQ ) && !defined( IOP_TASK ) + /// - ---- Set data range limits for daqLib routine +#if defined( SERVO2K ) || defined( SERVO4K ) + daq.filtExMin = GDS_2K_EXC_MIN; + daq.filtTpMin = GDS_2K_TP_MIN; #else - daq.filtExMin = GDS_16K_EXC_MIN; - daq.filtTpMin = GDS_16K_TP_MIN; + daq.filtExMin = GDS_16K_EXC_MIN; + daq.filtTpMin = GDS_16K_TP_MIN; #endif - daq.filtExMax = daq.filtExMin + MAX_MODULES; - daq.filtExSize = MAX_MODULES; - daq.xExMin = daq.filtExMax; - daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; - daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; - daq.filtTpSize = MAX_MODULES * 3; - daq.xTpMin = daq.filtTpMax; - daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; - - printf("DAQ Ex Min/Max = %d %d\n",daq.filtExMin,daq.filtExMax); - printf("DAQ XEx Min/Max = %d %d\n",daq.xExMin,daq.xExMax); - printf("DAQ Tp Min/Max = %d %d\n",daq.filtTpMin,daq.filtTpMax); - printf("DAQ XTp Min/Max = %d %d\n",daq.xTpMin,daq.xTpMax); - - /// - ---- Assign DAC testpoint pointers - for (ii = 0; ii < cdsPciModules.dacCount; ii++) - for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) // 16 per DAC regardless of the actual - testpoint[MAX_DAC_CHN_PER_MOD * ii + jj] = floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; - - // Zero out storage - memset(floatDacOut, 0, sizeof(floatDacOut)); + daq.filtExMax = daq.filtExMin + MAX_MODULES; + daq.filtExSize = MAX_MODULES; + daq.xExMin = daq.filtExMax; + daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; + daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; + daq.filtTpSize = MAX_MODULES * 3; + daq.xTpMin = daq.filtTpMax; + daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; + + printf( "DAQ Ex Min/Max = %d %d\n", daq.filtExMin, daq.filtExMax ); + printf( "DAQ XEx Min/Max = %d %d\n", daq.xExMin, daq.xExMax ); + printf( "DAQ Tp Min/Max = %d %d\n", daq.filtTpMin, daq.filtTpMax ); + printf( "DAQ XTp Min/Max = %d %d\n", daq.xTpMin, daq.xTpMax ); + + /// - ---- Assign DAC testpoint pointers + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + for ( jj = 0; jj < MAX_DAC_CHN_PER_MOD; + jj++ ) // 16 per DAC regardless of the actual + testpoint[ MAX_DAC_CHN_PER_MOD * ii + jj ] = + floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; + + // Zero out storage + memset( floatDacOut, 0, sizeof( floatDacOut ) ); #endif - pLocalEpics->epicsOutput.ipcStat = 0; - pLocalEpics->epicsOutput.fbNetStat = 0; - pLocalEpics->epicsOutput.tpCnt = 0; - -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Initialize DAQ function - status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - if(status == -1) - { - printf("DAQ init failed -- exiting\n"); - vmeDone = 1; - return(0); - } + pLocalEpics->epicsOutput.ipcStat = 0; + pLocalEpics->epicsOutput.fbNetStat = 0; + pLocalEpics->epicsOutput.tpCnt = 0; + +#if !defined( NO_DAQ ) && !defined( IOP_TASK ) + /// - ---- Initialize DAQ function + status = daqWrite( 0, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + 0, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + if ( status == -1 ) + { + printf( "DAQ init failed -- exiting\n" ); + vmeDone = 1; + return ( 0 ); + } #endif + // Clear the code exit flag + vmeDone = 0; + + /// \> Call user application software initialization routine. + printf( "Calling feCode() to initialize\n" ); + iopDacEnable = feCode( cycleNum, + dWord, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 1 ); + + /// \> Verify DAC channels defined for this app are not already in use. \n + /// - ---- User apps are allowed to share DAC modules but not DAC channels. + + // Clear timing diags. + initializeTimingDiags( &timeinfo ); + missedCycle = 0; + + /// \> If IOP, Initialize the ADC modules + initAdcModules( &adcInfo ); + + /// \> If IOP, Initialize the DAC module variables + initDacModules( ); + + pLocalEpics->epicsOutput.fe_status = INIT_SYNC; + printf( "*******************************\n" ); + printf( "* Running on timer! *\n" ); + printf( "*******************************\n" ); + int timeoff = ( BILLION - ( 60000000 * cycleOffset ) ) % BILLION; + /// Sync up to the 1Hz boundary + do + { + usleep( 1 ); + clock_gettime( CLOCK_REALTIME, &myTimer[ 0 ] ); + timeinfo.cycleTime = myTimer[ 0 ].tv_nsec; + } while ( timeinfo.cycleTime > timeoff && + timeinfo.cycleTime < ( timeoff - 10000 ) ); + printf( "cycle time = %d\n", timeinfo.cycleTime ); + timeSec = getGpsTimeProc( ); + startGpsTime = timeSec; + pLocalEpics->epicsOutput.startgpstime = startGpsTime; + printf( + "Triggered the ADC at %d and %d usec\n", timeSec, timeinfo.cycleTime ); + onePpsTime = cycleNum; + + nextstep = timeoff + 20000; + + /// ******************************************************************************\n + /// Enter the infinite FE control loop + /// ******************************************\n + + /// ******************************************************************************\n + + pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; + + while ( !vmeDone ) + { // Run forever until user hits reset + // This is local CPU timer (no ADCs) + // advance to the next cycle polling CPU cycles and microsleeping + do + { + clock_gettime( CLOCK_MONOTONIC, &myTimer[ 1 ] ); + clk = myTimer[ 1 ].tv_nsec; + } while ( clk < nextstep ); + adcinfo.adcHoldTime = + ( myTimer[ 1 ].tv_nsec - myTimer[ 0 ].tv_nsec ) / 1000; + if ( adcinfo.adcHoldTime < 0 ) + adcinfo.adcHoldTime += 1000000; + myTimer[ 0 ].tv_sec = myTimer[ 1 ].tv_sec; + myTimer[ 0 ].tv_nsec = myTimer[ 1 ].tv_nsec; + + ioMemCntr = ( cycleNum % IO_MEMORY_SLOTS ); + // Write GPS time and cycle count as indicator to slave that adc data is + // ready + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + for ( ii = 0; ii < IO_MEMORY_SLOT_VALS; ii++ ) + { + ioMemData->iodata[ jj ][ ioMemCntr ].data[ ii ] = + ioMemDataIop->iodata[ jj ][ cycleNum ].data[ ii ]; + dWord[ jj ][ ii ] = + ioMemData->iodata[ jj ][ ioMemCntr ].data[ ii ]; + ioMemDataIop->iodata[ jj ][ cycleNum ].data[ ii ] = 0; + } + ioMemData->iodata[ jj ][ ioMemCntr ].timeSec = timeSec; + ; + ioMemData->iodata[ jj ][ ioMemCntr ].cycle = cycleNum; + ioMemDataIop->gpsSecond = timeSec; + ioMemDataIop->cycleNum = cycleNum; + } + ioMemData->gpsSecond = timeSec; + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_CYCLE_START ] ); + + if ( cycleNum == 0 ) + { + pLocalEpics->epicsOutput.awgStat = + ( pEpicsComms->padSpace.awgtpman_gps != timeSec ); + if ( pLocalEpics->epicsOutput.awgStat ) + feStatus |= FE_ERROR_AWG; + // Increment GPS second on cycle 0 + timeSec++; + pLocalEpics->epicsOutput.timeDiag = timeSec; + int pll = + myTimer[ 0 ].tv_nsec / 1000 + ( 1000000 - ( timeoff / 1000 ) ); + pll %= 1000000; + if ( pll > 500000 ) + pdiff = ( 1000000 - pll ) * -1; + else + pdiff = pll; + pLocalEpics->epicsOutput.irigbTime = pdiff + 10; + // pLocalEpics->epicsOutput.irigbTime = (pdiff + (timeoff / 1000) + + // 11) ; + cycle_gps_time = timeSec; + } - // Clear the code exit flag - vmeDone = 0; - - /// \> Call user application software initialization routine. - printf("Calling feCode() to initialize\n"); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); - - -/// \> Verify DAC channels defined for this app are not already in use. \n -/// - ---- User apps are allowed to share DAC modules but not DAC channels. - - // Clear timing diags. - initializeTimingDiags(&timeinfo); - missedCycle = 0; - - /// \> If IOP, Initialize the ADC modules - initAdcModules(&adcInfo); - - /// \> If IOP, Initialize the DAC module variables - initDacModules(); - - pLocalEpics->epicsOutput.fe_status = INIT_SYNC; - printf("*******************************\n"); - printf("* Running on timer! *\n"); - printf("*******************************\n"); - int timeoff = (BILLION-(60000000 * cycleOffset)) % BILLION; - /// Sync up to the 1Hz boundary - do { - usleep(1); - clock_gettime(CLOCK_REALTIME, &myTimer[0]); - timeinfo.cycleTime = myTimer[0].tv_nsec; - } while(timeinfo.cycleTime > timeoff && timeinfo.cycleTime < (timeoff - 10000)); -printf("cycle time = %d\n",timeinfo.cycleTime); - timeSec = getGpsTimeProc() ; - startGpsTime = timeSec; - pLocalEpics->epicsOutput.startgpstime = startGpsTime; - printf("Triggered the ADC at %d and %d usec\n",timeSec,timeinfo.cycleTime); - onePpsTime = cycleNum; - - nextstep = timeoff + 20000; - - - /// ******************************************************************************\n - /// Enter the infinite FE control loop ******************************************\n - - /// ******************************************************************************\n - - pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; - - while(!vmeDone){ // Run forever until user hits reset - // This is local CPU timer (no ADCs) - // advance to the next cycle polling CPU cycles and microsleeping - do { - clock_gettime(CLOCK_MONOTONIC, &myTimer[1]); - clk = myTimer[1].tv_nsec; - } while(clk < nextstep); - adcinfo.adcHoldTime = (myTimer[1].tv_nsec - myTimer[0].tv_nsec) / 1000; - if(adcinfo.adcHoldTime < 0) adcinfo.adcHoldTime += 1000000; - myTimer[0].tv_sec = myTimer[1].tv_sec; - myTimer[0].tv_nsec = myTimer[1].tv_nsec; - - ioMemCntr = (cycleNum % IO_MEMORY_SLOTS); - // Write GPS time and cycle count as indicator to slave that adc data is ready - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - for(ii=0;ii<IO_MEMORY_SLOT_VALS;ii++) - { - ioMemData->iodata[jj][ioMemCntr].data[ii] = ioMemDataIop->iodata[jj][cycleNum].data[ii]; - dWord[jj][ii] = ioMemData->iodata[jj][ioMemCntr].data[ii]; - ioMemDataIop->iodata[jj][cycleNum].data[ii] = 0; - } - ioMemData->iodata[jj][ioMemCntr].timeSec = timeSec;; - ioMemData->iodata[jj][ioMemCntr].cycle = cycleNum; - ioMemDataIop->gpsSecond = timeSec; - ioMemDataIop->cycleNum = cycleNum; - } - ioMemData->gpsSecond = timeSec; - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_START]); - - if(cycleNum == 0) { - pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); - if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG; - // Increment GPS second on cycle 0 - timeSec ++; - pLocalEpics->epicsOutput.timeDiag = timeSec; - int pll = myTimer[0].tv_nsec / 1000 + (1000000 - (timeoff / 1000)); - pll %= 1000000; - if(pll > 500000) pdiff = (1000000 - pll) * -1 ; - else pdiff = pll; - pLocalEpics->epicsOutput.irigbTime = pdiff + 10; - // pLocalEpics->epicsOutput.irigbTime = (pdiff + (timeoff / 1000) + 11) ; - cycle_gps_time = timeSec; - } - - - -/// \> Call the front end specific application ******************\n -/// - -- This is where the user application produced by RCG gets called and executed. \n\n - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_START]); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,0); - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_USR_END]); - odcStateWord = 0; + /// \> Call the front end specific application ******************\n + /// - -- This is where the user application produced by RCG gets called + /// and executed. \n\n + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_USR_START ] ); + iopDacEnable = feCode( cycleNum, + dWord, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 0 ); + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_USR_END ] ); + odcStateWord = 0; /// WRITE DAC OUTPUTS ***************************************** \n /// Writing of DAC outputs is dependent on code compile option: \n -/// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user apps and writes to DAC hardware. \n +/// - -- IOP (ADC_MASTER) reads DAC output values from memory shared with user +/// apps and writes to DAC hardware. \n /// - -- USER APP (ADC_SLAVE) sends output values to memory shared with IOP. \n /// START OF IOP DAC WRITE ***************************************** \n - /// \> If DAC FIFO error, always output zero to DAC modules. \n - /// - -- Code will require restart to clear. - // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. +/// \> If DAC FIFO error, always output zero to DAC modules. \n +/// - -- Code will require restart to clear. +// COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. #ifndef DAC_WD_OVERRIDE - if(dacTimingError) iopDacEnable = 0; + if ( dacTimingError ) + iopDacEnable = 0; #endif - // Write out data to DAC modules - dkiTrip = 0; - /// \> Loop thru all DAC modules - for(jj=0;jj<cdsPciModules.dacCount;jj++) + // Write out data to DAC modules + dkiTrip = 0; + /// \> Loop thru all DAC modules + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) { - /// - -- Point to DAC memory buffer - // pDacData = (unsigned int *)(cdsPciModules.pci_dac[jj]); - /// - -- locate the proper DAC memory block - mm = cdsPciModules.dacConfig[jj]; - /// - -- Determine if memory block has been set with the correct cycle count by Slave app. - if(ioMemData->iodata[mm][ioMemCntrDac].cycle == ioClockDac) - { - dacEnable |= pBits[jj]; - }else { - dacEnable &= ~(pBits[jj]); - dacChanErr[jj] += 1; - } - /// - -- Set overflow limits, data mask, and chan count based on DAC type - limit = OVERFLOW_LIMIT_16BIT; - mask = GSAO_16BIT_MASK; - num_outs = GSAO_16BIT_CHAN_COUNT; - if (cdsPciModules.dacType[jj] == GSC_18AO8) { - limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit - mask = GSAO_18BIT_MASK; - num_outs = GSAO_18BIT_CHAN_COUNT; - } - /// - -- For each DAC channel - for (ii=0; ii < num_outs; ii++) - { -#ifdef FLIP_SIGNALS - dacOut[jj][ii] *= -1; -#endif - /// - ---- Read DAC output value from shared memory and reset memory to zero - if((!dacChanErr[jj]) && (iopDacEnable)) { - dac_out = ioMemData->iodata[mm][ioMemCntrDac].data[ii]; - /// - --------- Zero out data in case user app dies by next cycle - /// when two or more apps share same DAC module. - ioMemData->iodata[mm][ioMemCntrDac].data[ii] = 0; - } else { - dac_out = 0; - dkiTrip = 1; - } - /// - ---- Write out ADC duotone signal to first DAC, last channel, - /// if DAC duotone is enabled. - if((dacDuoEnable) && (ii==(num_outs-1)) && (jj == 0)) + /// - -- Point to DAC memory buffer + // pDacData = (unsigned int *)(cdsPciModules.pci_dac[jj]); + /// - -- locate the proper DAC memory block + mm = cdsPciModules.dacConfig[ jj ]; + /// - -- Determine if memory block has been set with the correct + /// cycle count by Slave app. + if ( ioMemData->iodata[ mm ][ ioMemCntrDac ].cycle == ioClockDac ) + { + dacEnable |= pBits[ jj ]; + } + else + { + dacEnable &= ~( pBits[ jj ] ); + dacChanErr[ jj ] += 1; + } + /// - -- Set overflow limits, data mask, and chan count based on DAC + /// type + limit = OVERFLOW_LIMIT_16BIT; + mask = GSAO_16BIT_MASK; + num_outs = GSAO_16BIT_CHAN_COUNT; + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) { - dac_out = adcData[0][ADC_DUOTONE_CHAN]; + limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit + mask = GSAO_18BIT_MASK; + num_outs = GSAO_18BIT_CHAN_COUNT; } - /// - ---- Check output values are within range of DAC \n - /// - --------- If overflow, clip at DAC limits and report errors - if(dac_out > limit || dac_out < -limit) + /// - -- For each DAC channel + for ( ii = 0; ii < num_outs; ii++ ) { - dacInfo.overflowDac[jj][ii] ++; - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++; - overflowAcc ++; - dacOF[jj] = 1; - odcStateWord |= ODC_DAC_OVF;; - if(dac_out > limit) dac_out = limit; - else dac_out = -limit; - } - /// - ---- If DAQKILL tripped, set output to zero. - if(!iopDacEnable) dac_out = 0; - /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen. - dacInfo.dacOutEpics[jj][ii] = dac_out; - - /// - ---- Load DAC testpoints - floatDacOut[16*jj + ii] = dac_out; - - /// - ---- Write to DAC local memory area, for later xmit to DAC module - // *pDacData = (unsigned int)(dac_out & mask); - // pDacData ++; - } - /// - -- Mark cycle count as having been used -1 \n - /// - --------- Forces slaves to mark this cycle or will not be used again by Master - ioMemData->iodata[mm][ioMemCntrDac].cycle = -1; - /// - -- DMA Write data to DAC module - #if 0 +#ifdef FLIP_SIGNALS + dacOut[ jj ][ ii ] *= -1; +#endif + /// - ---- Read DAC output value from shared memory and reset + /// memory to zero + if ( ( !dacChanErr[ jj ] ) && ( iopDacEnable ) ) + { + dac_out = + ioMemData->iodata[ mm ][ ioMemCntrDac ].data[ ii ]; + /// - --------- Zero out data in case user app dies by next + /// cycle when two or more apps share same DAC module. + ioMemData->iodata[ mm ][ ioMemCntrDac ].data[ ii ] = 0; + } + else + { + dac_out = 0; + dkiTrip = 1; + } + /// - ---- Write out ADC duotone signal to first DAC, last + /// channel, if DAC duotone is enabled. + if ( ( dacDuoEnable ) && ( ii == ( num_outs - 1 ) ) && + ( jj == 0 ) ) + { + dac_out = adcData[ 0 ][ ADC_DUOTONE_CHAN ]; + } + /// - ---- Check output values are within range of DAC \n + /// - --------- If overflow, clip at DAC limits and report + /// errors + if ( dac_out > limit || dac_out < -limit ) + { + dacInfo.overflowDac[ jj ][ ii ]++; + pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ]++; + overflowAcc++; + dacOF[ jj ] = 1; + odcStateWord |= ODC_DAC_OVF; + ; + if ( dac_out > limit ) + dac_out = limit; + else + dac_out = -limit; + } + /// - ---- If DAQKILL tripped, set output to zero. + if ( !iopDacEnable ) + dac_out = 0; + /// - ---- Load last values to EPICS channels for monitoring on + /// GDS_TP screen. + dacInfo.dacOutEpics[ jj ][ ii ] = dac_out; + + /// - ---- Load DAC testpoints + floatDacOut[ 16 * jj + ii ] = dac_out; + + /// - ---- Write to DAC local memory area, for later xmit to DAC + /// module + // *pDacData = (unsigned int)(dac_out & mask); + // pDacData ++; + } + /// - -- Mark cycle count as having been used -1 \n + /// - --------- Forces slaves to mark this cycle or will not be used + /// again by Master + ioMemData->iodata[ mm ][ ioMemCntrDac ].cycle = -1; + /// - -- DMA Write data to DAC module +#if 0 if(dacWriteEnable > 4) { if(cdsPciModules.dacType[jj] == GSC_16AO16) { gsc16ao16DmaStart(jj); @@ -596,283 +704,342 @@ printf("cycle time = %d\n",timeinfo.cycleTime); gsc18ao8DmaStart(jj); } } - #endif - } - /// \> Increment DAC memory block pointers for next cycle - ioClockDac = (ioClockDac + 1) % IOP_IO_RATE; - ioMemCntrDac = (ioMemCntrDac + 1) % IO_MEMORY_SLOTS; - if(dacWriteEnable < 10) dacWriteEnable ++; -/// END OF IOP DAC WRITE ************************************************* - - -/// BEGIN HOUSEKEEPING ************************************************ \n +#endif + } + /// \> Increment DAC memory block pointers for next cycle + ioClockDac = ( ioClockDac + 1 ) % IOP_IO_RATE; + ioMemCntrDac = ( ioMemCntrDac + 1 ) % IO_MEMORY_SLOTS; + if ( dacWriteEnable < 10 ) + dacWriteEnable++; + /// END OF IOP DAC WRITE + /// ************************************************* - pLocalEpics->epicsOutput.cycle = cycleNum; + /// BEGIN HOUSEKEEPING ************************************************ + /// \n -/// \> Cycle 18, Send timing info to EPICS at 1Hz - if(cycleNum ==HKP_TIMING_UPDATES) - { - sendTimingDiags2Epics(pLocalEpics, &timeinfo, &adcinfo); - - if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) - { - diagWord |= FE_ADC_HOLD_ERR; - feStatus |= FE_ERROR_TIMING; - - } - if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) - { - diagWord |= FE_PROC_TIME_ERR; - feStatus |= FE_ERROR_TIMING; - } - pLocalEpics->epicsOutput.stateWord = feStatus; - feStatus = 0; - if(pLocalEpics->epicsInput.diagReset || initialDiagReset) - { - initialDiagReset = 0; - pLocalEpics->epicsInput.diagReset = 0; - pLocalEpics->epicsInput.ipcDiagReset = 1; - // pLocalEpics->epicsOutput.diags[1] = 0; - timeinfo.timeHoldMax = 0; - diagWord = 0; - ipcErrBits = 0; - - // feStatus = 0; - for(jj=0;jj<cdsPciModules.adcCount;jj++) adcInfo.adcRdTimeMax[jj] = 0; - } - // Flip the onePPS various once/sec as a watchdog monitor. - // pLocalEpics->epicsOutput.onePps ^= 1; - pLocalEpics->epicsOutput.diagWord = diagWord; - for(jj=0;jj<cdsPciModules.adcCount;jj++) { - if(adcInfo.adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC) - pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC; - adcInfo.adcRdTimeErr[jj] = 0; - } - } + pLocalEpics->epicsOutput.cycle = cycleNum; + /// \> Cycle 18, Send timing info to EPICS at 1Hz + if ( cycleNum == HKP_TIMING_UPDATES ) + { + sendTimingDiags2Epics( pLocalEpics, &timeinfo, &adcinfo ); -/// \> Check for requests for filter module clear history requests. This is spread out over a number of cycles. - // Spread out filter coeff update, but keep updates at 16 Hz - // here we are rounding up: - // x/y rounded up equals (x + y - 1) / y - // - { - static const unsigned int mpc = (MAX_MODULES + (FE_RATE / 16) - 1) / (FE_RATE / 16); // Modules per cycle - unsigned int smpc = mpc * subcycle; // Start module counter - unsigned int empc = smpc + mpc; // End module counter - unsigned int i; - for (i = smpc; i < MAX_MODULES && i < empc ; i++) - checkFiltReset(i, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - } + if ( ( adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI ) || + ( adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO ) ) + { + diagWord |= FE_ADC_HOLD_ERR; + feStatus |= FE_ERROR_TIMING; + } + if ( timeinfo.timeHoldMax > CYCLE_TIME_ALRM ) + { + diagWord |= FE_PROC_TIME_ERR; + feStatus |= FE_ERROR_TIMING; + } + pLocalEpics->epicsOutput.stateWord = feStatus; + feStatus = 0; + if ( pLocalEpics->epicsInput.diagReset || initialDiagReset ) + { + initialDiagReset = 0; + pLocalEpics->epicsInput.diagReset = 0; + pLocalEpics->epicsInput.ipcDiagReset = 1; + // pLocalEpics->epicsOutput.diags[1] = 0; + timeinfo.timeHoldMax = 0; + diagWord = 0; + ipcErrBits = 0; + + // feStatus = 0; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + adcInfo.adcRdTimeMax[ jj ] = 0; + } + // Flip the onePPS various once/sec as a watchdog monitor. + // pLocalEpics->epicsOutput.onePps ^= 1; + pLocalEpics->epicsOutput.diagWord = diagWord; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + if ( adcInfo.adcRdTimeErr[ jj ] > MAX_ADC_WAIT_ERR_SEC ) + pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC; + adcInfo.adcRdTimeErr[ jj ] = 0; + } + } - /// \> Check if code exit is requested - if(cycleNum == MAX_MODULES) - vmeDone = stop_working_threads | checkEpicsReset(cycleNum, (struct CDS_EPICS *)pLocalEpics); + /// \> Check for requests for filter module clear history requests. This + /// is spread out over a number of cycles. + // Spread out filter coeff update, but keep updates at 16 Hz + // here we are rounding up: + // x/y rounded up equals (x + y - 1) / y + // + { + static const unsigned int mpc = + ( MAX_MODULES + ( FE_RATE / 16 ) - 1 ) / + ( FE_RATE / 16 ); // Modules per cycle + unsigned int smpc = mpc * subcycle; // Start module counter + unsigned int empc = smpc + mpc; // End module counter + unsigned int i; + for ( i = smpc; i < MAX_MODULES && i < empc; i++ ) + checkFiltReset( i, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); + } + /// \> Check if code exit is requested + if ( cycleNum == MAX_MODULES ) + vmeDone = stop_working_threads | + checkEpicsReset( cycleNum, (struct CDS_EPICS*)pLocalEpics ); /// \> Write data to DAQ. #ifndef NO_DAQ - - // Call daqLib - pLocalEpics->epicsOutput.daqByteCnt = - daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - // Send the current DAQ block size to the awgtpman for TP number checking - pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; - pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; - feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); - if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; - else odcStateWord &= ~(ODC_EXC_SET); - if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) - feStatus |= FE_ERROR_DAQ; + + // Call daqLib + pLocalEpics->epicsOutput.daqByteCnt = + daqWrite( 1, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + myGmError2, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + // Send the current DAQ block size to the awgtpman for TP number + // checking + pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; + pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; + feStatus |= ( FE_ERROR_EXC_SET & tpPtr->count ); + if ( FE_ERROR_EXC_SET & tpPtr->count ) + odcStateWord |= ODC_EXC_SET; + else + odcStateWord &= ~( ODC_EXC_SET ); + if ( pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING ) + feStatus |= FE_ERROR_DAQ; #endif -// ******************************************************************* -/// \> Cycle 19, write updated diag info to EPICS -// ******************************************************************* - if(cycleNum == HKP_DIAG_UPDATES) - { - pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime; - pLocalEpics->epicsOutput.ipcStat = ipcErrBits; - if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; - // Create FB status word for return to EPICS - mxStat = 0; - mxDiagR = daqPtr->reqAck; - if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; - if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; + // ******************************************************************* + /// \> Cycle 19, write updated diag info to EPICS + // ******************************************************************* + if ( cycleNum == HKP_DIAG_UPDATES ) + { + pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime; + pLocalEpics->epicsOutput.ipcStat = ipcErrBits; + if ( ipcErrBits & 0xf ) + feStatus |= FE_ERROR_IPC; + // Create FB status word for return to EPICS + mxStat = 0; + mxDiagR = daqPtr->reqAck; + if ( ( mxDiag & 1 ) != ( mxDiagR & 1 ) ) + mxStat = 1; + if ( ( mxDiag & 2 ) != ( mxDiagR & 2 ) ) + mxStat += 2; #ifdef DUAL_DAQ_DC - if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; - if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; + if ( ( mxDiag & 4 ) != ( mxDiagR & 4 ) ) + mxStat += 4; + if ( ( mxDiag & 8 ) != ( mxDiagR & 8 ) ) + mxStat += 8; #endif - pLocalEpics->epicsOutput.fbNetStat = mxStat; - mxDiag = mxDiagR; - if(mxStat != MX_OK) - feStatus |= FE_ERROR_DAQ;; - timeinfo.usrHoldTime = 0; - if(pLocalEpics->epicsInput.overflowReset) - { - if (pLocalEpics->epicsInput.overflowReset) { - for (ii = 0; ii < 16; ii++) { - for (jj = 0; jj < cdsPciModules.adcCount; jj++) { - adcInfo.overflowAdc[jj][ii] = 0; - adcInfo.overflowAdc[jj][ii + 16] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; - } - - for (jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; - } - } - } - } - if((pLocalEpics->epicsInput.overflowReset) || (adcInfo.overflowAdc > OVERFLOW_CNTR_LIMIT)) - { - pLocalEpics->epicsInput.overflowReset = 0; - pLocalEpics->epicsOutput.ovAccum = 0; - overflowAcc = 0; - } - } - -// ******************************************************************* -/// \> Cycle 20, Update latest DAC output values to EPICS -// ******************************************************************* - if(subcycle == HKP_DAC_EPICS_UPDATES) - { - // Send DAC output values at 16Hzfb - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacInfo.dacOutEpics[jj][ii]; - } - } - } - -// ******************************************************************* -/// \> Cycle 21, Update ADC/DAC status to EPICS. -// ******************************************************************* - if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) - { - pLocalEpics->epicsOutput.ovAccum = overflowAcc; - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - // SET/CLR Channel Hopping Error - if(adcChanErr[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(2); - feStatus |= FE_ERROR_ADC;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 2; - adcChanErr[jj] = 0; - // SET/CLR Overflow Error - if(adcOF[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(4); - feStatus |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 4; - adcOF[jj] = 0; - for(ii=0;ii<32;ii++) - { - - if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; + pLocalEpics->epicsOutput.fbNetStat = mxStat; + mxDiag = mxDiagR; + if ( mxStat != MX_OK ) + feStatus |= FE_ERROR_DAQ; + ; + timeinfo.usrHoldTime = 0; + if ( pLocalEpics->epicsInput.overflowReset ) + { + if ( pLocalEpics->epicsInput.overflowReset ) + { + for ( ii = 0; ii < 16; ii++ ) + { + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + adcInfo.overflowAdc[ jj ][ ii ] = 0; + adcInfo.overflowAdc[ jj ][ ii + 16 ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii + 16 ] = 0; + } + + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + pLocalEpics->epicsOutput + .overflowDacAcc[ jj ][ ii ] = 0; + } + } + } } - pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcInfo.overflowAdc[jj][ii]; - adcInfo.overflowAdc[jj][ii] = 0; - } - } - // If ADC channels not where they should be, we have no option but to exit - // from the RT code ie loops would be working with wrong input data. - if (chanHop) { - pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; - stop_working_threads = 1; - vmeDone = 1; - printf("Channel Hopping Detected on one or more ADC modules !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); - printf("Check GDSTP screen ADC status bits to id affected ADC modules\n"); - printf("Code is exiting ..............\n"); - continue; - } - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(dacOF[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT); - feStatus |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT; - dacOF[jj] = 0; - if(dacChanErr[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT); - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT; - dacChanErr[jj] = 0; - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - - if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; + if ( ( pLocalEpics->epicsInput.overflowReset ) || + ( adcInfo.overflowAdc > OVERFLOW_CNTR_LIMIT ) ) + { + pLocalEpics->epicsInput.overflowReset = 0; + pLocalEpics->epicsOutput.ovAccum = 0; + overflowAcc = 0; } - pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacInfo.overflowDac[jj][ii]; - dacInfo.overflowDac[jj][ii] = 0; + } + // ******************************************************************* + /// \> Cycle 20, Update latest DAC output values to EPICS + // ******************************************************************* + if ( subcycle == HKP_DAC_EPICS_UPDATES ) + { + // Send DAC output values at 16Hzfb + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { + pLocalEpics->epicsOutput.dacValue[ jj ][ ii ] = + dacInfo.dacOutEpics[ jj ][ ii ]; + } } } - } - // ********************************************************************* - // Capture end of cycle time. - // ********************************************************************* - clock_gettime(CLOCK_MONOTONIC, &cpuClock[CPU_TIME_CYCLE_END]); - - /// \> Compute code cycle time diag information. - timeinfo.cycleTime = BILLION * - (cpuClock[CPU_TIME_CYCLE_END].tv_sec - - cpuClock[CPU_TIME_CYCLE_START].tv_sec) + - cpuClock[CPU_TIME_CYCLE_END].tv_nsec - - cpuClock[CPU_TIME_CYCLE_START].tv_nsec; - timeinfo.cycleTime /= 1000; - pLocalEpics->epicsOutput.startgpstime = startGpsTime; - // Calc the max time of one cycle of the user code - // For IOP, more interested in time to get thru ADC read code and send to slave apps - timeinfo.usrTime = BILLION * - (cpuClock[CPU_TIME_USR_END].tv_sec - - cpuClock[CPU_TIME_CYCLE_START].tv_sec) + - cpuClock[CPU_TIME_USR_END].tv_nsec - - cpuClock[CPU_TIME_CYCLE_START].tv_nsec; - timeinfo.usrTime /= 1000; - - // Calculate timing max/mins/etc. - captureEocTiming(cycleNum, cycle_gps_time, &timeinfo, &adcinfo); - - /// \> Update internal cycle counters - cycleNum += 1; - cycleNum %= CYCLE_PER_SECOND; - nextstep = ((cycleNum * cyclensec) + timeoff)% 1000000000; - clock1Min += 1; - clock1Min %= CYCLE_PER_MINUTE; - if(subcycle == DAQ_CYCLE_CHANGE) - { - daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle; - } - if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ - { - /* Reset the data cycle counter */ - subcycle = 0; - } - else{ - /* Increment the internal cycle counter */ - subcycle ++; - } -/// \> If not exit request, then continue INFINITE LOOP ******* -} + // ******************************************************************* + /// \> Cycle 21, Update ADC/DAC status to EPICS. + // ******************************************************************* + if ( cycleNum == HKP_ADC_DAC_STAT_UPDATES ) + { + pLocalEpics->epicsOutput.ovAccum = overflowAcc; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + // SET/CLR Channel Hopping Error + if ( adcChanErr[ jj ] ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] &= ~( 2 ); + feStatus |= FE_ERROR_ADC; + ; + } + else + pLocalEpics->epicsOutput.statAdc[ jj ] |= 2; + adcChanErr[ jj ] = 0; + // SET/CLR Overflow Error + if ( adcOF[ jj ] ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] &= ~( 4 ); + feStatus |= FE_ERROR_OVERFLOW; + ; + } + else + pLocalEpics->epicsOutput.statAdc[ jj ] |= 4; + adcOF[ jj ] = 0; + for ( ii = 0; ii < 32; ii++ ) + { + + if ( pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] > + OVERFLOW_CNTR_LIMIT ) + { + pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] = 0; + } + pLocalEpics->epicsOutput.overflowAdc[ jj ][ ii ] = + adcInfo.overflowAdc[ jj ][ ii ]; + adcInfo.overflowAdc[ jj ][ ii ] = 0; + } + } + // If ADC channels not where they should be, we have no option but + // to exit from the RT code ie loops would be working with wrong + // input data. + if ( chanHop ) + { + pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; + stop_working_threads = 1; + vmeDone = 1; + printf( "Channel Hopping Detected on one or more ADC modules " + "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" ); + printf( "Check GDSTP screen ADC status bits to id affected ADC " + "modules\n" ); + printf( "Code is exiting ..............\n" ); + continue; + } + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + if ( dacOF[ jj ] ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= + ~( DAC_OVERFLOW_BIT ); + feStatus |= FE_ERROR_OVERFLOW; + ; + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_OVERFLOW_BIT; + dacOF[ jj ] = 0; + if ( dacChanErr[ jj ] ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= + ~( DAC_TIMING_BIT ); + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_TIMING_BIT; + dacChanErr[ jj ] = 0; + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { + + if ( pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] > + OVERFLOW_CNTR_LIMIT ) + { + pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] = 0; + } + pLocalEpics->epicsOutput.overflowDac[ jj ][ ii ] = + dacInfo.overflowDac[ jj ][ ii ]; + dacInfo.overflowDac[ jj ][ ii ] = 0; + } + } + } + // ********************************************************************* + // Capture end of cycle time. + // ********************************************************************* + clock_gettime( CLOCK_MONOTONIC, &cpuClock[ CPU_TIME_CYCLE_END ] ); + + /// \> Compute code cycle time diag information. + timeinfo.cycleTime = BILLION * + ( cpuClock[ CPU_TIME_CYCLE_END ].tv_sec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_sec ) + + cpuClock[ CPU_TIME_CYCLE_END ].tv_nsec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_nsec; + timeinfo.cycleTime /= 1000; + pLocalEpics->epicsOutput.startgpstime = startGpsTime; + // Calc the max time of one cycle of the user code + // For IOP, more interested in time to get thru ADC read code and send + // to slave apps + timeinfo.usrTime = BILLION * + ( cpuClock[ CPU_TIME_USR_END ].tv_sec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_sec ) + + cpuClock[ CPU_TIME_USR_END ].tv_nsec - + cpuClock[ CPU_TIME_CYCLE_START ].tv_nsec; + timeinfo.usrTime /= 1000; + + // Calculate timing max/mins/etc. + captureEocTiming( cycleNum, cycle_gps_time, &timeinfo, &adcinfo ); + + /// \> Update internal cycle counters + cycleNum += 1; + cycleNum %= CYCLE_PER_SECOND; + nextstep = ( ( cycleNum * cyclensec ) + timeoff ) % 1000000000; + clock1Min += 1; + clock1Min %= CYCLE_PER_MINUTE; + if ( subcycle == DAQ_CYCLE_CHANGE ) + { + daqCycle = ( daqCycle + 1 ) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; + if ( !( daqCycle % 2 ) ) + pLocalEpics->epicsOutput.epicsSync = daqCycle; + } + if ( subcycle == + END_OF_DAQ_BLOCK ) /*we have reached the 16Hz second barrier*/ + { + /* Reset the data cycle counter */ + subcycle = 0; + } + else + { + /* Increment the internal cycle counter */ + subcycle++; + } - printf("exiting from fe_code()\n"); - pLocalEpics->epicsOutput.cpuMeter = 0; + /// \> If not exit request, then continue INFINITE LOOP ******* + } + printf( "exiting from fe_code()\n" ); + pLocalEpics->epicsOutput.cpuMeter = 0; - /* System reset command received */ - return (void *)-1; + /* System reset command received */ + return (void*)-1; } diff --git a/src/fe/controllerLR.c b/src/fe/controllerLR.c index df96e0033..3654c31af 100644 --- a/src/fe/controllerLR.c +++ b/src/fe/controllerLR.c @@ -14,19 +14,21 @@ /// @file controllerIop.c /// @brief Main scheduler program for compiled real-time kernal object. \n /// @detail More information can be found in the following DCC document: -///< <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 CDS RT Sequencer Software</a> +///< <a +///<href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7688">T0900607 +///<CDS RT Sequencer Software</a> /// @author R.Bork, A.Ivanov /// @copyright Copyright (C) 2014 LIGO Project \n ///< California Institute of Technology \n ///< Massachusetts Institute of Technology \n\n -/// @license This program is free software: you can redistribute it and/or modify +/// @license This program is free software: you can redistribute it and/or +/// modify ///< it under the terms of the GNU General Public License as published by -///< the Free Software Foundation, version 3 of the License. \n -///< This program is distributed in the hope that it will be useful, -///< but WITHOUT ANY WARRANTY; without even the implied warranty of -///< MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -///< GNU General Public License for more details. - +///< the Free Software Foundation, version 3 of the License. \n This program +///< is distributed in the hope that it will be useful, but WITHOUT ANY +///< WARRANTY; without even the implied warranty of MERCHANTABILITY or +///< FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +///< for more details. #include <linux/version.h> #include <linux/init.h> @@ -49,117 +51,122 @@ // Code can be run without shutting down CPU by changing this compile flag #ifndef NO_CPU_SHUTDOWN -extern int vprintkl(const char*, va_list); -extern int printkl(const char*, ...); -extern long ligo_get_gps_driver_offset(void); -char fmt1[512]; -int printk(const char *fmt, ...) { +extern int vprintkl( const char*, va_list ); +extern int printkl( const char*, ... ); +extern long ligo_get_gps_driver_offset( void ); +char fmt1[ 512 ]; +int +printk( const char* fmt, ... ) +{ va_list args; - int r; + int r; - strcat(strcpy(fmt1, SYSTEM_NAME_STRING_LOWER), ": "); - strcat(fmt1, fmt); - va_start(args, fmt); - r = vprintkl(fmt1, args); - va_end(args); + strcat( strcpy( fmt1, SYSTEM_NAME_STRING_LOWER ), ": " ); + strcat( fmt1, fmt ); + va_start( args, fmt ); + r = vprintkl( fmt1, args ); + va_end( args ); return r; } #endif - -#include "fm10Gen.h" // CDS filter module defs and C code -#include "feComms.h" // Lvea control RFM network defs. -#include "daqmap.h" // DAQ network layout +#include "fm10Gen.h" // CDS filter module defs and C code +#include "feComms.h" // Lvea control RFM network defs. +#include "daqmap.h" // DAQ network layout #include "cds_types.h" #include "controller.h" #ifndef NO_DAQ #include "drv/fb.h" #ifdef USE_ZMQ - #include "drv/daqLibZmq.c" // DAQ/GDS connection software +#include "drv/daqLibZmq.c" // DAQ/GDS connection software #else - #include "drv/daqLib.c" // DAQ/GDS connection software +#include "drv/daqLib.c" // DAQ/GDS connection software #endif #endif -#include "drv/map.h" // PCI hardware defs -#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function -#include "timing.c" // timing module / IRIG-B functions +#include "drv/map.h" // PCI hardware defs +#include "drv/epicsXfer.c" // User defined EPICS to/from FE data transfer function +#include "timing.c" // timing module / IRIG-B functions -#include "drv/inputFilterModule.h" -#include "drv/inputFilterModule1.h" +#include "drv/inputFilterModule.h" +#include "drv/inputFilterModule1.h" #ifdef DOLPHIN_TEST #include "dolphin.c" #endif - #ifdef TIME_MASTER -TIMING_SIGNAL *pcieTimer; +TIMING_SIGNAL* pcieTimer; #endif - -adcInfo_t adcinfo; -dacInfo_t dacinfo; +adcInfo_t adcinfo; +dacInfo_t dacinfo; duotone_diag_t dt_diag; -timing_diag_t timeinfo; +timing_diag_t timeinfo; // Contec 64 input bits plus 64 output bits (Standard for aLIGO) /// Contec6464 input register values -unsigned int CDIO6464InputInput[MAX_DIO_MODULES]; // Binary input bits +unsigned int CDIO6464InputInput[ MAX_DIO_MODULES ]; // Binary input bits /// Contec6464 - Last output request sent to module. -unsigned int CDIO6464LastOutState[MAX_DIO_MODULES]; // Current requested value of the BO bits +unsigned int CDIO6464LastOutState[ MAX_DIO_MODULES ]; // Current requested value + // of the BO bits /// Contec6464 values to be written to the output register -unsigned int CDIO6464Output[MAX_DIO_MODULES]; // Binary output bits +unsigned int CDIO6464Output[ MAX_DIO_MODULES ]; // Binary output bits -// This Contect 16 input / 16 output DIO card is used to control timing slave by IOP +// This Contect 16 input / 16 output DIO card is used to control timing slave by +// IOP /// Contec1616 input register values -unsigned int CDIO1616InputInput[MAX_DIO_MODULES]; // Binary input bits +unsigned int CDIO1616InputInput[ MAX_DIO_MODULES ]; // Binary input bits /// Contec1616 output register values read back from the module -unsigned int CDIO1616Input[MAX_DIO_MODULES]; // Current value of the BO bits +unsigned int CDIO1616Input[ MAX_DIO_MODULES ]; // Current value of the BO bits /// Contec1616 values to be written to the output register -unsigned int CDIO1616Output[MAX_DIO_MODULES]; // Binary output bits +unsigned int CDIO1616Output[ MAX_DIO_MODULES ]; // Binary output bits /// Holds ID number of Contec1616 DIO card(s) used for timing control. -int tdsControl[3]; // Up to 3 timing control modules allowed in case I/O chassis are daisy chained +int tdsControl[ 3 ]; // Up to 3 timing control modules allowed in case I/O + // chassis are daisy chained /// Total number of timing control modules found on bus int tdsCount = 0; - /// Maintains present cycle count within a one second period. -int cycleNum = 0; -int adcCycleNum = 0; -int dtcycle = 0; -int dtc = 0; +int cycleNum = 0; +int adcCycleNum = 0; +int dtcycle = 0; +int dtc = 0; unsigned int odcStateWord = 0xffff; -/// Value of readback from DAC FIFO size registers; used in diags for FIFO overflow/underflow. -int out_buf_size = 0; // test checking DAC buffer size +/// Value of readback from DAC FIFO size registers; used in diags for FIFO +/// overflow/underflow. +int out_buf_size = 0; // test checking DAC buffer size unsigned int cycle_gps_time = 0; // Time at which ADCs triggered unsigned int cycle_gps_event_time = 0; // Time at which ADCs triggered -unsigned int cycle_gps_ns = 0; -unsigned int cycle_gps_event_ns = 0; -unsigned int gps_receiver_locked = 0; // Lock/unlock flag for GPS time card +unsigned int cycle_gps_ns = 0; +unsigned int cycle_gps_event_ns = 0; +unsigned int gps_receiver_locked = 0; // Lock/unlock flag for GPS time card /// GPS time in GPS seconds unsigned int timeSec = 0; unsigned int timeSecDiag = 0; /* 1 - error occured on shmem; 2 - RFM; 3 - Dolphin */ unsigned int ipcErrBits = 0; -int cardCountErr = 0; +int cardCountErr = 0; int ioClockDac = DAC_PRELOAD_CNT; int ioMemCntr = 0; int ioMemCntrDac = DAC_PRELOAD_CNT; -int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO +int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO int dacEnable = 0; -int pBits[9] = {1,2,4,8,16,32,64,128,256}; /// @param pBits[] Lookup table for quick power of 2 calcs -int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange counters -int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code -int dacTimingErrorPending[MAX_DAC_MODULES]; +int pBits[ 9 ] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256 +}; /// @param pBits[] Lookup table for quick power of 2 calcs +int dacOF[ MAX_DAC_MODULES ]; /// @param dacOF[] DAC overrange counters +int dacWriteEnable = + 0; /// @param dacWriteEnable No DAC outputs until >4 times through code +int dacTimingErrorPending[ MAX_DAC_MODULES ]; static int dacTimingError = 0; -struct rmIpcStr *daqPtr; -int dacWatchDog = 0; +struct rmIpcStr* daqPtr; +int dacWatchDog = 0; -int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); +int getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec ); // Include C code modules #include "moduleLoadIop.c" @@ -169,14 +176,13 @@ int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec); #include <drv/adc_info.c> #include <drv/dac_info.c> - -char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers -int cpuId = 1; +char daqArea[ 2 * DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers +int cpuId = 1; #ifdef DUAL_DAQ_DC - #define MX_OK 15 +#define MX_OK 15 #else - #define MX_OK 3 +#define MX_OK 3 #endif // Whether run on internal timer (when no ADC cards found) @@ -185,64 +191,75 @@ int run_on_timer = 0; // Initial diag reset flag int initialDiagReset = 1; -// Cache flushing mumbo jumbo suggested by Thomas Gleixner, it is probably useless -// Did not see any effect - char fp [64*1024]; - +// Cache flushing mumbo jumbo suggested by Thomas Gleixner, it is probably +// useless Did not see any effect +char fp[ 64 * 1024 ]; //*********************************************************************** -// TASK: fe_start() -// This routine is the skeleton for all front end code +// TASK: fe_start() +// This routine is the skeleton for all front end code //*********************************************************************** -/// This function is the main real-time sequencer or scheduler for all code built -/// using the RCG. \n -/// There are two primary modes of operation, based on two compile options: \n -/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). +/// This function is the main real-time sequencer or scheduler for all code +/// built using the RCG. \n There are two primary modes of operation, based on +/// two compile options: \n +/// - ADC_MASTER: Software is compiled as an I/O Processor (IOP). /// - ADC_SLAVE: Normal user control process. -/// This code runs in a continuous loop at the rate specified in the RCG model. The -/// loop is synchronized and triggered by the arrival of ADC data, the ADC module in turn -/// is triggered to sample by the 64KHz clock provided by the Timing Distribution System. -/// - -void *fe_start(void *arg) +/// This code runs in a continuous loop at the rate specified in the RCG model. +/// The loop is synchronized and triggered by the arrival of ADC data, the ADC +/// module in turn is triggered to sample by the 64KHz clock provided by the +/// Timing Distribution System. +/// - +void* +fe_start( void* arg ) { - int tempClock[4]; - int ii,jj,kk,ll; // Dummy loop counter variables - // int mm; - static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) - static int cpuClock[CPU_TIMER_CNT]; /// @param cpuClock[] Code timing diag variables - - - ///< Code runs longer for first few cycles on startup as it settles in, - ///< so this helps prevent long cycles during that time. - // int limit = OVERFLOW_LIMIT_16BIT; /// @param limit ADC/DAC overflow test value - // int mask = GSAI_DATA_MASK; /// @param mask Bit mask for ADC/DAC read/writes - // int num_outs = MAX_DAC_CHN_PER_MOD; /// @param num_outs Number of DAC channels variable - // volatile unsigned int *pDacData; /// @param *pDacData Pointer to DAC PCI data space - // int dacEnable = 0; - // int pBits[9] = {1,2,4,8,16,32,64,128,256}; /// @param pBits[] Lookup table for quick power of 2 calcs - int sync21ppsCycles = 0; /// @param sync32ppsCycles Number of attempts to sync to 1PPS - // int dkiTrip = 0; - RFM_FE_COMMS *pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared memory space - int myGmError2 = 0; /// @param myGmError2 Myrinet error variable - int status; /// @param status Typical function return value - float onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics - int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check - int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check + int tempClock[ 4 ]; + int ii, jj, kk, ll; // Dummy loop counter variables + // int mm; + static int clock1Min = 0; /// @param clockMin Minute counter (Not Used??) + static int cpuClock[ CPU_TIMER_CNT ]; /// @param cpuClock[] Code timing + /// diag variables + + ///< Code runs longer for first few cycles on startup as it settles in, + ///< so this helps prevent long cycles during that time. + // int limit = OVERFLOW_LIMIT_16BIT; /// @param limit ADC/DAC overflow + // test value int mask = GSAI_DATA_MASK; /// @param mask Bit mask + // for ADC/DAC read/writes int num_outs = MAX_DAC_CHN_PER_MOD; /// @param + // num_outs Number of DAC channels variable volatile unsigned int *pDacData; + // /// @param *pDacData Pointer to DAC PCI data space int dacEnable = 0; int + // pBits[9] = {1,2,4,8,16,32,64,128,256}; /// @param pBits[] Lookup table + // for quick power of 2 calcs + int sync21ppsCycles = + 0; /// @param sync32ppsCycles Number of attempts to sync to 1PPS + // int dkiTrip = 0; + RFM_FE_COMMS* pEpicsComms; /// @param *pEpicsComms Pointer to EPICS shared + /// memory space + int myGmError2 = 0; /// @param myGmError2 Myrinet error variable + int status; /// @param status Typical function return value + float + onePps; /// @param onePps Value of 1PPS signal, if used, for diagnostics + int onePpsHi = 0; /// @param onePpsHi One PPS diagnostic check + int onePpsTime = 0; /// @param onePpsTime One PPS diagnostic check #ifdef DIAG_TEST - float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for diagnostics - int onePpsHiTest[10]; /// @param onePpsHiTest[] One PPS diagnostic check - int onePpsTimeTest[10]; /// @param onePpsTimeTest[] One PPS diagnostic check + float onePpsTest; /// @param onePpsTest Value of 1PPS signal, if used, for + /// diagnostics + int onePpsHiTest[ 10 ]; /// @param onePpsHiTest[] One PPS diagnostic check + int onePpsTimeTest[ 10 ]; /// @param onePpsTimeTest[] One PPS diagnostic + /// check #endif - int dcuId; /// @param dcuId DAQ ID number for this process - static int missedCycle = 0; /// @param missedCycle Incremented error counter when too many values in ADC FIFO - int diagWord = 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS - int system = 0; - int sampleCount = 1; /// @param sampleCount Number of ADC samples to take per code cycle - int sync21pps = 0; /// @param sync21pps Code startup sync to 1PPS flag - int syncSource = SYNC_SRC_NONE; /// @param syncSource Code startup synchronization source - int mxStat = 0; /// @param mxStat Net diags when myrinet express is used - int mxDiag = 0; - int mxDiagR = 0; + int dcuId; /// @param dcuId DAQ ID number for this process + static int missedCycle = 0; /// @param missedCycle Incremented error counter + /// when too many values in ADC FIFO + int diagWord = + 0; /// @param diagWord Code diagnostic bit pattern returned to EPICS + int system = 0; + int sampleCount = + 1; /// @param sampleCount Number of ADC samples to take per code cycle + int sync21pps = 0; /// @param sync21pps Code startup sync to 1PPS flag + int syncSource = + SYNC_SRC_NONE; /// @param syncSource Code startup synchronization source + int mxStat = 0; /// @param mxStat Net diags when myrinet express is used + int mxDiag = 0; + int mxDiagR = 0; // ****** Share data #if 0 int ioClockDac = DAC_PRELOAD_CNT; @@ -251,392 +268,454 @@ void *fe_start(void *arg) int dac_out = 0; /// @param dac_out Integer value sent to DAC FIFO #endif - int feStatus = 0; - int dkiTrip = 0; - int adcInAlarm = 0; - int adcMissedCycle = 0; - int dac_restore = 0; - - int clk, clk1; // Used only when run on timer enabled (test mode) + int feStatus = 0; + int dkiTrip = 0; + int adcInAlarm = 0; + int adcMissedCycle = 0; + int dac_restore = 0; + int clk, clk1; // Used only when run on timer enabled (test mode) - // volatile GSA_18BIT_DAC_REG *dac18bitPtr; // Pointer to 16bit DAC memory area - // volatile GSA_20BIT_DAC_REG *dac20bitPtr; // Pointer to 20bit DAC memory area - // volatile GSC_DAC_REG *dac16bitPtr; // Pointer to 18bit DAC memory area - unsigned int usec = 0; + // volatile GSA_18BIT_DAC_REG *dac18bitPtr; // Pointer to 16bit DAC memory + // area volatile GSA_20BIT_DAC_REG *dac20bitPtr; // Pointer to 20bit DAC + // memory area volatile GSC_DAC_REG *dac16bitPtr; // Pointer to + // 18bit DAC memory area + unsigned int usec = 0; + unsigned long cpc; + float duotoneTimeDac; + float duotoneTime; - unsigned long cpc; - float duotoneTimeDac; - float duotoneTime; + // static int dacTimingErrorPending[MAX_DAC_MODULES]; + // static int dacTimingError = 0; + // int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange + // counters static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC + // outputs until >4 times through code int dacChanErr[MAX_DAC_MODULES]; - // static int dacTimingErrorPending[MAX_DAC_MODULES]; - // static int dacTimingError = 0; - // int dacOF[MAX_DAC_MODULES]; /// @param dacOF[] DAC overrange counters - // static int dacWriteEnable = 0; /// @param dacWriteEnable No DAC outputs until >4 times through code - // int dacChanErr[MAX_DAC_MODULES]; + /// **********************************************************************************************\n + /// Start Initialization Process \n + /// **********************************************************************************************\n + memset( tempClock, 0, sizeof( tempClock ) ); + /// \> Flush L1 cache + memset( fp, 0, 64 * 1024 ); + memset( fp, 1, 64 * 1024 ); + clflush_cache_range( (void*)fp, 64 * 1024 ); -/// **********************************************************************************************\n -/// Start Initialization Process \n -/// **********************************************************************************************\n - memset (tempClock, 0, sizeof(tempClock)); + fz_daz( ); /// \> Kill the denorms! - /// \> Flush L1 cache - memset (fp, 0, 64*1024); - memset (fp, 1, 64*1024); - clflush_cache_range ((void *)fp, 64*1024); + /// \> Init comms with EPICS processor */ + pEpicsComms = (RFM_FE_COMMS*)_epics_shm; + pLocalEpics = (CDS_EPICS*)&pEpicsComms->epicsSpace; + pEpicsDaq = (char*)&( pLocalEpics->epicsOutput ); - fz_daz(); /// \> Kill the denorms! - - /// \> Init comms with EPICS processor */ - pEpicsComms = (RFM_FE_COMMS *)_epics_shm; - pLocalEpics = (CDS_EPICS *)&pEpicsComms->epicsSpace; - pEpicsDaq = (char *)&(pLocalEpics->epicsOutput); - -adcInfo_t *padcinfo = (adcInfo_t *)&adcinfo; + adcInfo_t* padcinfo = (adcInfo_t*)&adcinfo; #ifdef OVERSAMPLE - /// \> Zero out filter histories - memset(dHistory, 0, sizeof(dHistory)); - memset(dDacHistory, 0, sizeof(dDacHistory)); + /// \> Zero out filter histories + memset( dHistory, 0, sizeof( dHistory ) ); + memset( dDacHistory, 0, sizeof( dDacHistory ) ); #endif - /// \> Set pointers to filter module data buffers. \n - /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD data.\n - /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done to: \n - /// - -------- Allow daqLib.c to retrieve filter module data directly from shared memory. \n - /// - -------- Avoid copy of filter module data between to memory locations, which was slow. \n - pDsp[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - pCoeff[system] = (VME_COEF *)(&pEpicsComms->coeffSpace); - dspPtr[system] = (FILT_MOD *)(&pEpicsComms->dspSpace); - - /// \> Clear the FE reset which comes from Epics - pLocalEpics->epicsInput.vmeReset = 0; - - // Clear input masks - pLocalEpics->epicsInput.burtRestore_mask = 0; - pLocalEpics->epicsInput.dacDuoSet_mask = 0; - -/// \> Init code synchronization source. - // Look for DIO card or IRIG-B Card - // if Contec 1616 BIO present, TDS slave will be used for timing. - if(cdsPciModules.cDio1616lCount) syncSource = SYNC_SRC_TDS; - else syncSource = SYNC_SRC_1PPS; - + /// \> Set pointers to filter module data buffers. \n + /// - ---- Prior to V2.8, separate local/shared memories for FILT_MOD + /// data.\n + /// - ---- V2.8 and later, code uses EPICS shared memory only. This was done + /// to: \n + /// - -------- Allow daqLib.c to retrieve filter module data directly from + /// shared memory. \n + /// - -------- Avoid copy of filter module data between to memory locations, + /// which was slow. \n + pDsp[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + pCoeff[ system ] = (VME_COEF*)( &pEpicsComms->coeffSpace ); + dspPtr[ system ] = (FILT_MOD*)( &pEpicsComms->dspSpace ); + + /// \> Clear the FE reset which comes from Epics + pLocalEpics->epicsInput.vmeReset = 0; + + // Clear input masks + pLocalEpics->epicsInput.burtRestore_mask = 0; + pLocalEpics->epicsInput.dacDuoSet_mask = 0; + + /// \> Init code synchronization source. + // Look for DIO card or IRIG-B Card + // if Contec 1616 BIO present, TDS slave will be used for timing. + if ( cdsPciModules.cDio1616lCount ) + syncSource = SYNC_SRC_TDS; + else + syncSource = SYNC_SRC_1PPS; #ifdef TIME_MASTER -pcieTimer = (TIMING_SIGNAL *) ((volatile char *)(cdsPciModules.dolphinWrite[0]) + IPC_PCIE_TIME_OFFSET); + pcieTimer = + (TIMING_SIGNAL*)( (volatile char*)( cdsPciModules.dolphinWrite[ 0 ] ) + + IPC_PCIE_TIME_OFFSET ); // printf("I am a TIMING MASTER **************\n"); #endif -/// < Read in all Filter Module EPICS coeff settings - for(ii=0;ii<MAX_MODULES;ii++) + /// < Read in all Filter Module EPICS coeff settings + for ( ii = 0; ii < MAX_MODULES; ii++ ) { - checkFiltReset(ii, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); + checkFiltReset( ii, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); } - // Need this FE dcuId to make connection to FB - dcuId = pLocalEpics->epicsInput.dcuId; - pLocalEpics->epicsOutput.dcuId = dcuId; - - // Reset timing diagnostics - pLocalEpics->epicsOutput.diagWord = 0; - pLocalEpics->epicsOutput.timeDiag = 0; - pLocalEpics->epicsOutput.timeErr = syncSource; - -/// \> Init IIR filter banks -// Initialize filter banks ********************************************* - for (system = 0; system < NUM_SYSTEMS; system++) { - for(ii=0;ii<MAX_MODULES;ii++){ - for(jj=0;jj<FILTERS;jj++){ - for(kk=0;kk<MAX_COEFFS;kk++){ - dspCoeff[system].coeffs[ii].filtCoeff[jj][kk] = 0.0; + // Need this FE dcuId to make connection to FB + dcuId = pLocalEpics->epicsInput.dcuId; + pLocalEpics->epicsOutput.dcuId = dcuId; + + // Reset timing diagnostics + pLocalEpics->epicsOutput.diagWord = 0; + pLocalEpics->epicsOutput.timeDiag = 0; + pLocalEpics->epicsOutput.timeErr = syncSource; + + /// \> Init IIR filter banks + // Initialize filter banks ********************************************* + for ( system = 0; system < NUM_SYSTEMS; system++ ) + { + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + for ( jj = 0; jj < FILTERS; jj++ ) + { + for ( kk = 0; kk < MAX_COEFFS; kk++ ) + { + dspCoeff[ system ].coeffs[ ii ].filtCoeff[ jj ][ kk ] = 0.0; + } + dspCoeff[ system ].coeffs[ ii ].filtSections[ jj ] = 0; + } } - dspCoeff[system].coeffs[ii].filtSections[jj] = 0; - } } - } - - /// \> Initialize all filter module excitation signals to zero - for (system = 0; system < NUM_SYSTEMS; system++) - for(ii=0;ii<MAX_MODULES;ii++) - // dsp[system].data[ii].exciteInput = 0.0; - pDsp[0]->data[ii].exciteInput = 0.0; + /// \> Initialize all filter module excitation signals to zero + for ( system = 0; system < NUM_SYSTEMS; system++ ) + for ( ii = 0; ii < MAX_MODULES; ii++ ) + // dsp[system].data[ii].exciteInput = 0.0; + pDsp[ 0 ]->data[ ii ].exciteInput = 0.0; - /// \> Initialize IIR filter bank values - if (initVars(pDsp[0], pDsp[0], dspCoeff, MAX_MODULES, pCoeff[0])) { - // printf("Filter module init failed, exiting\n"); - pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR; - return 0; + /// \> Initialize IIR filter bank values + if ( initVars( pDsp[ 0 ], pDsp[ 0 ], dspCoeff, MAX_MODULES, pCoeff[ 0 ] ) ) + { + // printf("Filter module init failed, exiting\n"); + pLocalEpics->epicsOutput.fe_status = FILT_INIT_ERROR; + return 0; } + udelay( 1000 ); -udelay(1000); - -/// \> Initialize DAQ variable/software -#if !defined(NO_DAQ) && !defined(IOP_TASK) - /// - ---- Set data range limits for daqLib routine -#if defined(SERVO2K) || defined(SERVO4K) - daq.filtExMin = GDS_2K_EXC_MIN; - daq.filtTpMin = GDS_2K_TP_MIN; +/// \> Initialize DAQ variable/software +#if !defined( NO_DAQ ) && !defined( IOP_TASK ) + /// - ---- Set data range limits for daqLib routine +#if defined( SERVO2K ) || defined( SERVO4K ) + daq.filtExMin = GDS_2K_EXC_MIN; + daq.filtTpMin = GDS_2K_TP_MIN; #else - daq.filtExMin = GDS_16K_EXC_MIN; - daq.filtTpMin = GDS_16K_TP_MIN; + daq.filtExMin = GDS_16K_EXC_MIN; + daq.filtTpMin = GDS_16K_TP_MIN; #endif - daq.filtExMax = daq.filtExMin + MAX_MODULES; - daq.filtExSize = MAX_MODULES; - daq.xExMin = daq.filtExMax; - daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; - daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; - daq.filtTpSize = MAX_MODULES * 3; - daq.xTpMin = daq.filtTpMax; - daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; - - /// - ---- Initialize DAQ function - status = daqWrite(0,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],0, (int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - if(status == -1) - { - // printf("DAQ init failed -- exiting\n"); - pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR; - vmeDone = 1; - return(0); - } + daq.filtExMax = daq.filtExMin + MAX_MODULES; + daq.filtExSize = MAX_MODULES; + daq.xExMin = daq.filtExMax; + daq.xExMax = daq.xExMin + GDS_MAX_NFM_EXC; + daq.filtTpMax = daq.filtTpMin + MAX_MODULES * 3; + daq.filtTpSize = MAX_MODULES * 3; + daq.xTpMin = daq.filtTpMax; + daq.xTpMax = daq.xTpMin + GDS_MAX_NFM_TP; + + /// - ---- Initialize DAQ function + status = daqWrite( 0, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + 0, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + if ( status == -1 ) + { + // printf("DAQ init failed -- exiting\n"); + pLocalEpics->epicsOutput.fe_status = DAQ_INIT_ERROR; + vmeDone = 1; + return ( 0 ); + } #endif - /// - ---- Assign DAC testpoint pointers - for (ii = 0; ii < cdsPciModules.dacCount; ii++) - for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) // 16 per DAC regardless of the actual - testpoint[MAX_DAC_CHN_PER_MOD * ii + jj] = floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; - - // Zero out storage - memset(floatDacOut, 0, sizeof(floatDacOut)); - - pLocalEpics->epicsOutput.ipcStat = 0; - pLocalEpics->epicsOutput.fbNetStat = 0; - pLocalEpics->epicsOutput.tpCnt = 0; - - // Clear the code exit flag - vmeDone = 0; - - /// \> Call user application software initialization routine. - // printf("Calling feCode() to initialize\n"); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0], (struct CDS_EPICS *)pLocalEpics,1); - - timeinfo.cpuTimeEverMax = 0; - timeinfo.cpuTimeEverMaxWhen = 0; - timeinfo.startGpsTime = 0; - timeinfo.usrHoldTime = 0; - timeinfo.timeHold = 0; - timeinfo.timeHoldHold = 0; - timeinfo.timeHoldWhen = 0; - timeinfo.timeHoldWhenHold = 0; - timeinfo.usrTime = 0; - timeinfo.cycleTime = 0; - missedCycle = 0; - - for(ii=0;ii<IOP_IO_RATE;ii++) { - dt_diag.adc[ii] = 0; - dt_diag.dac[ii] = 0; - } - dt_diag.totalAdc = 0.0; - dt_diag.totalDac = 0.0; - dt_diag.meanAdc = 0.0; - dt_diag.meanDac = 0.0; - dt_diag.dacDuoEnable = 0.0; - - /// \> Initialize the ADC modules ************************************* - pLocalEpics->epicsOutput.fe_status = INIT_ADC_MODS; - status = iop_adc_init_32(padcinfo); - // printf("ADC setup complete \n"); - - pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; - /// \> Initialize the DAC module variables ********************************** - status = iop_dac_init(dacTimingErrorPending); - - // printf("DAC setup complete \n"); - pLocalEpics->epicsOutput.fe_status = INIT_SYNC; - - - -/// \> Find the code syncrhonization source. \n -/// - Standard aLIGO Sync source is the Timing Distribution System (TDS) (SYNC_SRC_TDS). - if (!run_on_timer) { - switch(syncSource) - { - /// \>\> For SYNC_SRC_TDS, initialize system for synchronous start on 1PPS mark: - case SYNC_SRC_TDS: - /// - ---- Turn off TDS slave unit timing clocks, in turn removing clocks from ADC/DAC modules. - for(ii=0;ii<tdsCount;ii++) - { - CDIO1616Output[ii] = TDS_STOP_CLOCKS; - CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]); - } - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - /// - ---- Arm ADC modules - gsc16ai64Enable(cdsPciModules.adcCount); - /// - ---- Arm DAC outputs - gsc18ao8Enable(&cdsPciModules); - gsc16ao16Enable(&cdsPciModules); - // Set synched flag so later code will not check for 1PPS - sync21pps = 1; - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - /// - ---- Preload DAC FIFOS\n - /// - --------- Code runs intrinsically slower first few cycle after startup, so new DAC - /// values not written until a few cycle into run. \n - /// - --------- DAC timing diags will later check FIFO sizes to verify synchrounous timing. - #ifndef NO_DAC_PRELOAD - status = iop_dac_preload(dacPtr); - #endif - /// - ---- Start the timing clocks\n - /// - --------- Send start command to TDS slave.\n - /// - --------- TDS slave will begin sending 64KHz clocks synchronous to next 1PPS mark. - // CDIO1616Output[tdsControl] = 0x7B00000; - for(ii=0;ii<tdsCount;ii++) - { - // CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS; - CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; - CDIO1616Input[ii] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[ii], CDIO1616Output[ii]); - } - break; - case SYNC_SRC_1PPS: + /// - ---- Assign DAC testpoint pointers + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + for ( jj = 0; jj < MAX_DAC_CHN_PER_MOD; + jj++ ) // 16 per DAC regardless of the actual + testpoint[ MAX_DAC_CHN_PER_MOD * ii + jj ] = + floatDacOut + MAX_DAC_CHN_PER_MOD * ii + jj; + + // Zero out storage + memset( floatDacOut, 0, sizeof( floatDacOut ) ); + + pLocalEpics->epicsOutput.ipcStat = 0; + pLocalEpics->epicsOutput.fbNetStat = 0; + pLocalEpics->epicsOutput.tpCnt = 0; + + // Clear the code exit flag + vmeDone = 0; + + /// \> Call user application software initialization routine. + // printf("Calling feCode() to initialize\n"); + iopDacEnable = feCode( cycleNum, + dWord, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 1 ); + + timeinfo.cpuTimeEverMax = 0; + timeinfo.cpuTimeEverMaxWhen = 0; + timeinfo.startGpsTime = 0; + timeinfo.usrHoldTime = 0; + timeinfo.timeHold = 0; + timeinfo.timeHoldHold = 0; + timeinfo.timeHoldWhen = 0; + timeinfo.timeHoldWhenHold = 0; + timeinfo.usrTime = 0; + timeinfo.cycleTime = 0; + missedCycle = 0; + + for ( ii = 0; ii < IOP_IO_RATE; ii++ ) + { + dt_diag.adc[ ii ] = 0; + dt_diag.dac[ ii ] = 0; + } + dt_diag.totalAdc = 0.0; + dt_diag.totalDac = 0.0; + dt_diag.meanAdc = 0.0; + dt_diag.meanDac = 0.0; + dt_diag.dacDuoEnable = 0.0; + + /// \> Initialize the ADC modules ************************************* + pLocalEpics->epicsOutput.fe_status = INIT_ADC_MODS; + status = iop_adc_init_32( padcinfo ); + // printf("ADC setup complete \n"); + + pLocalEpics->epicsOutput.fe_status = INIT_DAC_MODS; + /// \> Initialize the DAC module variables + /// ********************************** + status = iop_dac_init( dacTimingErrorPending ); + + // printf("DAC setup complete \n"); + pLocalEpics->epicsOutput.fe_status = INIT_SYNC; + + /// \> Find the code syncrhonization source. \n + /// - Standard aLIGO Sync source is the Timing Distribution System (TDS) + /// (SYNC_SRC_TDS). + if ( !run_on_timer ) + { + switch ( syncSource ) + { + /// \>\> For SYNC_SRC_TDS, initialize system for synchronous start on + /// 1PPS mark: + case SYNC_SRC_TDS: + /// - ---- Turn off TDS slave unit timing clocks, in turn removing + /// clocks from ADC/DAC modules. + for ( ii = 0; ii < tdsCount; ii++ ) + { + CDIO1616Output[ ii ] = TDS_STOP_CLOCKS; + CDIO1616Input[ ii ] = contec1616WriteOutputRegister( + &cdsPciModules, tdsControl[ ii ], CDIO1616Output[ ii ] ); + } + udelay( MAX_UDELAY ); + udelay( MAX_UDELAY ); + /// - ---- Arm ADC modules + gsc16ai64Enable( cdsPciModules.adcCount ); + /// - ---- Arm DAC outputs + gsc18ao8Enable( &cdsPciModules ); + gsc16ao16Enable( &cdsPciModules ); + // Set synched flag so later code will not check for 1PPS + sync21pps = 1; + udelay( MAX_UDELAY ); + udelay( MAX_UDELAY ); +/// - ---- Preload DAC FIFOS\n +/// - --------- Code runs intrinsically slower first few cycle after startup, so +/// new DAC values not written until a few cycle into run. \n +/// - --------- DAC timing diags will later check FIFO sizes to verify +/// synchrounous timing. #ifndef NO_DAC_PRELOAD - status = iop_dac_preload(dacPtr); + status = iop_dac_preload( dacPtr ); #endif - // Arm ADC modules - // This has to be done sequentially, one at a time. - status = sync_adc_2_1pps(); - break; - default: { - // IRIG-B card not found, so use CPU time to get close to 1PPS on startup - // Pause until this second ends - break; - } - } - } - - - if (run_on_timer) { // NOT normal operating mode; used for test systems without I/O cards/chassis - // printf("*******************************\n"); - // printf("* Running on timer! *\n"); - // printf("*******************************\n"); - pLocalEpics->epicsOutput.fe_status = RUN_ON_TIMER; - } else { - // printf("Triggered the ADC\n"); - pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; - } - - onePpsTime = cycleNum; + /// - ---- Start the timing clocks\n + /// - --------- Send start command to TDS slave.\n + /// - --------- TDS slave will begin sending 64KHz clocks + /// synchronous to next 1PPS mark. + // CDIO1616Output[tdsControl] = 0x7B00000; + for ( ii = 0; ii < tdsCount; ii++ ) + { + // CDIO1616Output[ii] = TDS_START_ADC_NEG_DAC_POS; + CDIO1616Output[ ii ] = + TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; + CDIO1616Input[ ii ] = contec1616WriteOutputRegister( + &cdsPciModules, tdsControl[ ii ], CDIO1616Output[ ii ] ); + } + break; + case SYNC_SRC_1PPS: +#ifndef NO_DAC_PRELOAD + status = iop_dac_preload( dacPtr ); +#endif + // Arm ADC modules + // This has to be done sequentially, one at a time. + status = sync_adc_2_1pps( ); + break; + default: + { + // IRIG-B card not found, so use CPU time to get close to 1PPS on + // startup Pause until this second ends + break; + } + } + } + + if ( run_on_timer ) + { // NOT normal operating mode; used for test systems without I/O + // cards/chassis + // printf("*******************************\n"); + // printf("* Running on timer! *\n"); + // printf("*******************************\n"); + pLocalEpics->epicsOutput.fe_status = RUN_ON_TIMER; + } + else + { + // printf("Triggered the ADC\n"); + pLocalEpics->epicsOutput.fe_status = NORMAL_RUN; + } + + onePpsTime = cycleNum; #ifdef REMOTE_GPS - timeSec = remote_time((struct CDS_EPICS *)pLocalEpics); - printf ("Using remote GPS time %d \n",timeSec); + timeSec = remote_time( (struct CDS_EPICS*)pLocalEpics ); + printf( "Using remote GPS time %d \n", timeSec ); #else - timeSec = current_time_fe() -1; + timeSec = current_time_fe( ) - 1; #endif - rdtscll(adcinfo.adcTime); + rdtscll( adcinfo.adcTime ); - /// ******************************************************************************\n - /// Enter the infinite FE control loop ******************************************\n + /// ******************************************************************************\n + /// Enter the infinite FE control loop + /// ******************************************\n - /// ******************************************************************************\n - // Calculate how many CPU cycles per code cycle - cpc = cpu_khz * 1000; - cpc /= CYCLE_PER_SECOND; + /// ******************************************************************************\n + // Calculate how many CPU cycles per code cycle + cpc = cpu_khz * 1000; + cpc /= CYCLE_PER_SECOND; #ifdef NO_CPU_SHUTDOWN - usleep_range(2,4); + usleep_range( 2, 4 ); #endif - #ifdef NO_CPU_SHUTDOWN - while(!kthread_should_stop()){ + while ( !kthread_should_stop( ) ) + { #else - while(!vmeDone){ // Run forever until user hits reset + while ( !vmeDone ) + { // Run forever until user hits reset #endif - // ********************************************************************************************************** - // NORMAL OPERATION -- Wait for ADC data ready - // On startup, only want to read one sample such that first cycle - // coincides with GPS 1PPS. Thereafter, sampleCount will be - // increased to appropriate number of 65536 s/sec to match desired - // code rate eg 32 samples each time thru before proceeding to match 2048 system. - // ********************************************************************************************************** - -/// \> On 1PPS mark \n - if(cycleNum == 0) - { - /// - ---- Check awgtpman status. - //printf("awgtpman gps = %d local = %d\n", pEpicsComms->padSpace.awgtpman_gps, timeSec); - pLocalEpics->epicsOutput.awgStat = (pEpicsComms->padSpace.awgtpman_gps != timeSec); - if(pLocalEpics->epicsOutput.awgStat) feStatus |= FE_ERROR_AWG; - /// - ---- Check if DAC outputs are enabled, report error. - if(!iopDacEnable || dkiTrip) feStatus |= FE_ERROR_DAC_ENABLE; - - /// - ---- If IOP, Increment GPS second - timeSec ++; - pLocalEpics->epicsOutput.timeDiag = timeSec; - if (cycle_gps_time == 0) { - timeinfo.startGpsTime = timeSec; - pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime; - } - cycle_gps_time = timeSec; - } + // ********************************************************************************************************** + // NORMAL OPERATION -- Wait for ADC data ready + // On startup, only want to read one sample such that first cycle + // coincides with GPS 1PPS. Thereafter, sampleCount will be + // increased to appropriate number of 65536 s/sec to match desired + // code rate eg 32 samples each time thru before proceeding to match + // 2048 system. + // ********************************************************************************************************** + + /// \> On 1PPS mark \n + if ( cycleNum == 0 ) + { + /// - ---- Check awgtpman status. + // printf("awgtpman gps = %d local = %d\n", + // pEpicsComms->padSpace.awgtpman_gps, timeSec); + pLocalEpics->epicsOutput.awgStat = + ( pEpicsComms->padSpace.awgtpman_gps != timeSec ); + if ( pLocalEpics->epicsOutput.awgStat ) + feStatus |= FE_ERROR_AWG; + /// - ---- Check if DAC outputs are enabled, report error. + if ( !iopDacEnable || dkiTrip ) + feStatus |= FE_ERROR_DAC_ENABLE; + + /// - ---- If IOP, Increment GPS second + timeSec++; + pLocalEpics->epicsOutput.timeDiag = timeSec; + if ( cycle_gps_time == 0 ) + { + timeinfo.startGpsTime = timeSec; + pLocalEpics->epicsOutput.startgpstime = timeinfo.startGpsTime; + } + cycle_gps_time = timeSec; + } #ifdef NO_CPU_SHUTDOWN - if((cycleNum % 2048) == 0) usleep_range(2,4); + if ( ( cycleNum % 2048 ) == 0 ) + usleep_range( 2, 4 ); #endif -/// IF IOP *************************** \n -// Start of ADC Read ************************************************************************************* - /// \> IF IOP, Wait for ADC data ready - /// - ---- On startup, only want to read one sample such that first cycle - /// coincides with GPS 1PPS. Thereafter, sampleCount will be - /// increased to appropriate number of 65536 s/sec to match desired - /// code rate eg 32 samples each time thru before proceeding to match 2048 system. - // Read ADC data - status = iop_adc_read_32 (padcinfo, cpuClock); - if(status == ADC_BUS_DELAY && dacWriteEnable > 8) { - printf("ADC long cycle \n"); - adcInAlarm = 10; - adcMissedCycle = 0; - status = gsc16ao16ClearDacBuffer(0); - status = iop_dac_recover(1,dacPtr); - } - if(status == ADC_SHORT_CYCLE && adcInAlarm) adcMissedCycle ++; - if(adcInAlarm > 1) adcInAlarm --; - if(status == 0 && adcInAlarm == 1) { - printf("IOP missed %d ADC clocks\n",adcMissedCycle); - adcInAlarm = 0; - dac_restore = adcMissedCycle; - } - - - - - -// ************************************************************************************** -/// \> Call the front end specific application ******************\n -/// - -- This is where the user application produced by RCG gets called and executed. \n\n - rdtscll(cpuClock[CPU_TIME_USR_START]); - iopDacEnable = feCode(cycleNum,dWord,dacOut,dspPtr[0],&dspCoeff[0],(struct CDS_EPICS *)pLocalEpics,0); - rdtscll(cpuClock[CPU_TIME_USR_END]); -// ************************************************************************************** -// - /// - ---- Reset ADC DMA Start Flag \n - /// - --------- This allows ADC to dump next data set whenever it is ready - for(jj=0;jj<cdsPciModules.adcCount;jj++) - gsc16ai64DmaEnable(jj); - - odcStateWord = 0; - -// ******************************************************************** -/// WRITE DAC OUTPUTS ***************************************** \n -// ******************************************************************** + /// IF IOP *************************** \n + // Start of ADC Read + // ************************************************************************************* + /// \> IF IOP, Wait for ADC data ready + /// - ---- On startup, only want to read one sample such that first + /// cycle coincides with GPS 1PPS. Thereafter, sampleCount will be + /// increased to appropriate number of 65536 s/sec to match desired + /// code rate eg 32 samples each time thru before proceeding to match + /// 2048 system. + // Read ADC data + status = iop_adc_read_32( padcinfo, cpuClock ); + if ( status == ADC_BUS_DELAY && dacWriteEnable > 8 ) + { + printf( "ADC long cycle \n" ); + adcInAlarm = 10; + adcMissedCycle = 0; + status = gsc16ao16ClearDacBuffer( 0 ); + status = iop_dac_recover( 1, dacPtr ); + } + if ( status == ADC_SHORT_CYCLE && adcInAlarm ) + adcMissedCycle++; + if ( adcInAlarm > 1 ) + adcInAlarm--; + if ( status == 0 && adcInAlarm == 1 ) + { + printf( "IOP missed %d ADC clocks\n", adcMissedCycle ); + adcInAlarm = 0; + dac_restore = adcMissedCycle; + } - // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. + // ************************************************************************************** + /// \> Call the front end specific application ******************\n + /// - -- This is where the user application produced by RCG gets called + /// and executed. \n\n + rdtscll( cpuClock[ CPU_TIME_USR_START ] ); + iopDacEnable = feCode( cycleNum, + dWord, + dacOut, + dspPtr[ 0 ], + &dspCoeff[ 0 ], + (struct CDS_EPICS*)pLocalEpics, + 0 ); + rdtscll( cpuClock[ CPU_TIME_USR_END ] ); + // ************************************************************************************** + // + /// - ---- Reset ADC DMA Start Flag \n + /// - --------- This allows ADC to dump next data set whenever it is + /// ready + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + gsc16ai64DmaEnable( jj ); + + odcStateWord = 0; + + // ******************************************************************** + /// WRITE DAC OUTPUTS ***************************************** \n + // ******************************************************************** + + // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. #ifndef DAC_WD_OVERRIDE - // If a DAC module has bad timing then quit writing outputs - // if(dacTimingError) iopDacEnable = 0; + // If a DAC module has bad timing then quit writing outputs + // if(dacTimingError) iopDacEnable = 0; #endif #if 0 // Write out data to DAC modules @@ -649,470 +728,569 @@ udelay(1000); if(dac_restore > 4) dacWriteEnable = 0; dkiTrip = iop_dac_write(); if(dac_restore) dac_restore --; - #endif - +#endif -// *********************************************************************** -/// BEGIN HOUSEKEEPING ************************************************ \n -// *********************************************************************** + // *********************************************************************** + /// BEGIN HOUSEKEEPING ************************************************ + /// \n + // *********************************************************************** pLocalEpics->epicsOutput.cycle = cycleNum; -// ***************************************************************** -/// \> Cycle 0: \n -/// - ---- Read IRIGB time if symmetricom card (this is not standard, but supported for earlier cards. \n -// ***************************************************************** - if(dtcycle == HKP_READ_SYMCOM_IRIGB) - { - /// - ---- Calc duotone diagnostic mean values for past second and reset. - dt_diag.meanAdc = dt_diag.totalAdc/65536; - dt_diag.totalAdc = 0.0; - dt_diag.meanDac = dt_diag.totalDac/65536; - dt_diag.totalDac = 0.0; - } - -// ***************************************************************** -/// \> Cycle 1 and Spectricom IRIGB (standard), get IRIG-B time information. -// ***************************************************************** - // if(cycleNum == HKP_READ_TSYNC_IRIBB) - if(cycleNum == 0) - { - if(cdsPciModules.gpsType == TSYNC_RCVR) - { - gps_receiver_locked = getGpsuSecTsync(&usec); - pLocalEpics->epicsOutput.irigbTime = usec - 15; -/// - ---- If not in acceptable range, generate error. - if((usec > 30) || (usec < 24)) - { - feStatus |= FE_ERROR_TIMING;; - diagWord |= TIME_ERR_IRIGB;; - } - } + // ***************************************************************** + /// \> Cycle 0: \n + /// - ---- Read IRIGB time if symmetricom card (this is not standard, + /// but supported for earlier cards. \n + // ***************************************************************** + if ( dtcycle == HKP_READ_SYMCOM_IRIGB ) + { + /// - ---- Calc duotone diagnostic mean values for past second and + /// reset. + dt_diag.meanAdc = dt_diag.totalAdc / 65536; + dt_diag.totalAdc = 0.0; + dt_diag.meanDac = dt_diag.totalDac / 65536; + dt_diag.totalDac = 0.0; } -/// \> Update duotone diag information - dtc = (dtcycle % IO_MEMORY_SLOTS); - dt_diag.adc[(dtcycle + DT_SAMPLE_OFFSET) % IOP_IO_RATE] = - ioMemData->iodata[ADC_DUOTONE_BRD][dtc].data[ADC_DUOTONE_CHAN]; - dt_diag.totalAdc += - ioMemData->iodata[ADC_DUOTONE_BRD][dtc].data[ADC_DUOTONE_CHAN]; - dtcycle = (dtcycle + 1) % IOP_IO_RATE; - dtc = (dtcycle % IO_MEMORY_SLOTS); - dt_diag.adc[(dtcycle + DT_SAMPLE_OFFSET) % IOP_IO_RATE] = - ioMemData->iodata[ADC_DUOTONE_BRD][dtc].data[ADC_DUOTONE_CHAN]; - dt_diag.totalAdc += - ioMemData->iodata[ADC_DUOTONE_BRD][dtc].data[ADC_DUOTONE_CHAN]; - dtcycle = (dtcycle + 1) % IOP_IO_RATE; + // ***************************************************************** + /// \> Cycle 1 and Spectricom IRIGB (standard), get IRIG-B time + /// information. + // ***************************************************************** + // if(cycleNum == HKP_READ_TSYNC_IRIBB) + if ( cycleNum == 0 ) + { + if ( cdsPciModules.gpsType == TSYNC_RCVR ) + { + gps_receiver_locked = getGpsuSecTsync( &usec ); + pLocalEpics->epicsOutput.irigbTime = usec - 15; + /// - ---- If not in acceptable range, generate error. + if ( ( usec > 30 ) || ( usec < 24 ) ) + { + feStatus |= FE_ERROR_TIMING; + ; + diagWord |= TIME_ERR_IRIGB; + ; + } + } + } -// ***************************************************************** -/// \> Cycle 16, perform duotone diag calcs. -// ***************************************************************** + /// \> Update duotone diag information + dtc = ( dtcycle % IO_MEMORY_SLOTS ); + dt_diag.adc[ ( dtcycle + DT_SAMPLE_OFFSET ) % IOP_IO_RATE ] = + ioMemData->iodata[ ADC_DUOTONE_BRD ][ dtc ] + .data[ ADC_DUOTONE_CHAN ]; + dt_diag.totalAdc += ioMemData->iodata[ ADC_DUOTONE_BRD ][ dtc ] + .data[ ADC_DUOTONE_CHAN ]; + dtcycle = ( dtcycle + 1 ) % IOP_IO_RATE; + dtc = ( dtcycle % IO_MEMORY_SLOTS ); + dt_diag.adc[ ( dtcycle + DT_SAMPLE_OFFSET ) % IOP_IO_RATE ] = + ioMemData->iodata[ ADC_DUOTONE_BRD ][ dtc ] + .data[ ADC_DUOTONE_CHAN ]; + dt_diag.totalAdc += ioMemData->iodata[ ADC_DUOTONE_BRD ][ dtc ] + .data[ ADC_DUOTONE_CHAN ]; + dtcycle = ( dtcycle + 1 ) % IOP_IO_RATE; + + // ***************************************************************** + /// \> Cycle 16, perform duotone diag calcs. + // ***************************************************************** // if(cycleNum == HKP_DT_CALC) - if(cycleNum == 8) + if ( cycleNum == 8 ) { - duotoneTime = duotime(DT_SAMPLE_CNT, dt_diag.meanAdc, dt_diag.adc); - pLocalEpics->epicsOutput.dtTime = duotoneTime; - // if(((duotoneTime < MIN_DT_DIAG_VAL) || (duotoneTime > MAX_DT_DIAG_VAL)) && - // syncSource != SYNC_SRC_1PPS) - // feStatus |= FE_ERROR_TIMING; - duotoneTimeDac = 0; - pLocalEpics->epicsOutput.dacDtTime = duotoneTimeDac; + duotoneTime = + duotime( DT_SAMPLE_CNT, dt_diag.meanAdc, dt_diag.adc ); + pLocalEpics->epicsOutput.dtTime = duotoneTime; + // if(((duotoneTime < MIN_DT_DIAG_VAL) || (duotoneTime > + // MAX_DT_DIAG_VAL)) && syncSource != SYNC_SRC_1PPS) feStatus |= + // FE_ERROR_TIMING; + duotoneTimeDac = 0; + pLocalEpics->epicsOutput.dacDtTime = duotoneTimeDac; } -// ***************************************************************** -/// \> Cycle 17, set/reset DAC duotone switch if request has changed. -// ***************************************************************** - if(cycleNum == HKP_DAC_DT_SWITCH) - { - if(dt_diag.dacDuoEnable != pLocalEpics->epicsInput.dacDuoSet) - { - dt_diag.dacDuoEnable = pLocalEpics->epicsInput.dacDuoSet; - if(dt_diag.dacDuoEnable) - CDIO1616Output[0] = TDS_START_ADC_NEG_DAC_POS; - else CDIO1616Output[0] = TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; - CDIO1616Input[0] = contec1616WriteOutputRegister(&cdsPciModules, tdsControl[0], CDIO1616Output[0]); - } - } - + // ***************************************************************** + /// \> Cycle 17, set/reset DAC duotone switch if request has changed. + // ***************************************************************** + if ( cycleNum == HKP_DAC_DT_SWITCH ) + { + if ( dt_diag.dacDuoEnable != pLocalEpics->epicsInput.dacDuoSet ) + { + dt_diag.dacDuoEnable = pLocalEpics->epicsInput.dacDuoSet; + if ( dt_diag.dacDuoEnable ) + CDIO1616Output[ 0 ] = TDS_START_ADC_NEG_DAC_POS; + else + CDIO1616Output[ 0 ] = + TDS_START_ADC_NEG_DAC_POS | TDS_NO_DAC_DUOTONE; + CDIO1616Input[ 0 ] = contec1616WriteOutputRegister( + &cdsPciModules, tdsControl[ 0 ], CDIO1616Output[ 0 ] ); + } + } -// ***************************************************************** -/// \> Cycle 18, Send timing info to EPICS at 1Hz -// ***************************************************************** - if(cycleNum ==HKP_TIMING_UPDATES) - { - pLocalEpics->epicsOutput.cpuMeter = timeinfo.timeHold; - pLocalEpics->epicsOutput.cpuMeterMax = timeinfo.timeHoldMax; - pLocalEpics->epicsOutput.dacEnable = dacEnable; - timeinfo.timeHoldHold = timeinfo.timeHold; - timeinfo.timeHold = 0; - timeinfo.timeHoldWhenHold = timeinfo.timeHoldWhen; - - if (timeSec % 4 == 0) pLocalEpics->epicsOutput.adcWaitTime = - adcinfo.adcHoldTimeMin; - else if (timeSec % 4 == 1) - pLocalEpics->epicsOutput.adcWaitTime = adcinfo.adcHoldTimeMax; - else - pLocalEpics->epicsOutput.adcWaitTime = adcinfo.adcHoldTimeAvg/CYCLE_PER_SECOND; - adcinfo.adcHoldTimeAvgPerSec = adcinfo.adcHoldTimeAvg/CYCLE_PER_SECOND; - adcinfo.adcHoldTimeMax = 0; - adcinfo.adcHoldTimeMin = 0xffff; - adcinfo.adcHoldTimeAvg = 0; - if((adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI) || (adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO)) - { - diagWord |= FE_ADC_HOLD_ERR; - feStatus |= FE_ERROR_TIMING; - - } - if(timeinfo.timeHoldMax > CYCLE_TIME_ALRM) - { - diagWord |= FE_PROC_TIME_ERR; - feStatus |= FE_ERROR_TIMING; - } - pLocalEpics->epicsOutput.stateWord = feStatus; - feStatus = 0; - if(pLocalEpics->epicsInput.diagReset || initialDiagReset) - { - initialDiagReset = 0; - pLocalEpics->epicsInput.diagReset = 0; - pLocalEpics->epicsInput.ipcDiagReset = 1; - // pLocalEpics->epicsOutput.diags[1] = 0; - timeinfo.timeHoldMax = 0; - diagWord = 0; - ipcErrBits = 0; - - for(jj=0;jj<cdsPciModules.adcCount;jj++) adcinfo.adcRdTimeMax[jj] = 0; - } - pLocalEpics->epicsOutput.diagWord = diagWord; - for(jj=0;jj<cdsPciModules.adcCount;jj++) { - if(adcinfo.adcRdTimeErr[jj] > MAX_ADC_WAIT_ERR_SEC) - pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC; - adcinfo.adcRdTimeErr[jj] = 0; - } - } + // ***************************************************************** + /// \> Cycle 18, Send timing info to EPICS at 1Hz + // ***************************************************************** + if ( cycleNum == HKP_TIMING_UPDATES ) + { + pLocalEpics->epicsOutput.cpuMeter = timeinfo.timeHold; + pLocalEpics->epicsOutput.cpuMeterMax = timeinfo.timeHoldMax; + pLocalEpics->epicsOutput.dacEnable = dacEnable; + timeinfo.timeHoldHold = timeinfo.timeHold; + timeinfo.timeHold = 0; + timeinfo.timeHoldWhenHold = timeinfo.timeHoldWhen; + + if ( timeSec % 4 == 0 ) + pLocalEpics->epicsOutput.adcWaitTime = adcinfo.adcHoldTimeMin; + else if ( timeSec % 4 == 1 ) + pLocalEpics->epicsOutput.adcWaitTime = adcinfo.adcHoldTimeMax; + else + pLocalEpics->epicsOutput.adcWaitTime = + adcinfo.adcHoldTimeAvg / CYCLE_PER_SECOND; + adcinfo.adcHoldTimeAvgPerSec = + adcinfo.adcHoldTimeAvg / CYCLE_PER_SECOND; + adcinfo.adcHoldTimeMax = 0; + adcinfo.adcHoldTimeMin = 0xffff; + adcinfo.adcHoldTimeAvg = 0; + if ( ( adcinfo.adcHoldTime > CYCLE_TIME_ALRM_HI ) || + ( adcinfo.adcHoldTime < CYCLE_TIME_ALRM_LO ) ) + { + diagWord |= FE_ADC_HOLD_ERR; + feStatus |= FE_ERROR_TIMING; + } + if ( timeinfo.timeHoldMax > CYCLE_TIME_ALRM ) + { + diagWord |= FE_PROC_TIME_ERR; + feStatus |= FE_ERROR_TIMING; + } + pLocalEpics->epicsOutput.stateWord = feStatus; + feStatus = 0; + if ( pLocalEpics->epicsInput.diagReset || initialDiagReset ) + { + initialDiagReset = 0; + pLocalEpics->epicsInput.diagReset = 0; + pLocalEpics->epicsInput.ipcDiagReset = 1; + // pLocalEpics->epicsOutput.diags[1] = 0; + timeinfo.timeHoldMax = 0; + diagWord = 0; + ipcErrBits = 0; + + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + adcinfo.adcRdTimeMax[ jj ] = 0; + } + pLocalEpics->epicsOutput.diagWord = diagWord; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + if ( adcinfo.adcRdTimeErr[ jj ] > MAX_ADC_WAIT_ERR_SEC ) + pLocalEpics->epicsOutput.stateWord |= FE_ERROR_ADC; + adcinfo.adcRdTimeErr[ jj ] = 0; + } + } + // ***************************************************************** + /// \> Check for requests for filter module clear history requests. This + /// is spread out over a number of cycles. + // Spread out filter coeff update, but keep updates at 16 Hz + // here we are rounding up: + // x/y rounded up equals (x + y - 1) / y + // + // ***************************************************************** + { + static const unsigned int mpc = + ( MAX_MODULES + ( FE_RATE / 16 ) - 1 ) / + ( FE_RATE / 16 ); // Modules per cycle + unsigned int smpc = mpc * subcycle; // Start module counter + unsigned int empc = smpc + mpc; // End module counter + unsigned int i; + for ( i = smpc; i < MAX_MODULES && i < empc; i++ ) + checkFiltReset( i, + dspPtr[ 0 ], + pDsp[ 0 ], + &dspCoeff[ 0 ], + MAX_MODULES, + pCoeff[ 0 ] ); + } -// ***************************************************************** -/// \> Check for requests for filter module clear history requests. This is spread out over a number of cycles. - // Spread out filter coeff update, but keep updates at 16 Hz - // here we are rounding up: - // x/y rounded up equals (x + y - 1) / y - // -// ***************************************************************** - { - static const unsigned int mpc = (MAX_MODULES + (FE_RATE / 16) - 1) / (FE_RATE / 16); // Modules per cycle - unsigned int smpc = mpc * subcycle; // Start module counter - unsigned int empc = smpc + mpc; // End module counter - unsigned int i; - for (i = smpc; i < MAX_MODULES && i < empc ; i++) - checkFiltReset(i, dspPtr[0], pDsp[0], &dspCoeff[0], MAX_MODULES, pCoeff[0]); - } + // ***************************************************************** + /// \> Check if code exit is requested + if ( cycleNum == MAX_MODULES ) + vmeDone = stop_working_threads | + checkEpicsReset( cycleNum, (struct CDS_EPICS*)pLocalEpics ); + // ***************************************************************** + // If synced to 1PPS on startup, continue to check that code + // is still in sync with 1PPS. + // This is NOT normal aLIGO mode. + if ( syncSource == SYNC_SRC_1PPS ) + { -// ***************************************************************** - /// \> Check if code exit is requested - if(cycleNum == MAX_MODULES) - vmeDone = stop_working_threads | checkEpicsReset(cycleNum, (struct CDS_EPICS *)pLocalEpics); -// ***************************************************************** - // If synced to 1PPS on startup, continue to check that code - // is still in sync with 1PPS. - // This is NOT normal aLIGO mode. - if(syncSource == SYNC_SRC_1PPS) - { - - // Assign chan 32 to onePps - onePps = adcinfo.adcData[ADC_DUOTONE_BRD][ADC_DUOTONE_CHAN]; - if((onePps > ONE_PPS_THRESH) && (onePpsHi == 0)) - { - onePpsTime = cycleNum; - onePpsHi = 1; - } - if(onePps < ONE_PPS_THRESH) onePpsHi = 0; - - // Check if front end continues to be in sync with 1pps - // If not, set sync error flag - if(onePpsTime > 1) pLocalEpics->epicsOutput.timeErr |= TIME_ERR_1PPS; - } + // Assign chan 32 to onePps + onePps = adcinfo.adcData[ ADC_DUOTONE_BRD ][ ADC_DUOTONE_CHAN ]; + if ( ( onePps > ONE_PPS_THRESH ) && ( onePpsHi == 0 ) ) + { + onePpsTime = cycleNum; + onePpsHi = 1; + } + if ( onePps < ONE_PPS_THRESH ) + onePpsHi = 0; + + // Check if front end continues to be in sync with 1pps + // If not, set sync error flag + if ( onePpsTime > 1 ) + pLocalEpics->epicsOutput.timeErr |= TIME_ERR_1PPS; + } #ifdef DIAG_TEST - for(ii=0;ii<10;ii++) - { - if(ii<5) onePpsTest = adcinfo.adcData[0][ii]; - else onePpsTest = adcinfo.adcData[1][(ii-5)]; - if((onePpsTest > 400) && (onePpsHiTest[ii] == 0)) - { - onePpsTimeTest[ii] = cycleNum; - onePpsHiTest[ii] = 1; - if((ii == 0) || (ii == 5)) pLocalEpics->epicsOutput.timingTest[ii] = cycleNum * 15.26; - // Slaves do not see 1pps until after IOP signal loops around and back into ADC channel 0, - // therefore, need to subtract IOP loop time. - else pLocalEpics->epicsOutput.timingTest[ii] = (cycleNum * 15.26) - pLocalEpics->epicsOutput.timingTest[0]; - } - // Reset the diagnostic for next cycle - if(cycleNum > 2000) onePpsHiTest[ii] = 0; - } + for ( ii = 0; ii < 10; ii++ ) + { + if ( ii < 5 ) + onePpsTest = adcinfo.adcData[ 0 ][ ii ]; + else + onePpsTest = adcinfo.adcData[ 1 ][ ( ii - 5 ) ]; + if ( ( onePpsTest > 400 ) && ( onePpsHiTest[ ii ] == 0 ) ) + { + onePpsTimeTest[ ii ] = cycleNum; + onePpsHiTest[ ii ] = 1; + if ( ( ii == 0 ) || ( ii == 5 ) ) + pLocalEpics->epicsOutput.timingTest[ ii ] = + cycleNum * 15.26; + // Slaves do not see 1pps until after IOP signal loops around + // and back into ADC channel 0, therefore, need to subtract IOP + // loop time. + else + pLocalEpics->epicsOutput.timingTest[ ii ] = + ( cycleNum * 15.26 ) - + pLocalEpics->epicsOutput.timingTest[ 0 ]; + } + // Reset the diagnostic for next cycle + if ( cycleNum > 2000 ) + onePpsHiTest[ ii ] = 0; + } #endif // ***************************************************************** /// \> Write data to DAQ. // ***************************************************************** #ifndef NO_DAQ - - // Call daqLib - pLocalEpics->epicsOutput.daqByteCnt = - daqWrite(1,dcuId,daq,DAQ_RATE,testpoint,dspPtr[0],myGmError2,(int *)(pLocalEpics->epicsOutput.gdsMon),xExc,pEpicsDaq); - // Send the current DAQ block size to the awgtpman for TP number checking - pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; - pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; - feStatus |= (FE_ERROR_EXC_SET & tpPtr->count); - if (FE_ERROR_EXC_SET & tpPtr->count) odcStateWord |= ODC_EXC_SET; - else odcStateWord &= ~(ODC_EXC_SET); - if(pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING) - feStatus |= FE_ERROR_DAQ; + + // Call daqLib + pLocalEpics->epicsOutput.daqByteCnt = + daqWrite( 1, + dcuId, + daq, + DAQ_RATE, + testpoint, + dspPtr[ 0 ], + myGmError2, + (int*)( pLocalEpics->epicsOutput.gdsMon ), + xExc, + pEpicsDaq ); + // Send the current DAQ block size to the awgtpman for TP number + // checking + pEpicsComms->padSpace.feDaqBlockSize = curDaqBlockSize; + pLocalEpics->epicsOutput.tpCnt = tpPtr->count & 0xff; + feStatus |= ( FE_ERROR_EXC_SET & tpPtr->count ); + if ( FE_ERROR_EXC_SET & tpPtr->count ) + odcStateWord |= ODC_EXC_SET; + else + odcStateWord &= ~( ODC_EXC_SET ); + if ( pLocalEpics->epicsOutput.daqByteCnt > DAQ_DCU_RATE_WARNING ) + feStatus |= FE_ERROR_DAQ; #endif -// ***************************************************************** + // ***************************************************************** -/// \> Cycle 19, write updated diag info to EPICS - if(cycleNum == HKP_DIAG_UPDATES) - { - pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime; - pLocalEpics->epicsOutput.ipcStat = ipcErrBits; - if(ipcErrBits & 0xf) feStatus |= FE_ERROR_IPC; - // Create FB status word for return to EPICS - mxStat = 0; - mxDiagR = daqPtr->reqAck; - if((mxDiag & 1) != (mxDiagR & 1)) mxStat = 1; - if((mxDiag & 2) != (mxDiagR & 2)) mxStat += 2; + /// \> Cycle 19, write updated diag info to EPICS + if ( cycleNum == HKP_DIAG_UPDATES ) + { + pLocalEpics->epicsOutput.userTime = timeinfo.usrHoldTime; + pLocalEpics->epicsOutput.ipcStat = ipcErrBits; + if ( ipcErrBits & 0xf ) + feStatus |= FE_ERROR_IPC; + // Create FB status word for return to EPICS + mxStat = 0; + mxDiagR = daqPtr->reqAck; + if ( ( mxDiag & 1 ) != ( mxDiagR & 1 ) ) + mxStat = 1; + if ( ( mxDiag & 2 ) != ( mxDiagR & 2 ) ) + mxStat += 2; #ifdef DUAL_DAQ_DC - if((mxDiag & 4) != (mxDiagR & 4)) mxStat += 4; - if((mxDiag & 8) != (mxDiagR & 8)) mxStat += 8; + if ( ( mxDiag & 4 ) != ( mxDiagR & 4 ) ) + mxStat += 4; + if ( ( mxDiag & 8 ) != ( mxDiagR & 8 ) ) + mxStat += 8; #endif - pLocalEpics->epicsOutput.fbNetStat = mxStat; - mxDiag = mxDiagR; - if(mxStat != MX_OK) - feStatus |= FE_ERROR_DAQ;; - timeinfo.usrHoldTime = 0; - if(pLocalEpics->epicsInput.overflowReset) - { - if (pLocalEpics->epicsInput.overflowReset) { - for (ii = 0; ii < 16; ii++) { - for (jj = 0; jj < cdsPciModules.adcCount; jj++) { - adcinfo.overflowAdc[jj][ii] = 0; - adcinfo.overflowAdc[jj][ii + 16] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii + 16] = 0; - } - for (jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; - } - } - } - } - if((pLocalEpics->epicsInput.overflowReset) || (overflowAcc > OVERFLOW_CNTR_LIMIT)) - { - pLocalEpics->epicsInput.overflowReset = 0; - pLocalEpics->epicsOutput.ovAccum = 0; - overflowAcc = 0; - } - } - -/// \> Cycle 20, Update latest DAC output values to EPICS - if(subcycle == HKP_DAC_EPICS_UPDATES) - { - // Send DAC output values at 16Hzfb - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - pLocalEpics->epicsOutput.dacValue[jj][ii] = dacOutEpics[jj][ii]; - } - } - } + pLocalEpics->epicsOutput.fbNetStat = mxStat; + mxDiag = mxDiagR; + if ( mxStat != MX_OK ) + feStatus |= FE_ERROR_DAQ; + ; + timeinfo.usrHoldTime = 0; + if ( pLocalEpics->epicsInput.overflowReset ) + { + if ( pLocalEpics->epicsInput.overflowReset ) + { + for ( ii = 0; ii < 16; ii++ ) + { + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + adcinfo.overflowAdc[ jj ][ ii ] = 0; + adcinfo.overflowAdc[ jj ][ ii + 16 ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii ] = 0; + pLocalEpics->epicsOutput + .overflowAdcAcc[ jj ][ ii + 16 ] = 0; + } + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + pLocalEpics->epicsOutput + .overflowDacAcc[ jj ][ ii ] = 0; + } + } + } + } + if ( ( pLocalEpics->epicsInput.overflowReset ) || + ( overflowAcc > OVERFLOW_CNTR_LIMIT ) ) + { + pLocalEpics->epicsInput.overflowReset = 0; + pLocalEpics->epicsOutput.ovAccum = 0; + overflowAcc = 0; + } + } -// ***************************************************************** -/// \> Cycle 21, Update ADC/DAC status to EPICS. -// ***************************************************************** - if(cycleNum == HKP_ADC_DAC_STAT_UPDATES) - { + /// \> Cycle 20, Update latest DAC output values to EPICS + if ( subcycle == HKP_DAC_EPICS_UPDATES ) + { + // Send DAC output values at 16Hzfb + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { + pLocalEpics->epicsOutput.dacValue[ jj ][ ii ] = + dacOutEpics[ jj ][ ii ]; + } + } + } - pLocalEpics->epicsOutput.ovAccum = overflowAcc; - feStatus |= adc_status_update(&adcinfo); - feStatus |= dac_status_update(&dacinfo); - // If ADC channels not where they should be, we have no option but to exit - // from the RT code ie loops would be working with wrong input data. - if (adcinfo.chanHop) { - pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; - stop_working_threads = 1; - vmeDone = 1; - pLocalEpics->epicsOutput.fe_status = CHAN_HOP_ERROR; - continue; - } - } + // ***************************************************************** + /// \> Cycle 21, Update ADC/DAC status to EPICS. + // ***************************************************************** + if ( cycleNum == HKP_ADC_DAC_STAT_UPDATES ) + { -// ***************************************************************** -/// \> Cycle 300, If IOP and RFM cards, check own data diagnostics -// ***************************************************************** - // Deal with the own-data bits on the VMIC 5565 rfm cards - if (cdsPciModules.rfmCount > 0) { - if (cycleNum >= HKP_RFM_CHK_CYCLE && cycleNum < (HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount)) { - int mod = cycleNum - HKP_RFM_CHK_CYCLE; - status = vmic5565CheckOwnDataRcv(mod); - if(!status) ipcErrBits |= 4 + (mod * 4); - } - if (cycleNum >= (HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount) && cycleNum < (HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount*2)) { - int mod = cycleNum - HKP_RFM_CHK_CYCLE - cdsPciModules.rfmCount; - vmic5565ResetOwnDataLight(mod); - } - if (cycleNum >= (HKP_RFM_CHK_CYCLE + 2*cdsPciModules.rfmCount) && cycleNum < (HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount*3)) { - int mod = cycleNum - HKP_RFM_CHK_CYCLE - cdsPciModules.rfmCount*2; - // Write data out to the RFM to trigger the light - ((volatile long *)(cdsPciModules.pci_rfm[mod]))[2] = 0; - } - } + pLocalEpics->epicsOutput.ovAccum = overflowAcc; + feStatus |= adc_status_update( &adcinfo ); + feStatus |= dac_status_update( &dacinfo ); + // If ADC channels not where they should be, we have no option but + // to exit from the RT code ie loops would be working with wrong + // input data. + if ( adcinfo.chanHop ) + { + pLocalEpics->epicsOutput.stateWord = FE_ERROR_ADC; + stop_working_threads = 1; + vmeDone = 1; + pLocalEpics->epicsOutput.fe_status = CHAN_HOP_ERROR; + continue; + } + } -// ***************************************************************** -/// \> Cycle 400 to 400 + numDacModules, write DAC heartbeat to AI chassis (only for 18 bit DAC modules) -// DAC WD Write for 18 bit DAC modules -// Check once per second on code cycle 400 to dac count -// Only one write per code cycle to reduce time -// ***************************************************************** - if (cycleNum >= HKP_DAC_WD_CLK && cycleNum < (HKP_DAC_WD_CLK + cdsPciModules.dacCount)) - { - if (cycleNum == HKP_DAC_WD_CLK) dacWatchDog ^= 1; - jj = cycleNum - HKP_DAC_WD_CLK; - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - volatile GSA_18BIT_DAC_REG *dac18bitPtr; - dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]); - if(iopDacEnable && !dacChanErr[jj]) - dac18bitPtr->digital_io_ports = (dacWatchDog | GSAO_18BIT_DIO_RW); - - } - if(cdsPciModules.dacType[jj] == GSC_20AO8) - { - volatile GSA_20BIT_DAC_REG *dac20bitPtr; - dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]); - if(iopDacEnable && !dacChanErr[jj]) - dac20bitPtr->digital_io_ports = (dacWatchDog | GSAO_20BIT_DIO_RW); - } - } + // ***************************************************************** + /// \> Cycle 300, If IOP and RFM cards, check own data diagnostics + // ***************************************************************** + // Deal with the own-data bits on the VMIC 5565 rfm cards + if ( cdsPciModules.rfmCount > 0 ) + { + if ( cycleNum >= HKP_RFM_CHK_CYCLE && + cycleNum < ( HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount ) ) + { + int mod = cycleNum - HKP_RFM_CHK_CYCLE; + status = vmic5565CheckOwnDataRcv( mod ); + if ( !status ) + ipcErrBits |= 4 + ( mod * 4 ); + } + if ( cycleNum >= ( HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount ) && + cycleNum < ( HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount * 2 ) ) + { + int mod = cycleNum - HKP_RFM_CHK_CYCLE - cdsPciModules.rfmCount; + vmic5565ResetOwnDataLight( mod ); + } + if ( cycleNum >= + ( HKP_RFM_CHK_CYCLE + 2 * cdsPciModules.rfmCount ) && + cycleNum < ( HKP_RFM_CHK_CYCLE + cdsPciModules.rfmCount * 3 ) ) + { + int mod = + cycleNum - HKP_RFM_CHK_CYCLE - cdsPciModules.rfmCount * 2; + // Write data out to the RFM to trigger the light + ( (volatile long*)( cdsPciModules.pci_rfm[ mod ] ) )[ 2 ] = 0; + } + } -// ***************************************************************** -/// \> Cycle 500 to 500 + numDacModules, read back watchdog from AI chassis (18 bit DAC only) -// AI Chassis WD CHECK for 18 bit DAC modules -// Check once per second on code cycle HKP_DAC_WD_CHK to dac count -// Only one read per code cycle to reduce time -// ***************************************************************** - if (cycleNum >= HKP_DAC_WD_CHK && cycleNum < (HKP_DAC_WD_CHK + cdsPciModules.dacCount)) - { - jj = cycleNum - HKP_DAC_WD_CHK; - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - static int dacWDread = 0; - volatile GSA_18BIT_DAC_REG *dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]); - dacWDread = dac18bitPtr->digital_io_ports; - if(((dacWDread >> 8) & 1) > 0) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_WD_BIT); - } - else - pLocalEpics->epicsOutput.statDac[jj] |= DAC_WD_BIT; - - } - if(cdsPciModules.dacType[jj] == GSC_20AO8) + // ***************************************************************** + /// \> Cycle 400 to 400 + numDacModules, write DAC heartbeat to AI + /// chassis (only for 18 bit DAC modules) + // DAC WD Write for 18 bit DAC modules + // Check once per second on code cycle 400 to dac count + // Only one write per code cycle to reduce time + // ***************************************************************** + if ( cycleNum >= HKP_DAC_WD_CLK && + cycleNum < ( HKP_DAC_WD_CLK + cdsPciModules.dacCount ) ) { - static int dacWDread = 0; - volatile GSA_20BIT_DAC_REG *dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]); - dacWDread = dac20bitPtr->digital_io_ports; - if(((dacWDread >> 8) & 1) > 0) - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_WD_BIT); - else - pLocalEpics->epicsOutput.statDac[jj] |= DAC_WD_BIT; - } - } + if ( cycleNum == HKP_DAC_WD_CLK ) + dacWatchDog ^= 1; + jj = cycleNum - HKP_DAC_WD_CLK; + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) + { + volatile GSA_18BIT_DAC_REG* dac18bitPtr; + dac18bitPtr = (volatile GSA_18BIT_DAC_REG*)( dacPtr[ jj ] ); + if ( iopDacEnable && !dacChanErr[ jj ] ) + dac18bitPtr->digital_io_ports = + ( dacWatchDog | GSAO_18BIT_DIO_RW ); + } + if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + volatile GSA_20BIT_DAC_REG* dac20bitPtr; + dac20bitPtr = (volatile GSA_20BIT_DAC_REG*)( dacPtr[ jj ] ); + if ( iopDacEnable && !dacChanErr[ jj ] ) + dac20bitPtr->digital_io_ports = + ( dacWatchDog | GSAO_20BIT_DIO_RW ); + } + } + + // ***************************************************************** + /// \> Cycle 500 to 500 + numDacModules, read back watchdog from AI + /// chassis (18 bit DAC only) + // AI Chassis WD CHECK for 18 bit DAC modules + // Check once per second on code cycle HKP_DAC_WD_CHK to dac count + // Only one read per code cycle to reduce time + // ***************************************************************** + if ( cycleNum >= HKP_DAC_WD_CHK && + cycleNum < ( HKP_DAC_WD_CHK + cdsPciModules.dacCount ) ) + { + jj = cycleNum - HKP_DAC_WD_CHK; + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) + { + static int dacWDread = 0; + volatile GSA_18BIT_DAC_REG* dac18bitPtr = + (volatile GSA_18BIT_DAC_REG*)( dacPtr[ jj ] ); + dacWDread = dac18bitPtr->digital_io_ports; + if ( ( ( dacWDread >> 8 ) & 1 ) > 0 ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_WD_BIT ); + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_WD_BIT; + } + if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + static int dacWDread = 0; + volatile GSA_20BIT_DAC_REG* dac20bitPtr = + (volatile GSA_20BIT_DAC_REG*)( dacPtr[ jj ] ); + dacWDread = dac20bitPtr->digital_io_ports; + if ( ( ( dacWDread >> 8 ) & 1 ) > 0 ) + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_WD_BIT ); + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_WD_BIT; + } + } // ***************************************************************** -/// \> Cycle 600 to 600 + numDacModules, Check DAC FIFO Sizes to determine if DAC modules are synched to code -/// - ---- 18bit DAC reads out FIFO size dirrectly, but 16bit module only has a 4 bit register -/// area for FIFO empty, quarter full, etc. So, to make these bits useful in 16 bit module, -/// code must set a proper FIFO size in map.c code. +/// \> Cycle 600 to 600 + numDacModules, Check DAC FIFO Sizes to determine if +/// DAC modules are synched to code +/// - ---- 18bit DAC reads out FIFO size dirrectly, but 16bit module only has a +/// 4 bit register area for FIFO empty, quarter full, etc. So, to make these +/// bits useful in 16 bit module, code must set a proper FIFO size in map.c +/// code. // This code runs once per second. // ***************************************************************** #ifndef NO_DAC_PRELOAD - if (cycleNum >= HKP_DAC_FIFO_CHK && cycleNum < (HKP_DAC_FIFO_CHK + cdsPciModules.dacCount)) - { - status = check_dac_buffers(cycleNum); - } - if (dacTimingError) feStatus |= FE_ERROR_DAC; + if ( cycleNum >= HKP_DAC_FIFO_CHK && + cycleNum < ( HKP_DAC_FIFO_CHK + cdsPciModules.dacCount ) ) + { + status = check_dac_buffers( cycleNum ); + } + if ( dacTimingError ) + feStatus |= FE_ERROR_DAC; #endif -// ***************************************************************** -// Update end of cycle information -// ***************************************************************** - // Capture end of cycle time. - rdtscll(cpuClock[CPU_TIME_CYCLE_END]); - - /// \> Compute code cycle time diag information. - timeinfo.cycleTime = (cpuClock[CPU_TIME_CYCLE_END] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - // Hold the max cycle time over the last 1 second - if(timeinfo.cycleTime > timeinfo.timeHold) { - timeinfo.timeHold = timeinfo.cycleTime; - timeinfo.timeHoldWhen = cycleNum; - } - // Hold the max cycle time since last diag reset - if(timeinfo.cycleTime > timeinfo.timeHoldMax) timeinfo.timeHoldMax = timeinfo.cycleTime; - adcinfo.adcHoldTime = (cpuClock[CPU_TIME_CYCLE_START] - adcinfo.adcTime)/CPURATE; - // Avoid calculating the max hold time for the first few seconds - if (cycleNum != 0 && (timeinfo.startGpsTime+3) < cycle_gps_time) { - if(adcinfo.adcHoldTime > adcinfo.adcHoldTimeMax) - adcinfo.adcHoldTimeMax = adcinfo.adcHoldTime; - if(adcinfo.adcHoldTime < adcinfo.adcHoldTimeMin) - adcinfo.adcHoldTimeMin = adcinfo.adcHoldTime; - adcinfo.adcHoldTimeAvg += adcinfo.adcHoldTime; - if (adcinfo.adcHoldTimeMax > adcinfo.adcHoldTimeEverMax) { - adcinfo.adcHoldTimeEverMax = adcinfo.adcHoldTimeMax; - adcinfo.adcHoldTimeEverMaxWhen = cycle_gps_time; - } - if (timeinfo.timeHoldMax > timeinfo.cpuTimeEverMax) { - timeinfo.cpuTimeEverMax = timeinfo.timeHoldMax; - timeinfo.cpuTimeEverMaxWhen = cycle_gps_time; - } - } - adcinfo.adcTime = cpuClock[CPU_TIME_CYCLE_START]; - // Calc the max time of one cycle of the user code - // For IOP, more interested in time to get thru ADC read code and send to slave apps - timeinfo.usrTime = (cpuClock[CPU_TIME_USR_START] - cpuClock[CPU_TIME_CYCLE_START])/CPURATE; - if(timeinfo.usrTime > timeinfo.usrHoldTime) timeinfo.usrHoldTime = timeinfo.usrTime; - - /// \> Update internal cycle counters - cycleNum += 1; + // ***************************************************************** + // Update end of cycle information + // ***************************************************************** + // Capture end of cycle time. + rdtscll( cpuClock[ CPU_TIME_CYCLE_END ] ); + + /// \> Compute code cycle time diag information. + timeinfo.cycleTime = ( cpuClock[ CPU_TIME_CYCLE_END ] - + cpuClock[ CPU_TIME_CYCLE_START ] ) / + CPURATE; + // Hold the max cycle time over the last 1 second + if ( timeinfo.cycleTime > timeinfo.timeHold ) + { + timeinfo.timeHold = timeinfo.cycleTime; + timeinfo.timeHoldWhen = cycleNum; + } + // Hold the max cycle time since last diag reset + if ( timeinfo.cycleTime > timeinfo.timeHoldMax ) + timeinfo.timeHoldMax = timeinfo.cycleTime; + adcinfo.adcHoldTime = + ( cpuClock[ CPU_TIME_CYCLE_START ] - adcinfo.adcTime ) / CPURATE; + // Avoid calculating the max hold time for the first few seconds + if ( cycleNum != 0 && ( timeinfo.startGpsTime + 3 ) < cycle_gps_time ) + { + if ( adcinfo.adcHoldTime > adcinfo.adcHoldTimeMax ) + adcinfo.adcHoldTimeMax = adcinfo.adcHoldTime; + if ( adcinfo.adcHoldTime < adcinfo.adcHoldTimeMin ) + adcinfo.adcHoldTimeMin = adcinfo.adcHoldTime; + adcinfo.adcHoldTimeAvg += adcinfo.adcHoldTime; + if ( adcinfo.adcHoldTimeMax > adcinfo.adcHoldTimeEverMax ) + { + adcinfo.adcHoldTimeEverMax = adcinfo.adcHoldTimeMax; + adcinfo.adcHoldTimeEverMaxWhen = cycle_gps_time; + } + if ( timeinfo.timeHoldMax > timeinfo.cpuTimeEverMax ) + { + timeinfo.cpuTimeEverMax = timeinfo.timeHoldMax; + timeinfo.cpuTimeEverMaxWhen = cycle_gps_time; + } + } + adcinfo.adcTime = cpuClock[ CPU_TIME_CYCLE_START ]; + // Calc the max time of one cycle of the user code + // For IOP, more interested in time to get thru ADC read code and send + // to slave apps + timeinfo.usrTime = ( cpuClock[ CPU_TIME_USR_START ] - + cpuClock[ CPU_TIME_CYCLE_START ] ) / + CPURATE; + if ( timeinfo.usrTime > timeinfo.usrHoldTime ) + timeinfo.usrHoldTime = timeinfo.usrTime; + + /// \> Update internal cycle counters + cycleNum += 1; #ifdef DIAG_TEST - if(pLocalEpics->epicsInput.bumpCycle != 0) { - cycleNum += pLocalEpics->epicsInput.bumpCycle; - pLocalEpics->epicsInput.bumpCycle = 0; - } + if ( pLocalEpics->epicsInput.bumpCycle != 0 ) + { + cycleNum += pLocalEpics->epicsInput.bumpCycle; + pLocalEpics->epicsInput.bumpCycle = 0; + } #endif - cycleNum %= CYCLE_PER_SECOND; - clock1Min += 1; - clock1Min %= CYCLE_PER_MINUTE; - if(subcycle == DAQ_CYCLE_CHANGE) - { - daqCycle = (daqCycle + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - if(!(daqCycle % 2)) pLocalEpics->epicsOutput.epicsSync = daqCycle; - } - if(subcycle == END_OF_DAQ_BLOCK) /*we have reached the 16Hz second barrier*/ - { - /* Reset the data cycle counter */ - subcycle = 0; - } else { - /* Increment the internal cycle counter */ - subcycle ++; - } - -/// \> If not exit request, then continue INFINITE LOOP ******* - } + cycleNum %= CYCLE_PER_SECOND; + clock1Min += 1; + clock1Min %= CYCLE_PER_MINUTE; + if ( subcycle == DAQ_CYCLE_CHANGE ) + { + daqCycle = ( daqCycle + 1 ) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; + if ( !( daqCycle % 2 ) ) + pLocalEpics->epicsOutput.epicsSync = daqCycle; + } + if ( subcycle == + END_OF_DAQ_BLOCK ) /*we have reached the 16Hz second barrier*/ + { + /* Reset the data cycle counter */ + subcycle = 0; + } + else + { + /* Increment the internal cycle counter */ + subcycle++; + } - // printf("exiting from fe_code()\n"); - pLocalEpics->epicsOutput.cpuMeter = 0; + /// \> If not exit request, then continue INFINITE LOOP ******* + } + // printf("exiting from fe_code()\n"); + pLocalEpics->epicsOutput.cpuMeter = 0; - /* System reset command received */ - return (void *)-1; + /* System reset command received */ + return (void*)-1; } diff --git a/src/fe/dolphin.c b/src/fe/dolphin.c index 4b53f84d3..82d931d93 100644 --- a/src/fe/dolphin.c +++ b/src/fe/dolphin.c @@ -1,15 +1,16 @@ /// @file dolphin.c /// @brief File containing the Dolphin functions. \n -/// @detail This file contains Dolphin init and cleanup routines for kernel module code. +/// @detail This file contains Dolphin init and cleanup routines for kernel +/// module code. /// @author R.Bork #include <genif.h> #include "commData3.h" -sci_l_segment_handle_t segment[4]; -sci_map_handle_t client_map_handle[4]; -sci_r_segment_handle_t remote_segment_handle[4]; -sci_device_info_t sci_dev_info[4]; +sci_l_segment_handle_t segment[ 4 ]; +sci_map_handle_t client_map_handle[ 4 ]; +sci_r_segment_handle_t remote_segment_handle[ 4 ]; +sci_device_info_t sci_dev_info[ 4 ]; /* @@ -23,143 +24,173 @@ R_OK, SR_HEARTBEAT_RECEIVED } session_cb_reason_t; */ -int32_t session_callback(session_cb_arg_t IN arg, - session_cb_reason_t IN reason, - session_cb_status_t IN status, - uint32_t IN target_node, - uint32_t IN local_adapter_number) { -/// @brief This function contains the required Dolphin callback routine. \n - // printkl("Session callback reason=%d status=%d target_node=%d\n", reason, status, target_node); - // if (reason == SR_OK) iop_rfm_valid = 1; - if (reason == SR_OK || status == SR_OK) iop_rfm_valid = 1; - else iop_rfm_valid = 0; - // This is being called when the one of the other nodes is prepared for shutdown - // :TODO: may need to check target_node == <our local node> - //if (reason == SR_DISABLED || reason == SR_LOST) iop_rfm_valid = 0; - return 0; +int32_t +session_callback( session_cb_arg_t IN arg, + session_cb_reason_t IN reason, + session_cb_status_t IN status, + uint32_t IN target_node, + uint32_t IN local_adapter_number ) +{ + /// @brief This function contains the required Dolphin callback routine. \n + // printkl("Session callback reason=%d status=%d target_node=%d\n", reason, + // status, target_node); if (reason == SR_OK) iop_rfm_valid = 1; + if ( reason == SR_OK || status == SR_OK ) + iop_rfm_valid = 1; + else + iop_rfm_valid = 0; + // This is being called when the one of the other nodes is prepared for + // shutdown :TODO: may need to check target_node == <our local node> + // if (reason == SR_DISABLED || reason == SR_LOST) iop_rfm_valid = 0; + return 0; } /// Function for Dolphin connection callback -int32_t connect_callback(void IN *arg, - sci_r_segment_handle_t IN remote_segment_handle, - uint32_t IN reason, uint32_t IN status) { - // printkl("Connect callback reason=%d status=%d\n", reason, status); - if (reason == 1) iop_rfm_valid = 1; - if (reason == 3) iop_rfm_valid = 0; - if (reason == 5) iop_rfm_valid = 1; - return 0; +int32_t +connect_callback( void IN* arg, + sci_r_segment_handle_t IN remote_segment_handle, + uint32_t IN reason, + uint32_t IN status ) +{ + // printkl("Connect callback reason=%d status=%d\n", reason, status); + if ( reason == 1 ) + iop_rfm_valid = 1; + if ( reason == 3 ) + iop_rfm_valid = 0; + if ( reason == 5 ) + iop_rfm_valid = 1; + return 0; } -int32_t create_segment_callback(void IN *arg, - sci_l_segment_handle_t IN local_segment_handle, - uint32_t IN reason, - uint32_t IN source_node, - uint32_t IN local_adapter_number) { - // printkl("Create segment callback reason=%d source_node=%d\n", reason, source_node); - return 0; +int32_t +create_segment_callback( void IN* arg, + sci_l_segment_handle_t IN local_segment_handle, + uint32_t IN reason, + uint32_t IN source_node, + uint32_t IN local_adapter_number ) +{ + // printkl("Create segment callback reason=%d source_node=%d\n", reason, + // source_node); + return 0; } int -init_dolphin(int modules) { - scierror_t err; - char *addr; - char *read_addr; - int ii; - cdsPciModules.dolphinCount = 0; - for(ii=0;ii<modules;ii++) { - err = sci_create_segment(NO_BINDING, - 0, - ii, - DIS_BROADCAST, - IPC_TOTAL_ALLOC_SIZE, - create_segment_callback, - 0, - &segment[ii]); - // printk("DIS segment alloc status %d\n", err); - if (err) return -1; - - err = sci_set_local_segment_available(segment[ii], 0); - // printk("DIS segment making available status %d\n", err); - if (err) { - sci_remove_segment(&segment[ii], 0); - return -1; - } - - err = sci_export_segment(segment[ii], 0, DIS_BROADCAST); - // printk("DIS segment export status %d\n", err); - if (err) { - sci_remove_segment(&segment[ii], 0); - return -1; - } - - read_addr = sci_local_kernel_virtual_address(segment[ii]); - if (read_addr == 0) { - // printk("DIS sci_local_kernel_virtual_address returned 0\n"); - sci_remove_segment(&segment[ii], 0); - return -1; - } else { - // printk("Dolphin memory read at 0x%p\n", read_addr); - cdsPciModules.dolphinRead[ii] = (volatile unsigned long *)read_addr; - } - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - - err = sci_connect_segment(NO_BINDING, - 4, // DIS_BROADCAST_NODEID_GROUP_ALL - 0, - 0, - ii, - DIS_BROADCAST, - connect_callback, - 0, - &remote_segment_handle[ii]); - // printk("DIS connect segment status %d\n", err); - if (err) { - sci_remove_segment(&segment[ii], 0); - return -1; - } - - // usleep(20000); - udelay(MAX_UDELAY); - udelay(MAX_UDELAY); - err = sci_map_segment(remote_segment_handle[ii], - DIS_BROADCAST, - 0, - IPC_TOTAL_ALLOC_SIZE, - &client_map_handle[ii]); - // printk("DIS segment mapping status %d\n", err); - if (err) { - sci_disconnect_segment(&remote_segment_handle[ii], 0); - sci_remove_segment(&segment[ii], 0); - return -1; - } - - addr = sci_kernel_virtual_address_of_mapping(client_map_handle[ii]); - if (addr == 0) { - // printk ("Got zero pointer from sci_kernel_virtual_address_of_mapping\n"); - sci_disconnect_segment(&remote_segment_handle[ii], 0); - sci_remove_segment(&segment[ii], 0); - return -1; - } else { - // printk ("Dolphin memory write at 0x%p\n", addr); - cdsPciModules.dolphinWrite[ii] = (volatile unsigned long *)addr; - } - - sci_register_session_cb(ii,0,session_callback,0); - cdsPciModules.dolphinCount += 1; -} +init_dolphin( int modules ) +{ + scierror_t err; + char* addr; + char* read_addr; + int ii; + cdsPciModules.dolphinCount = 0; + for ( ii = 0; ii < modules; ii++ ) + { + err = sci_create_segment( NO_BINDING, + 0, + ii, + DIS_BROADCAST, + IPC_TOTAL_ALLOC_SIZE, + create_segment_callback, + 0, + &segment[ ii ] ); + // printk("DIS segment alloc status %d\n", err); + if ( err ) + return -1; - return 0; -} + err = sci_set_local_segment_available( segment[ ii ], 0 ); + // printk("DIS segment making available status %d\n", err); + if ( err ) + { + sci_remove_segment( &segment[ ii ], 0 ); + return -1; + } + + err = sci_export_segment( segment[ ii ], 0, DIS_BROADCAST ); + // printk("DIS segment export status %d\n", err); + if ( err ) + { + sci_remove_segment( &segment[ ii ], 0 ); + return -1; + } + + read_addr = sci_local_kernel_virtual_address( segment[ ii ] ); + if ( read_addr == 0 ) + { + // printk("DIS sci_local_kernel_virtual_address returned 0\n"); + sci_remove_segment( &segment[ ii ], 0 ); + return -1; + } + else + { + // printk("Dolphin memory read at 0x%p\n", read_addr); + cdsPciModules.dolphinRead[ ii ] = + (volatile unsigned long*)read_addr; + } + udelay( MAX_UDELAY ); + udelay( MAX_UDELAY ); + + err = sci_connect_segment( NO_BINDING, + 4, // DIS_BROADCAST_NODEID_GROUP_ALL + 0, + 0, + ii, + DIS_BROADCAST, + connect_callback, + 0, + &remote_segment_handle[ ii ] ); + // printk("DIS connect segment status %d\n", err); + if ( err ) + { + sci_remove_segment( &segment[ ii ], 0 ); + return -1; + } -void -finish_dolphin(void) { -int ii; - for(ii=0;ii<cdsPciModules.dolphinCount;ii++) { - sci_unmap_segment(&client_map_handle[ii], 0); - sci_disconnect_segment(&remote_segment_handle[ii], 0); - sci_unexport_segment(segment[ii], 0, 0); - sci_remove_segment(&segment[ii], 0); - sci_cancel_session_cb(ii, 0); + // usleep(20000); + udelay( MAX_UDELAY ); + udelay( MAX_UDELAY ); + err = sci_map_segment( remote_segment_handle[ ii ], + DIS_BROADCAST, + 0, + IPC_TOTAL_ALLOC_SIZE, + &client_map_handle[ ii ] ); + // printk("DIS segment mapping status %d\n", err); + if ( err ) + { + sci_disconnect_segment( &remote_segment_handle[ ii ], 0 ); + sci_remove_segment( &segment[ ii ], 0 ); + return -1; + } + + addr = sci_kernel_virtual_address_of_mapping( client_map_handle[ ii ] ); + if ( addr == 0 ) + { + // printk ("Got zero pointer from + // sci_kernel_virtual_address_of_mapping\n"); + sci_disconnect_segment( &remote_segment_handle[ ii ], 0 ); + sci_remove_segment( &segment[ ii ], 0 ); + return -1; + } + else + { + // printk ("Dolphin memory write at 0x%p\n", addr); + cdsPciModules.dolphinWrite[ ii ] = (volatile unsigned long*)addr; + } + + sci_register_session_cb( ii, 0, session_callback, 0 ); + cdsPciModules.dolphinCount += 1; + } + + return 0; } + +void +finish_dolphin( void ) +{ + int ii; + for ( ii = 0; ii < cdsPciModules.dolphinCount; ii++ ) + { + sci_unmap_segment( &client_map_handle[ ii ], 0 ); + sci_disconnect_segment( &remote_segment_handle[ ii ], 0 ); + sci_unexport_segment( segment[ ii ], 0, 0 ); + sci_remove_segment( &segment[ ii ], 0 ); + sci_cancel_session_cb( ii, 0 ); + } } diff --git a/src/fe/map.c b/src/fe/map.c index a0e64cc5d..dece46c97 100644 --- a/src/fe/map.c +++ b/src/fe/map.c @@ -29,393 +29,460 @@ #include <drv/spectracomGPS.c> #include <drv/gsc18ai32.c> - - // ***************************************************************************** -/// \brief Patch to properly handle PEX PCIe chip for newer (PCIe) General Standards +/// \brief Patch to properly handle PEX PCIe chip for newer (PCIe) General +/// Standards ///< DAC modules ie those that are integrated PCIe boards vs. earlier versions ///< built with carrier boards. \n This is extracted from code provided by GSC.. // ***************************************************************************** -void set_8111_prefetch(struct pci_dev *dacdev) { - struct pci_dev *dev = dacdev->bus->self; +void +set_8111_prefetch( struct pci_dev* dacdev ) +{ + struct pci_dev* dev = dacdev->bus->self; - printk("set_8111_prefetch: subsys=0x%x; vendor=0x%x\n", dev->device, dev->vendor); - if ((dev->device == 0x8111) && (dev->vendor == PLX_VID)) { - unsigned int reg; - // Handle PEX 8111 setup, enable prefetch, set pref size to 64 - // These numbers come from reverse engineering the GSC pxe8111 driver - // and using their prefetch program to enable the prefetch and set pref size to 64 - pci_write_config_dword(dev,132, 72); - pci_read_config_dword(dev,136, ®); - pci_write_config_dword(dev,136, reg); - pci_write_config_dword(dev,132, 72); - pci_read_config_dword(dev,136, ®); - pci_write_config_dword(dev,136, reg | 1); - pci_write_config_dword(dev,132, 12); - pci_read_config_dword(dev,136, ®); - pci_write_config_dword(dev,136, reg | 0x8000000); - } + printk( "set_8111_prefetch: subsys=0x%x; vendor=0x%x\n", + dev->device, + dev->vendor ); + if ( ( dev->device == 0x8111 ) && ( dev->vendor == PLX_VID ) ) + { + unsigned int reg; + // Handle PEX 8111 setup, enable prefetch, set pref size to 64 + // These numbers come from reverse engineering the GSC pxe8111 driver + // and using their prefetch program to enable the prefetch and set pref + // size to 64 + pci_write_config_dword( dev, 132, 72 ); + pci_read_config_dword( dev, 136, ® ); + pci_write_config_dword( dev, 136, reg ); + pci_write_config_dword( dev, 132, 72 ); + pci_read_config_dword( dev, 136, ® ); + pci_write_config_dword( dev, 136, reg | 1 ); + pci_write_config_dword( dev, 132, 12 ); + pci_read_config_dword( dev, 136, ® ); + pci_write_config_dword( dev, 136, reg | 0x8000000 ); + } } // ***************************************************************************** -/// Routine to find PCI modules and call the appropriate driver initialization software. +/// Routine to find PCI modules and call the appropriate driver initialization +/// software. // ***************************************************************************** -int mapPciModules(CDS_HARDWARE *pCds) +int +mapPciModules( CDS_HARDWARE* pCds ) { - static struct pci_dev *dacdev; - int status; - int i; - int modCount = 0; + static struct pci_dev* dacdev; + int status; + int i; + int modCount = 0; #ifndef ADC_SLAVE - int fast_adc_cnt = 0; - int adc_cnt = 0; + int fast_adc_cnt = 0; + int adc_cnt = 0; #endif - int dac_cnt = 0; - int dac_18bit_cnt = 0; - int dac_20bit_cnt = 0; - int bo_cnt = 0; - int use_it; + int dac_cnt = 0; + int dac_18bit_cnt = 0; + int dac_20bit_cnt = 0; + int bo_cnt = 0; + int use_it; - dacdev = NULL; - status = 0; + dacdev = NULL; + status = 0; - // Search system for any module with PLX-9056 and PLX id - while((dacdev = pci_get_device(PLX_VID, PLX_TID, dacdev))) { - // Check if this is an 18bit DAC from General Standards - if ((dacdev->subsystem_device == DAC_18BIT_SS_ID) && (dacdev->subsystem_vendor == PLX_VID)) - { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == GSC_18AO8 - && pCds->cards_used[i].instance == dac_18bit_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("18-bit dac card on bus %x; device %x\n", + // Search system for any module with PLX-9056 and PLX id + while ( ( dacdev = pci_get_device( PLX_VID, PLX_TID, dacdev ) ) ) + { + // Check if this is an 18bit DAC from General Standards + if ( ( dacdev->subsystem_device == DAC_18BIT_SS_ID ) && + ( dacdev->subsystem_vendor == PLX_VID ) ) + { + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == GSC_18AO8 && + pCds->cards_used[ i ].instance == dac_18bit_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "18-bit dac card on bus %x; device %x\n", dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = gsc18ao8Init(pCds,dacdev); - modCount ++; - } - dac_18bit_cnt++; - } - // Check if this is an 20bit DAC from General Standards - if ((dacdev->subsystem_device == DAC_20BIT_SS_ID) && (dacdev->subsystem_vendor == PLX_VID)) - { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == GSC_20AO8 - && pCds->cards_used[i].instance == dac_20bit_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("20-bit dac card on bus %x; device %x\n", + PCI_SLOT( dacdev->devfn ) ); + status = gsc18ao8Init( pCds, dacdev ); + modCount++; + } + dac_18bit_cnt++; + } + // Check if this is an 20bit DAC from General Standards + if ( ( dacdev->subsystem_device == DAC_20BIT_SS_ID ) && + ( dacdev->subsystem_vendor == PLX_VID ) ) + { + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == GSC_20AO8 && + pCds->cards_used[ i ].instance == dac_20bit_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "20-bit dac card on bus %x; device %x\n", dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = gsc20ao8Init(pCds,dacdev); - modCount ++; - } - dac_20bit_cnt++; - } - // if found, check if it is a DAC module - if((dacdev->subsystem_device == DAC_SS_ID) && (dacdev->subsystem_vendor == PLX_VID)) + PCI_SLOT( dacdev->devfn ) ); + status = gsc20ao8Init( pCds, dacdev ); + modCount++; + } + dac_20bit_cnt++; + } + // if found, check if it is a DAC module + if ( ( dacdev->subsystem_device == DAC_SS_ID ) && + ( dacdev->subsystem_vendor == PLX_VID ) ) { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* printk("DAC card on bus %x; device %x prim %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn), - dacdev->bus->secondary); - */ - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == GSC_16AO16 - && pCds->cards_used[i].instance == dac_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("dac card on bus %x; device %x\n", + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* printk("DAC card on bus %x; device %x prim %x\n", + dacdev->bus->number, + PCI_SLOT(dacdev->devfn), + dacdev->bus->secondary); + */ + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == GSC_16AO16 && + pCds->cards_used[ i ].instance == dac_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "dac card on bus %x; device %x\n", dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = gsc16ao16Init(pCds,dacdev); - modCount ++; - } - dac_cnt++; + PCI_SLOT( dacdev->devfn ) ); + status = gsc16ao16Init( pCds, dacdev ); + modCount++; + } + dac_cnt++; } - // if found, check if it is an ADC module + // if found, check if it is an ADC module #ifndef ADC_SLAVE - if((dacdev->subsystem_device == ADC_SS_ID) && (dacdev->subsystem_vendor == PLX_VID)) - { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* printk("ADC card on bus %x; device %x prim %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn), - dacdev->bus->secondary); - */ - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == GSC_16AI64SSA - && pCds->cards_used[i].instance == adc_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - /*printk("adc card on bus %x; device %x prim %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn), - dacdev->bus->secondary); - */ - status = gsc16ai64Init(pCds,dacdev); - modCount ++; - } - adc_cnt++; - } + if ( ( dacdev->subsystem_device == ADC_SS_ID ) && + ( dacdev->subsystem_vendor == PLX_VID ) ) + { + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* printk("ADC card on bus %x; device %x prim %x\n", + dacdev->bus->number, + PCI_SLOT(dacdev->devfn), + dacdev->bus->secondary); + */ + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == GSC_16AI64SSA && + pCds->cards_used[ i ].instance == adc_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + /*printk("adc card on bus %x; device %x prim %x\n", + dacdev->bus->number, + PCI_SLOT(dacdev->devfn), + dacdev->bus->secondary); + */ + status = gsc16ai64Init( pCds, dacdev ); + modCount++; + } + adc_cnt++; + } // if found, check if it is a Fast ADC module - // TODO: for the time of testing of the 18-bit board, it returned same PCI device number as the 16-bit fast GS board - // This number will most likely change in the future. - if((dacdev->subsystem_device == ADC_18AI32_SS_ID) && (dacdev->subsystem_vendor == PLX_VID)) + // TODO: for the time of testing of the 18-bit board, it returned same + // PCI device number as the 16-bit fast GS board This number will most + // likely change in the future. + if ( ( dacdev->subsystem_device == ADC_18AI32_SS_ID ) && + ( dacdev->subsystem_vendor == PLX_VID ) ) { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == GSC_18AI32SSC1M - && pCds->cards_used[i].instance == fast_adc_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("fast adc card on bus %x; device %x\n", + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == GSC_18AI32SSC1M && + pCds->cards_used[ i ].instance == fast_adc_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "fast adc card on bus %x; device %x\n", dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = gsc18ai32Init(pCds, dacdev); - modCount ++; - } - fast_adc_cnt++; + PCI_SLOT( dacdev->devfn ) ); + status = gsc18ai32Init( pCds, dacdev ); + modCount++; + } + fast_adc_cnt++; } - } + } #endif - dacdev = NULL; - status = 0; - bo_cnt = 0; - // Search for ACCESS PCI-DIO modules - while((dacdev = pci_get_device(ACC_VID, ACC_TID, dacdev))) { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == ACS_24DIO - && pCds->cards_used[i].instance == bo_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("Access 24 BIO card on bus %x; device %x vendor 0x%x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn), - dacdev->device); - status = accesDio24Init(pCds,dacdev); - modCount ++; - } - bo_cnt ++; - } + dacdev = NULL; + status = 0; + bo_cnt = 0; + // Search for ACCESS PCI-DIO modules + while ( ( dacdev = pci_get_device( ACC_VID, ACC_TID, dacdev ) ) ) + { + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == ACS_24DIO && + pCds->cards_used[ i ].instance == bo_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "Access 24 BIO card on bus %x; device %x vendor 0x%x\n", + dacdev->bus->number, + PCI_SLOT( dacdev->devfn ), + dacdev->device ); + status = accesDio24Init( pCds, dacdev ); + modCount++; + } + bo_cnt++; + } - dacdev = NULL; - status = 0; - bo_cnt = 0; - // Search for ACCESS PCI-IIRO-8 isolated I/O modules - while((dacdev = pci_get_device(ACC_VID, PCI_ANY_ID, dacdev))) { - if (dacdev->device != ACC_IIRO_TID && dacdev->device != ACC_IIRO_TID_OLD) - continue; - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == ACS_8DIO - && pCds->cards_used[i].instance == bo_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("Access 8 BIO card on bus %x; device %x vendor 0x%x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn), - dacdev->device); - status = accesIiro8Init(pCds,dacdev); - modCount ++; - } - bo_cnt ++; - } - - dacdev = NULL; - status = 0; - bo_cnt = 0; - // Search for ACCESS PCI-IIRO-16 isolated I/O modules - while((dacdev = pci_get_device(ACC_VID, PCI_ANY_ID, dacdev))) { - if (dacdev->device != ACC_IIRO_TID16 && dacdev->device != ACC_IIRO_TID16_OLD) - continue; - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == ACS_16DIO - && pCds->cards_used[i].instance == bo_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("Access BIO-16 card on bus %x; device %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = accesIiro16Init(pCds,dacdev); - modCount ++; - } - bo_cnt ++; - } + dacdev = NULL; + status = 0; + bo_cnt = 0; + // Search for ACCESS PCI-IIRO-8 isolated I/O modules + while ( ( dacdev = pci_get_device( ACC_VID, PCI_ANY_ID, dacdev ) ) ) + { + if ( dacdev->device != ACC_IIRO_TID && + dacdev->device != ACC_IIRO_TID_OLD ) + continue; + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == ACS_8DIO && + pCds->cards_used[ i ].instance == bo_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "Access 8 BIO card on bus %x; device %x vendor 0x%x\n", + dacdev->bus->number, + PCI_SLOT( dacdev->devfn ), + dacdev->device ); + status = accesIiro8Init( pCds, dacdev ); + modCount++; + } + bo_cnt++; + } - dacdev = NULL; - status = 0; - bo_cnt = 0; + dacdev = NULL; + status = 0; + bo_cnt = 0; + // Search for ACCESS PCI-IIRO-16 isolated I/O modules + while ( ( dacdev = pci_get_device( ACC_VID, PCI_ANY_ID, dacdev ) ) ) + { + if ( dacdev->device != ACC_IIRO_TID16 && + dacdev->device != ACC_IIRO_TID16_OLD ) + continue; + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == ACS_16DIO && + pCds->cards_used[ i ].instance == bo_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "Access BIO-16 card on bus %x; device %x\n", + dacdev->bus->number, + PCI_SLOT( dacdev->devfn ) ); + status = accesIiro16Init( pCds, dacdev ); + modCount++; + } + bo_cnt++; + } - // Search for Contec C_DIO_6464L_PE isolated I/O modules - while((dacdev = pci_get_device(CONTEC_VID, C_DIO_6464L_PE, dacdev))) { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == CON_6464DIO - && (pCds->cards_used[i].instance * 2) == bo_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("Contec 6464 DIO card on bus %x; device %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = contec6464Init(pCds,dacdev); - modCount ++; - modCount ++; - } - bo_cnt ++; - bo_cnt ++; - } + dacdev = NULL; + status = 0; + bo_cnt = 0; + // Search for Contec C_DIO_6464L_PE isolated I/O modules + while ( ( dacdev = pci_get_device( CONTEC_VID, C_DIO_6464L_PE, dacdev ) ) ) + { + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == CON_6464DIO && + ( pCds->cards_used[ i ].instance * 2 ) == bo_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "Contec 6464 DIO card on bus %x; device %x\n", + dacdev->bus->number, + PCI_SLOT( dacdev->devfn ) ); + status = contec6464Init( pCds, dacdev ); + modCount++; + modCount++; + } + bo_cnt++; + bo_cnt++; + } - dacdev = NULL; - status = 0; - bo_cnt = 0; + dacdev = NULL; + status = 0; + bo_cnt = 0; - // Search for Contec C_DIO_1616L_PE isolated I/O modules - while((dacdev = pci_get_device(CONTEC_VID, C_DIO_1616L_PE, dacdev))) { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == CON_1616DIO - && pCds->cards_used[i].instance == bo_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("Contec 1616 DIO card on bus %x; device %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = contec1616Init(pCds,dacdev); - modCount ++; - } - bo_cnt ++; - } + // Search for Contec C_DIO_1616L_PE isolated I/O modules + while ( ( dacdev = pci_get_device( CONTEC_VID, C_DIO_1616L_PE, dacdev ) ) ) + { + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == CON_1616DIO && + pCds->cards_used[ i ].instance == bo_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "Contec 1616 DIO card on bus %x; device %x\n", + dacdev->bus->number, + PCI_SLOT( dacdev->devfn ) ); + status = contec1616Init( pCds, dacdev ); + modCount++; + } + bo_cnt++; + } - dacdev = NULL; - status = 0; - bo_cnt = 0; + dacdev = NULL; + status = 0; + bo_cnt = 0; - // Search for Contec C_DO_32L_PE isolated I/O modules - while((dacdev = pci_get_device(CONTEC_VID, C_DO_32L_PE, dacdev))) { - use_it = 0; - if (pCds->cards) { - use_it = 0; - /* See if ought to use this one or not */ - for (i = 0; i < pCds->cards; i++) { - if (pCds->cards_used[i].type == CON_32DO - && pCds->cards_used[i].instance == bo_cnt) { - use_it = 1; - break; - } - } - } - if (use_it) { - printk("Contec BO card on bus %x; device %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = contec32OutInit(pCds,dacdev); - modCount ++; - } - bo_cnt ++; - } + // Search for Contec C_DO_32L_PE isolated I/O modules + while ( ( dacdev = pci_get_device( CONTEC_VID, C_DO_32L_PE, dacdev ) ) ) + { + use_it = 0; + if ( pCds->cards ) + { + use_it = 0; + /* See if ought to use this one or not */ + for ( i = 0; i < pCds->cards; i++ ) + { + if ( pCds->cards_used[ i ].type == CON_32DO && + pCds->cards_used[ i ].instance == bo_cnt ) + { + use_it = 1; + break; + } + } + } + if ( use_it ) + { + printk( "Contec BO card on bus %x; device %x\n", + dacdev->bus->number, + PCI_SLOT( dacdev->devfn ) ); + status = contec32OutInit( pCds, dacdev ); + modCount++; + } + bo_cnt++; + } - dacdev = NULL; - status = 0; + dacdev = NULL; + status = 0; - for (i = 0; i < MAX_RFM_MODULES; i++) { - pCds->pci_rfm[i] = 0; - } + for ( i = 0; i < MAX_RFM_MODULES; i++ ) + { + pCds->pci_rfm[ i ] = 0; + } #ifndef RFM_VIA_PCIE - // Search system for 5565 VMIC RFM modules - while((dacdev = pci_get_device(VMIC_VID, VMIC_TID, dacdev))) { - printk("5565 RFM card on bus %x; device %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = vmic5565Init(pCds,dacdev); - modCount ++; - } + // Search system for 5565 VMIC RFM modules + while ( ( dacdev = pci_get_device( VMIC_VID, VMIC_TID, dacdev ) ) ) + { + printk( "5565 RFM card on bus %x; device %x\n", + dacdev->bus->number, + PCI_SLOT( dacdev->devfn ) ); + status = vmic5565Init( pCds, dacdev ); + modCount++; + } #endif - dacdev = NULL; - status = 0; - pCds->gps = 0; - pCds->gpsType = 0; - // Look for Symmetricom GPS board + dacdev = NULL; + status = 0; + pCds->gps = 0; + pCds->gpsType = 0; + // Look for Symmetricom GPS board #if 0 if ((dacdev = pci_get_device(SYMCOM_VID, SYMCOM_BC635_TID, dacdev))) { printk("Symmetricom GPS card on bus %x; device %x\n", @@ -428,19 +495,21 @@ int mapPciModules(CDS_HARDWARE *pCds) } } #endif - dacdev = NULL; - status = 0; - // Look for TSYNC GPS board - if ((dacdev = pci_get_device(TSYNC_VID, TSYNC_TID, dacdev))) { - printk("TSYNC GPS card on bus %x; device %x\n", - dacdev->bus->number, - PCI_SLOT(dacdev->devfn)); - status = spectracomGpsInit(pCds,dacdev); - if (status == 0) { - // GPS board initialized and mapped - modCount ++; - } - } + dacdev = NULL; + status = 0; + // Look for TSYNC GPS board + if ( ( dacdev = pci_get_device( TSYNC_VID, TSYNC_TID, dacdev ) ) ) + { + printk( "TSYNC GPS card on bus %x; device %x\n", + dacdev->bus->number, + PCI_SLOT( dacdev->devfn ) ); + status = spectracomGpsInit( pCds, dacdev ); + if ( status == 0 ) + { + // GPS board initialized and mapped + modCount++; + } + } - return(modCount); + return ( modCount ); } diff --git a/src/fe/moduleLoadApp.c b/src/fe/moduleLoadApp.c index 968a10620..ca1399835 100644 --- a/src/fe/moduleLoadApp.c +++ b/src/fe/moduleLoadApp.c @@ -6,382 +6,421 @@ #include <linux/spinlock_types.h> // These externs and "16" need to go to a header file (mbuf.h) -extern void *kmalloc_area[16]; -extern int mbuf_allocate_area(char *name, int size, struct file *file); -extern void *fe_start_app(void *arg); -extern char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers +extern void* kmalloc_area[ 16 ]; +extern int mbuf_allocate_area( char* name, int size, struct file* file ); +extern void* fe_start_app( void* arg ); +extern char daqArea[ 2 * DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers - -// MAIN routine: Code starting point **************************************************************** +// MAIN routine: Code starting point +// **************************************************************** extern int need_to_load_IOP_first; -extern void set_fe_code_idle(void *(*ptr)(void *), unsigned int cpu); -extern void msleep(unsigned int); -struct task_struct *sthread; +extern void set_fe_code_idle( void* ( *ptr )(void*), unsigned int cpu ); +extern void msleep( unsigned int ); +struct task_struct* sthread; #include "moduleLoadCommon.c" /// Startup function for initialization of kernel module. -int rt_fe_init (void) +int +rt_fe_init( void ) { - int status; - int ii,jj,kk; /// @param ii,jj,kk default loop counters - char fname[128]; /// @param fname[128] Name of shared mem area to allocate for DAQ data - int cards; /// @param cards Number of PCIe cards found on bus - int adcCnt; /// @param adcCnt Number of ADC cards found by slave model. - int dacCnt; /// @param dacCnt Number of 16bit DAC cards found by slave model. - int dac18Cnt; /// @param dac18Cnt Number of 18bit DAC cards found by slave model. - int dac20Cnt; /// @param dac20Cnt Number of 20bit DAC cards found by slave model. - int doCnt; /// @param doCnt Total number of digital I/O cards found by slave model. - int do32Cnt; /// @param do32Cnt Total number of Contec 32 bit DIO cards found by slave model. - int doIIRO16Cnt; /// @param doIIRO16Cnt Total number of Acces I/O 16 bit relay cards found by slave model. - int doIIRO8Cnt; /// @param doIIRO8Cnt Total number of Acces I/O 8 bit relay cards found by slave model. - int cdo64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit output sections mapped by slave model. - int cdi64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit input sections mapped by slave model. - int ret; /// @param ret Return value from various Malloc calls to allocate memory. - int cnt; - extern int cpu_down(unsigned int); /// @param cpu_down CPU shutdown call. - extern int is_cpu_taken_by_rcg_model(unsigned int cpu); /// @param is_cpu_taken_by_rcg_model Check to verify CPU availability for shutdown. - - kk = 0; + int status; + int ii, jj, kk; /// @param ii,jj,kk default loop counters + char fname[ 128 ]; /// @param fname[128] Name of shared mem area to allocate + /// for DAQ data + int cards; /// @param cards Number of PCIe cards found on bus + int adcCnt; /// @param adcCnt Number of ADC cards found by slave model. + int dacCnt; /// @param dacCnt Number of 16bit DAC cards found by slave + /// model. + int dac18Cnt; /// @param dac18Cnt Number of 18bit DAC cards found by slave + /// model. + int dac20Cnt; /// @param dac20Cnt Number of 20bit DAC cards found by slave + /// model. + int doCnt; /// @param doCnt Total number of digital I/O cards found by slave + /// model. + int do32Cnt; /// @param do32Cnt Total number of Contec 32 bit DIO cards + /// found by slave model. + int doIIRO16Cnt; /// @param doIIRO16Cnt Total number of Acces I/O 16 bit + /// relay cards found by slave model. + int doIIRO8Cnt; /// @param doIIRO8Cnt Total number of Acces I/O 8 bit relay + /// cards found by slave model. + int cdo64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit + /// output sections mapped by slave model. + int cdi64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit + /// input sections mapped by slave model. + int ret; /// @param ret Return value from various Malloc calls to allocate + /// memory. + int cnt; + extern int cpu_down( unsigned int ); /// @param cpu_down CPU shutdown call. + extern int is_cpu_taken_by_rcg_model( + unsigned int cpu ); /// @param is_cpu_taken_by_rcg_model Check to verify + /// CPU availability for shutdown. + + kk = 0; #ifdef SPECIFIC_CPU #define CPUID SPECIFIC_CPU -#else -#define CPUID 1 +#else +#define CPUID 1 #endif #ifndef NO_CPU_SHUTDOWN - // See if our CPU core is free - if (is_cpu_taken_by_rcg_model(CPUID)) { - printk(KERN_ALERT "Error: CPU %d already taken\n", CPUID); - return -1; - } + // See if our CPU core is free + if ( is_cpu_taken_by_rcg_model( CPUID ) ) + { + printk( KERN_ALERT "Error: CPU %d already taken\n", CPUID ); + return -1; + } #endif - need_to_load_IOP_first = 0; - - jj = 0; - -// Allocate EPICS shmem area - ret = mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0); - if (ret < 0) { - printk("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _epics_shm = (unsigned char *)(kmalloc_area[ret]); -// Allocate IPC shmem area - ret = mbuf_allocate_area("ipc", 16*1024*1024, 0); - if (ret < 0) { - printk("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); - return -1; - } - _ipc_shm = (unsigned char *)(kmalloc_area[ret]); - -// Point to IOP/APP comms shmem area - ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000); - -// Allocate DAQ shmem area - sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER); - ret = mbuf_allocate_area(fname, 64*1024*1024, 0); - if (ret < 0) { - printk("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _daq_shm = (unsigned char *)(kmalloc_area[ret]); - daqPtr = (struct rmIpcStr *) _daq_shm; - - // Find and initialize all PCI I/O modules ******************************************************* - // Following I/O card info is from feCode - cards = sizeof(cards_used)/sizeof(cards_used[0]); - cdsPciModules.cards = cards; - cdsPciModules.cards_used = cards_used; - //return -1; - cdsPciModules.adcCount = 0; - cdsPciModules.dacCount = 0; - cdsPciModules.dioCount = 0; - cdsPciModules.doCount = 0; - -// If running as a slave process, I/O card information is via ipc shared memory - status = 0; - adcCnt = 0; - dacCnt = 0; - dac18Cnt = 0; - dac20Cnt = 0; - doCnt = 0; - do32Cnt = 0; - cdo64Cnt = 0; - cdi64Cnt = 0; - doIIRO16Cnt = 0; - doIIRO8Cnt = 0; - - // Have to search thru all cards and find desired instance for application - // Master will map ADC cards first, then DAC and finally DIO - for(ii=0;ii<ioMemData->totalCards;ii++) - { - for(jj=0;jj<cards;jj++) - { - switch(ioMemData->model[ii]) - { - case GSC_16AI64SSA: - if((cdsPciModules.cards_used[jj].type == GSC_16AI64SSA) && - (cdsPciModules.cards_used[jj].instance == adcCnt)) - { - kk = cdsPciModules.adcCount; - cdsPciModules.adcType[kk] = GSC_16AI64SSA; - cdsPciModules.adcConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.adcCount ++; - status ++; - } - break; - case GSC_16AO16: - if((cdsPciModules.cards_used[jj].type == GSC_16AO16) && - (cdsPciModules.cards_used[jj].instance == dacCnt)) - { - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_16AO16; - cdsPciModules.dacConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.pci_dac[kk] = (long)(ioMemData->iodata[ii]); - cdsPciModules.dacCount ++; - status ++; - } - break; - case GSC_18AO8: - if((cdsPciModules.cards_used[jj].type == GSC_18AO8) && - (cdsPciModules.cards_used[jj].instance == dac18Cnt)) - { - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_18AO8; - cdsPciModules.dacConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.pci_dac[kk] = (long)(ioMemData->iodata[ii]); - cdsPciModules.dacCount ++; - status ++; - } - break; + need_to_load_IOP_first = 0; + + jj = 0; + + // Allocate EPICS shmem area + ret = mbuf_allocate_area( SYSTEM_NAME_STRING_LOWER, 64 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printk( "mbuf_allocate_area() failed; ret = %d\n", ret ); + return -1; + } + _epics_shm = (unsigned char*)( kmalloc_area[ ret ] ); + // Allocate IPC shmem area + ret = mbuf_allocate_area( "ipc", 16 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printk( "mbuf_allocate_area(ipc) failed; ret = %d\n", ret ); + return -1; + } + _ipc_shm = (unsigned char*)( kmalloc_area[ ret ] ); + + // Point to IOP/APP comms shmem area + ioMemData = (IO_MEM_DATA*)( _ipc_shm + 0x4000 ); + + // Allocate DAQ shmem area + sprintf( fname, "%s_daq", SYSTEM_NAME_STRING_LOWER ); + ret = mbuf_allocate_area( fname, 64 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printk( "mbuf_allocate_area() failed; ret = %d\n", ret ); + return -1; + } + _daq_shm = (unsigned char*)( kmalloc_area[ ret ] ); + daqPtr = (struct rmIpcStr*)_daq_shm; + + // Find and initialize all PCI I/O modules + // ******************************************************* Following I/O + // card info is from feCode + cards = sizeof( cards_used ) / sizeof( cards_used[ 0 ] ); + cdsPciModules.cards = cards; + cdsPciModules.cards_used = cards_used; + // return -1; + cdsPciModules.adcCount = 0; + cdsPciModules.dacCount = 0; + cdsPciModules.dioCount = 0; + cdsPciModules.doCount = 0; + + // If running as a slave process, I/O card information is via ipc shared + // memory + status = 0; + adcCnt = 0; + dacCnt = 0; + dac18Cnt = 0; + dac20Cnt = 0; + doCnt = 0; + do32Cnt = 0; + cdo64Cnt = 0; + cdi64Cnt = 0; + doIIRO16Cnt = 0; + doIIRO8Cnt = 0; + + // Have to search thru all cards and find desired instance for application + // Master will map ADC cards first, then DAC and finally DIO + for ( ii = 0; ii < ioMemData->totalCards; ii++ ) + { + for ( jj = 0; jj < cards; jj++ ) + { + switch ( ioMemData->model[ ii ] ) + { + case GSC_16AI64SSA: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_16AI64SSA ) && + ( cdsPciModules.cards_used[ jj ].instance == adcCnt ) ) + { + kk = cdsPciModules.adcCount; + cdsPciModules.adcType[ kk ] = GSC_16AI64SSA; + cdsPciModules.adcConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.adcCount++; + status++; + } + break; + case GSC_16AO16: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_16AO16 ) && + ( cdsPciModules.cards_used[ jj ].instance == dacCnt ) ) + { + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_16AO16; + cdsPciModules.dacConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.pci_dac[ kk ] = + (long)( ioMemData->iodata[ ii ] ); + cdsPciModules.dacCount++; + status++; + } + break; + case GSC_18AO8: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_18AO8 ) && + ( cdsPciModules.cards_used[ jj ].instance == dac18Cnt ) ) + { + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_18AO8; + cdsPciModules.dacConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.pci_dac[ kk ] = + (long)( ioMemData->iodata[ ii ] ); + cdsPciModules.dacCount++; + status++; + } + break; case GSC_20AO8: - if(cdsPciModules.cards_used[jj].type == GSC_20AO8 && - (cdsPciModules.cards_used[jj].instance == dac20Cnt)) + if ( cdsPciModules.cards_used[ jj ].type == GSC_20AO8 && + ( cdsPciModules.cards_used[ jj ].instance == dac20Cnt ) ) { kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_20AO8; - cdsPciModules.dacConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.pci_dac[kk] = (long)(ioMemData->iodata[ii]); - cdsPciModules.dacCount ++; - status ++; + cdsPciModules.dacType[ kk ] = GSC_20AO8; + cdsPciModules.dacConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.pci_dac[ kk ] = + (long)( ioMemData->iodata[ ii ] ); + cdsPciModules.dacCount++; + status++; } break; - case CON_6464DIO: - if((cdsPciModules.cards_used[jj].type == CON_6464DIO) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDio6464lCount ++; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doInstance[kk] = doCnt; - status += 2; - } - if((cdsPciModules.cards_used[jj].type == CDO64) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = CDO64; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDio6464lCount ++; - cdsPciModules.doInstance[kk] = doCnt; - cdo64Cnt ++; - status ++; - } - if((cdsPciModules.cards_used[jj].type == CDI64) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = CDI64; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doInstance[kk] = doCnt; - cdsPciModules.doCount ++; - cdsPciModules.cDio6464lCount ++; - cdi64Cnt ++; - status ++; - } - break; - case CON_32DO: - if((cdsPciModules.cards_used[jj].type == CON_32DO) && - (cdsPciModules.cards_used[jj].instance == do32Cnt)) - { - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDo32lCount ++; - cdsPciModules.doInstance[kk] = do32Cnt; - status ++; - } - break; - case ACS_16DIO: - if((cdsPciModules.cards_used[jj].type == ACS_16DIO) && - (cdsPciModules.cards_used[jj].instance == doIIRO16Cnt)) - { - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.iiroDio1Count ++; - cdsPciModules.doInstance[kk] = doIIRO16Cnt; - status ++; - } - break; - case ACS_8DIO: - if((cdsPciModules.cards_used[jj].type == ACS_8DIO) && - (cdsPciModules.cards_used[jj].instance == doIIRO8Cnt)) - { - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.iiroDioCount ++; - cdsPciModules.doInstance[kk] = doIIRO8Cnt; - status ++; - } - break; - default: - break; - } - } - if(ioMemData->model[ii] == GSC_16AI64SSA) adcCnt ++; - if(ioMemData->model[ii] == GSC_16AO16) dacCnt ++; - if(ioMemData->model[ii] == GSC_18AO8) dac18Cnt ++; - if(ioMemData->model[ii] == GSC_20AO8) dac20Cnt ++; - if(ioMemData->model[ii] == CON_6464DIO) doCnt ++; - if(ioMemData->model[ii] == CON_32DO) do32Cnt ++; - if(ioMemData->model[ii] == ACS_16DIO) doIIRO16Cnt ++; - if(ioMemData->model[ii] == ACS_8DIO) doIIRO8Cnt ++; - } - // If no ADC cards were found, then SLAVE cannot run - if(!cdsPciModules.adcCount) - { - printk("No ADC cards found - exiting\n"); - return -1; - } - // This did not quite work for some reason - // Need to find a way to handle skipped DAC cards in slaves - //cdsPciModules.dacCount = ioMemData->dacCount; - if(status < cards) - { - printk(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); - cardCountErr = 1; - } - - // Print out all the I/O information - // Following routine is in moduleLoadCommon.c - print_io_info(&cdsPciModules); - -// Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style. -// Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O. -// Master unit only maps the RFM I/O space and passes pointers to SLAVES. - - // Slave gets RFM module count from MASTER. - cdsPciModules.rfmCount = ioMemData->rfmCount; - // dolphinCount is number of segments - cdsPciModules.dolphinCount = ioMemData->dolphinCount; - // dolphin read/write 0 is for local PCIe network traffic - cdsPciModules.dolphinRead[0] = ioMemData->dolphinRead[0]; - cdsPciModules.dolphinWrite[0] = ioMemData->dolphinWrite[0]; - // dolphin read/write 1 is for long range PCIe (RFM) traffic - cdsPciModules.dolphinRead[1] = ioMemData->dolphinRead[1]; - cdsPciModules.dolphinWrite[1] = ioMemData->dolphinWrite[1]; - for(ii=0;ii<cdsPciModules.rfmCount;ii++) - { - cdsPciModules.pci_rfm[ii] = ioMemData->pci_rfm[ii]; - cdsPciModules.pci_rfm_dma[ii] = ioMemData->pci_rfm_dma[ii]; - } - // User APP does not access IRIG-B cards - cdsPciModules.gps = 0; - cdsPciModules.gpsType = 0; - - // Initialize buffer for daqLib.c code - daqBuffer = (long)&daqArea[0]; - - - // Set Pointer to EPICS data - pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; - pLocalEpics->epicsOutput.fe_status = WAIT_BURT; - // Ensure EPICS is running - for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { - msleep(1000); - } - // If EPICS not running, EXIT - if (cnt == 10) { - pLocalEpics->epicsOutput.fe_status = BURT_RESTORE_ERROR; - // Cleanup - return -1; - } - - pLocalEpics->epicsInput.vmeReset = 0; -udelay(2000); + case CON_6464DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == CON_6464DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDio6464lCount++; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doInstance[ kk ] = doCnt; + status += 2; + } + if ( ( cdsPciModules.cards_used[ jj ].type == CDO64 ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = CDO64; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDio6464lCount++; + cdsPciModules.doInstance[ kk ] = doCnt; + cdo64Cnt++; + status++; + } + if ( ( cdsPciModules.cards_used[ jj ].type == CDI64 ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = CDI64; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doInstance[ kk ] = doCnt; + cdsPciModules.doCount++; + cdsPciModules.cDio6464lCount++; + cdi64Cnt++; + status++; + } + break; + case CON_32DO: + if ( ( cdsPciModules.cards_used[ jj ].type == CON_32DO ) && + ( cdsPciModules.cards_used[ jj ].instance == do32Cnt ) ) + { + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDo32lCount++; + cdsPciModules.doInstance[ kk ] = do32Cnt; + status++; + } + break; + case ACS_16DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == ACS_16DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == + doIIRO16Cnt ) ) + { + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.iiroDio1Count++; + cdsPciModules.doInstance[ kk ] = doIIRO16Cnt; + status++; + } + break; + case ACS_8DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == ACS_8DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == doIIRO8Cnt ) ) + { + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.iiroDioCount++; + cdsPciModules.doInstance[ kk ] = doIIRO8Cnt; + status++; + } + break; + default: + break; + } + } + if ( ioMemData->model[ ii ] == GSC_16AI64SSA ) + adcCnt++; + if ( ioMemData->model[ ii ] == GSC_16AO16 ) + dacCnt++; + if ( ioMemData->model[ ii ] == GSC_18AO8 ) + dac18Cnt++; + if ( ioMemData->model[ ii ] == GSC_20AO8 ) + dac20Cnt++; + if ( ioMemData->model[ ii ] == CON_6464DIO ) + doCnt++; + if ( ioMemData->model[ ii ] == CON_32DO ) + do32Cnt++; + if ( ioMemData->model[ ii ] == ACS_16DIO ) + doIIRO16Cnt++; + if ( ioMemData->model[ ii ] == ACS_8DIO ) + doIIRO8Cnt++; + } + // If no ADC cards were found, then SLAVE cannot run + if ( !cdsPciModules.adcCount ) + { + printk( "No ADC cards found - exiting\n" ); + return -1; + } + // This did not quite work for some reason + // Need to find a way to handle skipped DAC cards in slaves + // cdsPciModules.dacCount = ioMemData->dacCount; + if ( status < cards ) + { + printk( " ERROR **** Did not find correct number of cards! Expected %d " + "and Found %d\n", + cards, + status ); + cardCountErr = 1; + } + + // Print out all the I/O information + // Following routine is in moduleLoadCommon.c + print_io_info( &cdsPciModules ); + + // Following section maps Reflected Memory, both VMIC hardware style and + // Dolphin PCIe network style. Slave units will perform I/O transactions + // with RFM directly ie MASTER does not do RFM I/O. Master unit only maps + // the RFM I/O space and passes pointers to SLAVES. + + // Slave gets RFM module count from MASTER. + cdsPciModules.rfmCount = ioMemData->rfmCount; + // dolphinCount is number of segments + cdsPciModules.dolphinCount = ioMemData->dolphinCount; + // dolphin read/write 0 is for local PCIe network traffic + cdsPciModules.dolphinRead[ 0 ] = ioMemData->dolphinRead[ 0 ]; + cdsPciModules.dolphinWrite[ 0 ] = ioMemData->dolphinWrite[ 0 ]; + // dolphin read/write 1 is for long range PCIe (RFM) traffic + cdsPciModules.dolphinRead[ 1 ] = ioMemData->dolphinRead[ 1 ]; + cdsPciModules.dolphinWrite[ 1 ] = ioMemData->dolphinWrite[ 1 ]; + for ( ii = 0; ii < cdsPciModules.rfmCount; ii++ ) + { + cdsPciModules.pci_rfm[ ii ] = ioMemData->pci_rfm[ ii ]; + cdsPciModules.pci_rfm_dma[ ii ] = ioMemData->pci_rfm_dma[ ii ]; + } + // User APP does not access IRIG-B cards + cdsPciModules.gps = 0; + cdsPciModules.gpsType = 0; + + // Initialize buffer for daqLib.c code + daqBuffer = (long)&daqArea[ 0 ]; + + // Set Pointer to EPICS data + pLocalEpics = (CDS_EPICS*)&( (RFM_FE_COMMS*)_epics_shm )->epicsSpace; + pLocalEpics->epicsOutput.fe_status = WAIT_BURT; + // Ensure EPICS is running + for ( cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++ ) + { + msleep( 1000 ); + } + // If EPICS not running, EXIT + if ( cnt == 10 ) + { + pLocalEpics->epicsOutput.fe_status = BURT_RESTORE_ERROR; + // Cleanup + return -1; + } + + pLocalEpics->epicsInput.vmeReset = 0; + udelay( 2000 ); #ifdef NO_CPU_SHUTDOWN - sthread = kthread_create(fe_start_app, 0, "fe_start_app/%d", CPUID); - if (IS_ERR(sthread)){ - printk("Failed to kthread_create()\n"); - return -1; - } - kthread_bind(sthread, CPUID); - wake_up_process(sthread); + sthread = kthread_create( fe_start_app, 0, "fe_start_app/%d", CPUID ); + if ( IS_ERR( sthread ) ) + { + printk( "Failed to kthread_create()\n" ); + return -1; + } + kthread_bind( sthread, CPUID ); + wake_up_process( sthread ); #endif - pLocalEpics->epicsOutput.fe_status = LOCKING_CORE; + pLocalEpics->epicsOutput.fe_status = LOCKING_CORE; #ifndef NO_CPU_SHUTDOWN - set_fe_code_idle(fe_start_app, CPUID); - msleep(100); + set_fe_code_idle( fe_start_app, CPUID ); + msleep( 100 ); - cpu_down(CPUID); + cpu_down( CPUID ); - // The code runs on the disabled CPU + // The code runs on the disabled CPU #endif - return 0; + return 0; } -void rt_fe_cleanup (void) { - int i; - int ret; - extern int cpu_up(unsigned int cpu); - +void +rt_fe_cleanup( void ) +{ + int i; + int ret; + extern int cpu_up( unsigned int cpu ); #ifndef NO_CPU_SHUTDOWN - // Unset the code callback - set_fe_code_idle(0, CPUID); + // Unset the code callback + set_fe_code_idle( 0, CPUID ); #endif - printk("Setting stop_working_threads to 1\n"); - // Stop the code and wait + printk( "Setting stop_working_threads to 1\n" ); + // Stop the code and wait #ifdef NO_CPU_SHUTDOWN - ret = kthread_stop(sthread); + ret = kthread_stop( sthread ); #endif - stop_working_threads = 1; - msleep(1000); + stop_working_threads = 1; + msleep( 1000 ); #ifndef NO_CPU_SHUTDOWN - // Unset the code callback - set_fe_code_idle(0, CPUID); - // printk("Will bring back CPU %d\n", CPUID); - msleep(1000); - // Bring the CPU back up - cpu_up(CPUID); - //msleep(1000); - printk("Brought the CPU back up\n"); + // Unset the code callback + set_fe_code_idle( 0, CPUID ); + // printk("Will bring back CPU %d\n", CPUID); + msleep( 1000 ); + // Bring the CPU back up + cpu_up( CPUID ); + // msleep(1000); + printk( "Brought the CPU back up\n" ); #endif - printk("Just before returning from cleanup_module for " SYSTEM_NAME_STRING_LOWER "\n"); - + printk( "Just before returning from cleanup_module " + "for " SYSTEM_NAME_STRING_LOWER "\n" ); } -module_init(rt_fe_init); -module_exit(rt_fe_cleanup); -MODULE_DESCRIPTION("Control system"); -MODULE_AUTHOR("LIGO"); -MODULE_LICENSE("Dual BSD/GPL"); +module_init( rt_fe_init ); +module_exit( rt_fe_cleanup ); +MODULE_DESCRIPTION( "Control system" ); +MODULE_AUTHOR( "LIGO" ); +MODULE_LICENSE( "Dual BSD/GPL" ); diff --git a/src/fe/moduleLoadCommon.c b/src/fe/moduleLoadCommon.c index dba328a87..869b21eb6 100644 --- a/src/fe/moduleLoadCommon.c +++ b/src/fe/moduleLoadCommon.c @@ -1,103 +1,147 @@ /// @file moduleLoadCommon.c -/// @brief File contains common routines for moduleLoadIop.c and moduleLoadApp.c.` +/// @brief File contains common routines for moduleLoadIop.c and +/// moduleLoadApp.c.` -void print_io_info(CDS_HARDWARE *cdsp) { - int ii,jj,kk; - jj = 0; +void +print_io_info( CDS_HARDWARE* cdsp ) +{ + int ii, jj, kk; + jj = 0; #ifndef USER_SPACE - printf("" SYSTEM_NAME_STRING_LOWER ":startup time is %ld\n", current_time_fe()); - printf("" SYSTEM_NAME_STRING_LOWER ":cpu clock %u\n",cpu_khz); + printf( "" SYSTEM_NAME_STRING_LOWER ":startup time is %ld\n", + current_time_fe( ) ); + printf( "" SYSTEM_NAME_STRING_LOWER ":cpu clock %u\n", cpu_khz ); #endif - printf("" SYSTEM_NAME_STRING_LOWER ":EPICSM at 0x%lx\n", (unsigned long)_epics_shm); - printf("" SYSTEM_NAME_STRING_LOWER ":IPC at 0x%lx\n",(unsigned long)_ipc_shm); - printf("" SYSTEM_NAME_STRING_LOWER ":IOMEM at 0x%lx size 0x%lx\n",((unsigned long)_ipc_shm + 0x4000),sizeof(IO_MEM_DATA)); - printf("" SYSTEM_NAME_STRING_LOWER ":DAQSM at 0x%lx\n",(unsigned long)_daq_shm); - printf("" SYSTEM_NAME_STRING_LOWER ":configured to use %d cards\n", cdsp->cards); - kk = 0; - printf("***************************************************************************\n"); - printf("" SYSTEM_NAME_STRING_LOWER ":%d ADC cards found\n",cdsp->adcCount); - for(ii=0;ii<cdsp->adcCount;ii++) + printf( "" SYSTEM_NAME_STRING_LOWER ":EPICSM at 0x%lx\n", + (unsigned long)_epics_shm ); + printf( "" SYSTEM_NAME_STRING_LOWER ":IPC at 0x%lx\n", + (unsigned long)_ipc_shm ); + printf( "" SYSTEM_NAME_STRING_LOWER ":IOMEM at 0x%lx size 0x%lx\n", + ( (unsigned long)_ipc_shm + 0x4000 ), + sizeof( IO_MEM_DATA ) ); + printf( "" SYSTEM_NAME_STRING_LOWER ":DAQSM at 0x%lx\n", + (unsigned long)_daq_shm ); + printf( "" SYSTEM_NAME_STRING_LOWER ":configured to use %d cards\n", + cdsp->cards ); + kk = 0; + printf( "******************************************************************" + "*********\n" ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d ADC cards found\n", + cdsp->adcCount ); + for ( ii = 0; ii < cdsp->adcCount; ii++ ) + { + kk++; + if ( cdsp->adcType[ ii ] == GSC_18AISS6C ) { - kk ++; - if(cdsp->adcType[ii] == GSC_18AISS6C) - { - printf("\tADC %d is a GSC_18AISS6C module\n",ii); - printf("\t\tChannels = 6 \n"); - printf("\t\tFirmware Rev = %d \n\n",(cdsp->adcConfig[ii] & 0xfff)); - } - if(cdsp->adcType[ii] == GSC_16AI64SSA) - { - printf("\tADC %d is a GSC_16AI64SSA module\n",ii); - if((cdsp->adcConfig[ii] & 0x10000) > 0) jj = 32; - else jj = 64; - printf("\t\tChannels = %d \n",jj); - printf("\t\tFirmware Rev = %d \n\n",(cdsp->adcConfig[ii] & 0xfff)); - } - } - printf("***************************************************************************\n"); - printf("" SYSTEM_NAME_STRING_LOWER ":%d DAC cards found\n",cdsp->dacCount); - for(ii=0;ii<cdsp->dacCount;ii++) + printf( "\tADC %d is a GSC_18AISS6C module\n", ii ); + printf( "\t\tChannels = 6 \n" ); + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsp->adcConfig[ ii ] & 0xfff ) ); + } + if ( cdsp->adcType[ ii ] == GSC_16AI64SSA ) { - kk ++; - if(cdsp->dacType[ii] == GSC_18AO8) - { - printf("\tDAC %d is a GSC_18AO8 module\n",ii); - } - if(cdsPciModules.dacType[ii] == GSC_20AO8) - { - printf("\tDAC %d is a GSC_20AO8 module\n",ii); - printf("\t\tFirmware Revision: %d\n",(cdsPciModules.dacConfig[ii] & 0xffff)); - } - if(cdsp->dacType[ii] == GSC_16AO16) - { - printf("\tDAC %d is a GSC_16AO16 module\n",ii); - if((cdsp->dacConfig[ii] & 0x10000) == 0x10000) jj = 8; - if((cdsp->dacConfig[ii] & 0x20000) == 0x20000) jj = 12; - if((cdsp->dacConfig[ii] & 0x30000) == 0x30000) jj = 16; - printf("\t\tChannels = %d \n",jj); - if((cdsp->dacConfig[ii] & 0xC0000) == 0x0000) - { - printf("\t\tFilters = None\n"); - } - if((cdsp->dacConfig[ii] & 0xC0000) == 0x40000) - { - printf("\t\tFilters = 10kHz\n"); - } - if((cdsp->dacConfig[ii] & 0xC0000) == 0x80000) - { - printf("\t\tFilters = 100kHz\n"); - } - if((cdsp->dacConfig[ii] & 0x100000) == 0x100000) - { - printf("\t\tOutput Type = Differential\n"); - } - printf("\t\tFirmware Rev = %d \n\n",(cdsp->dacConfig[ii] & 0xfff)); - } - } - kk += cdsp->dioCount; - printf("***************************************************************************\n"); - printf("" SYSTEM_NAME_STRING_LOWER ":%d DIO cards found\n",cdsp->dioCount); - printf("***************************************************************************\n"); - printf("" SYSTEM_NAME_STRING_LOWER ":%d IIRO-8 Isolated DIO cards found\n",cdsp->iiroDioCount); - printf("***************************************************************************\n"); - printf("" SYSTEM_NAME_STRING_LOWER ":%d IIRO-16 Isolated DIO cards found\n",cdsp->iiroDio1Count); - printf("***************************************************************************\n"); - printf("" SYSTEM_NAME_STRING_LOWER ":%d Contec 32ch PCIe DO cards found\n",cdsp->cDo32lCount); - printf("" SYSTEM_NAME_STRING_LOWER ":%d Contec PCIe DIO1616 cards found\n",cdsp->cDio1616lCount); - printf("" SYSTEM_NAME_STRING_LOWER ":%d Contec PCIe DIO6464 cards found\n",cdsp->cDio6464lCount); - printf("" SYSTEM_NAME_STRING_LOWER ":%d DO cards found\n",cdsp->doCount); - printf("" SYSTEM_NAME_STRING_LOWER ":Total of %d I/O modules found and mapped\n",kk); - printf("***************************************************************************\n"); - printf("" SYSTEM_NAME_STRING_LOWER ":%d RFM cards found\n",cdsp->rfmCount); - for(ii=0;ii<cdsp->rfmCount;ii++) + printf( "\tADC %d is a GSC_16AI64SSA module\n", ii ); + if ( ( cdsp->adcConfig[ ii ] & 0x10000 ) > 0 ) + jj = 32; + else + jj = 64; + printf( "\t\tChannels = %d \n", jj ); + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsp->adcConfig[ ii ] & 0xfff ) ); + } + } + printf( "******************************************************************" + "*********\n" ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d DAC cards found\n", + cdsp->dacCount ); + for ( ii = 0; ii < cdsp->dacCount; ii++ ) + { + kk++; + if ( cdsp->dacType[ ii ] == GSC_18AO8 ) { - printf("\tRFM %d is a VMIC_%x module with Node ID %d\n", ii, cdsp->rfmType[ii], cdsp->rfmConfig[ii]); - printf("address is 0x%lx\n",cdsp->pci_rfm[ii]); - } - printf("***************************************************************************\n"); - if (cdsp->gps) { - printf("" SYSTEM_NAME_STRING_LOWER ":IRIG-B card found %d\n",cdsp->gpsType); - printf("***************************************************************************\n"); - } - + printf( "\tDAC %d is a GSC_18AO8 module\n", ii ); + } + if ( cdsPciModules.dacType[ ii ] == GSC_20AO8 ) + { + printf( "\tDAC %d is a GSC_20AO8 module\n", ii ); + printf( "\t\tFirmware Revision: %d\n", + ( cdsPciModules.dacConfig[ ii ] & 0xffff ) ); + } + if ( cdsp->dacType[ ii ] == GSC_16AO16 ) + { + printf( "\tDAC %d is a GSC_16AO16 module\n", ii ); + if ( ( cdsp->dacConfig[ ii ] & 0x10000 ) == 0x10000 ) + jj = 8; + if ( ( cdsp->dacConfig[ ii ] & 0x20000 ) == 0x20000 ) + jj = 12; + if ( ( cdsp->dacConfig[ ii ] & 0x30000 ) == 0x30000 ) + jj = 16; + printf( "\t\tChannels = %d \n", jj ); + if ( ( cdsp->dacConfig[ ii ] & 0xC0000 ) == 0x0000 ) + { + printf( "\t\tFilters = None\n" ); + } + if ( ( cdsp->dacConfig[ ii ] & 0xC0000 ) == 0x40000 ) + { + printf( "\t\tFilters = 10kHz\n" ); + } + if ( ( cdsp->dacConfig[ ii ] & 0xC0000 ) == 0x80000 ) + { + printf( "\t\tFilters = 100kHz\n" ); + } + if ( ( cdsp->dacConfig[ ii ] & 0x100000 ) == 0x100000 ) + { + printf( "\t\tOutput Type = Differential\n" ); + } + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsp->dacConfig[ ii ] & 0xfff ) ); + } + } + kk += cdsp->dioCount; + printf( "******************************************************************" + "*********\n" ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d DIO cards found\n", + cdsp->dioCount ); + printf( "******************************************************************" + "*********\n" ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d IIRO-8 Isolated DIO cards found\n", + cdsp->iiroDioCount ); + printf( "******************************************************************" + "*********\n" ); + printf( "" SYSTEM_NAME_STRING_LOWER + ":%d IIRO-16 Isolated DIO cards found\n", + cdsp->iiroDio1Count ); + printf( "******************************************************************" + "*********\n" ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d Contec 32ch PCIe DO cards found\n", + cdsp->cDo32lCount ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d Contec PCIe DIO1616 cards found\n", + cdsp->cDio1616lCount ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d Contec PCIe DIO6464 cards found\n", + cdsp->cDio6464lCount ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d DO cards found\n", cdsp->doCount ); + printf( "" SYSTEM_NAME_STRING_LOWER + ":Total of %d I/O modules found and mapped\n", + kk ); + printf( "******************************************************************" + "*********\n" ); + printf( "" SYSTEM_NAME_STRING_LOWER ":%d RFM cards found\n", + cdsp->rfmCount ); + for ( ii = 0; ii < cdsp->rfmCount; ii++ ) + { + printf( "\tRFM %d is a VMIC_%x module with Node ID %d\n", + ii, + cdsp->rfmType[ ii ], + cdsp->rfmConfig[ ii ] ); + printf( "address is 0x%lx\n", cdsp->pci_rfm[ ii ] ); + } + printf( "******************************************************************" + "*********\n" ); + if ( cdsp->gps ) + { + printf( "" SYSTEM_NAME_STRING_LOWER ":IRIG-B card found %d\n", + cdsp->gpsType ); + printf( "**************************************************************" + "*************\n" ); + } } diff --git a/src/fe/moduleLoadTS.c b/src/fe/moduleLoadTS.c index b710248ec..27216843d 100644 --- a/src/fe/moduleLoadTS.c +++ b/src/fe/moduleLoadTS.c @@ -7,1157 +7,1409 @@ #include <proc.h> // These externs and "16" need to go to a header file (mbuf.h) -extern void *kmalloc_area[16]; -extern int mbuf_allocate_area(char *name, int size, struct file *file); -extern void *fe_start(void *arg); -extern int run_on_timer; -extern char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers +extern void* kmalloc_area[ 16 ]; +extern int mbuf_allocate_area( char* name, int size, struct file* file ); +extern void* fe_start( void* arg ); +extern int run_on_timer; +extern char daqArea[ 2 * DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers #include FE_PROC_FILE /// /proc filesystem directory entry -struct proc_dir_entry *proc_dir_entry; +struct proc_dir_entry* proc_dir_entry; /// /proc/{sysname}/status entry -struct proc_dir_entry *proc_entry; +struct proc_dir_entry* proc_entry; /// /proc/{sysname}/gps entry -struct proc_dir_entry *proc_gps_entry; +struct proc_dir_entry* proc_gps_entry; /// /proc/{sysname}/epics directory entry -struct proc_dir_entry *proc_epics_dir_entry; +struct proc_dir_entry* proc_epics_dir_entry; /// /proc/{sysname}/futures entry -struct proc_dir_entry *proc_futures_entry; +struct proc_dir_entry* proc_futures_entry; -void remove_epics_proc_files(void); -int create_epics_proc_files(void); -struct task_struct *sthread; +void remove_epics_proc_files( void ); +int create_epics_proc_files( void ); +struct task_struct* sthread; /// Routine to read the /proc/{model}/status file. \n \n /// We give all of our information in one go, so if the /// user asks us if we have more information the \n /// answer should always be no. -/// +/// /// This is important because the standard read /// function from the library would continue to issue \n /// the read system call until the kernel replies /// that it has no more information, or until its \n /// buffer is filled. int -procfile_status_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) +procfile_status_read( char* buffer, + char** buffer_location, + off_t offset, + int buffer_length, + int* eof, + void* data ) { - int ret, i; - i = 0; - *buffer = 0; - - /* - * We give all of our information in one go, so if the - * user asks us if we have more information the - * answer should always be no. - * - * This is important because the standard read - * function from the library would continue to issue - * the read system call until the kernel replies - * that it has no more information, or until its - * buffer is filled. - */ - if (offset > 0) { - /* we have finished to read, return 0 */ - ret = 0; - } else { -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) || defined(COMMDATA_INLINE) - char b[128]; -#if defined(SERVO64K) || defined(SERVO32K) - static const int nb = 32; -#elif defined(SERVO16K) - static const int nb = 64; + int ret, i; + i = 0; + *buffer = 0; + + /* + * We give all of our information in one go, so if the + * user asks us if we have more information the + * answer should always be no. + * + * This is important because the standard read + * function from the library would continue to issue + * the read system call until the kernel replies + * that it has no more information, or until its + * buffer is filled. + */ + if ( offset > 0 ) + { + /* we have finished to read, return 0 */ + ret = 0; + } + else + { +#if defined( SERVO64K ) || defined( SERVO32K ) || defined( SERVO16K ) || \ + defined( COMMDATA_INLINE ) + char b[ 128 ]; +#if defined( SERVO64K ) || defined( SERVO32K ) + static const int nb = 32; +#elif defined( SERVO16K ) + static const int nb = 64; #endif #endif - /* fill the buffer, return the buffer size */ - ret = sprintf(buffer, - - "startGpsTime=%d\n" - "uptime=%d\n" - "cpuTimeEverMax=%d\n" - "cpuTimeEverMaxWhen=%d\n" - "adcHoldTime=%d\n" - "adcHoldTimeEverMax=%d\n" - "adcHoldTimeEverMaxWhen=%d\n" - "adcHoldTimeMax=%d\n" - "adcHoldTimeMin=%d\n" - "adcHoldTimeAvg=%d\n" - "usrTime=%d\n" - "usrHoldTime=%d\n" - "cycle=%d\n" - "gps=%d\n" - "buildDate=%s\n" - "cpuTimeMax(cur,past sec)=%d,%d\n" - "cpuTimeMaxCycle(cur,past sec)=%d,%d\n", - - startGpsTime, - cycle_gps_time - startGpsTime, - cpuTimeEverMax, - cpuTimeEverMaxWhen, - adcHoldTime, - adcHoldTimeEverMax, - adcHoldTimeEverMaxWhen, - adcHoldTimeMax, - adcHoldTimeMin, - adcHoldTimeAvgPerSec, - usrTime, - usrHoldTime, - cycleNum, - cycle_gps_time, - build_date, - cycleTime, timeHoldHold, - timeHoldWhen, timeHoldWhenHold); -#if defined(SERVO64K) || defined(SERVO32K) || defined(SERVO16K) - strcat(buffer, "cycleHist: "); - for (i = 0; i < nb; i++) { - if (!cycleHistMax[i]) continue; - sprintf(b, "%d=%d@%d ", i, cycleHistMax[i], cycleHistWhenHold[i]); - strcat(buffer, b); - } - strcat(buffer, "\n"); + /* fill the buffer, return the buffer size */ + ret = sprintf( buffer, + + "startGpsTime=%d\n" + "uptime=%d\n" + "cpuTimeEverMax=%d\n" + "cpuTimeEverMaxWhen=%d\n" + "adcHoldTime=%d\n" + "adcHoldTimeEverMax=%d\n" + "adcHoldTimeEverMaxWhen=%d\n" + "adcHoldTimeMax=%d\n" + "adcHoldTimeMin=%d\n" + "adcHoldTimeAvg=%d\n" + "usrTime=%d\n" + "usrHoldTime=%d\n" + "cycle=%d\n" + "gps=%d\n" + "buildDate=%s\n" + "cpuTimeMax(cur,past sec)=%d,%d\n" + "cpuTimeMaxCycle(cur,past sec)=%d,%d\n", + + startGpsTime, + cycle_gps_time - startGpsTime, + cpuTimeEverMax, + cpuTimeEverMaxWhen, + adcHoldTime, + adcHoldTimeEverMax, + adcHoldTimeEverMaxWhen, + adcHoldTimeMax, + adcHoldTimeMin, + adcHoldTimeAvgPerSec, + usrTime, + usrHoldTime, + cycleNum, + cycle_gps_time, + build_date, + cycleTime, + timeHoldHold, + timeHoldWhen, + timeHoldWhenHold ); +#if defined( SERVO64K ) || defined( SERVO32K ) || defined( SERVO16K ) + strcat( buffer, "cycleHist: " ); + for ( i = 0; i < nb; i++ ) + { + if ( !cycleHistMax[ i ] ) + continue; + sprintf( + b, "%d=%d@%d ", i, cycleHistMax[ i ], cycleHistWhenHold[ i ] ); + strcat( buffer, b ); + } + strcat( buffer, "\n" ); #endif #ifdef ADC_MASTER - /* Output DAC buffer size information */ - for (i = 0; i < cdsPciModules.dacCount; i++) { - if (cdsPciModules.dacType[i] == GSC_18AO8) { - sprintf(b, "DAC #%d 18-bit buf_size=%d\n", i, dacOutBufSize[i]); - } else if (cdsPciModules.dacType[i] == GSC_20AO8) { - sprintf(b, "DAC #%d 20-bit buf_size=%d\n", i, dacOutBufSize[i]); - } else { - sprintf(b, "DAC #%d 16-bit fifo_status=%d (%s)\n", i, dacOutBufSize[i], - dacOutBufSize[i] & 8? "full": - (dacOutBufSize[i] & 1? "empty": - (dacOutBufSize[i] & 4? "high quarter": "OK"))); - } - strcat(buffer, b); - } - /* Output ADC read time information */ - for (i = 0; i < cdsPciModules.adcCount; i++) { - sprintf(b, "ADC #%d read time MAX=%d Current=%d\n", i, adcRdTimeMax[i],adcRdTime[i]); - strcat(buffer, b); - } + /* Output DAC buffer size information */ + for ( i = 0; i < cdsPciModules.dacCount; i++ ) + { + if ( cdsPciModules.dacType[ i ] == GSC_18AO8 ) + { + sprintf( + b, "DAC #%d 18-bit buf_size=%d\n", i, dacOutBufSize[ i ] ); + } + else if ( cdsPciModules.dacType[ i ] == GSC_20AO8 ) + { + sprintf( + b, "DAC #%d 20-bit buf_size=%d\n", i, dacOutBufSize[ i ] ); + } + else + { + sprintf( b, + "DAC #%d 16-bit fifo_status=%d (%s)\n", + i, + dacOutBufSize[ i ], + dacOutBufSize[ i ] & 8 + ? "full" + : ( dacOutBufSize[ i ] & 1 + ? "empty" + : ( dacOutBufSize[ i ] & 4 ? "high quarter" + : "OK" ) ) ); + } + strcat( buffer, b ); + } + /* Output ADC read time information */ + for ( i = 0; i < cdsPciModules.adcCount; i++ ) + { + sprintf( b, + "ADC #%d read time MAX=%d Current=%d\n", + i, + adcRdTimeMax[ i ], + adcRdTime[ i ] ); + strcat( buffer, b ); + } #endif #ifdef COMMDATA_INLINE - // See if we have any IPC with errors and print the numbers out - // - sprintf(b, "ipcErrBits=0x%x\n", ipcErrBits); - strcat(buffer, b); - - // The following loop has a chance to overflow the buffer, - // which is set to PROC_BLOCK_SIZE. (PAGE_SIZE-1024 = 3072 bytes). - // We will simply stop printing at that point. -#define PROC_BLOCK_SIZE (3*1024) - unsigned int byte_cnt = strlen(buffer) + 1; - for (i = 0; i < myIpcCount; i++) { - if (ipcInfo[i].errTotal) { - unsigned int cnt = - sprintf(b, "IPC net=%d num=%d name=%s sender=%s errcnt=%d\n", - ipcInfo[i].netType, ipcInfo[i].ipcNum, - ipcInfo[i].name, ipcInfo[i].senderModelName, - ipcInfo[i].errTotal); - if (byte_cnt + cnt > PROC_BLOCK_SIZE) break; - byte_cnt += cnt; - strcat(buffer, b); - } - } + // See if we have any IPC with errors and print the numbers out + // + sprintf( b, "ipcErrBits=0x%x\n", ipcErrBits ); + strcat( buffer, b ); + + // The following loop has a chance to overflow the buffer, + // which is set to PROC_BLOCK_SIZE. (PAGE_SIZE-1024 = 3072 bytes). + // We will simply stop printing at that point. +#define PROC_BLOCK_SIZE ( 3 * 1024 ) + unsigned int byte_cnt = strlen( buffer ) + 1; + for ( i = 0; i < myIpcCount; i++ ) + { + if ( ipcInfo[ i ].errTotal ) + { + unsigned int cnt = + sprintf( b, + "IPC net=%d num=%d name=%s sender=%s errcnt=%d\n", + ipcInfo[ i ].netType, + ipcInfo[ i ].ipcNum, + ipcInfo[ i ].name, + ipcInfo[ i ].senderModelName, + ipcInfo[ i ].errTotal ); + if ( byte_cnt + cnt > PROC_BLOCK_SIZE ) + break; + byte_cnt += cnt; + strcat( buffer, b ); + } + } #endif - ret = strlen(buffer); - } + ret = strlen( buffer ); + } - return ret; + return ret; } /// Routine to read the /proc/{model}/gps file. \n \n /// int -procfile_gps_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) +procfile_gps_read( char* buffer, + char** buffer_location, + off_t offset, + int buffer_length, + int* eof, + void* data ) { - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - /* print current GPS time and zero padded fraction */ - return sprintf(buffer, "%d.%02d\n", cycle_gps_time, (cycleNum*100/CYCLE_PER_SECOND)%100); - } - // Never reached + *buffer = 0; + + if ( offset > 0 ) + { + /* we have finished to read, return 0 */ + return 0; + } + else + { + /* fill the buffer, return the buffer size */ + /* print current GPS time and zero padded fraction */ + return sprintf( buffer, + "%d.%02d\n", + cycle_gps_time, + ( cycleNum * 100 / CYCLE_PER_SECOND ) % 100 ); + } + // Never reached } /// Routine to read the /proc/{model}/epics/{chname} files. \n \n /// int -procfile_epics_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) +procfile_epics_read( char* buffer, + char** buffer_location, + off_t offset, + int buffer_length, + int* eof, + void* data ) { - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - struct proc_epics *pe = (struct proc_epics *)data; - unsigned int ncel = pe->nrow * pe->ncol; // Matrix size - switch (pe -> type) { - case 0: /* int */ - return sprintf(buffer, "%s%d\n", - (*((char *)(((void *)pLocalEpics) + pe->mask_idx)))? "\t": "", - *((int *)(((void *)pLocalEpics) + pe->idx))); - // printf("Accessing data at %x\n", (((void *)pLocalEpics) + pe->idx)); - break; - case 1: /* double */ { - char lb[64]; - if (ncel) { /* Print Matrix */ - unsigned int i, j; - unsigned int nrow = pe->nrow; - unsigned int ncol = pe->ncol; - unsigned int s = 0; - unsigned int masked = *((char *)(((void *)pLocalEpics) + pe->mask_idx)); - for (i = 0; i < nrow; i++) { - if (masked) s += sprintf(buffer + s, "\t"); - for (j = 0; j < ncol; j++) { - s += sprintf(buffer + s, "%s ", dtoa_r(lb, ((double *)(((void *)pLocalEpics) + pe->idx))[ncol*i + j])); - } - s += sprintf(buffer + s, "\n"); - } - return s; - } else { /* Print single value */ - return sprintf(buffer, "%s%s\n", - (*((char *)(((void *)pLocalEpics) + pe->mask_idx)))? "\t": "", - dtoa_r(lb, *((double *)(((void *)pLocalEpics) + pe->idx)))); - } - break; - } - } - } - // Never reached + *buffer = 0; + + if ( offset > 0 ) + { + /* we have finished to read, return 0 */ + return 0; + } + else + { + /* fill the buffer, return the buffer size */ + struct proc_epics* pe = (struct proc_epics*)data; + unsigned int ncel = pe->nrow * pe->ncol; // Matrix size + switch ( pe->type ) + { + case 0: /* int */ + return sprintf( + buffer, + "%s%d\n", + ( *( (char*)( ( (void*)pLocalEpics ) + pe->mask_idx ) ) ) ? "\t" + : "", + *( (int*)( ( (void*)pLocalEpics ) + pe->idx ) ) ); + // printf("Accessing data at %x\n", (((void *)pLocalEpics) + + //pe->idx)); + break; + case 1: /* double */ + { + char lb[ 64 ]; + if ( ncel ) + { /* Print Matrix */ + unsigned int i, j; + unsigned int nrow = pe->nrow; + unsigned int ncol = pe->ncol; + unsigned int s = 0; + unsigned int masked = + *( (char*)( ( (void*)pLocalEpics ) + pe->mask_idx ) ); + for ( i = 0; i < nrow; i++ ) + { + if ( masked ) + s += sprintf( buffer + s, "\t" ); + for ( j = 0; j < ncol; j++ ) + { + s += sprintf( + buffer + s, + "%s ", + dtoa_r( + lb, + ( (double*)( ( (void*)pLocalEpics ) + + pe->idx ) )[ ncol * i + j ] ) ); + } + s += sprintf( buffer + s, "\n" ); + } + return s; + } + else + { /* Print single value */ + return sprintf( + buffer, + "%s%s\n", + ( *( (char*)( ( (void*)pLocalEpics ) + pe->mask_idx ) ) ) + ? "\t" + : "", + dtoa_r( + lb, + *( (double*)( ( (void*)pLocalEpics ) + pe->idx ) ) ) ); + } + break; + } + } + } + // Never reached } -#define PROC_BLOCK_SIZE (3*1024) +#define PROC_BLOCK_SIZE ( 3 * 1024 ) // Scan a double double -simple_strtod(char *start, char **end) { - int integer; - if (*start != '.') { - integer = simple_strtol(start, end, 10); - if (*end == start) return 0.0; - start = *end; - } else integer = 0; - if (*start != '.') return integer; - else { - start++; - double frac = simple_strtol(start, end, 10); - if (*end == start) return integer; - int i; - for (i = 0; i < (*end - start); i++) frac /= 10.0; - return ((double)integer) + frac; - } - // Never reached +simple_strtod( char* start, char** end ) +{ + int integer; + if ( *start != '.' ) + { + integer = simple_strtol( start, end, 10 ); + if ( *end == start ) + return 0.0; + start = *end; + } + else + integer = 0; + if ( *start != '.' ) + return integer; + else + { + start++; + double frac = simple_strtol( start, end, 10 ); + if ( *end == start ) + return integer; + int i; + for ( i = 0; i < ( *end - start ); i++ ) + frac /= 10.0; + return ( (double)integer ) + frac; + } + // Never reached } - int -procfile_epics_write(struct file *file, const char __user *buf, - unsigned long count, void *data) +procfile_epics_write( struct file* file, + const char __user* buf, + unsigned long count, + void* data ) { - ssize_t ret = -ENOMEM; - char *page; - char *start; - unsigned int future = 0; - - if (count > PROC_BLOCK_SIZE) - return -EOVERFLOW; - - start = page = (char *)__get_free_page(GFP_KERNEL); - if (page) { + ssize_t ret = -ENOMEM; + char* page; + char* start; + unsigned int future = 0; + + if ( count > PROC_BLOCK_SIZE ) + return -EOVERFLOW; + + start = page = (char*)__get_free_page( GFP_KERNEL ); + if ( page ) + { + ret = -EFAULT; + if ( copy_from_user( page, buf, count ) ) + goto out; + page[ count ] = 0; + ret = count; + struct proc_epics* pe = (struct proc_epics*)data; + char* end; + for ( ; isspace( *start ); start++ ) + ; + // See if this a single-character command + switch ( *start ) + { + case 'm': + *( (char*)( ( (void*)pLocalEpics ) + pe->mask_idx ) ) = 1; + start++; + break; + case 'u': + *( (char*)( ( (void*)pLocalEpics ) + pe->mask_idx ) ) = 0; + start++; + break; + case 'f': + future = 1; + start++; + break; + } + for ( ; isspace( *start ); start++ ) + ; + double new_double = 0.0; + int new_int = 0; + switch ( pe->type ) + { + case 0: /* int */ + new_int = simple_strtol( start, &end, 10 ); + if ( new_int > INT_MAX || new_int < INT_MIN ) + { ret = -EFAULT; - if (copy_from_user(page, buf, count)) - goto out; - page[count] = 0; - ret = count; - struct proc_epics *pe = (struct proc_epics *)data; - char *end; - for(;isspace(*start);start++); - // See if this a single-character command - switch (*start) { - case 'm': - *((char *)(((void *)pLocalEpics) + pe->mask_idx)) = 1; - start++; - break; - case 'u': - *((char *)(((void *)pLocalEpics) + pe->mask_idx)) = 0; - start++; - break; - case 'f': - future=1; - start++; - break; - } - for(;isspace(*start);start++); - double new_double = 0.0; - int new_int = 0; - switch (pe -> type) { - case 0: /* int */ - new_int = simple_strtol(start, &end, 10); - if (new_int > INT_MAX || new_int < INT_MIN) { - ret = -EFAULT; - goto out; - } - break; - case 1: /* double */ - new_double = simple_strtod(start, &end); - //printf("User wrote %s\n", dtoa1(new_double)); - break; - } - if (end == start) goto out; - // See if this is a matrix - int idx = 0; - int ncel = pe->nrow * pe->ncol; - if (ncel) { - // Expect the cell index number next - start = end; - for(;isspace(*start);start++); - idx = simple_strtol(start, &end, 10); - if (idx >= ncel || idx < 0) { - ret = -EFAULT; - goto out; - } - - } - if (!future) { - switch (pe -> type) { - case 0: /* int */ - *((int *)(((void *)pLocalEpics) + pe->idx)) = new_int; - break; - case 1: /* double */ - ((double *)(((void *)pLocalEpics) + pe->idx))[idx] = new_double; - break; - } - } else if ((*((char *)(((void *)pLocalEpics) + pe->mask_idx)))) { // Allow to setup a future only if masked - unsigned long cycle; - start = end; - for(;isspace(*start);start++); - // check for gps seconds - double gps = simple_strtod(start, &end); - if (end == start) { - gps = cycle_gps_time + 5; - cycle = cycleNum; - } else { - // Convert gps time - unsigned long gps_int = gps; - gps -= gps_int; - cycle = gps * CYCLE_PER_SECOND; - gps = gps_int; - } - // Add new future setpoint - // Find first available slot - int i; - static DEFINE_SPINLOCK(fut_lock); - spin_lock(&fut_lock); - for (i = 0; (i < MAX_PROC_FUTURES) && proc_futures[i].proc_epics; i++); - if (i == MAX_PROC_FUTURES) { - spin_unlock(&fut_lock); - ret = -ENOMEM; - } else { - // Found a slot - proc_futures[i].cycle = cycle; - proc_futures[i].gps = gps; - proc_futures[i].val = pe->type? new_double: new_int; - proc_futures[i].idx = idx; - - // This pointer has to be set last; Indicates a vailid entry for the - // real-time code in controller.c - proc_futures[i].proc_epics = pe; // FE code reads/writes this variable - spin_unlock(&fut_lock); - } - } else ret = -EFAULT; + goto out; + } + break; + case 1: /* double */ + new_double = simple_strtod( start, &end ); + // printf("User wrote %s\n", dtoa1(new_double)); + break; } + if ( end == start ) + goto out; + // See if this is a matrix + int idx = 0; + int ncel = pe->nrow * pe->ncol; + if ( ncel ) + { + // Expect the cell index number next + start = end; + for ( ; isspace( *start ); start++ ) + ; + idx = simple_strtol( start, &end, 10 ); + if ( idx >= ncel || idx < 0 ) + { + ret = -EFAULT; + goto out; + } + } + if ( !future ) + { + switch ( pe->type ) + { + case 0: /* int */ + *( (int*)( ( (void*)pLocalEpics ) + pe->idx ) ) = new_int; + break; + case 1: /* double */ + ( (double*)( ( (void*)pLocalEpics ) + pe->idx ) )[ idx ] = + new_double; + break; + } + } + else if ( ( *( (char*)( ( (void*)pLocalEpics ) + pe->mask_idx ) ) ) ) + { // Allow to setup a future only if masked + unsigned long cycle; + start = end; + for ( ; isspace( *start ); start++ ) + ; + // check for gps seconds + double gps = simple_strtod( start, &end ); + if ( end == start ) + { + gps = cycle_gps_time + 5; + cycle = cycleNum; + } + else + { + // Convert gps time + unsigned long gps_int = gps; + gps -= gps_int; + cycle = gps * CYCLE_PER_SECOND; + gps = gps_int; + } + // Add new future setpoint + // Find first available slot + int i; + static DEFINE_SPINLOCK( fut_lock ); + spin_lock( &fut_lock ); + for ( i = 0; + ( i < MAX_PROC_FUTURES ) && proc_futures[ i ].proc_epics; + i++ ) + ; + if ( i == MAX_PROC_FUTURES ) + { + spin_unlock( &fut_lock ); + ret = -ENOMEM; + } + else + { + // Found a slot + proc_futures[ i ].cycle = cycle; + proc_futures[ i ].gps = gps; + proc_futures[ i ].val = pe->type ? new_double : new_int; + proc_futures[ i ].idx = idx; + + // This pointer has to be set last; Indicates a vailid entry for + // the real-time code in controller.c + proc_futures[ i ].proc_epics = + pe; // FE code reads/writes this variable + spin_unlock( &fut_lock ); + } + } + else + ret = -EFAULT; + } out: - free_page((unsigned long)page); - return ret; + free_page( (unsigned long)page ); + return ret; } /// Routine to read the /proc/{model}/epics/futures files. \n \n /// -// :TODO: the function does not check for buffer overflow, Linux kernel catches it though, +// :TODO: the function does not check for buffer overflow, Linux kernel catches +// it though, // when proc_futures contains too many entries. int -procfile_futures_read(char *buffer, - char **buffer_location, - off_t offset, int buffer_length, int *eof, void *data) +procfile_futures_read( char* buffer, + char** buffer_location, + off_t offset, + int buffer_length, + int* eof, + void* data ) { - *buffer = 0; - - if (offset > 0) { - /* we have finished to read, return 0 */ - return 0; - } else { - /* fill the buffer, return the buffer size */ - char b[128]; - int i; - for (i = 0; i < MAX_PROC_FUTURES; i++) { - // Copy the entry to avoid race with the FE code - struct proc_futures pf = proc_futures[i]; - if (pf.proc_epics) { - char s[64]; - char s1[64]; - if (pf.idx) { /* matrix */ - sprintf(b, "%s %s@%s %d %d\n", pf.proc_epics->name, dtoa_r(s, pf.val), dtoa_r(s1, pf.idx), pf.gps, pf.cycle); - } else { - sprintf(b, "%s %s %d %d\n", pf.proc_epics->name, dtoa_r(s, pf.val), pf.gps, pf.cycle); - } - strcat(buffer, b); - } - } - return strlen(buffer); - } - // Never reached -} + *buffer = 0; + if ( offset > 0 ) + { + /* we have finished to read, return 0 */ + return 0; + } + else + { + /* fill the buffer, return the buffer size */ + char b[ 128 ]; + int i; + for ( i = 0; i < MAX_PROC_FUTURES; i++ ) + { + // Copy the entry to avoid race with the FE code + struct proc_futures pf = proc_futures[ i ]; + if ( pf.proc_epics ) + { + char s[ 64 ]; + char s1[ 64 ]; + if ( pf.idx ) + { /* matrix */ + sprintf( b, + "%s %s@%s %d %d\n", + pf.proc_epics->name, + dtoa_r( s, pf.val ), + dtoa_r( s1, pf.idx ), + pf.gps, + pf.cycle ); + } + else + { + sprintf( b, + "%s %s %d %d\n", + pf.proc_epics->name, + dtoa_r( s, pf.val ), + pf.gps, + pf.cycle ); + } + strcat( buffer, b ); + } + } + return strlen( buffer ); + } + // Never reached +} -static const ner = sizeof(proc_epics)/sizeof(struct proc_epics); +static const ner = sizeof( proc_epics ) / sizeof( struct proc_epics ); /// Function to create /proc/{model}/epics/* files /// int -create_epics_proc_files() { - int i; - - for (i = 0; i < ner; i++) proc_epics_entry[i] = 0; - - for (i = 0; i < ner; i++) { - //printf("%s\n", proc_epics[i].name); - proc_epics_entry[i] = create_proc_entry(proc_epics[i].name, PROC_MODE, proc_epics_dir_entry); - if (proc_epics_entry[i] == NULL) { - remove_epics_proc_files(); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics/%s\n", SYSTEM_NAME_STRING_LOWER, proc_epics[i].name); - return 0; - } - proc_epics_entry[i]->mode = S_IFREG | S_IRUGO; - switch (proc_epics[i].in) { - case 0: - proc_epics_entry[i]->write_proc = procfile_epics_write; - proc_epics_entry[i]->mode |= S_IWUGO; - // Fall through - case 1: - proc_epics_entry[i]->read_proc = procfile_epics_read; - break; - } - proc_epics_entry[i]->uid = PROC_UID; - proc_epics_entry[i]->gid = 0; - unsigned int ncel = proc_epics[i].nrow * proc_epics[i].ncol; // Enough space to deal with the matrix - proc_epics_entry[i]->size = ncel? 64 * ncel: 128; - proc_epics_entry[i]->data = proc_epics + i; - } - proc_futures_entry = create_proc_entry("futures", PROC_MODE, proc_epics_dir_entry); - if (proc_futures_entry == NULL) { - remove_epics_proc_files(); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics/futures\n", SYSTEM_NAME_STRING_LOWER); - return 0; - } - proc_futures_entry->mode = S_IFREG | S_IRUGO; - proc_futures_entry->uid = PROC_UID; - proc_futures_entry->gid = 0; - proc_futures_entry->size = 10240; - proc_futures_entry->read_proc = procfile_futures_read; - return 1; +create_epics_proc_files( ) +{ + int i; + + for ( i = 0; i < ner; i++ ) + proc_epics_entry[ i ] = 0; + + for ( i = 0; i < ner; i++ ) + { + // printf("%s\n", proc_epics[i].name); + proc_epics_entry[ i ] = create_proc_entry( + proc_epics[ i ].name, PROC_MODE, proc_epics_dir_entry ); + if ( proc_epics_entry[ i ] == NULL ) + { + remove_epics_proc_files( ); + printk( KERN_ALERT + "Error: Could not initialize /proc/%s/epics/%s\n", + SYSTEM_NAME_STRING_LOWER, + proc_epics[ i ].name ); + return 0; + } + proc_epics_entry[ i ]->mode = S_IFREG | S_IRUGO; + switch ( proc_epics[ i ].in ) + { + case 0: + proc_epics_entry[ i ]->write_proc = procfile_epics_write; + proc_epics_entry[ i ]->mode |= S_IWUGO; + // Fall through + case 1: + proc_epics_entry[ i ]->read_proc = procfile_epics_read; + break; + } + proc_epics_entry[ i ]->uid = PROC_UID; + proc_epics_entry[ i ]->gid = 0; + unsigned int ncel = proc_epics[ i ].nrow * + proc_epics[ i ].ncol; // Enough space to deal with the matrix + proc_epics_entry[ i ]->size = ncel ? 64 * ncel : 128; + proc_epics_entry[ i ]->data = proc_epics + i; + } + proc_futures_entry = + create_proc_entry( "futures", PROC_MODE, proc_epics_dir_entry ); + if ( proc_futures_entry == NULL ) + { + remove_epics_proc_files( ); + printk( KERN_ALERT + "Error: Could not initialize /proc/%s/epics/futures\n", + SYSTEM_NAME_STRING_LOWER ); + return 0; + } + proc_futures_entry->mode = S_IFREG | S_IRUGO; + proc_futures_entry->uid = PROC_UID; + proc_futures_entry->gid = 0; + proc_futures_entry->size = 10240; + proc_futures_entry->read_proc = procfile_futures_read; + return 1; } /// Function to delete /proc/{model}/epics/* files /// -void remove_epics_proc_files() { - int i; - for (i = 0; i < ner; i++) - if (proc_epics_entry[i] != NULL) { - remove_proc_entry(proc_epics[i].name, proc_epics_dir_entry); - proc_epics_entry[i] = 0; - } - remove_proc_entry("futures", proc_epics_dir_entry); +void +remove_epics_proc_files( ) +{ + int i; + for ( i = 0; i < ner; i++ ) + if ( proc_epics_entry[ i ] != NULL ) + { + remove_proc_entry( proc_epics[ i ].name, proc_epics_dir_entry ); + proc_epics_entry[ i ] = 0; + } + remove_proc_entry( "futures", proc_epics_dir_entry ); } -// MAIN routine: Code starting point **************************************************************** +// MAIN routine: Code starting point +// **************************************************************** #ifdef ADC_MASTER int need_to_load_IOP_first; -EXPORT_SYMBOL(need_to_load_IOP_first); +EXPORT_SYMBOL( need_to_load_IOP_first ); #endif #ifdef ADC_SLAVE extern int need_to_load_IOP_first; #endif -extern void set_fe_code_idle(void *(*ptr)(void *), unsigned int cpu); -extern void msleep(unsigned int); +extern void set_fe_code_idle( void* ( *ptr )(void*), unsigned int cpu ); +extern void msleep( unsigned int ); /// Startup function for initialization of kernel module. -int init_module (void) +int +init_module( void ) { - int status; - int ii,jj,kk; /// @param ii,jj,kk default loop counters - char fname[128]; /// @param fname[128] Name of shared mem area to allocate for DAQ data - int cards; /// @param cards Number of PCIe cards found on bus + int status; + int ii, jj, kk; /// @param ii,jj,kk default loop counters + char fname[ 128 ]; /// @param fname[128] Name of shared mem area to allocate + /// for DAQ data + int cards; /// @param cards Number of PCIe cards found on bus #ifdef ADC_SLAVE - int adcCnt; /// @param adcCnt Number of ADC cards found by slave model. - int dacCnt; /// @param dacCnt Number of 16bit DAC cards found by slave model. - int dac18Cnt; /// @param dac18Cnt Number of 18bit DAC cards found by slave model. - int dac20Cnt; /// @param dac20Cnt Number of 20bit DAC cards found by slave model. - int doCnt; /// @param doCnt Total number of digital I/O cards found by slave model. - int do32Cnt; /// @param do32Cnt Total number of Contec 32 bit DIO cards found by slave model. - int doIIRO16Cnt; /// @param doIIRO16Cnt Total number of Acces I/O 16 bit relay cards found by slave model. - int doIIRO8Cnt; /// @param doIIRO8Cnt Total number of Acces I/O 8 bit relay cards found by slave model. - int cdo64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit output sections mapped by slave model. - int cdi64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit input sections mapped by slave model. + int adcCnt; /// @param adcCnt Number of ADC cards found by slave model. + int dacCnt; /// @param dacCnt Number of 16bit DAC cards found by slave + /// model. + int dac18Cnt; /// @param dac18Cnt Number of 18bit DAC cards found by slave + /// model. + int dac20Cnt; /// @param dac20Cnt Number of 20bit DAC cards found by slave + /// model. + int doCnt; /// @param doCnt Total number of digital I/O cards found by slave + /// model. + int do32Cnt; /// @param do32Cnt Total number of Contec 32 bit DIO cards + /// found by slave model. + int doIIRO16Cnt; /// @param doIIRO16Cnt Total number of Acces I/O 16 bit + /// relay cards found by slave model. + int doIIRO8Cnt; /// @param doIIRO8Cnt Total number of Acces I/O 8 bit relay + /// cards found by slave model. + int cdo64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit + /// output sections mapped by slave model. + int cdi64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit + /// input sections mapped by slave model. #endif - int ret; /// @param ret Return value from various Malloc calls to allocate memory. - int cnt; - extern int cpu_down(unsigned int); /// @param cpu_down CPU shutdown call. - extern int is_cpu_taken_by_rcg_model(unsigned int cpu); /// @param is_cpu_taken_by_rcg_model Check to verify CPU availability for shutdown. - - kk = 0; + int ret; /// @param ret Return value from various Malloc calls to allocate + /// memory. + int cnt; + extern int cpu_down( unsigned int ); /// @param cpu_down CPU shutdown call. + extern int is_cpu_taken_by_rcg_model( + unsigned int cpu ); /// @param is_cpu_taken_by_rcg_model Check to verify + /// CPU availability for shutdown. + + kk = 0; #ifdef SPECIFIC_CPU #define CPUID SPECIFIC_CPU -#else -#define CPUID 1 +#else +#define CPUID 1 #endif #ifndef NO_CPU_SHUTDOWN - // See if our CPU core is free - if (is_cpu_taken_by_rcg_model(CPUID)) { - printk(KERN_ALERT "Error: CPU %d already taken\n", CPUID); - return -1; - } + // See if our CPU core is free + if ( is_cpu_taken_by_rcg_model( CPUID ) ) + { + printk( KERN_ALERT "Error: CPU %d already taken\n", CPUID ); + return -1; + } #endif #ifdef ADC_SLAVE - need_to_load_IOP_first = 0; + need_to_load_IOP_first = 0; #endif #ifdef DOLPHIN_TEST - status = init_dolphin(2); - if (status != 0) { - return -1; - } + status = init_dolphin( 2 ); + if ( status != 0 ) + { + return -1; + } #endif -return 0; - - // Create /proc filesystem tree - proc_dir_entry = proc_mkdir(SYSTEM_NAME_STRING_LOWER, NULL); - if (proc_dir_entry == NULL) { - printk(KERN_ALERT "Error: Could not initialize /proc/%s\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_entry = create_proc_entry("status", PROC_MODE, proc_dir_entry); - if (proc_entry == NULL) { - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/status\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_gps_entry = create_proc_entry("gps", PROC_MODE, proc_dir_entry); - if (proc_gps_entry == NULL) { - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/gps\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_epics_dir_entry = proc_mkdir("epics", proc_dir_entry); - if (proc_epics_dir_entry == NULL) { - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - printk(KERN_ALERT "Error: Could not initialize /proc/%s/epics\n", SYSTEM_NAME_STRING_LOWER); - return -ENOMEM; - } - - proc_entry->read_proc = procfile_status_read; - proc_entry->mode = S_IFREG | S_IRUGO; - proc_entry->uid = PROC_UID; - proc_entry->gid = 0; - proc_entry->size = 10240; - - proc_gps_entry->read_proc = procfile_gps_read; - proc_gps_entry->mode = S_IFREG | S_IRUGO; - proc_gps_entry->uid = PROC_UID; - proc_gps_entry->gid = 0; - proc_gps_entry->size = 128; - proc_gps_entry->data = &cycle_gps_time; - - // Create all /proc/{system}/epics/* files, one file per existing Epics channel - if (create_epics_proc_files() == 0) { - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); - return -ENOMEM; - } - - printf("startup time is %ld\n", current_time()); - jj = 0; - printf("cpu clock %u\n",cpu_khz); - - - ret = mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _epics_shm = (unsigned char *)(kmalloc_area[ret]); - printf("EPICSM at 0x%x\n", _epics_shm); - ret = mbuf_allocate_area("ipc", 4*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); - return -1; - } - _ipc_shm = (unsigned char *)(kmalloc_area[ret]); - - printf("IPC at 0x%x\n",_ipc_shm); - ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000); - printf("IOMEM at 0x%x size 0x%x\n",(_ipc_shm + 0x4000),sizeof(IO_MEM_DATA)); - - -// If DAQ is via shared memory (Framebuilder code running on same machine or MX networking is used) -// attach DAQ shared memory location. - sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER); - ret = mbuf_allocate_area(fname, 64*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _daq_shm = (unsigned char *)(kmalloc_area[ret]); - // printf("Allocated daq shmem; set at 0x%x\n", _daq_shm); - printf("DAQSM at 0x%x\n",_daq_shm); - daqPtr = (struct rmIpcStr *) _daq_shm; - -// Open new GDS TP data shared memory in support of ZMQ - sprintf(fname, "%s_gds", SYSTEM_NAME_STRING_LOWER); - ret = mbuf_allocate_area(fname, 16*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _gds_shm = (unsigned char *)(kmalloc_area[ret]); - printf("GDSSM at 0x%x\n",_gds_shm); - - // Find and initialize all PCI I/O modules ******************************************************* - // Following I/O card info is from feCode - cards = sizeof(cards_used)/sizeof(cards_used[0]); - printf("configured to use %d cards\n", cards); - cdsPciModules.cards = cards; - cdsPciModules.cards_used = cards_used; - //return -1; - printf("Initializing PCI Modules\n"); - cdsPciModules.adcCount = 0; - cdsPciModules.dacCount = 0; - cdsPciModules.dioCount = 0; - cdsPciModules.doCount = 0; + return 0; + + // Create /proc filesystem tree + proc_dir_entry = proc_mkdir( SYSTEM_NAME_STRING_LOWER, NULL ); + if ( proc_dir_entry == NULL ) + { + printk( KERN_ALERT "Error: Could not initialize /proc/%s\n", + SYSTEM_NAME_STRING_LOWER ); + return -ENOMEM; + } + + proc_entry = create_proc_entry( "status", PROC_MODE, proc_dir_entry ); + if ( proc_entry == NULL ) + { + remove_proc_entry( SYSTEM_NAME_STRING_LOWER, NULL ); + printk( KERN_ALERT "Error: Could not initialize /proc/%s/status\n", + SYSTEM_NAME_STRING_LOWER ); + return -ENOMEM; + } + + proc_gps_entry = create_proc_entry( "gps", PROC_MODE, proc_dir_entry ); + if ( proc_gps_entry == NULL ) + { + remove_proc_entry( "status", proc_dir_entry ); + remove_proc_entry( SYSTEM_NAME_STRING_LOWER, NULL ); + printk( KERN_ALERT "Error: Could not initialize /proc/%s/gps\n", + SYSTEM_NAME_STRING_LOWER ); + return -ENOMEM; + } + + proc_epics_dir_entry = proc_mkdir( "epics", proc_dir_entry ); + if ( proc_epics_dir_entry == NULL ) + { + remove_proc_entry( "gps", proc_dir_entry ); + remove_proc_entry( "status", proc_dir_entry ); + remove_proc_entry( SYSTEM_NAME_STRING_LOWER, NULL ); + printk( KERN_ALERT "Error: Could not initialize /proc/%s/epics\n", + SYSTEM_NAME_STRING_LOWER ); + return -ENOMEM; + } + + proc_entry->read_proc = procfile_status_read; + proc_entry->mode = S_IFREG | S_IRUGO; + proc_entry->uid = PROC_UID; + proc_entry->gid = 0; + proc_entry->size = 10240; + + proc_gps_entry->read_proc = procfile_gps_read; + proc_gps_entry->mode = S_IFREG | S_IRUGO; + proc_gps_entry->uid = PROC_UID; + proc_gps_entry->gid = 0; + proc_gps_entry->size = 128; + proc_gps_entry->data = &cycle_gps_time; + + // Create all /proc/{system}/epics/* files, one file per existing Epics + // channel + if ( create_epics_proc_files( ) == 0 ) + { + remove_proc_entry( "epics", proc_dir_entry ); + remove_proc_entry( "gps", proc_dir_entry ); + remove_proc_entry( "status", proc_dir_entry ); + remove_proc_entry( SYSTEM_NAME_STRING_LOWER, NULL ); + return -ENOMEM; + } + + printf( "startup time is %ld\n", current_time( ) ); + jj = 0; + printf( "cpu clock %u\n", cpu_khz ); + + ret = mbuf_allocate_area( SYSTEM_NAME_STRING_LOWER, 64 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", ret ); + return -1; + } + _epics_shm = (unsigned char*)( kmalloc_area[ ret ] ); + printf( "EPICSM at 0x%x\n", _epics_shm ); + ret = mbuf_allocate_area( "ipc", 4 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printf( "mbuf_allocate_area(ipc) failed; ret = %d\n", ret ); + return -1; + } + _ipc_shm = (unsigned char*)( kmalloc_area[ ret ] ); + + printf( "IPC at 0x%x\n", _ipc_shm ); + ioMemData = (IO_MEM_DATA*)( _ipc_shm + 0x4000 ); + printf( "IOMEM at 0x%x size 0x%x\n", + ( _ipc_shm + 0x4000 ), + sizeof( IO_MEM_DATA ) ); + + // If DAQ is via shared memory (Framebuilder code running on same machine or + // MX networking is used) attach DAQ shared memory location. + sprintf( fname, "%s_daq", SYSTEM_NAME_STRING_LOWER ); + ret = mbuf_allocate_area( fname, 64 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", ret ); + return -1; + } + _daq_shm = (unsigned char*)( kmalloc_area[ ret ] ); + // printf("Allocated daq shmem; set at 0x%x\n", _daq_shm); + printf( "DAQSM at 0x%x\n", _daq_shm ); + daqPtr = (struct rmIpcStr*)_daq_shm; + + // Open new GDS TP data shared memory in support of ZMQ + sprintf( fname, "%s_gds", SYSTEM_NAME_STRING_LOWER ); + ret = mbuf_allocate_area( fname, 16 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", ret ); + return -1; + } + _gds_shm = (unsigned char*)( kmalloc_area[ ret ] ); + printf( "GDSSM at 0x%x\n", _gds_shm ); + + // Find and initialize all PCI I/O modules + // ******************************************************* Following I/O + // card info is from feCode + cards = sizeof( cards_used ) / sizeof( cards_used[ 0 ] ); + printf( "configured to use %d cards\n", cards ); + cdsPciModules.cards = cards; + cdsPciModules.cards_used = cards_used; + // return -1; + printf( "Initializing PCI Modules\n" ); + cdsPciModules.adcCount = 0; + cdsPciModules.dacCount = 0; + cdsPciModules.dioCount = 0; + cdsPciModules.doCount = 0; #ifndef ADC_SLAVE - // Call PCI initialization routine in map.c file. - status = mapPciModules(&cdsPciModules); - //return 0; + // Call PCI initialization routine in map.c file. + status = mapPciModules( &cdsPciModules ); + // return 0; #endif #ifdef ADC_SLAVE -// If running as a slave process, I/O card information is via ipc shared memory - printf("%d PCI cards found\n",ioMemData->totalCards); - status = 0; - adcCnt = 0; - dacCnt = 0; - dac18Cnt = 0; - dac20Cnt = 0; - doCnt = 0; - do32Cnt = 0; - cdo64Cnt = 0; - cdi64Cnt = 0; - doIIRO16Cnt = 0; - doIIRO8Cnt = 0; - - // Have to search thru all cards and find desired instance for application - // Master will map ADC cards first, then DAC and finally DIO - for(ii=0;ii<ioMemData->totalCards;ii++) - { - /* - printf("Model %d = %d\n",ii,ioMemData->model[ii]); - */ - for(jj=0;jj<cards;jj++) - { - /* - printf("Model %d = %d, type = %d, instance = %d, dacCnt = %d \n", - ii,ioMemData->model[ii], - cdsPciModules.cards_used[jj].type, - cdsPciModules.cards_used[jj].instance, - dacCnt); - */ - switch(ioMemData->model[ii]) - { - case GSC_16AI64SSA: - if((cdsPciModules.cards_used[jj].type == GSC_16AI64SSA) && - (cdsPciModules.cards_used[jj].instance == adcCnt)) - { - printf("Found ADC at %d %d\n",jj,ioMemData->ipc[ii]); - kk = cdsPciModules.adcCount; - cdsPciModules.adcType[kk] = GSC_16AI64SSA; - cdsPciModules.adcConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.adcCount ++; - status ++; - } - break; - case GSC_16AO16: - if((cdsPciModules.cards_used[jj].type == GSC_16AO16) && - (cdsPciModules.cards_used[jj].instance == dacCnt)) - { - printf("Found DAC at %d %d\n",jj,ioMemData->ipc[ii]); - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_16AO16; - cdsPciModules.dacConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.pci_dac[kk] = (long)(ioMemData->iodata[ii]); - cdsPciModules.dacCount ++; - status ++; - } - break; - case GSC_18AO8: - if((cdsPciModules.cards_used[jj].type == GSC_18AO8) && - (cdsPciModules.cards_used[jj].instance == dac18Cnt)) - { - printf("Found DAC at %d %d\n",jj,ioMemData->ipc[ii]); - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_18AO8; - cdsPciModules.dacConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.pci_dac[kk] = (long)(ioMemData->iodata[ii]); - cdsPciModules.dacCount ++; - status ++; - } - break; - case GSC_20AO8: - if(cdsPciModules.cards_used[jj].type == GSC_20AO8 && - (cdsPciModules.cards_used[jj].instance == dac20Cnt)) - { - printf("Found DAC at %d %d\n",jj,ioMemData->ipc[ii]); - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_20AO8; - cdsPciModules.dacConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.pci_dac[kk] = (long)(ioMemData->iodata[ii]); - cdsPciModules.dacCount ++; - status ++; - } + // If running as a slave process, I/O card information is via ipc shared + // memory + printf( "%d PCI cards found\n", ioMemData->totalCards ); + status = 0; + adcCnt = 0; + dacCnt = 0; + dac18Cnt = 0; + dac20Cnt = 0; + doCnt = 0; + do32Cnt = 0; + cdo64Cnt = 0; + cdi64Cnt = 0; + doIIRO16Cnt = 0; + doIIRO8Cnt = 0; + + // Have to search thru all cards and find desired instance for application + // Master will map ADC cards first, then DAC and finally DIO + for ( ii = 0; ii < ioMemData->totalCards; ii++ ) + { + /* + printf("Model %d = %d\n",ii,ioMemData->model[ii]); + */ + for ( jj = 0; jj < cards; jj++ ) + { + /* + printf("Model %d = %d, type = %d, instance = %d, dacCnt = %d \n", + ii,ioMemData->model[ii], + cdsPciModules.cards_used[jj].type, + cdsPciModules.cards_used[jj].instance, + dacCnt); + */ + switch ( ioMemData->model[ ii ] ) + { + case GSC_16AI64SSA: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_16AI64SSA ) && + ( cdsPciModules.cards_used[ jj ].instance == adcCnt ) ) + { + printf( "Found ADC at %d %d\n", jj, ioMemData->ipc[ ii ] ); + kk = cdsPciModules.adcCount; + cdsPciModules.adcType[ kk ] = GSC_16AI64SSA; + cdsPciModules.adcConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.adcCount++; + status++; + } + break; + case GSC_16AO16: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_16AO16 ) && + ( cdsPciModules.cards_used[ jj ].instance == dacCnt ) ) + { + printf( "Found DAC at %d %d\n", jj, ioMemData->ipc[ ii ] ); + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_16AO16; + cdsPciModules.dacConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.pci_dac[ kk ] = + (long)( ioMemData->iodata[ ii ] ); + cdsPciModules.dacCount++; + status++; + } + break; + case GSC_18AO8: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_18AO8 ) && + ( cdsPciModules.cards_used[ jj ].instance == dac18Cnt ) ) + { + printf( "Found DAC at %d %d\n", jj, ioMemData->ipc[ ii ] ); + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_18AO8; + cdsPciModules.dacConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.pci_dac[ kk ] = + (long)( ioMemData->iodata[ ii ] ); + cdsPciModules.dacCount++; + status++; + } + break; + case GSC_20AO8: + if ( cdsPciModules.cards_used[ jj ].type == GSC_20AO8 && + ( cdsPciModules.cards_used[ jj ].instance == dac20Cnt ) ) + { + printf( "Found DAC at %d %d\n", jj, ioMemData->ipc[ ii ] ); + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_20AO8; + cdsPciModules.dacConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.pci_dac[ kk ] = + (long)( ioMemData->iodata[ ii ] ); + cdsPciModules.dacCount++; + status++; + } + break; + case CON_6464DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == CON_6464DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + printf( "Found 6464 DIO CONTEC at %d 0x%x\n", + jj, + ioMemData->ipc[ ii ] ); + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDio6464lCount++; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doInstance[ kk ] = doCnt; + status += 2; + } + if ( ( cdsPciModules.cards_used[ jj ].type == CDO64 ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = CDO64; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDio6464lCount++; + cdsPciModules.doInstance[ kk ] = doCnt; + printf( "Found 6464 DOUT CONTEC at %d 0x%x index %d \n", + jj, + ioMemData->ipc[ ii ], + doCnt ); + cdo64Cnt++; + status++; + } + if ( ( cdsPciModules.cards_used[ jj ].type == CDI64 ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + // printf("Found 6464 DIN CONTEC at %d + // 0x%x\n",jj,ioMemData->ipc[ii]); + cdsPciModules.doType[ kk ] = CDI64; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doInstance[ kk ] = doCnt; + cdsPciModules.doCount++; + printf( "Found 6464 DIN CONTEC at %d 0x%x index %d \n", + jj, + ioMemData->ipc[ ii ], + doCnt ); + cdsPciModules.cDio6464lCount++; + cdi64Cnt++; + status++; + } + break; + case CON_32DO: + if ( ( cdsPciModules.cards_used[ jj ].type == CON_32DO ) && + ( cdsPciModules.cards_used[ jj ].instance == do32Cnt ) ) + { + kk = cdsPciModules.doCount; + printf( "Found 32 DO CONTEC at %d 0x%x\n", + jj, + ioMemData->ipc[ ii ] ); + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDo32lCount++; + cdsPciModules.doInstance[ kk ] = do32Cnt; + status++; + } + break; + case ACS_16DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == ACS_16DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == + doIIRO16Cnt ) ) + { + kk = cdsPciModules.doCount; + printf( "Found Access IIRO-16 at %d 0x%x\n", + jj, + ioMemData->ipc[ ii ] ); + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.iiroDio1Count++; + cdsPciModules.doInstance[ kk ] = doIIRO16Cnt; + status++; + } break; - case CON_6464DIO: - if((cdsPciModules.cards_used[jj].type == CON_6464DIO) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - printf("Found 6464 DIO CONTEC at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDio6464lCount ++; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doInstance[kk] = doCnt; - status += 2; - } - if((cdsPciModules.cards_used[jj].type == CDO64) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = CDO64; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDio6464lCount ++; - cdsPciModules.doInstance[kk] = doCnt; - printf("Found 6464 DOUT CONTEC at %d 0x%x index %d \n",jj,ioMemData->ipc[ii],doCnt); - cdo64Cnt ++; - status ++; - } - if((cdsPciModules.cards_used[jj].type == CDI64) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - // printf("Found 6464 DIN CONTEC at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = CDI64; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doInstance[kk] = doCnt; - cdsPciModules.doCount ++; - printf("Found 6464 DIN CONTEC at %d 0x%x index %d \n",jj,ioMemData->ipc[ii],doCnt); - cdsPciModules.cDio6464lCount ++; - cdi64Cnt ++; - status ++; - } - break; - case CON_32DO: - if((cdsPciModules.cards_used[jj].type == CON_32DO) && - (cdsPciModules.cards_used[jj].instance == do32Cnt)) - { - kk = cdsPciModules.doCount; - printf("Found 32 DO CONTEC at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDo32lCount ++; - cdsPciModules.doInstance[kk] = do32Cnt; - status ++; - } - break; - case ACS_16DIO: - if((cdsPciModules.cards_used[jj].type == ACS_16DIO) && - (cdsPciModules.cards_used[jj].instance == doIIRO16Cnt)) - { - kk = cdsPciModules.doCount; - printf("Found Access IIRO-16 at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.iiroDio1Count ++; - cdsPciModules.doInstance[kk] = doIIRO16Cnt; - status ++; - } - break; - case ACS_8DIO: - if((cdsPciModules.cards_used[jj].type == ACS_8DIO) && - (cdsPciModules.cards_used[jj].instance == doIIRO8Cnt)) - { - kk = cdsPciModules.doCount; - printf("Found Access IIRO-8 at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.iiroDioCount ++; - cdsPciModules.doInstance[kk] = doIIRO8Cnt; - status ++; - } - break; - default: - break; - } - } - if(ioMemData->model[ii] == GSC_16AI64SSA) adcCnt ++; - if(ioMemData->model[ii] == GSC_16AO16) dacCnt ++; - if(ioMemData->model[ii] == GSC_18AO8) dac18Cnt ++; - if(ioMemData->model[ii] == GSC_20AO8) dac20Cnt ++; - if(ioMemData->model[ii] == CON_6464DIO) doCnt ++; - if(ioMemData->model[ii] == CON_32DO) do32Cnt ++; - if(ioMemData->model[ii] == ACS_16DIO) doIIRO16Cnt ++; - if(ioMemData->model[ii] == ACS_8DIO) doIIRO8Cnt ++; - } - // If no ADC cards were found, then SLAVE cannot run - if(!cdsPciModules.adcCount) - { - printf("No ADC cards found - exiting\n"); - return -1; - } - // This did not quite work for some reason - // Need to find a way to handle skipped DAC cards in slaves - //cdsPciModules.dacCount = ioMemData->dacCount; + case ACS_8DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == ACS_8DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == doIIRO8Cnt ) ) + { + kk = cdsPciModules.doCount; + printf( "Found Access IIRO-8 at %d 0x%x\n", + jj, + ioMemData->ipc[ ii ] ); + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.iiroDioCount++; + cdsPciModules.doInstance[ kk ] = doIIRO8Cnt; + status++; + } + break; + default: + break; + } + } + if ( ioMemData->model[ ii ] == GSC_16AI64SSA ) + adcCnt++; + if ( ioMemData->model[ ii ] == GSC_16AO16 ) + dacCnt++; + if ( ioMemData->model[ ii ] == GSC_18AO8 ) + dac18Cnt++; + if ( ioMemData->model[ ii ] == GSC_20AO8 ) + dac20Cnt++; + if ( ioMemData->model[ ii ] == CON_6464DIO ) + doCnt++; + if ( ioMemData->model[ ii ] == CON_32DO ) + do32Cnt++; + if ( ioMemData->model[ ii ] == ACS_16DIO ) + doIIRO16Cnt++; + if ( ioMemData->model[ ii ] == ACS_8DIO ) + doIIRO8Cnt++; + } + // If no ADC cards were found, then SLAVE cannot run + if ( !cdsPciModules.adcCount ) + { + printf( "No ADC cards found - exiting\n" ); + return -1; + } + // This did not quite work for some reason + // Need to find a way to handle skipped DAC cards in slaves + // cdsPciModules.dacCount = ioMemData->dacCount; #endif - printf("%d PCI cards found \n",status); - if(status < cards) - { - printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); - cardCountErr = 1; - } - - // Print out all the I/O information - printf("***************************************************************************\n"); + printf( "%d PCI cards found \n", status ); + if ( status < cards ) + { + printf( " ERROR **** Did not find correct number of cards! Expected %d " + "and Found %d\n", + cards, + status ); + cardCountErr = 1; + } + + // Print out all the I/O information + printf( "******************************************************************" + "*********\n" ); #ifdef ADC_MASTER - // Master send module counds to SLAVE via ipc shm - ioMemData->totalCards = status; - ioMemData->adcCount = cdsPciModules.adcCount; - ioMemData->dacCount = cdsPciModules.dacCount; - ioMemData->bioCount = cdsPciModules.doCount; - // kk will act as ioMem location counter for mapping modules - kk = cdsPciModules.adcCount; + // Master send module counds to SLAVE via ipc shm + ioMemData->totalCards = status; + ioMemData->adcCount = cdsPciModules.adcCount; + ioMemData->dacCount = cdsPciModules.dacCount; + ioMemData->bioCount = cdsPciModules.doCount; + // kk will act as ioMem location counter for mapping modules + kk = cdsPciModules.adcCount; #endif - printf("%d ADC cards found\n",cdsPciModules.adcCount); - for(ii=0;ii<cdsPciModules.adcCount;ii++) - { + printf( "%d ADC cards found\n", cdsPciModules.adcCount ); + for ( ii = 0; ii < cdsPciModules.adcCount; ii++ ) + { #ifdef ADC_MASTER - // MASTER maps ADC modules first in ipc shm for SLAVES - ioMemData->model[ii] = cdsPciModules.adcType[ii]; - ioMemData->ipc[ii] = ii; // ioData memory buffer location for SLAVE to use + // MASTER maps ADC modules first in ipc shm for SLAVES + ioMemData->model[ ii ] = cdsPciModules.adcType[ ii ]; + ioMemData->ipc[ ii ] = + ii; // ioData memory buffer location for SLAVE to use #endif - if(cdsPciModules.adcType[ii] == GSC_18AISS6C) - { - printf("\tADC %d is a GSC_18AISS6C module\n",ii); - printf("\t\tChannels = 6 \n"); - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.adcConfig[ii] & 0xfff)); - } - if(cdsPciModules.adcType[ii] == GSC_16AI64SSA) - { - printf("\tADC %d is a GSC_16AI64SSA module\n",ii); - if((cdsPciModules.adcConfig[ii] & 0x10000) > 0) jj = 32; - else jj = 64; - printf("\t\tChannels = %d \n",jj); - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.adcConfig[ii] & 0xfff)); - } + if ( cdsPciModules.adcType[ ii ] == GSC_18AISS6C ) + { + printf( "\tADC %d is a GSC_18AISS6C module\n", ii ); + printf( "\t\tChannels = 6 \n" ); + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsPciModules.adcConfig[ ii ] & 0xfff ) ); } - printf("***************************************************************************\n"); - printf("%d DAC cards found\n",cdsPciModules.dacCount); - for(ii=0;ii<cdsPciModules.dacCount;ii++) + if ( cdsPciModules.adcType[ ii ] == GSC_16AI64SSA ) { - if(cdsPciModules.dacType[ii] == GSC_18AO8) - { - printf("\tDAC %d is a GSC_18AO8 module\n",ii); - printf("\t\tFirmware Revision: %d\n",(cdsPciModules.dacConfig[ii] & 0xffff)); - } - if(cdsPciModules.dacType[ii] == GSC_20AO8) - { - printf("\tDAC %d is a GSC_20AO8 module\n",ii); - printf("\t\tFirmware Revision: %d\n",(cdsPciModules.dacConfig[ii] & 0xffff)); - } - if(cdsPciModules.dacType[ii] == GSC_16AO16) - { - printf("\tDAC %d is a GSC_16AO16 module\n",ii); - if((cdsPciModules.dacConfig[ii] & 0x10000) == 0x10000) jj = 8; - if((cdsPciModules.dacConfig[ii] & 0x20000) == 0x20000) jj = 12; - if((cdsPciModules.dacConfig[ii] & 0x30000) == 0x30000) jj = 16; - printf("\t\tChannels = %d \n",jj); - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x0000) - { - printf("\t\tFilters = None\n"); - } - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x40000) - { - printf("\t\tFilters = 10kHz\n"); - } - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x80000) - { - printf("\t\tFilters = 100kHz\n"); - } - if((cdsPciModules.dacConfig[ii] & 0x100000) == 0x100000) - { - printf("\t\tOutput Type = Differential\n"); - } - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.dacConfig[ii] & 0xfff)); - } + printf( "\tADC %d is a GSC_16AI64SSA module\n", ii ); + if ( ( cdsPciModules.adcConfig[ ii ] & 0x10000 ) > 0 ) + jj = 32; + else + jj = 64; + printf( "\t\tChannels = %d \n", jj ); + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsPciModules.adcConfig[ ii ] & 0xfff ) ); + } + } + printf( "******************************************************************" + "*********\n" ); + printf( "%d DAC cards found\n", cdsPciModules.dacCount ); + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + { + if ( cdsPciModules.dacType[ ii ] == GSC_18AO8 ) + { + printf( "\tDAC %d is a GSC_18AO8 module\n", ii ); + printf( "\t\tFirmware Revision: %d\n", + ( cdsPciModules.dacConfig[ ii ] & 0xffff ) ); + } + if ( cdsPciModules.dacType[ ii ] == GSC_20AO8 ) + { + printf( "\tDAC %d is a GSC_20AO8 module\n", ii ); + printf( "\t\tFirmware Revision: %d\n", + ( cdsPciModules.dacConfig[ ii ] & 0xffff ) ); + } + if ( cdsPciModules.dacType[ ii ] == GSC_16AO16 ) + { + printf( "\tDAC %d is a GSC_16AO16 module\n", ii ); + if ( ( cdsPciModules.dacConfig[ ii ] & 0x10000 ) == 0x10000 ) + jj = 8; + if ( ( cdsPciModules.dacConfig[ ii ] & 0x20000 ) == 0x20000 ) + jj = 12; + if ( ( cdsPciModules.dacConfig[ ii ] & 0x30000 ) == 0x30000 ) + jj = 16; + printf( "\t\tChannels = %d \n", jj ); + if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x0000 ) + { + printf( "\t\tFilters = None\n" ); + } + if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x40000 ) + { + printf( "\t\tFilters = 10kHz\n" ); + } + if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x80000 ) + { + printf( "\t\tFilters = 100kHz\n" ); + } + if ( ( cdsPciModules.dacConfig[ ii ] & 0x100000 ) == 0x100000 ) + { + printf( "\t\tOutput Type = Differential\n" ); + } + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsPciModules.dacConfig[ ii ] & 0xfff ) ); + } #ifdef ADC_MASTER - // Pass DAC info to SLAVE processes - ioMemData->model[kk] = cdsPciModules.dacType[ii]; - ioMemData->ipc[kk] = kk; - // Following used by MASTER to point to ipc memory for inputting DAC data from SLAVES - cdsPciModules.dacConfig[ii] = kk; -printf("MASTER DAC SLOT %d %d\n",ii,cdsPciModules.dacConfig[ii]); - kk ++; + // Pass DAC info to SLAVE processes + ioMemData->model[ kk ] = cdsPciModules.dacType[ ii ]; + ioMemData->ipc[ kk ] = kk; + // Following used by MASTER to point to ipc memory for inputting DAC + // data from SLAVES + cdsPciModules.dacConfig[ ii ] = kk; + printf( "MASTER DAC SLOT %d %d\n", ii, cdsPciModules.dacConfig[ ii ] ); + kk++; #endif - } - printf("***************************************************************************\n"); - printf("%d DIO cards found\n",cdsPciModules.dioCount); - printf("***************************************************************************\n"); - printf("%d IIRO-8 Isolated DIO cards found\n",cdsPciModules.iiroDioCount); - printf("***************************************************************************\n"); - printf("%d IIRO-16 Isolated DIO cards found\n",cdsPciModules.iiroDio1Count); - printf("***************************************************************************\n"); - printf("%d Contec 32ch PCIe DO cards found\n",cdsPciModules.cDo32lCount); - printf("%d Contec PCIe DIO1616 cards found\n",cdsPciModules.cDio1616lCount); - printf("%d Contec PCIe DIO6464 cards found\n",cdsPciModules.cDio6464lCount); - printf("%d DO cards found\n",cdsPciModules.doCount); + } + printf( "******************************************************************" + "*********\n" ); + printf( "%d DIO cards found\n", cdsPciModules.dioCount ); + printf( "******************************************************************" + "*********\n" ); + printf( "%d IIRO-8 Isolated DIO cards found\n", + cdsPciModules.iiroDioCount ); + printf( "******************************************************************" + "*********\n" ); + printf( "%d IIRO-16 Isolated DIO cards found\n", + cdsPciModules.iiroDio1Count ); + printf( "******************************************************************" + "*********\n" ); + printf( "%d Contec 32ch PCIe DO cards found\n", cdsPciModules.cDo32lCount ); + printf( "%d Contec PCIe DIO1616 cards found\n", + cdsPciModules.cDio1616lCount ); + printf( "%d Contec PCIe DIO6464 cards found\n", + cdsPciModules.cDio6464lCount ); + printf( "%d DO cards found\n", cdsPciModules.doCount ); #ifdef ADC_MASTER - // MASTER sends DIO module information to SLAVES - // Note that for DIO, SLAVE modules will perform the I/O directly and therefore need to - // know the PCIe address of these modules. - ioMemData->bioCount = cdsPciModules.doCount; - for(ii=0;ii<cdsPciModules.doCount;ii++) + // MASTER sends DIO module information to SLAVES + // Note that for DIO, SLAVE modules will perform the I/O directly and + // therefore need to know the PCIe address of these modules. + ioMemData->bioCount = cdsPciModules.doCount; + for ( ii = 0; ii < cdsPciModules.doCount; ii++ ) + { + // MASTER needs to find Contec 1616 I/O card to control timing slave. + if ( cdsPciModules.doType[ ii ] == CON_1616DIO ) { - // MASTER needs to find Contec 1616 I/O card to control timing slave. - if(cdsPciModules.doType[ii] == CON_1616DIO) - { - tdsControl[tdsCount] = ii; - printf("TDS controller %d is at %d\n",tdsCount,ii); - tdsCount ++; - } - ioMemData->model[kk] = cdsPciModules.doType[ii]; - // Unlike ADC and DAC, where a memory buffer number is passed, a PCIe address is passed - // for DIO cards. - ioMemData->ipc[kk] = cdsPciModules.pci_do[ii]; - kk ++; - } - printf("Total of %d I/O modules found and mapped\n",kk); + tdsControl[ tdsCount ] = ii; + printf( "TDS controller %d is at %d\n", tdsCount, ii ); + tdsCount++; + } + ioMemData->model[ kk ] = cdsPciModules.doType[ ii ]; + // Unlike ADC and DAC, where a memory buffer number is passed, a PCIe + // address is passed for DIO cards. + ioMemData->ipc[ kk ] = cdsPciModules.pci_do[ ii ]; + kk++; + } + printf( "Total of %d I/O modules found and mapped\n", kk ); #endif - printf("***************************************************************************\n"); -// Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style. -// Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O. -// Master unit only maps the RFM I/O space and passes pointers to SLAVES. + printf( "******************************************************************" + "*********\n" ); + // Following section maps Reflected Memory, both VMIC hardware style and + // Dolphin PCIe network style. Slave units will perform I/O transactions + // with RFM directly ie MASTER does not do RFM I/O. Master unit only maps + // the RFM I/O space and passes pointers to SLAVES. #ifdef ADC_SLAVE - // Slave gets RFM module count from MASTER. - cdsPciModules.rfmCount = ioMemData->rfmCount; - // dolphinCount is number of Dolphin segments - cdsPciModules.dolphinCount = ioMemData->dolphinCount; - // dolphin read/write 0 is for local PCIe network traffic - cdsPciModules.dolphinRead[0] = ioMemData->dolphinRead[0]; - cdsPciModules.dolphinWrite[0] = ioMemData->dolphinWrite[0]; - // dolphin read/write 1 is for long range PCIe (RFM) traffic - cdsPciModules.dolphinRead[1] = ioMemData->dolphinRead[1]; - cdsPciModules.dolphinWrite[1] = ioMemData->dolphinWrite[1]; + // Slave gets RFM module count from MASTER. + cdsPciModules.rfmCount = ioMemData->rfmCount; + // dolphinCount is number of Dolphin segments + cdsPciModules.dolphinCount = ioMemData->dolphinCount; + // dolphin read/write 0 is for local PCIe network traffic + cdsPciModules.dolphinRead[ 0 ] = ioMemData->dolphinRead[ 0 ]; + cdsPciModules.dolphinWrite[ 0 ] = ioMemData->dolphinWrite[ 0 ]; + // dolphin read/write 1 is for long range PCIe (RFM) traffic + cdsPciModules.dolphinRead[ 1 ] = ioMemData->dolphinRead[ 1 ]; + cdsPciModules.dolphinWrite[ 1 ] = ioMemData->dolphinWrite[ 1 ]; #endif - printf("%d RFM cards found\n",cdsPciModules.rfmCount); + printf( "%d RFM cards found\n", cdsPciModules.rfmCount ); #ifdef ADC_MASTER - ioMemData->rfmCount = cdsPciModules.rfmCount; + ioMemData->rfmCount = cdsPciModules.rfmCount; #endif - for(ii=0;ii<cdsPciModules.rfmCount;ii++) - { - printf("\tRFM %d is a VMIC_%x module with Node ID %d\n", ii, cdsPciModules.rfmType[ii], cdsPciModules.rfmConfig[ii]); + for ( ii = 0; ii < cdsPciModules.rfmCount; ii++ ) + { + printf( "\tRFM %d is a VMIC_%x module with Node ID %d\n", + ii, + cdsPciModules.rfmType[ ii ], + cdsPciModules.rfmConfig[ ii ] ); #ifdef ADC_SLAVE - cdsPciModules.pci_rfm[ii] = ioMemData->pci_rfm[ii]; - cdsPciModules.pci_rfm_dma[ii] = ioMemData->pci_rfm_dma[ii]; + cdsPciModules.pci_rfm[ ii ] = ioMemData->pci_rfm[ ii ]; + cdsPciModules.pci_rfm_dma[ ii ] = ioMemData->pci_rfm_dma[ ii ]; #endif - printf("address is 0x%lx\n",cdsPciModules.pci_rfm[ii]); + printf( "address is 0x%lx\n", cdsPciModules.pci_rfm[ ii ] ); #ifdef ADC_MASTER - // Master sends RFM memory pointers to SLAVES - ioMemData->pci_rfm[ii] = cdsPciModules.pci_rfm[ii]; - ioMemData->pci_rfm_dma[ii] = cdsPciModules.pci_rfm_dma[ii]; + // Master sends RFM memory pointers to SLAVES + ioMemData->pci_rfm[ ii ] = cdsPciModules.pci_rfm[ ii ]; + ioMemData->pci_rfm_dma[ ii ] = cdsPciModules.pci_rfm_dma[ ii ]; #endif - } - // ioMemData->dolphinCount = 0; + } + // ioMemData->dolphinCount = 0; #ifdef DOLPHIN_TEST - // dolphinCount is number of segments - ioMemData->dolphinCount = cdsPciModules.dolphinCount; - // dolphin read/write 0 is for local PCIe network traffic - ioMemData->dolphinRead[0] = cdsPciModules.dolphinRead[0]; - ioMemData->dolphinWrite[0] = cdsPciModules.dolphinWrite[0]; - // dolphin read/write 1 is for long range PCIe (RFM) traffic - ioMemData->dolphinRead[1] = cdsPciModules.dolphinRead[1]; - ioMemData->dolphinWrite[1] = cdsPciModules.dolphinWrite[1]; + // dolphinCount is number of segments + ioMemData->dolphinCount = cdsPciModules.dolphinCount; + // dolphin read/write 0 is for local PCIe network traffic + ioMemData->dolphinRead[ 0 ] = cdsPciModules.dolphinRead[ 0 ]; + ioMemData->dolphinWrite[ 0 ] = cdsPciModules.dolphinWrite[ 0 ]; + // dolphin read/write 1 is for long range PCIe (RFM) traffic + ioMemData->dolphinRead[ 1 ] = cdsPciModules.dolphinRead[ 1 ]; + ioMemData->dolphinWrite[ 1 ] = cdsPciModules.dolphinWrite[ 1 ]; #else #ifdef ADC_MASTER -// Clear Dolphin pointers so the slave sees NULLs - ioMemData->dolphinCount = 0; - ioMemData->dolphinRead[0] = 0; - ioMemData->dolphinWrite[0] = 0; - ioMemData->dolphinRead[1] = 0; - ioMemData->dolphinWrite[1] = 0; + // Clear Dolphin pointers so the slave sees NULLs + ioMemData->dolphinCount = 0; + ioMemData->dolphinRead[ 0 ] = 0; + ioMemData->dolphinWrite[ 0 ] = 0; + ioMemData->dolphinRead[ 1 ] = 0; + ioMemData->dolphinWrite[ 1 ] = 0; #endif #endif - printf("***************************************************************************\n"); - if (cdsPciModules.gps) { - printf("IRIG-B card found %d\n",cdsPciModules.gpsType); - printf("***************************************************************************\n"); - } - - - // Code will run on internal timer if no ADC modules are found - if (cdsPciModules.adcCount == 0) { - printf("No ADC modules found, running on timer\n"); - run_on_timer = 1; - //munmap(_epics_shm, MMAP_SIZE); - //close(wfd); - //return 0; - } - - // Initialize buffer for daqLib.c code - printf("Initializing space for daqLib buffers\n"); - daqBuffer = (long)&daqArea[0]; - + printf( "******************************************************************" + "*********\n" ); + if ( cdsPciModules.gps ) + { + printf( "IRIG-B card found %d\n", cdsPciModules.gpsType ); + printf( "**************************************************************" + "*************\n" ); + } + + // Code will run on internal timer if no ADC modules are found + if ( cdsPciModules.adcCount == 0 ) + { + printf( "No ADC modules found, running on timer\n" ); + run_on_timer = 1; + // munmap(_epics_shm, MMAP_SIZE); + // close(wfd); + // return 0; + } + + // Initialize buffer for daqLib.c code + printf( "Initializing space for daqLib buffers\n" ); + daqBuffer = (long)&daqArea[ 0 ]; + #ifndef NO_DAQ #ifndef SHMEM_DAQ - printf("Initializing Network\n"); - numFb = 1; - if (numFb <= 0) { - printf("Couldn't initialize Myrinet network connection\n"); - return -1; - } - printf("Found %d frameBuilders on network\n",numFb); + printf( "Initializing Network\n" ); + numFb = 1; + if ( numFb <= 0 ) + { + printf( "Couldn't initialize Myrinet network connection\n" ); + return -1; + } + printf( "Found %d frameBuilders on network\n", numFb ); #endif #endif - - pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; - for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { - printf("Epics burt restore is %d\n", pLocalEpics->epicsInput.burtRestore); - msleep(1000); - } - if (cnt == 10) { - // Cleanup - remove_epics_proc_files(); - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); + pLocalEpics = (CDS_EPICS*)&( (RFM_FE_COMMS*)_epics_shm )->epicsSpace; + for ( cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++ ) + { + printf( "Epics burt restore is %d\n", + pLocalEpics->epicsInput.burtRestore ); + msleep( 1000 ); + } + if ( cnt == 10 ) + { + // Cleanup + remove_epics_proc_files( ); + remove_proc_entry( "epics", proc_dir_entry ); + remove_proc_entry( "gps", proc_dir_entry ); + remove_proc_entry( "status", proc_dir_entry ); + remove_proc_entry( SYSTEM_NAME_STRING_LOWER, NULL ); #ifdef DOLPHIN_TEST - finish_dolphin(); + finish_dolphin( ); #endif - return -1; - } + return -1; + } - pLocalEpics->epicsInput.vmeReset = 0; + pLocalEpics->epicsInput.vmeReset = 0; #ifdef NO_CPU_SHUTDOWN - sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID); - if (IS_ERR(sthread)){ - printf("Failed to kthread_create()\n"); - return -1; - } - kthread_bind(sthread, CPUID); - wake_up_process(sthread); + sthread = kthread_create( fe_start, 0, "fe_start/%d", CPUID ); + if ( IS_ERR( sthread ) ) + { + printf( "Failed to kthread_create()\n" ); + return -1; + } + kthread_bind( sthread, CPUID ); + wake_up_process( sthread ); #endif - #ifndef NO_CPU_SHUTDOWN - set_fe_code_idle(fe_start, CPUID); - msleep(100); + set_fe_code_idle( fe_start, CPUID ); + msleep( 100 ); - cpu_down(CPUID); + cpu_down( CPUID ); - // The code runs on the disabled CPU + // The code runs on the disabled CPU #endif - return 0; + return 0; } -void cleanup_module (void) { - int i; - int ret; - extern int __cpuinit cpu_up(unsigned int cpu); +void +cleanup_module( void ) +{ + int i; + int ret; + extern int __cpuinit cpu_up( unsigned int cpu ); - remove_epics_proc_files(); - remove_proc_entry("epics", proc_dir_entry); - remove_proc_entry("gps", proc_dir_entry); - remove_proc_entry("status", proc_dir_entry); - remove_proc_entry(SYSTEM_NAME_STRING_LOWER, NULL); + remove_epics_proc_files( ); + remove_proc_entry( "epics", proc_dir_entry ); + remove_proc_entry( "gps", proc_dir_entry ); + remove_proc_entry( "status", proc_dir_entry ); + remove_proc_entry( SYSTEM_NAME_STRING_LOWER, NULL ); #ifndef NO_CPU_SHUTDOWN - // Unset the code callback - set_fe_code_idle(0, CPUID); + // Unset the code callback + set_fe_code_idle( 0, CPUID ); #endif - printk("Setting stop_working_threads to 1\n"); - // Stop the code and wait + printk( "Setting stop_working_threads to 1\n" ); + // Stop the code and wait #ifdef NO_CPU_SHUTDOWN - ret = kthread_stop(sthread); + ret = kthread_stop( sthread ); #endif - stop_working_threads = 1; - msleep(1000); + stop_working_threads = 1; + msleep( 1000 ); #ifdef DOLPHIN_TEST - finish_dolphin(); + finish_dolphin( ); #endif #ifndef NO_CPU_SHUTDOWN - // Unset the code callback - set_fe_code_idle(0, CPUID); - printkl("Will bring back CPU %d\n", CPUID); - msleep(1000); - // Unmask all masked epics channels - for (i = 0; i < ner; i++) { - *((char *)(((void *)pLocalEpics) + proc_epics[i].mask_idx)) = 0; - } - // Bring the CPU back up - cpu_up(CPUID); - //msleep(1000); - printk("Brought the CPU back up\n"); + // Unset the code callback + set_fe_code_idle( 0, CPUID ); + printkl( "Will bring back CPU %d\n", CPUID ); + msleep( 1000 ); + // Unmask all masked epics channels + for ( i = 0; i < ner; i++ ) + { + *( (char*)( ( (void*)pLocalEpics ) + proc_epics[ i ].mask_idx ) ) = 0; + } + // Bring the CPU back up + cpu_up( CPUID ); + // msleep(1000); + printk( "Brought the CPU back up\n" ); #endif - printk("Just before returning from cleanup_module for " SYSTEM_NAME_STRING_LOWER "\n"); - + printk( "Just before returning from cleanup_module " + "for " SYSTEM_NAME_STRING_LOWER "\n" ); } -MODULE_DESCRIPTION("Control system"); -MODULE_AUTHOR("LIGO"); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION( "Control system" ); +MODULE_AUTHOR( "LIGO" ); +MODULE_LICENSE( "Dual BSD/GPL" ); diff --git a/src/fe/moduleLoadVirtual.c b/src/fe/moduleLoadVirtual.c index 76b8129ac..a055bbf62 100644 --- a/src/fe/moduleLoadVirtual.c +++ b/src/fe/moduleLoadVirtual.c @@ -7,257 +7,276 @@ #include <proc.h> // These externs and "16" need to go to a header file (mbuf.h) -extern void *kmalloc_area[16]; -extern int mbuf_allocate_area(char *name, int size, struct file *file); -extern void *fe_start(void *arg); -extern int run_on_timer; -extern char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers -struct task_struct *sthread; - - -// MAIN routine: Code starting point **************************************************************** +extern void* kmalloc_area[ 16 ]; +extern int mbuf_allocate_area( char* name, int size, struct file* file ); +extern void* fe_start( void* arg ); +extern int run_on_timer; +extern char daqArea[ 2 * DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers +struct task_struct* sthread; + +// MAIN routine: Code starting point +// **************************************************************** int need_to_load_IOP_first; -EXPORT_SYMBOL(need_to_load_IOP_first); +EXPORT_SYMBOL( need_to_load_IOP_first ); -extern void set_fe_code_idle(void *(*ptr)(void *), unsigned int cpu); -extern void msleep(unsigned int); +extern void set_fe_code_idle( void* ( *ptr )(void*), unsigned int cpu ); +extern void msleep( unsigned int ); #include "moduleLoadCommon.c" /// Startup function for initialization of kernel module. -int init_module (void) +int +init_module( void ) { - int status; - int ii,jj,kk; /// @param ii,jj,kk default loop counters - char fname[128]; /// @param fname[128] Name of shared mem area to allocate for DAQ data - int cards; /// @param cards Number of PCIe cards found on bus - int ret; /// @param ret Return value from various Malloc calls to allocate memory. - int cnt; - extern int cpu_down(unsigned int); /// @param cpu_down CPU shutdown call. - extern int is_cpu_taken_by_rcg_model(unsigned int cpu); /// @param is_cpu_taken_by_rcg_model Check to verify CPU availability for shutdown. - - kk = 0; + int status; + int ii, jj, kk; /// @param ii,jj,kk default loop counters + char fname[ 128 ]; /// @param fname[128] Name of shared mem area to allocate + /// for DAQ data + int cards; /// @param cards Number of PCIe cards found on bus + int ret; /// @param ret Return value from various Malloc calls to allocate + /// memory. + int cnt; + extern int cpu_down( unsigned int ); /// @param cpu_down CPU shutdown call. + extern int is_cpu_taken_by_rcg_model( + unsigned int cpu ); /// @param is_cpu_taken_by_rcg_model Check to verify + /// CPU availability for shutdown. + + kk = 0; #ifdef SPECIFIC_CPU #define CPUID SPECIFIC_CPU -#else -#define CPUID 1 +#else +#define CPUID 1 #endif #ifndef NO_CPU_SHUTDOWN - // See if our CPU core is free - if (is_cpu_taken_by_rcg_model(CPUID)) { - printk(KERN_ALERT "Error: CPU %d already taken\n", CPUID); - return -1; - } + // See if our CPU core is free + if ( is_cpu_taken_by_rcg_model( CPUID ) ) + { + printk( KERN_ALERT "Error: CPU %d already taken\n", CPUID ); + return -1; + } #endif - #ifdef DOLPHIN_TEST - status = init_dolphin(1); - if (status != 0) { - return -1; - } + status = init_dolphin( 1 ); + if ( status != 0 ) + { + return -1; + } #endif - jj = 0; - - -// Allocate EPICS memory area - ret = mbuf_allocate_area(SYSTEM_NAME_STRING_LOWER, 64*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _epics_shm = (unsigned char *)(kmalloc_area[ret]); -// Allocate IPC memory area - ret = mbuf_allocate_area("ipc", 4*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area(ipc) failed; ret = %d\n", ret); - return -1; - } - _ipc_shm = (unsigned char *)(kmalloc_area[ret]); - -// Assign pointer to IOP/USER app comms space - ioMemData = (IO_MEM_DATA *)(_ipc_shm+ 0x4000); - - -// Allocate DAQ memory area - sprintf(fname, "%s_daq", SYSTEM_NAME_STRING_LOWER); - ret = mbuf_allocate_area(fname, 64*1024*1024, 0); - if (ret < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", ret); - return -1; - } - _daq_shm = (unsigned char *)(kmalloc_area[ret]); - daqPtr = (struct rmIpcStr *) _daq_shm; - - // Find and initialize all PCI I/O modules ************************************************** - // Following I/O card info is from feCode - cards = sizeof(cards_used)/sizeof(cards_used[0]); - cdsPciModules.cards = cards; - cdsPciModules.cards_used = cards_used; - cdsPciModules.adcCount = 0; - cdsPciModules.dacCount = 0; - cdsPciModules.dioCount = 0; - cdsPciModules.doCount = 0; - - // Call PCI initialization routine in map.c file. - status = mapPciModules(&cdsPciModules); - if(status < cards) - { - printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); - cardCountErr = 1; - } - - // Master send module counds to SLAVE via ipc shm - ioMemData->totalCards = status; - ioMemData->adcCount = cdsPciModules.adcCount; - ioMemData->dacCount = cdsPciModules.dacCount; - ioMemData->bioCount = cdsPciModules.doCount; - // kk will act as ioMem location counter for mapping modules - kk = cdsPciModules.adcCount; - for(ii=0;ii<cdsPciModules.adcCount;ii++) + jj = 0; + + // Allocate EPICS memory area + ret = mbuf_allocate_area( SYSTEM_NAME_STRING_LOWER, 64 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", ret ); + return -1; + } + _epics_shm = (unsigned char*)( kmalloc_area[ ret ] ); + // Allocate IPC memory area + ret = mbuf_allocate_area( "ipc", 4 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printf( "mbuf_allocate_area(ipc) failed; ret = %d\n", ret ); + return -1; + } + _ipc_shm = (unsigned char*)( kmalloc_area[ ret ] ); + + // Assign pointer to IOP/USER app comms space + ioMemData = (IO_MEM_DATA*)( _ipc_shm + 0x4000 ); + + // Allocate DAQ memory area + sprintf( fname, "%s_daq", SYSTEM_NAME_STRING_LOWER ); + ret = mbuf_allocate_area( fname, 64 * 1024 * 1024, 0 ); + if ( ret < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", ret ); + return -1; + } + _daq_shm = (unsigned char*)( kmalloc_area[ ret ] ); + daqPtr = (struct rmIpcStr*)_daq_shm; + + // Find and initialize all PCI I/O modules + // ************************************************** Following I/O card + // info is from feCode + cards = sizeof( cards_used ) / sizeof( cards_used[ 0 ] ); + cdsPciModules.cards = cards; + cdsPciModules.cards_used = cards_used; + cdsPciModules.adcCount = 0; + cdsPciModules.dacCount = 0; + cdsPciModules.dioCount = 0; + cdsPciModules.doCount = 0; + + // Call PCI initialization routine in map.c file. + status = mapPciModules( &cdsPciModules ); + if ( status < cards ) + { + printf( " ERROR **** Did not find correct number of cards! Expected %d " + "and Found %d\n", + cards, + status ); + cardCountErr = 1; + } + + // Master send module counds to SLAVE via ipc shm + ioMemData->totalCards = status; + ioMemData->adcCount = cdsPciModules.adcCount; + ioMemData->dacCount = cdsPciModules.dacCount; + ioMemData->bioCount = cdsPciModules.doCount; + // kk will act as ioMem location counter for mapping modules + kk = cdsPciModules.adcCount; + for ( ii = 0; ii < cdsPciModules.adcCount; ii++ ) + { + // MASTER maps ADC modules first in ipc shm for SLAVES + ioMemData->model[ ii ] = cdsPciModules.adcType[ ii ]; + ioMemData->ipc[ ii ] = + ii; // ioData memory buffer location for SLAVE to use + } + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + { + // Pass DAC info to SLAVE processes + ioMemData->model[ kk ] = cdsPciModules.dacType[ ii ]; + ioMemData->ipc[ kk ] = kk; + // Following used by MASTER to point to ipc memory for inputting DAC + // data from SLAVES + cdsPciModules.dacConfig[ ii ] = kk; + kk++; + } + // MASTER sends DIO module information to SLAVES + // Note that for DIO, SLAVE modules will perform the I/O directly and + // therefore need to know the PCIe address of these modules. + ioMemData->bioCount = cdsPciModules.doCount; + for ( ii = 0; ii < cdsPciModules.doCount; ii++ ) + { + // MASTER needs to find Contec 1616 I/O card to control timing slave. + if ( cdsPciModules.doType[ ii ] == CON_1616DIO ) { - // MASTER maps ADC modules first in ipc shm for SLAVES - ioMemData->model[ii] = cdsPciModules.adcType[ii]; - ioMemData->ipc[ii] = ii; // ioData memory buffer location for SLAVE to use + tdsControl[ tdsCount ] = ii; + tdsCount++; } - for(ii=0;ii<cdsPciModules.dacCount;ii++) - { - // Pass DAC info to SLAVE processes - ioMemData->model[kk] = cdsPciModules.dacType[ii]; - ioMemData->ipc[kk] = kk; - // Following used by MASTER to point to ipc memory for inputting DAC data from SLAVES - cdsPciModules.dacConfig[ii] = kk; - kk ++; - } - // MASTER sends DIO module information to SLAVES - // Note that for DIO, SLAVE modules will perform the I/O directly and therefore need to - // know the PCIe address of these modules. - ioMemData->bioCount = cdsPciModules.doCount; - for(ii=0;ii<cdsPciModules.doCount;ii++) - { - // MASTER needs to find Contec 1616 I/O card to control timing slave. - if(cdsPciModules.doType[ii] == CON_1616DIO) - { - tdsControl[tdsCount] = ii; - tdsCount ++; - } - ioMemData->model[kk] = cdsPciModules.doType[ii]; - // Unlike ADC and DAC, where a memory buffer number is passed, a PCIe address is passed - // for DIO cards. - ioMemData->ipc[kk] = cdsPciModules.pci_do[ii]; - kk ++; - } -// Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style. -// Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O. -// Master unit only maps the RFM I/O space and passes pointers to SLAVES. - - ioMemData->rfmCount = cdsPciModules.rfmCount; - for(ii=0;ii<cdsPciModules.rfmCount;ii++) - { - // Master sends RFM memory pointers to SLAVES - ioMemData->pci_rfm[ii] = cdsPciModules.pci_rfm[ii]; - ioMemData->pci_rfm_dma[ii] = cdsPciModules.pci_rfm_dma[ii]; - } - // ioMemData->dolphinCount = 0; + ioMemData->model[ kk ] = cdsPciModules.doType[ ii ]; + // Unlike ADC and DAC, where a memory buffer number is passed, a PCIe + // address is passed for DIO cards. + ioMemData->ipc[ kk ] = cdsPciModules.pci_do[ ii ]; + kk++; + } + // Following section maps Reflected Memory, both VMIC hardware style and + // Dolphin PCIe network style. Slave units will perform I/O transactions + // with RFM directly ie MASTER does not do RFM I/O. Master unit only maps + // the RFM I/O space and passes pointers to SLAVES. + + ioMemData->rfmCount = cdsPciModules.rfmCount; + for ( ii = 0; ii < cdsPciModules.rfmCount; ii++ ) + { + // Master sends RFM memory pointers to SLAVES + ioMemData->pci_rfm[ ii ] = cdsPciModules.pci_rfm[ ii ]; + ioMemData->pci_rfm_dma[ ii ] = cdsPciModules.pci_rfm_dma[ ii ]; + } + // ioMemData->dolphinCount = 0; #ifdef DOLPHIN_TEST - ioMemData->dolphinCount = cdsPciModules.dolphinCount; - ioMemData->dolphinRead[0] = cdsPciModules.dolphinRead[0]; - ioMemData->dolphinWrite[0] = cdsPciModules.dolphinWrite[0]; + ioMemData->dolphinCount = cdsPciModules.dolphinCount; + ioMemData->dolphinRead[ 0 ] = cdsPciModules.dolphinRead[ 0 ]; + ioMemData->dolphinWrite[ 0 ] = cdsPciModules.dolphinWrite[ 0 ]; #else -// Clear Dolphin pointers so the slave sees NULLs - ioMemData->dolphinCount = 0; - ioMemData->dolphinRead[0] = 0; - ioMemData->dolphinWrite[0] = 0; + // Clear Dolphin pointers so the slave sees NULLs + ioMemData->dolphinCount = 0; + ioMemData->dolphinRead[ 0 ] = 0; + ioMemData->dolphinWrite[ 0 ] = 0; #endif - // Print out all the I/O information - print_io_info(&cdsPciModules); - - // Code will run on internal timer if no ADC modules are found - if (cdsPciModules.adcCount == 0) run_on_timer = 1; - - // Initialize buffer for daqLib.c code - // printf("Initializing space for daqLib buffers\n"); - daqBuffer = (long)&daqArea[0]; - -// Set pointer to EPICS area - pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; - // Ensure EPICS running else exit - for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { - msleep(1000); - } - if (cnt == 10) { - // Cleanup + // Print out all the I/O information + print_io_info( &cdsPciModules ); + + // Code will run on internal timer if no ADC modules are found + if ( cdsPciModules.adcCount == 0 ) + run_on_timer = 1; + + // Initialize buffer for daqLib.c code + // printf("Initializing space for daqLib buffers\n"); + daqBuffer = (long)&daqArea[ 0 ]; + + // Set pointer to EPICS area + pLocalEpics = (CDS_EPICS*)&( (RFM_FE_COMMS*)_epics_shm )->epicsSpace; + // Ensure EPICS running else exit + for ( cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++ ) + { + msleep( 1000 ); + } + if ( cnt == 10 ) + { + // Cleanup #ifdef DOLPHIN_TEST - finish_dolphin(); + finish_dolphin( ); #endif - return -1; - } + return -1; + } - pLocalEpics->epicsInput.vmeReset = 0; + pLocalEpics->epicsInput.vmeReset = 0; #ifdef NO_CPU_SHUTDOWN - sthread = kthread_create(fe_start, 0, "fe_start/%d", CPUID); - if (IS_ERR(sthread)){ - printf("Failed to kthread_create()\n"); - return -1; - } - kthread_bind(sthread, CPUID); - wake_up_process(sthread); + sthread = kthread_create( fe_start, 0, "fe_start/%d", CPUID ); + if ( IS_ERR( sthread ) ) + { + printf( "Failed to kthread_create()\n" ); + return -1; + } + kthread_bind( sthread, CPUID ); + wake_up_process( sthread ); #endif - #ifndef NO_CPU_SHUTDOWN - // The code runs on the disabled CPU - set_fe_code_idle(fe_start, CPUID); - msleep(100); + // The code runs on the disabled CPU + set_fe_code_idle( fe_start, CPUID ); + msleep( 100 ); - cpu_down(CPUID); + cpu_down( CPUID ); #endif - return 0; + return 0; } -void cleanup_module (void) { - int i; - int ret; - extern int __cpuinit cpu_up(unsigned int cpu); +void +cleanup_module( void ) +{ + int i; + int ret; + extern int __cpuinit cpu_up( unsigned int cpu ); #ifndef NO_CPU_SHUTDOWN - // Unset the code callback - set_fe_code_idle(0, CPUID); + // Unset the code callback + set_fe_code_idle( 0, CPUID ); #endif - printk("Setting stop_working_threads to 1\n"); - // Stop the code and wait + printk( "Setting stop_working_threads to 1\n" ); + // Stop the code and wait #ifdef NO_CPU_SHUTDOWN - ret = kthread_stop(sthread); + ret = kthread_stop( sthread ); #endif - stop_working_threads = 1; - msleep(1000); + stop_working_threads = 1; + msleep( 1000 ); #ifdef DOLPHIN_TEST - finish_dolphin(); + finish_dolphin( ); #endif #ifndef NO_CPU_SHUTDOWN - // Unset the code callback - set_fe_code_idle(0, CPUID); - // printkl("Will bring back CPU %d\n", CPUID); - msleep(1000); - // Bring the CPU back up - cpu_up(CPUID); - //msleep(1000); - printk("Brought the CPU back up\n"); + // Unset the code callback + set_fe_code_idle( 0, CPUID ); + // printkl("Will bring back CPU %d\n", CPUID); + msleep( 1000 ); + // Bring the CPU back up + cpu_up( CPUID ); + // msleep(1000); + printk( "Brought the CPU back up\n" ); #endif - printk("Just before returning from cleanup_module for " SYSTEM_NAME_STRING_LOWER "\n"); - + printk( "Just before returning from cleanup_module " + "for " SYSTEM_NAME_STRING_LOWER "\n" ); } -MODULE_DESCRIPTION("Control system"); -MODULE_AUTHOR("LIGO"); -MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION( "Control system" ); +MODULE_AUTHOR( "LIGO" ); +MODULE_LICENSE( "Dual BSD/GPL" ); diff --git a/src/fe/rcguser.c b/src/fe/rcguser.c index a230c63af..85c64dad4 100644 --- a/src/fe/rcguser.c +++ b/src/fe/rcguser.c @@ -1,5 +1,6 @@ /// @file moduleLoad.c -/// @brief File contains startup routines for running user app in user space. +/// @brief File contains startup routines for running user app in user +///space. #include <unistd.h> #include <ctype.h> @@ -20,9 +21,9 @@ #include "moduleLoadCommon.c" // These externs and "16" need to go to a header file (mbuf.h) -extern int fe_start_app_user(); -extern char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers -extern char *addr; +extern int fe_start_app_user( ); +extern char daqArea[ 2 * DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers +extern char* addr; // Scan a double #if 0 @@ -47,334 +48,385 @@ simple_strtod(char *start, char **end) { } #endif -void usage() +void +usage( ) { - fprintf(stderr,"Usage: rcgUser -m system_name \n"); - fprintf(stderr, "-h - help\n"); + fprintf( stderr, "Usage: rcgUser -m system_name \n" ); + fprintf( stderr, "-h - help\n" ); } - /// Startup function for initialization of kernel module. -int main (int argc, char **argv) +int +main( int argc, char** argv ) { - int status; - int ii,jj,kk; /// @param ii,jj,kk default loop counters - char fname[128]; /// @param fname[128] Name of shared mem area to allocate for DAQ data - int cards; /// @param cards Number of PCIe cards found on bus - int adcCnt; /// @param adcCnt Number of ADC cards found by slave model. - int dacCnt; /// @param dacCnt Number of 16bit DAC cards found by slave model. - int dac18Cnt; /// @param dac18Cnt Number of 18bit DAC cards found by slave model. - int doCnt; /// @param doCnt Total number of digital I/O cards found by slave model. - int do32Cnt; /// @param do32Cnt Total number of Contec 32 bit DIO cards found by slave model. - int doIIRO16Cnt; /// @param doIIRO16Cnt Total number of Acces I/O 16 bit relay cards found by slave model. - int doIIRO8Cnt; /// @param doIIRO8Cnt Total number of Acces I/O 8 bit relay cards found by slave model. - int cdo64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit output sections mapped by slave model. - int cdi64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit input sections mapped by slave model. - int ret; /// @param ret Return value from various Malloc calls to allocate memory. - int cnt; - char *sysname; - char shm_name[64]; - int c; + int status; + int ii, jj, kk; /// @param ii,jj,kk default loop counters + char fname[ 128 ]; /// @param fname[128] Name of shared mem area to allocate + /// for DAQ data + int cards; /// @param cards Number of PCIe cards found on bus + int adcCnt; /// @param adcCnt Number of ADC cards found by slave model. + int dacCnt; /// @param dacCnt Number of 16bit DAC cards found by slave + /// model. + int dac18Cnt; /// @param dac18Cnt Number of 18bit DAC cards found by slave + /// model. + int doCnt; /// @param doCnt Total number of digital I/O cards found by slave + /// model. + int do32Cnt; /// @param do32Cnt Total number of Contec 32 bit DIO cards + /// found by slave model. + int doIIRO16Cnt; /// @param doIIRO16Cnt Total number of Acces I/O 16 bit + /// relay cards found by slave model. + int doIIRO8Cnt; /// @param doIIRO8Cnt Total number of Acces I/O 8 bit relay + /// cards found by slave model. + int cdo64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit + /// output sections mapped by slave model. + int cdi64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit + /// input sections mapped by slave model. + int ret; /// @param ret Return value from various Malloc calls to allocate + /// memory. + int cnt; + char* sysname; + char shm_name[ 64 ]; + int c; + while ( ( c = getopt( argc, argv, "m:help" ) ) != EOF ) + switch ( c ) + { + case 'm': + sysname = optarg; + printf( "sysname = %s\n", sysname ); + break; + case 'help': + default: + usage( ); + exit( 1 ); + } - while ((c = getopt(argc, argv, "m:help")) != EOF) switch(c) { - case 'm': - sysname = optarg; - printf("sysname = %s\n",sysname); - break; - case 'help': - default: - usage(); - exit(1); - } + kk = 0; - kk = 0; + jj = 0; + // printf("cpu clock %u\n",cpu_khz); - jj = 0; - // printf("cpu clock %u\n",cpu_khz); + sprintf( shm_name, "%s", sysname ); + findSharedMemory( sysname ); + _epics_shm = (char*)addr; + ; + if ( _epics_shm < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", _epics_shm ); + return -1; + } + printf( "EPICSM at 0x%lx\n", (long)_epics_shm ); + sprintf( shm_name, "%s", "ipc" ); + findSharedMemory( "ipc" ); + _ipc_shm = (char*)addr; + if ( _ipc_shm < 0 ) + { + printf( "mbuf_allocate_area(ipc) failed; ret = %d\n", _ipc_shm ); + return -1; + } - sprintf(shm_name,"%s",sysname); - findSharedMemory(sysname); - _epics_shm = (char *)addr;; - if (_epics_shm < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", _epics_shm); - return -1; - } - printf("EPICSM at 0x%lx\n", (long)_epics_shm); + printf( "IPC at 0x%lx\n", (long)_ipc_shm ); + ioMemData = (volatile IO_MEM_DATA*)( ( (char*)_ipc_shm ) + 0x4000 ); + printf( + "IOMEM at 0x%lx size 0x%x\n", (long)ioMemData, sizeof( IO_MEM_DATA ) ); + printf( "%d PCI cards found\n", ioMemData->totalCards ); - sprintf(shm_name,"%s","ipc"); - findSharedMemory("ipc"); - _ipc_shm = (char *)addr; - if (_ipc_shm< 0) { - printf("mbuf_allocate_area(ipc) failed; ret = %d\n", _ipc_shm); - return -1; - } + // If DAQ is via shared memory (Framebuilder code running on same machine or + // MX networking is used) attach DAQ shared memory location. + sprintf( shm_name, "%s_daq", sysname ); + findSharedMemory( shm_name ); + _daq_shm = (char*)addr; + if ( _daq_shm < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", _daq_shm ); + return -1; + } + // printf("Allocated daq shmem; set at 0x%x\n", _daq_shm); + printf( "DAQSM at 0x%lx\n", _daq_shm ); + daqPtr = (struct rmIpcStr*)_daq_shm; - printf("IPC at 0x%lx\n",(long)_ipc_shm); - ioMemData = (volatile IO_MEM_DATA *)(((char *)_ipc_shm) + 0x4000); - printf("IOMEM at 0x%lx size 0x%x\n",(long)ioMemData,sizeof(IO_MEM_DATA)); - printf("%d PCI cards found\n",ioMemData->totalCards); + // Open new GDS TP data shared memory in support of ZMQ + sprintf( shm_name, "%s_gds", sysname ); + findSharedMemory( shm_name ); + _gds_shm = (char*)addr; + if ( _gds_shm < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", _gds_shm ); + return -1; + } + printf( "GDSSM at 0x%lx\n", _gds_shm ); + // Find and initialize all PCI I/O modules + // ******************************************************* Following I/O + // card info is from feCode + cards = sizeof( cards_used ) / sizeof( cards_used[ 0 ] ); + printf( "configured to use %d cards\n", cards ); + cdsPciModules.cards = cards; + cdsPciModules.cards_used = cards_used; + // return -1; + printf( "Initializing PCI Modules\n" ); + cdsPciModules.adcCount = 0; + cdsPciModules.dacCount = 0; + cdsPciModules.dioCount = 0; + cdsPciModules.doCount = 0; -// If DAQ is via shared memory (Framebuilder code running on same machine or MX networking is used) -// attach DAQ shared memory location. - sprintf(shm_name, "%s_daq", sysname); - findSharedMemory(shm_name); - _daq_shm = (char *)addr; - if (_daq_shm < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", _daq_shm); - return -1; - } - // printf("Allocated daq shmem; set at 0x%x\n", _daq_shm); - printf("DAQSM at 0x%lx\n",_daq_shm); - daqPtr = (struct rmIpcStr *) _daq_shm; + // If running as a slave process, I/O card information is via ipc shared + // memory + printf( "%d PCI cards found\n", ioMemData->totalCards ); + status = 0; + adcCnt = 0; + dacCnt = 0; + dac18Cnt = 0; + doCnt = 0; + do32Cnt = 0; + cdo64Cnt = 0; + cdi64Cnt = 0; + doIIRO16Cnt = 0; + doIIRO8Cnt = 0; -// Open new GDS TP data shared memory in support of ZMQ - sprintf(shm_name, "%s_gds", sysname); - findSharedMemory(shm_name); - _gds_shm = (char *)addr; - if (_gds_shm < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", _gds_shm); - return -1; + // Have to search thru all cards and find desired instance for application + // Master will map ADC cards first, then DAC and finally DIO + for ( ii = 0; ii < ioMemData->totalCards; ii++ ) + { + /* + printf("Model %d = %d\n",ii,ioMemData->model[ii]); + */ + for ( jj = 0; jj < cards; jj++ ) + { + /* + printf("Model %d = %d, type = %d, instance = %d, dacCnt = %d \n", + ii,ioMemData->model[ii], + cdsPciModules.cards_used[jj].type, + cdsPciModules.cards_used[jj].instance, + dacCnt); + */ + switch ( ioMemData->model[ ii ] ) + { + case GSC_16AI64SSA: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_16AI64SSA ) && + ( cdsPciModules.cards_used[ jj ].instance == adcCnt ) ) + { + printf( "Found ADC at %d %d\n", jj, ioMemData->ipc[ ii ] ); + kk = cdsPciModules.adcCount; + cdsPciModules.adcType[ kk ] = GSC_16AI64SSA; + cdsPciModules.adcConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.adcCount++; + status++; + } + break; + case GSC_16AO16: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_16AO16 ) && + ( cdsPciModules.cards_used[ jj ].instance == dacCnt ) ) + { + printf( "Found DAC at %d %d\n", jj, ioMemData->ipc[ ii ] ); + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_16AO16; + cdsPciModules.dacConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.pci_dac[ kk ] = + (long)( ioMemData->iodata[ ii ] ); + cdsPciModules.dacCount++; + status++; + } + break; + case GSC_18AO8: + if ( ( cdsPciModules.cards_used[ jj ].type == GSC_18AO8 ) && + ( cdsPciModules.cards_used[ jj ].instance == dac18Cnt ) ) + { + printf( "Found DAC at %d %d\n", jj, ioMemData->ipc[ ii ] ); + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_18AO8; + cdsPciModules.dacConfig[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.pci_dac[ kk ] = + (long)( ioMemData->iodata[ ii ] ); + cdsPciModules.dacCount++; + status++; + } + break; + case CON_6464DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == CON_6464DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + printf( "Found 6464 DIO CONTEC at %d 0x%x\n", + jj, + ioMemData->ipc[ ii ] ); + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDio6464lCount++; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doInstance[ kk ] = doCnt; + status += 2; + } + if ( ( cdsPciModules.cards_used[ jj ].type == CDO64 ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = CDO64; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDio6464lCount++; + cdsPciModules.doInstance[ kk ] = doCnt; + printf( "Found 6464 DOUT CONTEC at %d 0x%x index %d \n", + jj, + ioMemData->ipc[ ii ], + doCnt ); + cdo64Cnt++; + status++; + } + if ( ( cdsPciModules.cards_used[ jj ].type == CDI64 ) && + ( cdsPciModules.cards_used[ jj ].instance == doCnt ) ) + { + kk = cdsPciModules.doCount; + // printf("Found 6464 DIN CONTEC at %d + // 0x%x\n",jj,ioMemData->ipc[ii]); + cdsPciModules.doType[ kk ] = CDI64; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doInstance[ kk ] = doCnt; + cdsPciModules.doCount++; + printf( "Found 6464 DIN CONTEC at %d 0x%x index %d \n", + jj, + ioMemData->ipc[ ii ], + doCnt ); + cdsPciModules.cDio6464lCount++; + cdi64Cnt++; + status++; + } + break; + case CON_32DO: + if ( ( cdsPciModules.cards_used[ jj ].type == CON_32DO ) && + ( cdsPciModules.cards_used[ jj ].instance == do32Cnt ) ) + { + kk = cdsPciModules.doCount; + printf( "Found 32 DO CONTEC at %d 0x%x\n", + jj, + ioMemData->ipc[ ii ] ); + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.cDo32lCount++; + cdsPciModules.doInstance[ kk ] = do32Cnt; + status++; + } + break; + case ACS_16DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == ACS_16DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == + doIIRO16Cnt ) ) + { + kk = cdsPciModules.doCount; + printf( "Found Access IIRO-16 at %d 0x%x\n", + jj, + ioMemData->ipc[ ii ] ); + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.iiroDio1Count++; + cdsPciModules.doInstance[ kk ] = doIIRO16Cnt; + status++; + } + break; + case ACS_8DIO: + if ( ( cdsPciModules.cards_used[ jj ].type == ACS_8DIO ) && + ( cdsPciModules.cards_used[ jj ].instance == doIIRO8Cnt ) ) + { + kk = cdsPciModules.doCount; + printf( "Found Access IIRO-8 at %d 0x%x\n", + jj, + ioMemData->ipc[ ii ] ); + cdsPciModules.doType[ kk ] = ioMemData->model[ ii ]; + cdsPciModules.pci_do[ kk ] = ioMemData->ipc[ ii ]; + cdsPciModules.doCount++; + cdsPciModules.iiroDioCount++; + cdsPciModules.doInstance[ kk ] = doIIRO8Cnt; + status++; + } + break; + default: + break; + } } - printf("GDSSM at 0x%lx\n",_gds_shm); + if ( ioMemData->model[ ii ] == GSC_16AI64SSA ) + adcCnt++; + if ( ioMemData->model[ ii ] == GSC_16AO16 ) + dacCnt++; + if ( ioMemData->model[ ii ] == GSC_18AO8 ) + dac18Cnt++; + if ( ioMemData->model[ ii ] == CON_6464DIO ) + doCnt++; + if ( ioMemData->model[ ii ] == CON_32DO ) + do32Cnt++; + if ( ioMemData->model[ ii ] == ACS_16DIO ) + doIIRO16Cnt++; + if ( ioMemData->model[ ii ] == ACS_8DIO ) + doIIRO8Cnt++; + } + // If no ADC cards were found, then SLAVE cannot run + if ( !cdsPciModules.adcCount ) + { + printf( "No ADC cards found - exiting\n" ); + return -1; + } + // This did not quite work for some reason + // Need to find a way to handle skipped DAC cards in slaves + // cdsPciModules.dacCount = ioMemData->dacCount; + printf( "%d PCI cards found \n", status ); + if ( status < cards ) + { + printf( " ERROR **** Did not find correct number of cards! Expected %d " + "and Found %d\n", + cards, + status ); + cardCountErr = 1; + } - // Find and initialize all PCI I/O modules ******************************************************* - // Following I/O card info is from feCode - cards = sizeof(cards_used)/sizeof(cards_used[0]); - printf("configured to use %d cards\n", cards); - cdsPciModules.cards = cards; - cdsPciModules.cards_used = cards_used; - //return -1; - printf("Initializing PCI Modules\n"); - cdsPciModules.adcCount = 0; - cdsPciModules.dacCount = 0; - cdsPciModules.dioCount = 0; - cdsPciModules.doCount = 0; + // Print out all the I/O information -// If running as a slave process, I/O card information is via ipc shared memory - printf("%d PCI cards found\n",ioMemData->totalCards); - status = 0; - adcCnt = 0; - dacCnt = 0; - dac18Cnt = 0; - doCnt = 0; - do32Cnt = 0; - cdo64Cnt = 0; - cdi64Cnt = 0; - doIIRO16Cnt = 0; - doIIRO8Cnt = 0; + // Following section maps Reflected Memory, both VMIC hardware style and + // Dolphin PCIe network style. Slave units will perform I/O transactions + // with RFM directly ie MASTER does not do RFM I/O. Master unit only maps + // the RFM I/O space and passes pointers to SLAVES. - // Have to search thru all cards and find desired instance for application - // Master will map ADC cards first, then DAC and finally DIO - for(ii=0;ii<ioMemData->totalCards;ii++) - { - /* - printf("Model %d = %d\n",ii,ioMemData->model[ii]); - */ - for(jj=0;jj<cards;jj++) - { - /* - printf("Model %d = %d, type = %d, instance = %d, dacCnt = %d \n", - ii,ioMemData->model[ii], - cdsPciModules.cards_used[jj].type, - cdsPciModules.cards_used[jj].instance, - dacCnt); - */ - switch(ioMemData->model[ii]) - { - case GSC_16AI64SSA: - if((cdsPciModules.cards_used[jj].type == GSC_16AI64SSA) && - (cdsPciModules.cards_used[jj].instance == adcCnt)) - { - printf("Found ADC at %d %d\n",jj,ioMemData->ipc[ii]); - kk = cdsPciModules.adcCount; - cdsPciModules.adcType[kk] = GSC_16AI64SSA; - cdsPciModules.adcConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.adcCount ++; - status ++; - } - break; - case GSC_16AO16: - if((cdsPciModules.cards_used[jj].type == GSC_16AO16) && - (cdsPciModules.cards_used[jj].instance == dacCnt)) - { - printf("Found DAC at %d %d\n",jj,ioMemData->ipc[ii]); - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_16AO16; - cdsPciModules.dacConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.pci_dac[kk] = (long)(ioMemData->iodata[ii]); - cdsPciModules.dacCount ++; - status ++; - } - break; - case GSC_18AO8: - if((cdsPciModules.cards_used[jj].type == GSC_18AO8) && - (cdsPciModules.cards_used[jj].instance == dac18Cnt)) - { - printf("Found DAC at %d %d\n",jj,ioMemData->ipc[ii]); - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_18AO8; - cdsPciModules.dacConfig[kk] = ioMemData->ipc[ii]; - cdsPciModules.pci_dac[kk] = (long)(ioMemData->iodata[ii]); - cdsPciModules.dacCount ++; - status ++; - } - break; - case CON_6464DIO: - if((cdsPciModules.cards_used[jj].type == CON_6464DIO) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - printf("Found 6464 DIO CONTEC at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDio6464lCount ++; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doInstance[kk] = doCnt; - status += 2; - } - if((cdsPciModules.cards_used[jj].type == CDO64) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = CDO64; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDio6464lCount ++; - cdsPciModules.doInstance[kk] = doCnt; - printf("Found 6464 DOUT CONTEC at %d 0x%x index %d \n",jj,ioMemData->ipc[ii],doCnt); - cdo64Cnt ++; - status ++; - } - if((cdsPciModules.cards_used[jj].type == CDI64) && - (cdsPciModules.cards_used[jj].instance == doCnt)) - { - kk = cdsPciModules.doCount; - // printf("Found 6464 DIN CONTEC at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = CDI64; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doInstance[kk] = doCnt; - cdsPciModules.doCount ++; - printf("Found 6464 DIN CONTEC at %d 0x%x index %d \n",jj,ioMemData->ipc[ii],doCnt); - cdsPciModules.cDio6464lCount ++; - cdi64Cnt ++; - status ++; - } - break; - case CON_32DO: - if((cdsPciModules.cards_used[jj].type == CON_32DO) && - (cdsPciModules.cards_used[jj].instance == do32Cnt)) - { - kk = cdsPciModules.doCount; - printf("Found 32 DO CONTEC at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.cDo32lCount ++; - cdsPciModules.doInstance[kk] = do32Cnt; - status ++; - } - break; - case ACS_16DIO: - if((cdsPciModules.cards_used[jj].type == ACS_16DIO) && - (cdsPciModules.cards_used[jj].instance == doIIRO16Cnt)) - { - kk = cdsPciModules.doCount; - printf("Found Access IIRO-16 at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.iiroDio1Count ++; - cdsPciModules.doInstance[kk] = doIIRO16Cnt; - status ++; - } - break; - case ACS_8DIO: - if((cdsPciModules.cards_used[jj].type == ACS_8DIO) && - (cdsPciModules.cards_used[jj].instance == doIIRO8Cnt)) - { - kk = cdsPciModules.doCount; - printf("Found Access IIRO-8 at %d 0x%x\n",jj,ioMemData->ipc[ii]); - cdsPciModules.doType[kk] = ioMemData->model[ii]; - cdsPciModules.pci_do[kk] = ioMemData->ipc[ii]; - cdsPciModules.doCount ++; - cdsPciModules.iiroDioCount ++; - cdsPciModules.doInstance[kk] = doIIRO8Cnt; - status ++; - } - break; - default: - break; - } - } - if(ioMemData->model[ii] == GSC_16AI64SSA) adcCnt ++; - if(ioMemData->model[ii] == GSC_16AO16) dacCnt ++; - if(ioMemData->model[ii] == GSC_18AO8) dac18Cnt ++; - if(ioMemData->model[ii] == CON_6464DIO) doCnt ++; - if(ioMemData->model[ii] == CON_32DO) do32Cnt ++; - if(ioMemData->model[ii] == ACS_16DIO) doIIRO16Cnt ++; - if(ioMemData->model[ii] == ACS_8DIO) doIIRO8Cnt ++; - } - // If no ADC cards were found, then SLAVE cannot run - if(!cdsPciModules.adcCount) - { - printf("No ADC cards found - exiting\n"); - return -1; - } - // This did not quite work for some reason - // Need to find a way to handle skipped DAC cards in slaves - //cdsPciModules.dacCount = ioMemData->dacCount; - printf("%d PCI cards found \n",status); - if(status < cards) - { - printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); - cardCountErr = 1; - } - - - // Print out all the I/O information + // Slave gets RFM module count from MASTER. + cdsPciModules.rfmCount = ioMemData->rfmCount; + cdsPciModules.dolphinCount = ioMemData->dolphinCount; + cdsPciModules.dolphinRead[ 0 ] = ioMemData->dolphinRead[ 0 ]; + cdsPciModules.dolphinWrite[ 0 ] = ioMemData->dolphinWrite[ 0 ]; + for ( ii = 0; ii < cdsPciModules.rfmCount; ii++ ) + { + cdsPciModules.pci_rfm[ ii ] = ioMemData->pci_rfm[ ii ]; + cdsPciModules.pci_rfm_dma[ ii ] = ioMemData->pci_rfm_dma[ ii ]; + } + printf( "******************************************************************" + "*********\n" ); + if ( cdsPciModules.gps ) + { + printf( "IRIG-B card found %d\n", cdsPciModules.gpsType ); + printf( "**************************************************************" + "*************\n" ); + } + print_io_info( &cdsPciModules ); -// Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style. -// Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O. -// Master unit only maps the RFM I/O space and passes pointers to SLAVES. + // Initialize buffer for daqLib.c code + printf( "Initializing space for daqLib buffers\n" ); + daqBuffer = (long)&daqArea[ 0 ]; - // Slave gets RFM module count from MASTER. - cdsPciModules.rfmCount = ioMemData->rfmCount; - cdsPciModules.dolphinCount = ioMemData->dolphinCount; - cdsPciModules.dolphinRead[0] = ioMemData->dolphinRead[0]; - cdsPciModules.dolphinWrite[0] = ioMemData->dolphinWrite[0]; - for(ii=0;ii<cdsPciModules.rfmCount;ii++) - { - cdsPciModules.pci_rfm[ii] = ioMemData->pci_rfm[ii]; - cdsPciModules.pci_rfm_dma[ii] = ioMemData->pci_rfm_dma[ii]; - } - printf("***************************************************************************\n"); - if (cdsPciModules.gps) { - printf("IRIG-B card found %d\n",cdsPciModules.gpsType); - printf("***************************************************************************\n"); - } - - print_io_info(&cdsPciModules); - - // Initialize buffer for daqLib.c code - printf("Initializing space for daqLib buffers\n"); - daqBuffer = (long)&daqArea[0]; - - pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; - for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { - printf("Epics burt restore is %d\n", pLocalEpics->epicsInput.burtRestore); - usleep(1000000); - } - if (cnt == 10) { - return -1; - } + pLocalEpics = (CDS_EPICS*)&( (RFM_FE_COMMS*)_epics_shm )->epicsSpace; + for ( cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++ ) + { + printf( "Epics burt restore is %d\n", + pLocalEpics->epicsInput.burtRestore ); + usleep( 1000000 ); + } + if ( cnt == 10 ) + { + return -1; + } - pLocalEpics->epicsInput.vmeReset = 0; - fe_start_app_user(); + pLocalEpics->epicsInput.vmeReset = 0; + fe_start_app_user( ); - return 0; + return 0; } diff --git a/src/fe/rcguserIop.c b/src/fe/rcguserIop.c index ec936dd78..7ba4606f4 100644 --- a/src/fe/rcguserIop.c +++ b/src/fe/rcguserIop.c @@ -17,12 +17,11 @@ #include <string.h> #include <signal.h> - // These externs and "16" need to go to a header file (mbuf.h) -extern int fe_start_iop_user(); -extern char daqArea[2*DAQ_DCU_SIZE]; // Space allocation for daqLib buffers -extern char *addr; -extern int cycleOffset; +extern int fe_start_iop_user( ); +extern char daqArea[ 2 * DAQ_DCU_SIZE ]; // Space allocation for daqLib buffers +extern char* addr; +extern int cycleOffset; // Scan a double #if 0 @@ -47,389 +46,444 @@ simple_strtod(char *start, char **end) { } #endif -void usage() +void +usage( ) { - fprintf(stderr,"Usage: rcgUser -m system_name \n"); - fprintf(stderr, "-h - help\n"); + fprintf( stderr, "Usage: rcgUser -m system_name \n" ); + fprintf( stderr, "-h - help\n" ); } - /// Startup function for initialization of kernel module. -int main (int argc, char **argv) +int +main( int argc, char** argv ) { - int status; - int ii,jj,kk,mm; /// @param ii,jj,kk default loop counters - char fname[128]; /// @param fname[128] Name of shared mem area to allocate for DAQ data - int cards; /// @param cards Number of PCIe cards found on bus - int adcCnt; /// @param adcCnt Number of ADC cards found by slave model. - int dacCnt; /// @param dacCnt Number of 16bit DAC cards found by slave model. - int dac18Cnt; /// @param dac18Cnt Number of 18bit DAC cards found by slave model. - int doCnt; /// @param doCnt Total number of digital I/O cards found by slave model. - int do32Cnt; /// @param do32Cnt Total number of Contec 32 bit DIO cards found by slave model. - int doIIRO16Cnt; /// @param doIIRO16Cnt Total number of Acces I/O 16 bit relay cards found by slave model. - int doIIRO8Cnt; /// @param doIIRO8Cnt Total number of Acces I/O 8 bit relay cards found by slave model. - int cdo64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit output sections mapped by slave model. - int cdi64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit input sections mapped by slave model. - int ret; /// @param ret Return value from various Malloc calls to allocate memory. - int cnt; - char *sysname; - char shm_name[64]; - int c; - char *modelname; + int status; + int ii, jj, kk, mm; /// @param ii,jj,kk default loop counters + char fname[ 128 ]; /// @param fname[128] Name of shared mem area to allocate + /// for DAQ data + int cards; /// @param cards Number of PCIe cards found on bus + int adcCnt; /// @param adcCnt Number of ADC cards found by slave model. + int dacCnt; /// @param dacCnt Number of 16bit DAC cards found by slave + /// model. + int dac18Cnt; /// @param dac18Cnt Number of 18bit DAC cards found by slave + /// model. + int doCnt; /// @param doCnt Total number of digital I/O cards found by slave + /// model. + int do32Cnt; /// @param do32Cnt Total number of Contec 32 bit DIO cards + /// found by slave model. + int doIIRO16Cnt; /// @param doIIRO16Cnt Total number of Acces I/O 16 bit + /// relay cards found by slave model. + int doIIRO8Cnt; /// @param doIIRO8Cnt Total number of Acces I/O 8 bit relay + /// cards found by slave model. + int cdo64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit + /// output sections mapped by slave model. + int cdi64Cnt; /// @param cdo64Cnt Total number of Contec 6464 DIO card 32bit + /// input sections mapped by slave model. + int ret; /// @param ret Return value from various Malloc calls to allocate + /// memory. + int cnt; + char* sysname; + char shm_name[ 64 ]; + int c; + char* modelname; + + cycleOffset = 0; + + while ( ( c = getopt( argc, argv, "m:t:help" ) ) != EOF ) + switch ( c ) + { + case 'm': + sysname = optarg; + printf( "sysname = %s\n", sysname ); + break; + case 't': + cycleOffset = atoi( optarg ); + printf( "cycle offset = %d\n", cycleOffset ); + break; + case 'help': + default: + usage( ); + exit( 1 ); + } - cycleOffset = 0; + kk = 0; - while ((c = getopt(argc, argv, "m:t:help")) != EOF) switch(c) { - case 'm': - sysname = optarg; - printf("sysname = %s\n",sysname); - break; - case 't': - cycleOffset = atoi(optarg); - printf("cycle offset = %d\n",cycleOffset); - break; - case 'help': - default: - usage(); - exit(1); - } + jj = 0; + int i = 0; + char* p = strtok( argv[ 0 ], "/" ); + char* array[ 5 ]; - kk = 0; + while ( p != NULL ) + { + array[ i++ ] = p; + p = strtok( NULL, "/" ); + } + modelname = array[ i - 1 ]; + sysname = array[ i - 1 ]; - jj = 0; - int i = 0; - char *p = strtok (argv[0], "/"); - char *array[5]; + printf( "model name is %s \n", sysname ); - while (p != NULL) + sprintf( shm_name, "%s", sysname ); + findSharedMemory( sysname ); + _epics_shm = (char*)addr; + ; + if ( _epics_shm < 0 ) { - array[i++] = p; - p = strtok (NULL, "/"); + printf( "mbuf_allocate_area() failed; ret = %d\n", _epics_shm ); + return -1; } - modelname = array[i-1]; - sysname = array[i-1]; - - printf("model name is %s \n",sysname); - + printf( "EPICSM at 0x%lx\n", (long)_epics_shm ); - sprintf(shm_name,"%s",sysname); - findSharedMemory(sysname); - _epics_shm = (char *)addr;; - if (_epics_shm < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", _epics_shm); - return -1; - } - printf("EPICSM at 0x%lx\n", (long)_epics_shm); + sprintf( shm_name, "%s", "ipc" ); + findSharedMemory( "ipc" ); + _ipc_shm = (char*)addr; + if ( _ipc_shm < 0 ) + { + printf( "mbuf_allocate_area(ipc) failed; ret = %d\n", _ipc_shm ); + return -1; + } - sprintf(shm_name,"%s","ipc"); - findSharedMemory("ipc"); - _ipc_shm = (char *)addr; - if (_ipc_shm< 0) { - printf("mbuf_allocate_area(ipc) failed; ret = %d\n", _ipc_shm); - return -1; + printf( "IPC at 0x%lx\n", (long)_ipc_shm ); + ioMemData = (volatile IO_MEM_DATA*)( ( (char*)_ipc_shm ) + 0x4000 ); + printf( + "IOMEM at 0x%lx size 0x%x\n", (long)ioMemData, sizeof( IO_MEM_DATA ) ); + printf( "%d PCI cards found\n", ioMemData->totalCards ); + + // If DAQ is via shared memory (Framebuilder code running on same machine or + // MX networking is used) attach DAQ shared memory location. + sprintf( shm_name, "%s_daq", sysname ); + findSharedMemory( shm_name ); + _daq_shm = (char*)addr; + if ( _daq_shm < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", _daq_shm ); + return -1; + } + // printf("Allocated daq shmem; set at 0x%x\n", _daq_shm); + printf( "DAQSM at 0x%lx\n", _daq_shm ); + daqPtr = (struct rmIpcStr*)_daq_shm; + + // Open new IO shared memory in support of no hardware I/O + sprintf( shm_name, "%s_io_space", sysname ); + findSharedMemory( shm_name ); + _io_shm = (char*)addr; + if ( _io_shm < 0 ) + { + printf( "mbuf_allocate_area() failed; ret = %d\n", _io_shm ); + return -1; + } + printf( "IO SPACE at 0x%lx\n", _io_shm ); + ioMemDataIop = (volatile IO_MEM_DATA_IOP*)( ( (char*)_io_shm ) ); + + // Find and initialize all PCI I/O modules + // ******************************************************* Following I/O + // card info is from feCode + cards = sizeof( cards_used ) / sizeof( cards_used[ 0 ] ); + printf( "configured to use %d cards\n", cards ); + cdsPciModules.cards = cards; + cdsPciModules.cards_used = cards_used; + // return -1; + printf( "Initializing PCI Modules for IOP\n" ); + for ( jj = 0; jj < cards; jj++ ) + printf( + "Card %d type = %d\n", jj, cdsPciModules.cards_used[ jj ].type ); + cdsPciModules.adcCount = 0; + cdsPciModules.dacCount = 0; + cdsPciModules.dioCount = 0; + cdsPciModules.doCount = 0; + + // If running as a slave process, I/O card information is via ipc shared + // memory + printf( "%d PCI cards found\n", cards ); + status = 0; + adcCnt = 0; + dacCnt = 0; + dac18Cnt = 0; + doCnt = 0; + do32Cnt = 0; + cdo64Cnt = 0; + cdi64Cnt = 0; + doIIRO16Cnt = 0; + doIIRO8Cnt = 0; + + ioMemData->totalCards = cards; + + // Have to search thru all cards and find desired instance for application + // Master will map ADC cards first, then DAC and finally DIO + for ( jj = 0; jj < cards; jj++ ) + { + /* + printf("Model %d = %d, type = %d, instance = %d, dacCnt = %d \n", + ii,ioMemData->model[ii], + cdsPciModules.cards_used[jj].type, + cdsPciModules.cards_used[jj].instance, + dacCnt); + */ + switch ( cdsPciModules.cards_used[ jj ].type ) + { + case GSC_16AI64SSA: + kk = cdsPciModules.adcCount; + cdsPciModules.adcType[ kk ] = GSC_16AI64SSA; + cdsPciModules.adcCount++; + status++; + break; + case GSC_16AO16: + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_16AO16; + cdsPciModules.dacCount++; + status++; + break; + case GSC_18AO8: + kk = cdsPciModules.dacCount; + cdsPciModules.dacType[ kk ] = GSC_18AO8; + cdsPciModules.dacCount++; + status++; + break; + case CON_6464DIO: + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = CON_6464DIO; + cdsPciModules.doCount++; + cdsPciModules.cDio6464lCount++; + // cdsPciModules.doInstance[kk] = cDio6464lCount; + status += 2; + break; + case CON_32DO: + kk = cdsPciModules.doCount; + cdsPciModules.doType[ kk ] = CON_32DO; + cdsPciModules.doCount++; + cdsPciModules.cDo32lCount++; + cdsPciModules.doInstance[ kk ] = do32Cnt; + status++; + break; + case ACS_16DIO: + kk = cdsPciModules.doCount; + cdsPciModules.doCount++; + cdsPciModules.iiroDio1Count++; + cdsPciModules.doInstance[ kk ] = doIIRO16Cnt; + status++; + break; + case ACS_8DIO: + kk = cdsPciModules.doCount; + cdsPciModules.doCount++; + cdsPciModules.iiroDioCount++; + cdsPciModules.doInstance[ kk ] = doIIRO8Cnt; + status++; + break; + default: + break; } + } + // If no ADC cards were found, then SLAVE cannot run + if ( !cdsPciModules.adcCount ) + { + printf( "No ADC cards found - exiting\n" ); + return -1; + } + // This did not quite work for some reason + // Need to find a way to handle skipped DAC cards in slaves + // cdsPciModules.dacCount = ioMemData->dacCount; - printf("IPC at 0x%lx\n",(long)_ipc_shm); - ioMemData = (volatile IO_MEM_DATA *)(((char *)_ipc_shm) + 0x4000); - printf("IOMEM at 0x%lx size 0x%x\n",(long)ioMemData,sizeof(IO_MEM_DATA)); - printf("%d PCI cards found\n",ioMemData->totalCards); - + printf( "%d PCI cards found \n", status ); + if ( status < cards ) + { + printf( " ERROR **** Did not find correct number of cards! Expected %d " + "and Found %d\n", + cards, + status ); + cardCountErr = 1; + } -// If DAQ is via shared memory (Framebuilder code running on same machine or MX networking is used) -// attach DAQ shared memory location. - sprintf(shm_name, "%s_daq", sysname); - findSharedMemory(shm_name); - _daq_shm = (char *)addr; - if (_daq_shm < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", _daq_shm); - return -1; + // Print out all the I/O information + printf( "******************************************************************" + "*********\n" ); + // Master send module counds to SLAVE via ipc shm + ioMemData->totalCards = status; + ioMemData->adcCount = cdsPciModules.adcCount; + ioMemData->dacCount = cdsPciModules.dacCount; + ioMemData->bioCount = cdsPciModules.doCount; + // kk will act as ioMem location counter for mapping modules + kk = cdsPciModules.adcCount; + printf( "%d ADC cards found\n", cdsPciModules.adcCount ); + for ( ii = 0; ii < cdsPciModules.adcCount; ii++ ) + { + // MASTER maps ADC modules first in ipc shm for SLAVES + ioMemData->model[ ii ] = cdsPciModules.adcType[ ii ]; + ioMemData->ipc[ ii ] = + ii; // ioData memory buffer location for SLAVE to use + ioMemDataIop->model[ ii ] = cdsPciModules.adcType[ ii ]; + ioMemDataIop->ipc[ ii ] = + ii; // ioData memory buffer location for SLAVE to use + for ( jj = 0; jj < 65536; jj++ ) + { + for ( mm = 0; mm < 32; mm++ ) + { + ioMemDataIop->iodata[ ii ][ jj ].data[ mm ] = jj - 32767; + } } - // printf("Allocated daq shmem; set at 0x%x\n", _daq_shm); - printf("DAQSM at 0x%lx\n",_daq_shm); - daqPtr = (struct rmIpcStr *) _daq_shm; - - -// Open new IO shared memory in support of no hardware I/O - sprintf(shm_name, "%s_io_space", sysname); - findSharedMemory(shm_name); - _io_shm = (char *)addr; - if (_io_shm < 0) { - printf("mbuf_allocate_area() failed; ret = %d\n", _io_shm); - return -1; + if ( cdsPciModules.adcType[ ii ] == GSC_18AISS6C ) + { + printf( "\tADC %d is a GSC_18AISS6C module\n", ii ); + printf( "\t\tChannels = 6 \n" ); + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsPciModules.adcConfig[ ii ] & 0xfff ) ); } - printf("IO SPACE at 0x%lx\n",_io_shm); - ioMemDataIop = (volatile IO_MEM_DATA_IOP *)(((char *)_io_shm)) ; - - // Find and initialize all PCI I/O modules ******************************************************* - // Following I/O card info is from feCode - cards = sizeof(cards_used)/sizeof(cards_used[0]); - printf("configured to use %d cards\n", cards); - cdsPciModules.cards = cards; - cdsPciModules.cards_used = cards_used; - //return -1; - printf("Initializing PCI Modules for IOP\n"); - for(jj=0;jj<cards;jj++) - printf("Card %d type = %d\n",jj,cdsPciModules.cards_used[jj].type); - cdsPciModules.adcCount = 0; - cdsPciModules.dacCount = 0; - cdsPciModules.dioCount = 0; - cdsPciModules.doCount = 0; - -// If running as a slave process, I/O card information is via ipc shared memory - printf("%d PCI cards found\n",cards); - status = 0; - adcCnt = 0; - dacCnt = 0; - dac18Cnt = 0; - doCnt = 0; - do32Cnt = 0; - cdo64Cnt = 0; - cdi64Cnt = 0; - doIIRO16Cnt = 0; - doIIRO8Cnt = 0; - - ioMemData->totalCards = cards; - - // Have to search thru all cards and find desired instance for application - // Master will map ADC cards first, then DAC and finally DIO - for(jj=0;jj<cards;jj++) - { - /* - printf("Model %d = %d, type = %d, instance = %d, dacCnt = %d \n", - ii,ioMemData->model[ii], - cdsPciModules.cards_used[jj].type, - cdsPciModules.cards_used[jj].instance, - dacCnt); - */ - switch(cdsPciModules.cards_used[jj].type) - { - case GSC_16AI64SSA: - kk = cdsPciModules.adcCount; - cdsPciModules.adcType[kk] = GSC_16AI64SSA; - cdsPciModules.adcCount ++; - status ++; - break; - case GSC_16AO16: - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_16AO16; - cdsPciModules.dacCount ++; - status ++; - break; - case GSC_18AO8: - kk = cdsPciModules.dacCount; - cdsPciModules.dacType[kk] = GSC_18AO8; - cdsPciModules.dacCount ++; - status ++; - break; - case CON_6464DIO: - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = CON_6464DIO; - cdsPciModules.doCount ++; - cdsPciModules.cDio6464lCount ++; - // cdsPciModules.doInstance[kk] = cDio6464lCount; - status += 2; - break; - case CON_32DO: - kk = cdsPciModules.doCount; - cdsPciModules.doType[kk] = CON_32DO; - cdsPciModules.doCount ++; - cdsPciModules.cDo32lCount ++; - cdsPciModules.doInstance[kk] = do32Cnt; - status ++; - break; - case ACS_16DIO: - kk = cdsPciModules.doCount; - cdsPciModules.doCount ++; - cdsPciModules.iiroDio1Count ++; - cdsPciModules.doInstance[kk] = doIIRO16Cnt; - status ++; - break; - case ACS_8DIO: - kk = cdsPciModules.doCount; - cdsPciModules.doCount ++; - cdsPciModules.iiroDioCount ++; - cdsPciModules.doInstance[kk] = doIIRO8Cnt; - status ++; - break; - default: - break; - } - } - // If no ADC cards were found, then SLAVE cannot run - if(!cdsPciModules.adcCount) - { - printf("No ADC cards found - exiting\n"); - return -1; - } - // This did not quite work for some reason - // Need to find a way to handle skipped DAC cards in slaves - //cdsPciModules.dacCount = ioMemData->dacCount; - - printf("%d PCI cards found \n",status); - if(status < cards) - { - printf(" ERROR **** Did not find correct number of cards! Expected %d and Found %d\n",cards,status); - cardCountErr = 1; - } - - // Print out all the I/O information - printf("***************************************************************************\n"); - // Master send module counds to SLAVE via ipc shm - ioMemData->totalCards = status; - ioMemData->adcCount = cdsPciModules.adcCount; - ioMemData->dacCount = cdsPciModules.dacCount; - ioMemData->bioCount = cdsPciModules.doCount; - // kk will act as ioMem location counter for mapping modules - kk = cdsPciModules.adcCount; - printf("%d ADC cards found\n",cdsPciModules.adcCount); - for(ii=0;ii<cdsPciModules.adcCount;ii++) + if ( cdsPciModules.adcType[ ii ] == GSC_16AI64SSA ) { - // MASTER maps ADC modules first in ipc shm for SLAVES - ioMemData->model[ii] = cdsPciModules.adcType[ii]; - ioMemData->ipc[ii] = ii; // ioData memory buffer location for SLAVE to use - ioMemDataIop->model[ii] = cdsPciModules.adcType[ii]; - ioMemDataIop->ipc[ii] = ii; // ioData memory buffer location for SLAVE to use - for(jj=0;jj<65536;jj++) { - for(mm=0;mm<32;mm++) { - ioMemDataIop->iodata[ii][jj].data[mm] = jj - 32767; - } - } - if(cdsPciModules.adcType[ii] == GSC_18AISS6C) - { - printf("\tADC %d is a GSC_18AISS6C module\n",ii); - printf("\t\tChannels = 6 \n"); - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.adcConfig[ii] & 0xfff)); - } - if(cdsPciModules.adcType[ii] == GSC_16AI64SSA) - { - printf("\tADC %d is a GSC_16AI64SSA module\n",ii); - if((cdsPciModules.adcConfig[ii] & 0x10000) > 0) jj = 32; - else jj = 64; - printf("\t\tChannels = %d \n",jj); - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.adcConfig[ii] & 0xfff)); - } + printf( "\tADC %d is a GSC_16AI64SSA module\n", ii ); + if ( ( cdsPciModules.adcConfig[ ii ] & 0x10000 ) > 0 ) + jj = 32; + else + jj = 64; + printf( "\t\tChannels = %d \n", jj ); + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsPciModules.adcConfig[ ii ] & 0xfff ) ); } - printf("***************************************************************************\n"); - printf("%d DAC cards found\n",cdsPciModules.dacCount); - for(ii=0;ii<cdsPciModules.dacCount;ii++) + } + printf( "******************************************************************" + "*********\n" ); + printf( "%d DAC cards found\n", cdsPciModules.dacCount ); + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + { + if ( cdsPciModules.dacType[ ii ] == GSC_18AO8 ) { - if(cdsPciModules.dacType[ii] == GSC_18AO8) - { - printf("\tDAC %d is a GSC_18AO8 module\n",ii); - } - if(cdsPciModules.dacType[ii] == GSC_16AO16) - { - printf("\tDAC %d is a GSC_16AO16 module\n",ii); - if((cdsPciModules.dacConfig[ii] & 0x10000) == 0x10000) jj = 8; - if((cdsPciModules.dacConfig[ii] & 0x20000) == 0x20000) jj = 12; - if((cdsPciModules.dacConfig[ii] & 0x30000) == 0x30000) jj = 16; - printf("\t\tChannels = %d \n",jj); - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x0000) - { - printf("\t\tFilters = None\n"); - } - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x40000) - { - printf("\t\tFilters = 10kHz\n"); - } - if((cdsPciModules.dacConfig[ii] & 0xC0000) == 0x80000) - { - printf("\t\tFilters = 100kHz\n"); - } - if((cdsPciModules.dacConfig[ii] & 0x100000) == 0x100000) - { - printf("\t\tOutput Type = Differential\n"); - } - printf("\t\tFirmware Rev = %d \n\n",(cdsPciModules.dacConfig[ii] & 0xfff)); - } - // Pass DAC info to SLAVE processes - ioMemData->model[kk] = cdsPciModules.dacType[ii]; - ioMemData->ipc[kk] = kk; - // Following used by MASTER to point to ipc memory for inputting DAC data from SLAVES - cdsPciModules.dacConfig[ii] = kk; -printf("MASTER DAC SLOT %d %d\n",ii,cdsPciModules.dacConfig[ii]); - kk ++; - } - printf("***************************************************************************\n"); - printf("%d DIO cards found\n",cdsPciModules.dioCount); - printf("***************************************************************************\n"); - printf("%d IIRO-8 Isolated DIO cards found\n",cdsPciModules.iiroDioCount); - printf("***************************************************************************\n"); - printf("%d IIRO-16 Isolated DIO cards found\n",cdsPciModules.iiroDio1Count); - printf("***************************************************************************\n"); - printf("%d Contec 32ch PCIe DO cards found\n",cdsPciModules.cDo32lCount); - printf("%d Contec PCIe DIO1616 cards found\n",cdsPciModules.cDio1616lCount); - printf("%d Contec PCIe DIO6464 cards found\n",cdsPciModules.cDio6464lCount); - printf("%d DO cards found\n",cdsPciModules.doCount); - // MASTER sends DIO module information to SLAVES - // Note that for DIO, SLAVE modules will perform the I/O directly and therefore need to - // know the PCIe address of these modules. - ioMemData->bioCount = cdsPciModules.doCount; - for(ii=0;ii<cdsPciModules.doCount;ii++) + printf( "\tDAC %d is a GSC_18AO8 module\n", ii ); + } + if ( cdsPciModules.dacType[ ii ] == GSC_16AO16 ) { - // MASTER needs to find Contec 1616 I/O card to control timing slave. - if(cdsPciModules.doType[ii] == CON_1616DIO) - { - tdsControl[tdsCount] = ii; - printf("TDS controller %d is at %d\n",tdsCount,ii); - tdsCount ++; - } - ioMemData->model[kk] = cdsPciModules.doType[ii]; - // Unlike ADC and DAC, where a memory buffer number is passed, a PCIe address is passed - // for DIO cards. - ioMemData->ipc[kk] = kk; - kk ++; - } - printf("Total of %d I/O modules found and mapped\n",kk); - printf("***************************************************************************\n"); -// Following section maps Reflected Memory, both VMIC hardware style and Dolphin PCIe network style. -// Slave units will perform I/O transactions with RFM directly ie MASTER does not do RFM I/O. -// Master unit only maps the RFM I/O space and passes pointers to SLAVES. - - printf("%d RFM cards found\n",cdsPciModules.rfmCount); - ioMemData->rfmCount = cdsPciModules.rfmCount; - for(ii=0;ii<cdsPciModules.rfmCount;ii++) + printf( "\tDAC %d is a GSC_16AO16 module\n", ii ); + if ( ( cdsPciModules.dacConfig[ ii ] & 0x10000 ) == 0x10000 ) + jj = 8; + if ( ( cdsPciModules.dacConfig[ ii ] & 0x20000 ) == 0x20000 ) + jj = 12; + if ( ( cdsPciModules.dacConfig[ ii ] & 0x30000 ) == 0x30000 ) + jj = 16; + printf( "\t\tChannels = %d \n", jj ); + if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x0000 ) + { + printf( "\t\tFilters = None\n" ); + } + if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x40000 ) + { + printf( "\t\tFilters = 10kHz\n" ); + } + if ( ( cdsPciModules.dacConfig[ ii ] & 0xC0000 ) == 0x80000 ) + { + printf( "\t\tFilters = 100kHz\n" ); + } + if ( ( cdsPciModules.dacConfig[ ii ] & 0x100000 ) == 0x100000 ) + { + printf( "\t\tOutput Type = Differential\n" ); + } + printf( "\t\tFirmware Rev = %d \n\n", + ( cdsPciModules.dacConfig[ ii ] & 0xfff ) ); + } + // Pass DAC info to SLAVE processes + ioMemData->model[ kk ] = cdsPciModules.dacType[ ii ]; + ioMemData->ipc[ kk ] = kk; + // Following used by MASTER to point to ipc memory for inputting DAC + // data from SLAVES + cdsPciModules.dacConfig[ ii ] = kk; + printf( "MASTER DAC SLOT %d %d\n", ii, cdsPciModules.dacConfig[ ii ] ); + kk++; + } + printf( "******************************************************************" + "*********\n" ); + printf( "%d DIO cards found\n", cdsPciModules.dioCount ); + printf( "******************************************************************" + "*********\n" ); + printf( "%d IIRO-8 Isolated DIO cards found\n", + cdsPciModules.iiroDioCount ); + printf( "******************************************************************" + "*********\n" ); + printf( "%d IIRO-16 Isolated DIO cards found\n", + cdsPciModules.iiroDio1Count ); + printf( "******************************************************************" + "*********\n" ); + printf( "%d Contec 32ch PCIe DO cards found\n", cdsPciModules.cDo32lCount ); + printf( "%d Contec PCIe DIO1616 cards found\n", + cdsPciModules.cDio1616lCount ); + printf( "%d Contec PCIe DIO6464 cards found\n", + cdsPciModules.cDio6464lCount ); + printf( "%d DO cards found\n", cdsPciModules.doCount ); + // MASTER sends DIO module information to SLAVES + // Note that for DIO, SLAVE modules will perform the I/O directly and + // therefore need to know the PCIe address of these modules. + ioMemData->bioCount = cdsPciModules.doCount; + for ( ii = 0; ii < cdsPciModules.doCount; ii++ ) + { + // MASTER needs to find Contec 1616 I/O card to control timing slave. + if ( cdsPciModules.doType[ ii ] == CON_1616DIO ) { - printf("\tRFM %d is a VMIC_%x module with Node ID %d\n", ii, cdsPciModules.rfmType[ii], cdsPciModules.rfmConfig[ii]); - printf("address is 0x%lx\n",cdsPciModules.pci_rfm[ii]); - // Master sends RFM memory pointers to SLAVES - ioMemData->pci_rfm[ii] = cdsPciModules.pci_rfm[ii]; - ioMemData->pci_rfm_dma[ii] = cdsPciModules.pci_rfm_dma[ii]; - } - // ioMemData->dolphinCount = 0; + tdsControl[ tdsCount ] = ii; + printf( "TDS controller %d is at %d\n", tdsCount, ii ); + tdsCount++; + } + ioMemData->model[ kk ] = cdsPciModules.doType[ ii ]; + // Unlike ADC and DAC, where a memory buffer number is passed, a PCIe + // address is passed for DIO cards. + ioMemData->ipc[ kk ] = kk; + kk++; + } + printf( "Total of %d I/O modules found and mapped\n", kk ); + printf( "******************************************************************" + "*********\n" ); + // Following section maps Reflected Memory, both VMIC hardware style and + // Dolphin PCIe network style. Slave units will perform I/O transactions + // with RFM directly ie MASTER does not do RFM I/O. Master unit only maps + // the RFM I/O space and passes pointers to SLAVES. + + printf( "%d RFM cards found\n", cdsPciModules.rfmCount ); + ioMemData->rfmCount = cdsPciModules.rfmCount; + for ( ii = 0; ii < cdsPciModules.rfmCount; ii++ ) + { + printf( "\tRFM %d is a VMIC_%x module with Node ID %d\n", + ii, + cdsPciModules.rfmType[ ii ], + cdsPciModules.rfmConfig[ ii ] ); + printf( "address is 0x%lx\n", cdsPciModules.pci_rfm[ ii ] ); + // Master sends RFM memory pointers to SLAVES + ioMemData->pci_rfm[ ii ] = cdsPciModules.pci_rfm[ ii ]; + ioMemData->pci_rfm_dma[ ii ] = cdsPciModules.pci_rfm_dma[ ii ]; + } + // ioMemData->dolphinCount = 0; #ifdef DOLPHIN_TEST - ioMemData->dolphinCount = cdsPciModules.dolphinCount; - ioMemData->dolphinRead[0] = cdsPciModules.dolphinRead[0]; - ioMemData->dolphinWrite[0] = cdsPciModules.dolphinWrite[0]; + ioMemData->dolphinCount = cdsPciModules.dolphinCount; + ioMemData->dolphinRead[ 0 ] = cdsPciModules.dolphinRead[ 0 ]; + ioMemData->dolphinWrite[ 0 ] = cdsPciModules.dolphinWrite[ 0 ]; #else -// Clear Dolphin pointers so the slave sees NULLs - ioMemData->dolphinCount = 0; - ioMemData->dolphinRead[0] = 0; - ioMemData->dolphinWrite[0] = 0; + // Clear Dolphin pointers so the slave sees NULLs + ioMemData->dolphinCount = 0; + ioMemData->dolphinRead[ 0 ] = 0; + ioMemData->dolphinWrite[ 0 ] = 0; #endif - printf("***************************************************************************\n"); - if (cdsPciModules.gps) { - printf("IRIG-B card found %d\n",cdsPciModules.gpsType); - printf("***************************************************************************\n"); - } + printf( "******************************************************************" + "*********\n" ); + if ( cdsPciModules.gps ) + { + printf( "IRIG-B card found %d\n", cdsPciModules.gpsType ); + printf( "**************************************************************" + "*************\n" ); + } + // Initialize buffer for daqLib.c code + printf( "Initializing space for daqLib buffers\n" ); + daqBuffer = (long)&daqArea[ 0 ]; - // Initialize buffer for daqLib.c code - printf("Initializing space for daqLib buffers\n"); - daqBuffer = (long)&daqArea[0]; - - pLocalEpics = (CDS_EPICS *)&((RFM_FE_COMMS *)_epics_shm)->epicsSpace; - for (cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++) { - printf("Epics burt restore is %d\n", pLocalEpics->epicsInput.burtRestore); - usleep(1000000); - } - if (cnt == 10) { - return -1; - } + pLocalEpics = (CDS_EPICS*)&( (RFM_FE_COMMS*)_epics_shm )->epicsSpace; + for ( cnt = 0; cnt < 10 && pLocalEpics->epicsInput.burtRestore == 0; cnt++ ) + { + printf( "Epics burt restore is %d\n", + pLocalEpics->epicsInput.burtRestore ); + usleep( 1000000 ); + } + if ( cnt == 10 ) + { + return -1; + } - pLocalEpics->epicsInput.vmeReset = 0; - fe_start_iop_user(); + pLocalEpics->epicsInput.vmeReset = 0; + fe_start_iop_user( ); - return 0; + return 0; } diff --git a/src/fe/timing.c b/src/fe/timing.c index 1849f0b45..a58d3ef49 100644 --- a/src/fe/timing.c +++ b/src/fe/timing.c @@ -5,13 +5,15 @@ /// \brief Get current kernel time (in GPS) /// @return Current time in form of GPS Seconds. //*********************************************************************** -inline unsigned long current_time_fe(void) { - struct timespec t; - extern struct timespec current_kernel_time(void); - t = current_kernel_time(); - // Added leap second for July 1, 2015 - t.tv_sec += - 315964819 + 33 + 3 + 1; - return t.tv_sec; +inline unsigned long +current_time_fe( void ) +{ + struct timespec t; + extern struct timespec current_kernel_time( void ); + t = current_kernel_time( ); + // Added leap second for July 1, 2015 + t.tv_sec += -315964819 + 33 + 3 + 1; + return t.tv_sec; } //*********************************************************************** @@ -19,65 +21,66 @@ inline unsigned long current_time_fe(void) { ///< Code should only run on IOP //*********************************************************************** #ifdef ADC_MASTER -inline float duotime(int count, float meanVal, float data[]) +inline float +duotime( int count, float meanVal, float data[] ) { - float x,y,sumX,sumY,sumXX,sumXY,msumX; - int ii; - float xInc; - float offset,slope,answer; - float den; - - x = 0; - sumX = 0; - sumY = 0; - sumXX = 0; - sumXY= 0; - xInc = 1000000/IOP_IO_RATE; - + float x, y, sumX, sumY, sumXX, sumXY, msumX; + int ii; + float xInc; + float offset, slope, answer; + float den; - for(ii=0;ii<count;ii++) - { - y = data[ii]; - sumX += x; - sumY += y; - sumXX += x * x; - sumXY += x * y; - x += xInc; - } - msumX = sumX * -1; - den = (count*sumXX-sumX*sumX); - if(den == 0.0) - { - return(-1000); - } - offset = (msumX*sumXY+sumXX*sumY)/den; - slope = (msumX*sumY+count*sumXY)/den; - if(slope == 0.0) - { - return(-1000); - } - meanVal -= offset; - answer = meanVal/slope - 91.552; - return(answer); + x = 0; + sumX = 0; + sumY = 0; + sumXX = 0; + sumXY = 0; + xInc = 1000000 / IOP_IO_RATE; + for ( ii = 0; ii < count; ii++ ) + { + y = data[ ii ]; + sumX += x; + sumY += y; + sumXX += x * x; + sumXY += x * y; + x += xInc; + } + msumX = sumX * -1; + den = ( count * sumXX - sumX * sumX ); + if ( den == 0.0 ) + { + return ( -1000 ); + } + offset = ( msumX * sumXY + sumXX * sumY ) / den; + slope = ( msumX * sumY + count * sumXY ) / den; + if ( slope == 0.0 ) + { + return ( -1000 ); + } + meanVal -= offset; + answer = meanVal / slope - 91.552; + return ( answer ); } -inline void initializeDuotoneDiags(duotone_diag_t *dt_diag) +inline void +initializeDuotoneDiags( duotone_diag_t* dt_diag ) { - int ii; - for(ii=0;ii<IOP_IO_RATE;ii++) { - dt_diag->adc[ii] = 0; - dt_diag->dac[ii] = 0; + int ii; + for ( ii = 0; ii < IOP_IO_RATE; ii++ ) + { + dt_diag->adc[ ii ] = 0; + dt_diag->dac[ ii ] = 0; } dt_diag->totalAdc = 0.0; dt_diag->totalDac = 0.0; dt_diag->meanAdc = 0.0; dt_diag->meanDac = 0.0; dt_diag->dacDuoEnable = 0.0; - } #endif -inline void initializeTimingDiags(timing_diag_t *timeinfo) +inline void +initializeTimingDiags( timing_diag_t* timeinfo ) { timeinfo->cpuTimeEverMax = 0; timeinfo->cpuTimeEverMaxWhen = 0; @@ -89,11 +92,11 @@ inline void initializeTimingDiags(timing_diag_t *timeinfo) timeinfo->timeHoldWhenHold = 0; timeinfo->usrTime = 0; timeinfo->cycleTime = 0; - } -inline void sendTimingDiags2Epics(volatile CDS_EPICS *pLocalEpics, - timing_diag_t *timeinfo, - adcInfo_t *adcinfo) +inline void +sendTimingDiags2Epics( volatile CDS_EPICS* pLocalEpics, + timing_diag_t* timeinfo, + adcInfo_t* adcinfo ) { pLocalEpics->epicsOutput.cpuMeter = timeinfo->timeHold; pLocalEpics->epicsOutput.cpuMeterMax = timeinfo->timeHoldMax; @@ -103,41 +106,50 @@ inline void sendTimingDiags2Epics(volatile CDS_EPICS *pLocalEpics, timeinfo->timeHoldWhenHold = timeinfo->timeHoldWhen; timeinfo->usrHoldTime = 0; - pLocalEpics->epicsOutput.adcWaitTime = adcinfo->adcHoldTimeAvg/(CYCLE_PER_SECOND / UNDERSAMPLE); + pLocalEpics->epicsOutput.adcWaitTime = + adcinfo->adcHoldTimeAvg / ( CYCLE_PER_SECOND / UNDERSAMPLE ); pLocalEpics->epicsOutput.adcWaitMin = adcinfo->adcHoldTimeMin; pLocalEpics->epicsOutput.adcWaitMax = adcinfo->adcHoldTimeMax; - adcinfo->adcHoldTimeAvgPerSec = adcinfo->adcHoldTimeAvg/CYCLE_PER_SECOND; + adcinfo->adcHoldTimeAvgPerSec = adcinfo->adcHoldTimeAvg / CYCLE_PER_SECOND; adcinfo->adcHoldTimeMax = 0; adcinfo->adcHoldTimeMin = 0xffff; adcinfo->adcHoldTimeAvg = 0; - } -inline void captureEocTiming(int cycle, unsigned int cycle_gps, timing_diag_t *timeinfo,adcInfo_t *adcinfo) +inline void +captureEocTiming( int cycle, + unsigned int cycle_gps, + timing_diag_t* timeinfo, + adcInfo_t* adcinfo ) { // Hold the max cycle time over the last 1 second - if(timeinfo->cycleTime > timeinfo->timeHold) { - timeinfo->timeHold = timeinfo->cycleTime; - timeinfo->timeHoldWhen = cycle; + if ( timeinfo->cycleTime > timeinfo->timeHold ) + { + timeinfo->timeHold = timeinfo->cycleTime; + timeinfo->timeHoldWhen = cycle; } // Hold the max cycle time since last diag reset - if(timeinfo->cycleTime > timeinfo->timeHoldMax) timeinfo->timeHoldMax = timeinfo->cycleTime; + if ( timeinfo->cycleTime > timeinfo->timeHoldMax ) + timeinfo->timeHoldMax = timeinfo->cycleTime; // Avoid calculating the max hold time for the first few seconds // if (cycle != 0 && (timeinfo->startGpsTime+3) < cycle_gps) { - if ((timeinfo->startGpsTime+3) < cycle_gps) { - if(adcinfo->adcHoldTime > adcinfo->adcHoldTimeMax) - adcinfo->adcHoldTimeMax = adcinfo->adcHoldTime; - if(adcinfo->adcHoldTime < adcinfo->adcHoldTimeMin) - adcinfo->adcHoldTimeMin = adcinfo->adcHoldTime; - adcinfo->adcHoldTimeAvg += adcinfo->adcHoldTime; - if (adcinfo->adcHoldTimeMax > adcinfo->adcHoldTimeEverMax) { - adcinfo->adcHoldTimeEverMax = adcinfo->adcHoldTimeMax; - adcinfo->adcHoldTimeEverMaxWhen = cycle_gps; - } - if (timeinfo->timeHoldMax > timeinfo->cpuTimeEverMax) { - timeinfo->cpuTimeEverMax = timeinfo->timeHoldMax; - timeinfo->cpuTimeEverMaxWhen = cycle_gps; - } + if ( ( timeinfo->startGpsTime + 3 ) < cycle_gps ) + { + if ( adcinfo->adcHoldTime > adcinfo->adcHoldTimeMax ) + adcinfo->adcHoldTimeMax = adcinfo->adcHoldTime; + if ( adcinfo->adcHoldTime < adcinfo->adcHoldTimeMin ) + adcinfo->adcHoldTimeMin = adcinfo->adcHoldTime; + adcinfo->adcHoldTimeAvg += adcinfo->adcHoldTime; + if ( adcinfo->adcHoldTimeMax > adcinfo->adcHoldTimeEverMax ) + { + adcinfo->adcHoldTimeEverMax = adcinfo->adcHoldTimeMax; + adcinfo->adcHoldTimeEverMaxWhen = cycle_gps; + } + if ( timeinfo->timeHoldMax > timeinfo->cpuTimeEverMax ) + { + timeinfo->cpuTimeEverMax = timeinfo->timeHoldMax; + timeinfo->cpuTimeEverMaxWhen = cycle_gps; + } } } diff --git a/src/include/drv/accesDio24.c b/src/include/drv/accesDio24.c index 064c6bbd2..e8c3f5226 100644 --- a/src/include/drv/accesDio24.c +++ b/src/include/drv/accesDio24.c @@ -4,65 +4,71 @@ // ***************************************************************************** /// \brief Routine to initialize ACCESS 24bit DIO modules -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +///I/O ///< register mapping information. -/// @parm[in] *diodev PCI address information passed by the mapping code in map.c +/// @parm[in] *diodev PCI address information passed by the mapping code in +///map.c // ***************************************************************************** -int accesDio24Init(CDS_HARDWARE *pHardware, struct pci_dev *diodev) +int +accesDio24Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev ) { - static unsigned int pci_io_addr; - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - int pedStatus;; /// @param pedStatus Status return from call to enable device. + static unsigned int pci_io_addr; + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + int pedStatus; + ; /// @param pedStatus Status return from call to enable device. - /// Get index into CDS_HARDWARE struct based on total number of DIO cards found by mapping routine - /// in map.c - devNum = pHardware->dioCount; - /// Enable the module. - pedStatus = pci_enable_device(diodev); - /// Find the I/O address space for this module. - pci_read_config_dword(diodev,PCI_BASE_ADDRESS_2,&pci_io_addr); - printk("dio pci2 = 0x%x\n",pci_io_addr); - /// Write I/O address info into the CDS_HARDWARE structure. - pHardware->pci_do[devNum] = (pci_io_addr - 1); - printk("diospace = 0x%x\n",pHardware->pci_do[devNum]); - outb_p(DIO_C_OUTPUT,pHardware->pci_do[devNum]+DIO_CTRL_REG); - /// Clear the present output from the module. - outb(0x00,pHardware->pci_do[devNum]+DIO_C_REG); - /// Fill in remaining info into CDS_HARDWARE structure. - pHardware->doType[devNum] = ACS_24DIO; - pHardware->doInstance[devNum] = pHardware->dioCount; - pHardware->dioCount ++; - pHardware->doCount ++; - /// Return device enable status. - return(pedStatus); + /// Get index into CDS_HARDWARE struct based on total number of DIO cards + /// found by mapping routine in map.c + devNum = pHardware->dioCount; + /// Enable the module. + pedStatus = pci_enable_device( diodev ); + /// Find the I/O address space for this module. + pci_read_config_dword( diodev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + printk( "dio pci2 = 0x%x\n", pci_io_addr ); + /// Write I/O address info into the CDS_HARDWARE structure. + pHardware->pci_do[ devNum ] = ( pci_io_addr - 1 ); + printk( "diospace = 0x%x\n", pHardware->pci_do[ devNum ] ); + outb_p( DIO_C_OUTPUT, pHardware->pci_do[ devNum ] + DIO_CTRL_REG ); + /// Clear the present output from the module. + outb( 0x00, pHardware->pci_do[ devNum ] + DIO_C_REG ); + /// Fill in remaining info into CDS_HARDWARE structure. + pHardware->doType[ devNum ] = ACS_24DIO; + pHardware->doInstance[ devNum ] = pHardware->dioCount; + pHardware->dioCount++; + pHardware->doCount++; + /// Return device enable status. + return ( pedStatus ); } // ***************************************************************************** /// \brief Routine to read ACCESS 24bit DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. // ***************************************************************************** -unsigned int accesDio24ReadInputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +accesDio24ReadInputRegister( CDS_HARDWARE* pHardware, int modNum ) { - unsigned int data; /// @param data Data read back from the module input register. - /// Read module data via standard PCI I/O space. - data = inb(pHardware->pci_do[modNum]); - /// Return the status of the read operation. - return(data); + unsigned int + data; /// @param data Data read back from the module input register. + /// Read module data via standard PCI I/O space. + data = inb( pHardware->pci_do[ modNum ] ); + /// Return the status of the read operation. + return ( data ); } // ***************************************************************************** /// \brief Routine to write ACCESS 24bit DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. /// @param[in] data Data to be written to the module. // ***************************************************************************** -void accesDio24WriteOutputRegister(CDS_HARDWARE *pHardware, int modNum, int data) +void +accesDio24WriteOutputRegister( CDS_HARDWARE* pHardware, int modNum, int data ) { - /// Write module data via standard PCI I/O space. - outb(data & 0xff,pHardware->pci_do[modNum]+DIO_C_REG); + /// Write module data via standard PCI I/O space. + outb( data & 0xff, pHardware->pci_do[ modNum ] + DIO_C_REG ); } - - diff --git a/src/include/drv/accesIIRO16.c b/src/include/drv/accesIIRO16.c index c22fd25a9..39a458895 100644 --- a/src/include/drv/accesIIRO16.c +++ b/src/include/drv/accesIIRO16.c @@ -1,72 +1,82 @@ /// \file accesIIRO16.c /// \brief File contain subroutines for initializing and read/write ops ///< for Acces I/O 16 bit relay I/O modules. \n -///< For board info, see <a href="http://accesio.com/go.cgi?p=../pcie/pcie-iiro-16.html">PCIe-IIRO-16 Manual</a> +///< For board info, see <a +///< href="http://accesio.com/go.cgi?p=../pcie/pcie-iiro-16.html">PCIe-IIRO-16 +///< Manual</a> #include "accesIIRO16.h" // ***************************************************************************** /// \brief Routine to initialize ACCESS IIRO-16 Isolated DIO modules -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @parm[in] *diodev PCI address information passed by the mapping code in map.c +/// @parm[in] *diodev PCI address information passed by the mapping code in +/// map.c // ***************************************************************************** -int accesIiro16Init(CDS_HARDWARE *pHardware, struct pci_dev *diodev) +int +accesIiro16Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev ) { - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - int pedStatus; /// @param pedStatus Status return from call to enable device. + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. - /// Get index into CDS_HARDWARE struct based on total number of DIO cards found by mapping routine - /// in map.c - devNum = pHardware->doCount; - /// Enable the module. - pedStatus = pci_enable_device(diodev); - /// Find the I/O address space for this module. - pci_read_config_dword(diodev,PCI_BASE_ADDRESS_2,&pci_io_addr); - printk("iiro-16 dio pci2 = 0x%x\n",pci_io_addr); - /// Fill module data into the CDS_HARDWARE structure. - pHardware->pci_do[devNum] = pci_io_addr-1; - pHardware->doType[devNum] = ACS_16DIO; - pHardware->doInstance[devNum] = pHardware->iiroDio1Count; - pHardware->iiroDio1Count ++; - printk("iiro-16 diospace = 0x%x\n",pHardware->pci_do[devNum]); + /// Get index into CDS_HARDWARE struct based on total number of DIO cards + /// found by mapping routine in map.c + devNum = pHardware->doCount; + /// Enable the module. + pedStatus = pci_enable_device( diodev ); + /// Find the I/O address space for this module. + pci_read_config_dword( diodev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + printk( "iiro-16 dio pci2 = 0x%x\n", pci_io_addr ); + /// Fill module data into the CDS_HARDWARE structure. + pHardware->pci_do[ devNum ] = pci_io_addr - 1; + pHardware->doType[ devNum ] = ACS_16DIO; + pHardware->doInstance[ devNum ] = pHardware->iiroDio1Count; + pHardware->iiroDio1Count++; + printk( "iiro-16 diospace = 0x%x\n", pHardware->pci_do[ devNum ] ); - pHardware->doCount ++; - /// Return device enable status. - return(pedStatus); + pHardware->doCount++; + /// Return device enable status. + return ( pedStatus ); } // ***************************************************************************** /// \brief Routine to read input register of ACCESS IIRO-16 Isolated DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. // ***************************************************************************** -unsigned int accesIiro16ReadInputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +accesIiro16ReadInputRegister( CDS_HARDWARE* pHardware, int modNum ) { - unsigned int v, v1; /// @param v,v1 data returned from read operation. - /// Read lower byte via standard PCI I/O space. - v = inb(pHardware->pci_do[modNum] + IIRO_DIO16_INPUT); - /// Read upper byte via standard PCI I/O space. - v1 = inb(pHardware->pci_do[modNum] + 4 + IIRO_DIO16_INPUT); - /// Return data as 16bit word. - return v | (v1 << 8); -return (v); + unsigned int v, v1; /// @param v,v1 data returned from read operation. + /// Read lower byte via standard PCI I/O space. + v = inb( pHardware->pci_do[ modNum ] + IIRO_DIO16_INPUT ); + /// Read upper byte via standard PCI I/O space. + v1 = inb( pHardware->pci_do[ modNum ] + 4 + IIRO_DIO16_INPUT ); + /// Return data as 16bit word. + return v | ( v1 << 8 ); + return ( v ); } // ***************************************************************************** /// \brief Routine to write ACCESS IIRO-16 Isolated DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. /// @param[in] data Data to be written to the module. // ***************************************************************************** -void accesIiro16WriteOutputRegister(CDS_HARDWARE *pHardware, int modNum, int data) +void +accesIiro16WriteOutputRegister( CDS_HARDWARE* pHardware, int modNum, int data ) { - /// Write data lower byte to module via standard PCI I/O space. - outb(data & 0xff, pHardware->pci_do[modNum] + IIRO_DIO16_OUTPUT); - /// Write data upper byte to module via standard PCI I/O space. - outb((data >> 8) & 0xff, pHardware->pci_do[modNum] + 4 + IIRO_DIO16_OUTPUT); + /// Write data lower byte to module via standard PCI I/O space. + outb( data & 0xff, pHardware->pci_do[ modNum ] + IIRO_DIO16_OUTPUT ); + /// Write data upper byte to module via standard PCI I/O space. + outb( ( data >> 8 ) & 0xff, + pHardware->pci_do[ modNum ] + 4 + IIRO_DIO16_OUTPUT ); } - diff --git a/src/include/drv/accesIIRO8.c b/src/include/drv/accesIIRO8.c index 3cd379496..0eb9871b6 100644 --- a/src/include/drv/accesIIRO8.c +++ b/src/include/drv/accesIIRO8.c @@ -1,79 +1,90 @@ /// \file accesIIRO8.c /// \brief File contain subroutines for initializing and read/write ops ///< for Acces I/O 8 bit relay I/O modules. \n -///< For board info, see <a href="http://accesio.com/go.cgi?p=../pcie/pcie-iiro-8.html">PCIe-IIRO-8 Manual</a> +///< For board info, see <a +///< href="http://accesio.com/go.cgi?p=../pcie/pcie-iiro-8.html">PCIe-IIRO-8 +///< Manual</a> #include "accesIIRO8.h" // ***************************************************************************** /// \brief Routine to initialize ACCESS IIRO-8 Isolated DIO modules -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @parm[in] *diodev PCI address information passed by the mapping code in map.c +/// @parm[in] *diodev PCI address information passed by the mapping code in +/// map.c // ***************************************************************************** -int accesIiro8Init(CDS_HARDWARE *pHardware, struct pci_dev *diodev) +int +accesIiro8Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev ) { - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - int pedStatus; /// @param pedStatus Status return from call to enable device. + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. - /// Get index into CDS_HARDWARE struct based on total number of DIO cards found by mapping routine - /// in map.c - devNum = pHardware->doCount; - /// Enable the module. - pedStatus = pci_enable_device(diodev); - /// Find the I/O address space for this module. - pci_read_config_dword(diodev,PCI_BASE_ADDRESS_2,&pci_io_addr); - printk("iiro-8 dio pci2 = 0x%x\n",pci_io_addr); - /// Write I/O address info into the CDS_HARDWARE structure. - pHardware->pci_do[devNum] = pci_io_addr-1; - /// Fill in remaining info into CDS_HARDWARE structure. - pHardware->doType[devNum] = ACS_8DIO; - pHardware->doInstance[devNum] = pHardware->iiroDioCount; - pHardware->iiroDioCount ++; - printk("iiro-8 diospace = 0x%x\n",pHardware->pci_do[devNum]); - pHardware->doCount ++; - /// Return device enable status. - return(pedStatus); + /// Get index into CDS_HARDWARE struct based on total number of DIO cards + /// found by mapping routine in map.c + devNum = pHardware->doCount; + /// Enable the module. + pedStatus = pci_enable_device( diodev ); + /// Find the I/O address space for this module. + pci_read_config_dword( diodev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + printk( "iiro-8 dio pci2 = 0x%x\n", pci_io_addr ); + /// Write I/O address info into the CDS_HARDWARE structure. + pHardware->pci_do[ devNum ] = pci_io_addr - 1; + /// Fill in remaining info into CDS_HARDWARE structure. + pHardware->doType[ devNum ] = ACS_8DIO; + pHardware->doInstance[ devNum ] = pHardware->iiroDioCount; + pHardware->iiroDioCount++; + printk( "iiro-8 diospace = 0x%x\n", pHardware->pci_do[ devNum ] ); + pHardware->doCount++; + /// Return device enable status. + return ( pedStatus ); } - // ***************************************************************************** /// \brief Routine to read ACCESS IIRO-8 Isolated DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. // ***************************************************************************** -unsigned int accesIiro8ReadInputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +accesIiro8ReadInputRegister( CDS_HARDWARE* pHardware, int modNum ) { - unsigned int data; /// @param data Data read back from the module input register. - data = inb(pHardware->pci_do[modNum] + IIRO_DIO8_INPUT); - return(data); + unsigned int + data; /// @param data Data read back from the module input register. + data = inb( pHardware->pci_do[ modNum ] + IIRO_DIO8_INPUT ); + return ( data ); } // ***************************************************************************** -/// \brief Routine to read back output register of ACCESS IIRO-8 Isolated DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// \brief Routine to read back output register of ACCESS IIRO-8 Isolated DIO +/// modules +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. // ***************************************************************************** -unsigned int accesIiro8ReadOutputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +accesIiro8ReadOutputRegister( CDS_HARDWARE* pHardware, int modNum ) { - unsigned int data; /// @param data Data read back from the module input register. - data = inb(pHardware->pci_do[modNum] + IIRO_DIO8_OUTPUT); - return(data); + unsigned int + data; /// @param data Data read back from the module input register. + data = inb( pHardware->pci_do[ modNum ] + IIRO_DIO8_OUTPUT ); + return ( data ); } // ***************************************************************************** /// \brief Routine to write ACCESS IIRO-8 Isolated DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. /// @param[in] data Data to be written to the module. // ***************************************************************************** -void accesIiro8WriteOutputRegister(CDS_HARDWARE *pHardware, int modNum, int data) +void +accesIiro8WriteOutputRegister( CDS_HARDWARE* pHardware, int modNum, int data ) { - outb(data & 0xff, pHardware->pci_do[modNum] + IIRO_DIO8_OUTPUT); + outb( data & 0xff, pHardware->pci_do[ modNum ] + IIRO_DIO8_OUTPUT ); } - - diff --git a/src/include/drv/adc_info.c b/src/include/drv/adc_info.c index cdac01b65..e47c05335 100644 --- a/src/include/drv/adc_info.c +++ b/src/include/drv/adc_info.c @@ -1,37 +1,44 @@ -inline int adc_status_update(adcInfo_t *); +inline int adc_status_update( adcInfo_t* ); -inline int adc_status_update(adcInfo_t *adcinfo) +inline int +adc_status_update( adcInfo_t* adcinfo ) { - int ii,jj; - int status = 0; + int ii, jj; + int status = 0; - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - // SET/CLR Channel Hopping Error - if(adcinfo->adcChanErr[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(2); - status |= FE_ERROR_ADC;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 2; - adcinfo->adcChanErr[jj] = 0; - // SET/CLR Overflow Error - if(adcinfo->adcOF[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(4); - status |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 4; - adcinfo->adcOF[jj] = 0; - for(ii=0;ii<32;ii++) - { - if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - } - pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcinfo->overflowAdc[jj][ii]; - adcinfo->overflowAdc[jj][ii] = 0; - - } - } - return status; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + // SET/CLR Channel Hopping Error + if ( adcinfo->adcChanErr[ jj ] ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] &= ~( 2 ); + status |= FE_ERROR_ADC; + ; + } + else + pLocalEpics->epicsOutput.statAdc[ jj ] |= 2; + adcinfo->adcChanErr[ jj ] = 0; + // SET/CLR Overflow Error + if ( adcinfo->adcOF[ jj ] ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] &= ~( 4 ); + status |= FE_ERROR_OVERFLOW; + ; + } + else + pLocalEpics->epicsOutput.statAdc[ jj ] |= 4; + adcinfo->adcOF[ jj ] = 0; + for ( ii = 0; ii < 32; ii++ ) + { + if ( pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] > + OVERFLOW_CNTR_LIMIT ) + { + pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] = 0; + } + pLocalEpics->epicsOutput.overflowAdc[ jj ][ ii ] = + adcinfo->overflowAdc[ jj ][ ii ]; + adcinfo->overflowAdc[ jj ][ ii ] = 0; + } + } + return status; } diff --git a/src/include/drv/app_adc_read.c b/src/include/drv/app_adc_read.c index afb9cc043..794fcf077 100644 --- a/src/include/drv/app_adc_read.c +++ b/src/include/drv/app_adc_read.c @@ -1,92 +1,115 @@ -inline int app_adc_read (int ,int ,adcInfo_t *,int []); -inline int app_adc_status_update(adcInfo_t *); +inline int app_adc_read( int, int, adcInfo_t*, int[] ); +inline int app_adc_status_update( adcInfo_t* ); -inline int app_adc_read (int ioMemCtr,int ioClk,adcInfo_t *adcinfo,int cpuClk[]) +inline int +app_adc_read( int ioMemCtr, int ioClk, adcInfo_t* adcinfo, int cpuClk[] ) { - int ii,jj; - int limit = OVERFLOW_LIMIT_16BIT; - int mm; + int ii, jj; + int limit = OVERFLOW_LIMIT_16BIT; + int mm; - /// \> SLAVE gets its adc data from MASTER via ipc shared memory\n - /// \> For each ADC defined: - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - mm = cdsPciModules.adcConfig[jj]; - cpuClk[CPU_TIME_RDY_ADC] = rdtsc_ordered(); - /// - ---- Wait for proper timestamp in shared memory, indicating data ready. - do{ - cpuClk[CPU_TIME_ADC_WAIT] = rdtsc_ordered(); - adcinfo->adcWait = (cpuClk[CPU_TIME_ADC_WAIT] - cpuClk[CPU_TIME_RDY_ADC])/CPURATE; - }while((ioMemData->iodata[mm][ioMemCtr].cycle != ioClk) && (adcinfo->adcWait < MAX_ADC_WAIT_SLAVE)); - timeSec = ioMemData->iodata[mm][ioMemCtr].timeSec; - if (cycle_gps_time == 0) { - startGpsTime = timeSec; - pLocalEpics->epicsOutput.startgpstime = startGpsTime; - } - cycle_gps_time = timeSec; + /// \> SLAVE gets its adc data from MASTER via ipc shared memory\n + /// \> For each ADC defined: + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + mm = cdsPciModules.adcConfig[ jj ]; + cpuClk[ CPU_TIME_RDY_ADC ] = rdtsc_ordered( ); + /// - ---- Wait for proper timestamp in shared memory, indicating data + /// ready. + do + { + cpuClk[ CPU_TIME_ADC_WAIT ] = rdtsc_ordered( ); + adcinfo->adcWait = + ( cpuClk[ CPU_TIME_ADC_WAIT ] - cpuClk[ CPU_TIME_RDY_ADC ] ) / + CPURATE; + } while ( ( ioMemData->iodata[ mm ][ ioMemCtr ].cycle != ioClk ) && + ( adcinfo->adcWait < MAX_ADC_WAIT_SLAVE ) ); + timeSec = ioMemData->iodata[ mm ][ ioMemCtr ].timeSec; + if ( cycle_gps_time == 0 ) + { + startGpsTime = timeSec; + pLocalEpics->epicsOutput.startgpstime = startGpsTime; + } + cycle_gps_time = timeSec; - /// - --------- If data not ready in time, set error, release DAC channel reservation and exit the code. - if(adcinfo->adcWait >= MAX_ADC_WAIT_SLAVE) return 1; - for(ii=0;ii<MAX_ADC_CHN_PER_MOD;ii++) - { - /// - ---- Read data from shared memory. - adcinfo->adcData[jj][ii] = ioMemData->iodata[mm][ioMemCtr].data[ii]; + /// - --------- If data not ready in time, set error, release DAC + /// channel reservation and exit the code. + if ( adcinfo->adcWait >= MAX_ADC_WAIT_SLAVE ) + return 1; + for ( ii = 0; ii < MAX_ADC_CHN_PER_MOD; ii++ ) + { + /// - ---- Read data from shared memory. + adcinfo->adcData[ jj ][ ii ] = + ioMemData->iodata[ mm ][ ioMemCtr ].data[ ii ]; #ifdef FLIP_SIGNALS - adcinfo->adcData[jj][ii] *= -1; + adcinfo->adcData[ jj ][ ii ] *= -1; #endif - dWord[jj][ii] = adcinfo->adcData[jj][ii]; + dWord[ jj ][ ii ] = adcinfo->adcData[ jj ][ ii ]; #ifdef OVERSAMPLE - /// - ---- Downsample ADC data from 64K to rate of user application - if (dWordUsed[jj][ii]) { - dWord[jj][ii] = iir_filter_biquad(dWord[jj][ii],FE_OVERSAMPLE_COEFF,2,&dHistory[ii+jj*32][0]); - } - /// - ---- Check for ADC data over/under range - if((adcinfo->adcData[jj][ii] > limit) || (adcinfo->adcData[jj][ii] < -limit)) - { - adcinfo->overflowAdc[jj][ii] ++; - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] ++; - overflowAcc ++; - adcinfo->adcOF[jj] = 1; - odcStateWord |= ODC_ADC_OVF; - } + /// - ---- Downsample ADC data from 64K to rate of user application + if ( dWordUsed[ jj ][ ii ] ) + { + dWord[ jj ][ ii ] = + iir_filter_biquad( dWord[ jj ][ ii ], + FE_OVERSAMPLE_COEFF, + 2, + &dHistory[ ii + jj * 32 ][ 0 ] ); + } + /// - ---- Check for ADC data over/under range + if ( ( adcinfo->adcData[ jj ][ ii ] > limit ) || + ( adcinfo->adcData[ jj ][ ii ] < -limit ) ) + { + adcinfo->overflowAdc[ jj ][ ii ]++; + pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ]++; + overflowAcc++; + adcinfo->adcOF[ jj ] = 1; + odcStateWord |= ODC_ADC_OVF; + } #endif - } - } - return 0; + } + } + return 0; } -inline int app_adc_status_update(adcInfo_t *adcinfo) +inline int +app_adc_status_update( adcInfo_t* adcinfo ) { - int ii,jj; - int status = 0; + int ii, jj; + int status = 0; - for(jj=0;jj<cdsPciModules.adcCount;jj++) - { - // SET/CLR Channel Hopping Error - if(adcinfo->adcChanErr[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(2); - status |= FE_ERROR_ADC;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 2; - adcinfo->adcChanErr[jj] = 0; - // SET/CLR Overflow Error - if(adcinfo->adcOF[jj]) - { - pLocalEpics->epicsOutput.statAdc[jj] &= ~(4); - status |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statAdc[jj] |= 4; - adcinfo->adcOF[jj] = 0; - for(ii=0;ii<32;ii++) - { - if (pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowAdcAcc[jj][ii] = 0; - } - pLocalEpics->epicsOutput.overflowAdc[jj][ii] = adcinfo->overflowAdc[jj][ii]; - adcinfo->overflowAdc[jj][ii] = 0; - - } - } - return status; + for ( jj = 0; jj < cdsPciModules.adcCount; jj++ ) + { + // SET/CLR Channel Hopping Error + if ( adcinfo->adcChanErr[ jj ] ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] &= ~( 2 ); + status |= FE_ERROR_ADC; + ; + } + else + pLocalEpics->epicsOutput.statAdc[ jj ] |= 2; + adcinfo->adcChanErr[ jj ] = 0; + // SET/CLR Overflow Error + if ( adcinfo->adcOF[ jj ] ) + { + pLocalEpics->epicsOutput.statAdc[ jj ] &= ~( 4 ); + status |= FE_ERROR_OVERFLOW; + ; + } + else + pLocalEpics->epicsOutput.statAdc[ jj ] |= 4; + adcinfo->adcOF[ jj ] = 0; + for ( ii = 0; ii < 32; ii++ ) + { + if ( pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] > + OVERFLOW_CNTR_LIMIT ) + { + pLocalEpics->epicsOutput.overflowAdcAcc[ jj ][ ii ] = 0; + } + pLocalEpics->epicsOutput.overflowAdc[ jj ][ ii ] = + adcinfo->overflowAdc[ jj ][ ii ]; + adcinfo->overflowAdc[ jj ][ ii ] = 0; + } + } + return status; } diff --git a/src/include/drv/app_dac_functions.c b/src/include/drv/app_dac_functions.c index 03b004d0d..c5bd6bdf7 100644 --- a/src/include/drv/app_dac_functions.c +++ b/src/include/drv/app_dac_functions.c @@ -1,167 +1,210 @@ -inline int app_dac_init(void); -inline int app_dac_status_update(dacInfo_t *); -inline int app_dac_write(int , int , dacInfo_t *); +inline int app_dac_init( void ); +inline int app_dac_status_update( dacInfo_t* ); +inline int app_dac_write( int, int, dacInfo_t* ); -inline int app_dac_init() +inline int +app_dac_init( ) { - int ii,jj; - int pd; -/// \> Verify DAC channels defined for this app are not already in use. \n -/// - ---- User apps are allowed to share DAC modules but not DAC channels. - // See if my DAC channel map overlaps with already running models - for (ii = 0; ii < cdsPciModules.dacCount; ii++) { - pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number - for (jj = 0; jj < 16; jj++) { - if (dacOutUsed[ii][jj]) { - if (ioMemData->dacOutUsed[pd][jj]) { - // printf("Failed to allocate DAC channel.\n"); - // printf("DAC local %d global %d channel %d is already allocated.\n", ii, pd, jj); - return 1; - } - } + int ii, jj; + int pd; + /// \> Verify DAC channels defined for this app are not already in use. \n + /// - ---- User apps are allowed to share DAC modules but not DAC channels. + // See if my DAC channel map overlaps with already running models + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + { + pd = cdsPciModules.dacConfig[ ii ] - + ioMemData->adcCount; // physical DAC number + for ( jj = 0; jj < 16; jj++ ) + { + if ( dacOutUsed[ ii ][ jj ] ) + { + if ( ioMemData->dacOutUsed[ pd ][ jj ] ) + { + // printf("Failed to allocate DAC channel.\n"); + // printf("DAC local %d global %d channel %d is already + // allocated.\n", ii, pd, jj); + return 1; + } + } + } + } + for ( ii = 0; ii < cdsPciModules.dacCount; ii++ ) + { + pd = cdsPciModules.dacConfig[ ii ] - + ioMemData->adcCount; // physical DAC number + for ( jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++ ) + { + if ( dacOutUsed[ ii ][ jj ] ) + { + ioMemData->dacOutUsed[ pd ][ jj ] = 1; + } + } } - } - for (ii = 0; ii < cdsPciModules.dacCount; ii++) { - pd = cdsPciModules.dacConfig[ii] - ioMemData->adcCount; // physical DAC number - for (jj = 0; jj < MAX_DAC_CHN_PER_MOD; jj++) { - if (dacOutUsed[ii][jj]) { - ioMemData->dacOutUsed[pd][jj] = 1; - } - } - } -return 0; + return 0; } -inline int app_dac_status_update(dacInfo_t *dacinfo) +inline int +app_dac_status_update( dacInfo_t* dacinfo ) { - int ii,jj; - int status = 0; - + int ii, jj; + int status = 0; - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(dacOF[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT); - status |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT; - dacOF[jj] = 0; - if(dacChanErr[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT); - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT; - dacChanErr[jj] = 0; - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + if ( dacOF[ jj ] ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_OVERFLOW_BIT ); + status |= FE_ERROR_OVERFLOW; + ; + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_OVERFLOW_BIT; + dacOF[ jj ] = 0; + if ( dacChanErr[ jj ] ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_TIMING_BIT ); + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_TIMING_BIT; + dacChanErr[ jj ] = 0; + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { - if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; + if ( pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] > + OVERFLOW_CNTR_LIMIT ) + { + pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] = 0; } - pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacinfo->overflowDac[jj][ii]; - dacinfo->overflowDac[jj][ii] = 0; - } - } - return status; + pLocalEpics->epicsOutput.overflowDac[ jj ][ ii ] = + dacinfo->overflowDac[ jj ][ ii ]; + dacinfo->overflowDac[ jj ][ ii ] = 0; + } + } + return status; } - -inline int app_dac_write(int ioMemCtrDac, int ioClkDac, dacInfo_t *dacinfo) +inline int +app_dac_write( int ioMemCtrDac, int ioClkDac, dacInfo_t* dacinfo ) { - int ii,jj,mm,kk; - int limit,mask,num_outs; - double dac_in = 0.0; - int dac_out = 0; - int dacOF[MAX_DAC_MODULES]; - int memCtr = 0; + int ii, jj, mm, kk; + int limit, mask, num_outs; + double dac_in = 0.0; + int dac_out = 0; + int dacOF[ MAX_DAC_MODULES ]; + int memCtr = 0; - /// \> Loop thru all DAC modules - for(jj=0;jj<cdsPciModules.dacCount;jj++) + /// \> Loop thru all DAC modules + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + /// - -- locate the proper DAC memory block + mm = cdsPciModules.dacConfig[ jj ]; + /// - -- Set overflow limits, data mask, and chan count based on DAC + /// type + limit = OVERFLOW_LIMIT_16BIT; + mask = GSAO_16BIT_MASK; + num_outs = GSAO_16BIT_CHAN_COUNT; + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) { - /// - -- locate the proper DAC memory block - mm = cdsPciModules.dacConfig[jj]; - /// - -- Set overflow limits, data mask, and chan count based on DAC type - limit = OVERFLOW_LIMIT_16BIT; - mask = GSAO_16BIT_MASK; - num_outs = GSAO_16BIT_CHAN_COUNT; - if (cdsPciModules.dacType[jj] == GSC_18AO8) { - limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit - mask = GSAO_18BIT_MASK; - num_outs = GSAO_18BIT_CHAN_COUNT; - } - if (cdsPciModules.dacType[jj] == GSC_20AO8) { - limit = OVERFLOW_LIMIT_20BIT; // 20 bit limit - mask = GSAO_20BIT_MASK; - num_outs = GSAO_20BIT_CHAN_COUNT; - } - /// - -- If user app < 64k rate (typical), need to upsample from code rate to IOP rate - for (kk=0; kk < OVERSAMPLE_TIMES; kk++) { - /// - -- For each DAC channel - for (ii=0; ii < num_outs; ii++) - { + limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit + mask = GSAO_18BIT_MASK; + num_outs = GSAO_18BIT_CHAN_COUNT; + } + if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + limit = OVERFLOW_LIMIT_20BIT; // 20 bit limit + mask = GSAO_20BIT_MASK; + num_outs = GSAO_20BIT_CHAN_COUNT; + } + /// - -- If user app < 64k rate (typical), need to upsample from code + /// rate to IOP rate + for ( kk = 0; kk < OVERSAMPLE_TIMES; kk++ ) + { + /// - -- For each DAC channel + for ( ii = 0; ii < num_outs; ii++ ) + { #ifdef FLIP_SIGNALS - dacOut[jj][ii] *= -1; + dacOut[ jj ][ ii ] *= -1; #endif - /// - ---- Read in DAC value, if channel is used by the application, and run thru upsample filter\n - if (dacOutUsed[jj][ii]) { + /// - ---- Read in DAC value, if channel is used by the + /// application, and run thru upsample filter\n + if ( dacOutUsed[ jj ][ ii ] ) + { #ifdef OVERSAMPLE_DAC #ifdef NO_ZERO_PAD - /// - --------- If set to NO_ZERO_PAD (not standard setting), then DAC output value is - /// repeatedly run thru the filter OVERSAMPE_TIMES.\n - dac_in = dacOut[jj][ii]; - dac_in = iir_filter_biquad(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]); + /// - --------- If set to NO_ZERO_PAD (not standard + /// setting), then DAC output value is repeatedly run thru + /// the filter OVERSAMPE_TIMES.\n + dac_in = dacOut[ jj ][ ii ]; + dac_in = iir_filter_biquad( + dac_in, + FE_OVERSAMPLE_COEFF, + 2, + &dDacHistory[ ii + jj * MAX_DAC_CHN_PER_MOD ][ 0 ] ); #else - /// - --------- Otherwise zero padding is used (standard), - /// ie DAC output value is applied to filter on first - /// interation, thereafter zeros are applied. - dac_in = kk == 0? (double)dacOut[jj][ii]: 0.0; - dac_in = iir_filter_biquad(dac_in,FE_OVERSAMPLE_COEFF,2,&dDacHistory[ii+jj*MAX_DAC_CHN_PER_MOD][0]); - dac_in *= OVERSAMPLE_TIMES; + /// - --------- Otherwise zero padding is used (standard), + /// ie DAC output value is applied to filter on first + /// interation, thereafter zeros are applied. + dac_in = kk == 0 ? (double)dacOut[ jj ][ ii ] : 0.0; + dac_in = iir_filter_biquad( + dac_in, + FE_OVERSAMPLE_COEFF, + 2, + &dDacHistory[ ii + jj * MAX_DAC_CHN_PER_MOD ][ 0 ] ); + dac_in *= OVERSAMPLE_TIMES; #endif #else - dac_in = dacOut[jj][ii]; + dac_in = dacOut[ jj ][ ii ]; #endif - } - /// - ---- If channel is not used, then set value to zero. - else - dac_in = 0.0; - /// - ---- Smooth out some of the double > short roundoff errors - if(dac_in > 0.0) dac_in += 0.5; - else dac_in -= 0.5; - dac_out = dac_in; + } + /// - ---- If channel is not used, then set value to zero. + else + dac_in = 0.0; + /// - ---- Smooth out some of the double > short roundoff errors + if ( dac_in > 0.0 ) + dac_in += 0.5; + else + dac_in -= 0.5; + dac_out = dac_in; - /// - ---- Check output values are within range of DAC \n - /// - --------- If overflow, clip at DAC limits and report errors - if(dac_out > limit || dac_out < -limit) - { - dacinfo->overflowDac[jj][ii] ++; - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++; - overflowAcc ++; - dacOF[jj] = 1; - odcStateWord |= ODC_DAC_OVF;; - if(dac_out > limit) dac_out = limit; - else dac_out = -limit; - } - /// - ---- If DAQKILL tripped, set output to zero. - if(!iopDacEnable) dac_out = 0; - /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen. - dacinfo->dacOutEpics[jj][ii] = dac_out; + /// - ---- Check output values are within range of DAC \n + /// - --------- If overflow, clip at DAC limits and report + /// errors + if ( dac_out > limit || dac_out < -limit ) + { + dacinfo->overflowDac[ jj ][ ii ]++; + pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ]++; + overflowAcc++; + dacOF[ jj ] = 1; + odcStateWord |= ODC_DAC_OVF; + ; + if ( dac_out > limit ) + dac_out = limit; + else + dac_out = -limit; + } + /// - ---- If DAQKILL tripped, set output to zero. + if ( !iopDacEnable ) + dac_out = 0; + /// - ---- Load last values to EPICS channels for monitoring on + /// GDS_TP screen. + dacinfo->dacOutEpics[ jj ][ ii ] = dac_out; - /// - ---- Load DAC testpoints - floatDacOut[16*jj + ii] = dac_out; - /// - ---- Determine shared memory location for new DAC output data - memCtr = (ioMemCtrDac + kk) % IO_MEMORY_SLOTS; - /// - ---- Write DAC output to shared memory. \n - /// - --------- Only write to DAC channels being used to allow two or more - /// slaves to write to same DAC module. - if (dacOutUsed[jj][ii]) - ioMemData->iodata[mm][memCtr].data[ii] = dac_out; - } - /// - ---- Write cycle count to make DAC data complete - if(iopDacEnable) - ioMemData->iodata[mm][memCtr].cycle = (ioClkDac + kk) % IOP_IO_RATE; - } - } - return 0; + /// - ---- Load DAC testpoints + floatDacOut[ 16 * jj + ii ] = dac_out; + /// - ---- Determine shared memory location for new DAC output + /// data + memCtr = ( ioMemCtrDac + kk ) % IO_MEMORY_SLOTS; + /// - ---- Write DAC output to shared memory. \n + /// - --------- Only write to DAC channels being used to allow + /// two or more slaves to write to same DAC module. + if ( dacOutUsed[ jj ][ ii ] ) + ioMemData->iodata[ mm ][ memCtr ].data[ ii ] = dac_out; + } + /// - ---- Write cycle count to make DAC data complete + if ( iopDacEnable ) + ioMemData->iodata[ mm ][ memCtr ].cycle = + ( ioClkDac + kk ) % IOP_IO_RATE; + } + } + return 0; } diff --git a/src/include/drv/app_dio_routines.c b/src/include/drv/app_dio_routines.c index 7bc105621..5bd9dfcdb 100644 --- a/src/include/drv/app_dio_routines.c +++ b/src/include/drv/app_dio_routines.c @@ -1,102 +1,144 @@ -inline int app_dio_init(void); -inline int app_dio_read_write(void); +inline int app_dio_init( void ); +inline int app_dio_read_write( void ); -inline int app_dio_init() +inline int +app_dio_init( ) { - int ii,kk; + int ii, kk; - /// \> Read Dio card initial values - /// - ---- SLAVE units read/write their own DIO \n - /// - ---- MASTER units ignore DIO for speed reasons \n - for(kk=0;kk<cdsPciModules.doCount;kk++) + /// \> Read Dio card initial values + /// - ---- SLAVE units read/write their own DIO \n + /// - ---- MASTER units ignore DIO for speed reasons \n + for ( kk = 0; kk < cdsPciModules.doCount; kk++ ) { - ii = cdsPciModules.doInstance[kk]; - if(cdsPciModules.doType[kk] == ACS_8DIO) - { - rioInputInput[ii] = accesIiro8ReadInputRegister(&cdsPciModules, kk) & 0xff; - rioInputOutput[ii] = accesIiro8ReadOutputRegister(&cdsPciModules, kk) & 0xff; - rioOutputHold[ii] = -1; - } else if(cdsPciModules.doType[kk] == ACS_16DIO) { - rioInput1[ii] = accesIiro16ReadInputRegister(&cdsPciModules, kk) & 0xffff; - rioOutputHold1[ii] = -1; - } else if (cdsPciModules.doType[kk] == CON_32DO) { - CDO32Input[ii] = contec32ReadOutputRegister(&cdsPciModules, kk); - } else if (cdsPciModules.doType[kk] == CON_6464DIO) { - CDIO6464LastOutState[ii] = contec6464ReadOutputRegister(&cdsPciModules, kk); - // printf ("Initial state of contec6464 number %d = 0x%x \n",ii,CDIO6464LastOutState[ii]); - } else if (cdsPciModules.doType[kk] == CDI64) { - CDIO6464LastOutState[ii] = contec6464ReadOutputRegister(&cdsPciModules, kk); - // printf ("Initial state of contec6464 number %d = 0x%x \n",ii,CDIO6464LastOutState[ii]); - } else if(cdsPciModules.doType[kk] == ACS_24DIO) { - dioInput[ii] = accesDio24ReadInputRegister(&cdsPciModules, kk); - } + ii = cdsPciModules.doInstance[ kk ]; + if ( cdsPciModules.doType[ kk ] == ACS_8DIO ) + { + rioInputInput[ ii ] = + accesIiro8ReadInputRegister( &cdsPciModules, kk ) & 0xff; + rioInputOutput[ ii ] = + accesIiro8ReadOutputRegister( &cdsPciModules, kk ) & 0xff; + rioOutputHold[ ii ] = -1; + } + else if ( cdsPciModules.doType[ kk ] == ACS_16DIO ) + { + rioInput1[ ii ] = + accesIiro16ReadInputRegister( &cdsPciModules, kk ) & 0xffff; + rioOutputHold1[ ii ] = -1; + } + else if ( cdsPciModules.doType[ kk ] == CON_32DO ) + { + CDO32Input[ ii ] = contec32ReadOutputRegister( &cdsPciModules, kk ); + } + else if ( cdsPciModules.doType[ kk ] == CON_6464DIO ) + { + CDIO6464LastOutState[ ii ] = + contec6464ReadOutputRegister( &cdsPciModules, kk ); + // printf ("Initial state of contec6464 number %d = 0x%x + // \n",ii,CDIO6464LastOutState[ii]); + } + else if ( cdsPciModules.doType[ kk ] == CDI64 ) + { + CDIO6464LastOutState[ ii ] = + contec6464ReadOutputRegister( &cdsPciModules, kk ); + // printf ("Initial state of contec6464 number %d = 0x%x + // \n",ii,CDIO6464LastOutState[ii]); + } + else if ( cdsPciModules.doType[ kk ] == ACS_24DIO ) + { + dioInput[ ii ] = accesDio24ReadInputRegister( &cdsPciModules, kk ); + } } - return 0; + return 0; } -inline int app_dio_read_write() +inline int +app_dio_read_write( ) { - int ii,kk; + int ii, kk; - // Read DIO cards, one card per cycle - if(cdsPciModules.doCount) + // Read DIO cards, one card per cycle + if ( cdsPciModules.doCount ) { - kk = cycleNum % cdsPciModules.doCount; - ii = cdsPciModules.doInstance[kk]; - if(cdsPciModules.doType[kk] == ACS_8DIO) - { - rioInputInput[ii] = accesIiro8ReadInputRegister(&cdsPciModules, kk) & 0xff; - rioInputOutput[ii] = accesIiro8ReadOutputRegister(&cdsPciModules, kk) & 0xff; - } - if(cdsPciModules.doType[kk] == ACS_16DIO) - { - rioInput1[ii] = accesIiro16ReadInputRegister(&cdsPciModules, kk) & 0xffff; - } - if(cdsPciModules.doType[kk] == ACS_24DIO) - { - dioInput[ii] = accesDio24ReadInputRegister(&cdsPciModules, kk); - } - if (cdsPciModules.doType[kk] == CON_6464DIO) { - CDIO6464InputInput[ii] = contec6464ReadInputRegister(&cdsPciModules, kk); - } - if (cdsPciModules.doType[kk] == CDI64) { - CDIO6464InputInput[ii] = contec6464ReadInputRegister(&cdsPciModules, kk); - } - } -/// \> Write Dio cards only on change - for(kk=0;kk < cdsPciModules.doCount;kk++) + kk = cycleNum % cdsPciModules.doCount; + ii = cdsPciModules.doInstance[ kk ]; + if ( cdsPciModules.doType[ kk ] == ACS_8DIO ) + { + rioInputInput[ ii ] = + accesIiro8ReadInputRegister( &cdsPciModules, kk ) & 0xff; + rioInputOutput[ ii ] = + accesIiro8ReadOutputRegister( &cdsPciModules, kk ) & 0xff; + } + if ( cdsPciModules.doType[ kk ] == ACS_16DIO ) + { + rioInput1[ ii ] = + accesIiro16ReadInputRegister( &cdsPciModules, kk ) & 0xffff; + } + if ( cdsPciModules.doType[ kk ] == ACS_24DIO ) + { + dioInput[ ii ] = accesDio24ReadInputRegister( &cdsPciModules, kk ); + } + if ( cdsPciModules.doType[ kk ] == CON_6464DIO ) + { + CDIO6464InputInput[ ii ] = + contec6464ReadInputRegister( &cdsPciModules, kk ); + } + if ( cdsPciModules.doType[ kk ] == CDI64 ) + { + CDIO6464InputInput[ ii ] = + contec6464ReadInputRegister( &cdsPciModules, kk ); + } + } + /// \> Write Dio cards only on change + for ( kk = 0; kk < cdsPciModules.doCount; kk++ ) { - ii = cdsPciModules.doInstance[kk]; - if((cdsPciModules.doType[kk] == ACS_8DIO) && (rioOutput[ii] != rioOutputHold[ii])) + ii = cdsPciModules.doInstance[ kk ]; + if ( ( cdsPciModules.doType[ kk ] == ACS_8DIO ) && + ( rioOutput[ ii ] != rioOutputHold[ ii ] ) ) { - accesIiro8WriteOutputRegister(&cdsPciModules, kk, rioOutput[ii]); - rioOutputHold[ii] = rioOutput[ii]; - } else - if((cdsPciModules.doType[kk] == ACS_16DIO) && (rioOutput1[ii] != rioOutputHold1[ii])) + accesIiro8WriteOutputRegister( + &cdsPciModules, kk, rioOutput[ ii ] ); + rioOutputHold[ ii ] = rioOutput[ ii ]; + } + else if ( ( cdsPciModules.doType[ kk ] == ACS_16DIO ) && + ( rioOutput1[ ii ] != rioOutputHold1[ ii ] ) ) { - accesIiro16WriteOutputRegister(&cdsPciModules, kk, rioOutput1[ii]); - rioOutputHold1[ii] = rioOutput1[ii]; - } else - if(cdsPciModules.doType[kk] == CON_32DO) + accesIiro16WriteOutputRegister( + &cdsPciModules, kk, rioOutput1[ ii ] ); + rioOutputHold1[ ii ] = rioOutput1[ ii ]; + } + else if ( cdsPciModules.doType[ kk ] == CON_32DO ) { - if (CDO32Input[ii] != CDO32Output[ii]) { - CDO32Input[ii] = contec32WriteOutputRegister(&cdsPciModules, kk, CDO32Output[ii]); + if ( CDO32Input[ ii ] != CDO32Output[ ii ] ) + { + CDO32Input[ ii ] = contec32WriteOutputRegister( + &cdsPciModules, kk, CDO32Output[ ii ] ); } - } else if (cdsPciModules.doType[kk] == CON_6464DIO) { - if (CDIO6464LastOutState[ii] != CDIO6464Output[ii]) { - CDIO6464LastOutState[ii] = contec6464WriteOutputRegister(&cdsPciModules, kk, CDIO6464Output[ii]); - } - } else if (cdsPciModules.doType[kk] == CDO64) { - if (CDIO6464LastOutState[ii] != CDIO6464Output[ii]) { - CDIO6464LastOutState[ii] = contec6464WriteOutputRegister(&cdsPciModules, kk, CDIO6464Output[ii]); - } - } else - if((cdsPciModules.doType[kk] == ACS_24DIO) && (dioOutputHold[ii] != dioOutput[ii])) - { - accesDio24WriteOutputRegister(&cdsPciModules, kk, dioOutput[ii]); - dioOutputHold[ii] = dioOutput[ii]; - } + } + else if ( cdsPciModules.doType[ kk ] == CON_6464DIO ) + { + if ( CDIO6464LastOutState[ ii ] != CDIO6464Output[ ii ] ) + { + CDIO6464LastOutState[ ii ] = contec6464WriteOutputRegister( + &cdsPciModules, kk, CDIO6464Output[ ii ] ); + } + } + else if ( cdsPciModules.doType[ kk ] == CDO64 ) + { + if ( CDIO6464LastOutState[ ii ] != CDIO6464Output[ ii ] ) + { + CDIO6464LastOutState[ ii ] = contec6464WriteOutputRegister( + &cdsPciModules, kk, CDIO6464Output[ ii ] ); + } + } + else if ( ( cdsPciModules.doType[ kk ] == ACS_24DIO ) && + ( dioOutputHold[ ii ] != dioOutput[ ii ] ) ) + { + accesDio24WriteOutputRegister( + &cdsPciModules, kk, dioOutput[ ii ] ); + dioOutputHold[ ii ] = dioOutput[ ii ]; + } } - return 0; + return 0; } diff --git a/src/include/drv/contec1616.c b/src/include/drv/contec1616.c index 7111b1094..4a703edda 100644 --- a/src/include/drv/contec1616.c +++ b/src/include/drv/contec1616.c @@ -1,84 +1,96 @@ /// \file contec1616.c /// \brief File contain subroutines for initializing and read/write ops ///< for Contec 16input/16output digital I/O modules. \n -///< This module is supported solely for use in controlling timing slave -///< modules in I/O chassis ie it is not intended for general use as a +///< This module is supported solely for use in controlling timing +///<slave modules in I/O chassis ie it is not intended for general use as a ///< digital I/O board for users. \n -///< For board info, see <a href="http://www.contec.com/product.php?id=1611">DIO-1616L-PE Manual</a> +///< For board info, see <a +///< href="http://www.contec.com/product.php?id=1611">DIO-1616L-PE Manual</a> #include "contec1616.h" // ***************************************************************************** /// \brief Routine to initialize CONTEC PCIe 1616 DIO modules -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @parm[in] *diodev PCI address information passed by the mapping code in map.c +/// @parm[in] *diodev PCI address information passed by the mapping code in +/// map.c // ***************************************************************************** -int contec1616Init(CDS_HARDWARE *pHardware, struct pci_dev *diodev) +int +contec1616Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev ) { - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - int pedStatus; /// @param pedStatus Status return from call to enable device. - int id; /// @param id Card ID number read from switch on Contec module. + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. + int id; /// @param id Card ID number read from switch on Contec module. - - /// Get index into CDS_HARDWARE struct based on total number of DIO cards found by mapping routine - /// in map.c - devNum = pHardware->doCount; - /// Enable the module. - pedStatus = pci_enable_device(diodev); - /// Find the I/O address space for this module. - pci_read_config_dword(diodev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("contec 1616 dio pci2 = 0x%x\n",pci_io_addr); - /// Write I/O address info into the CDS_HARDWARE structure. - pHardware->pci_do[devNum] = pci_io_addr-1; - printk("contec 1616 diospace = 0x%x\n",pHardware->pci_do[devNum]); - /// Read board number switch setting on module - pci_read_config_dword(diodev,PCI_REVISION_ID,&id); - printk("contec dio pci2 card number= 0x%x\n",(id & 0xf)); - /// Fill in remaining info into CDS_HARDWARE structure. - pHardware->doType[devNum] = CON_1616DIO; - pHardware->doCount ++; - pHardware->doInstance[devNum] = pHardware->cDio1616lCount; - pHardware->cDio1616lCount ++; - /// Return board ID number. - return(id); + /// Get index into CDS_HARDWARE struct based on total number of DIO cards + /// found by mapping routine in map.c + devNum = pHardware->doCount; + /// Enable the module. + pedStatus = pci_enable_device( diodev ); + /// Find the I/O address space for this module. + pci_read_config_dword( diodev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "contec 1616 dio pci2 = 0x%x\n", pci_io_addr ); + /// Write I/O address info into the CDS_HARDWARE structure. + pHardware->pci_do[ devNum ] = pci_io_addr - 1; + printk( "contec 1616 diospace = 0x%x\n", pHardware->pci_do[ devNum ] ); + /// Read board number switch setting on module + pci_read_config_dword( diodev, PCI_REVISION_ID, &id ); + printk( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) ); + /// Fill in remaining info into CDS_HARDWARE structure. + pHardware->doType[ devNum ] = CON_1616DIO; + pHardware->doCount++; + pHardware->doInstance[ devNum ] = pHardware->cDio1616lCount; + pHardware->cDio1616lCount++; + /// Return board ID number. + return ( id ); } // ***************************************************************************** /// \brief Routine to write to CONTEC PCIe-16 DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. /// @param[in] data Data to be written to the module. // ***************************************************************************** -unsigned int contec1616WriteOutputRegister(CDS_HARDWARE *pHardware, int modNum, unsigned int data) +unsigned int +contec1616WriteOutputRegister( CDS_HARDWARE* pHardware, + int modNum, + unsigned int data ) { - outl(data,pHardware->pci_do[modNum]); - return(data); + outl( data, pHardware->pci_do[ modNum ] ); + return ( data ); } // ***************************************************************************** -/// \brief Routine to read back data from output register of CONTEC PCIe-16 DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// \brief Routine to read back data from output register of CONTEC PCIe-16 DIO +/// modules +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. // ***************************************************************************** -unsigned int contec1616ReadOutputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +contec1616ReadOutputRegister( CDS_HARDWARE* pHardware, int modNum ) { - // The binary output state bits register is at +2 - return(inl(pHardware->pci_do[modNum] + 2)); + // The binary output state bits register is at +2 + return ( inl( pHardware->pci_do[ modNum ] + 2 ) ); } // ***************************************************************************** -/// \brief Routine to read data from input register of CONTEC PCIe-16 DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// \brief Routine to read data from input register of CONTEC PCIe-16 DIO +/// modules +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. // ***************************************************************************** -unsigned int contec1616ReadInputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +contec1616ReadInputRegister( CDS_HARDWARE* pHardware, int modNum ) { - // Reading at +0 gives the input bits - return(inl(pHardware->pci_do[modNum])); + // Reading at +0 gives the input bits + return ( inl( pHardware->pci_do[ modNum ] ) ); } - diff --git a/src/include/drv/contec32o.c b/src/include/drv/contec32o.c index 2462082ce..a657c4775 100644 --- a/src/include/drv/contec32o.c +++ b/src/include/drv/contec32o.c @@ -1,50 +1,55 @@ /// \file contec32o.c /// \brief File contain subroutines for initializing and read/write ops ///< for Contec 32 output digital I/O modules. \n -///< For board info, see <a href="http://www.contec.com/product.php?id=1723">DO-32L-PE Manual</a> +///< For board info, see <a +///< href="http://www.contec.com/product.php?id=1723">DO-32L-PE Manual</a> // ***************************************************************************** /// Routine to Initialize CONTEC PCIe-32 Isolated DO modules // ***************************************************************************** -int contec32OutInit(CDS_HARDWARE *pHardware, struct pci_dev *diodev) +int +contec32OutInit( CDS_HARDWARE* pHardware, struct pci_dev* diodev ) { - static unsigned int pci_io_addr; - int devNum; - int id; - int pedStatus; + static unsigned int pci_io_addr; + int devNum; + int id; + int pedStatus; - devNum = pHardware->doCount; - pedStatus = pci_enable_device(diodev); - pci_read_config_dword(diodev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("contec dio pci2 = 0x%x\n",pci_io_addr); - pHardware->pci_do[devNum] = pci_io_addr-1; - printk("contec32L diospace = 0x%x\n",pHardware->pci_do[devNum]); - pci_read_config_dword(diodev,PCI_REVISION_ID,&id); - printk("contec dio pci2 card number= 0x%x\n",(id & 0xf)); - pHardware->doType[devNum] = CON_32DO; - pHardware->doCount ++; - pHardware->doInstance[devNum] = pHardware->cDo32lCount; - //printk("pHardware count is at %d\n",pHardware->doCount); - //printk("pHardware cDo32lCount is at %d\n", pHardware->cDo32lCount); - pHardware->cDo32lCount ++; - return(0); + devNum = pHardware->doCount; + pedStatus = pci_enable_device( diodev ); + pci_read_config_dword( diodev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "contec dio pci2 = 0x%x\n", pci_io_addr ); + pHardware->pci_do[ devNum ] = pci_io_addr - 1; + printk( "contec32L diospace = 0x%x\n", pHardware->pci_do[ devNum ] ); + pci_read_config_dword( diodev, PCI_REVISION_ID, &id ); + printk( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) ); + pHardware->doType[ devNum ] = CON_32DO; + pHardware->doCount++; + pHardware->doInstance[ devNum ] = pHardware->cDo32lCount; + // printk("pHardware count is at %d\n",pHardware->doCount); + // printk("pHardware cDo32lCount is at %d\n", pHardware->cDo32lCount); + pHardware->cDo32lCount++; + return ( 0 ); } // ***************************************************************************** /// Routine to write CONTEC PCIe-32 Isolated DO modules // ***************************************************************************** -unsigned int contec32WriteOutputRegister(CDS_HARDWARE *pHardware, int modNum, unsigned int data) +unsigned int +contec32WriteOutputRegister( CDS_HARDWARE* pHardware, + int modNum, + unsigned int data ) { - //printk("writeCDO32l modNum = %d\n",modNum); - //printk("writeCDO32l data = %d\n",data); - outl(data,pHardware->pci_do[modNum]); - return(inl(pHardware->pci_do[modNum])); + // printk("writeCDO32l modNum = %d\n",modNum); + // printk("writeCDO32l data = %d\n",data); + outl( data, pHardware->pci_do[ modNum ] ); + return ( inl( pHardware->pci_do[ modNum ] ) ); } // ***************************************************************************** /// Routine to read CONTEC PCIe-32 Isolated DO modules // ***************************************************************************** -unsigned int contec32ReadOutputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +contec32ReadOutputRegister( CDS_HARDWARE* pHardware, int modNum ) { - return(inl(pHardware->pci_do[modNum])); + return ( inl( pHardware->pci_do[ modNum ] ) ); } - diff --git a/src/include/drv/contec6464.c b/src/include/drv/contec6464.c index 6c072bdb7..d171e9d56 100644 --- a/src/include/drv/contec6464.c +++ b/src/include/drv/contec6464.c @@ -1,93 +1,105 @@ /// \file contec6464.c /// \brief File contain subroutines for initializing and read/write ops ///< for Contec 64input/64output digital I/O modules. \n -///< For board info, see <a href="http://www.contec.com/product.php?id=1710">DIO-6464L-PE Manual</a> +///< For board info, see <a +///< href="http://www.contec.com/product.php?id=1710">DIO-6464L-PE Manual</a> #include "contec6464.h" // ***************************************************************************** /// \brief Routine to initialize CONTEC PCIe 6464 DIO module -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @parm[in] *diodev PCI address information passed by the mapping code in map.c +/// @parm[in] *diodev PCI address information passed by the mapping code in +/// map.c // ***************************************************************************** -int contec6464Init(CDS_HARDWARE *pHardware, struct pci_dev *diodev) +int +contec6464Init( CDS_HARDWARE* pHardware, struct pci_dev* diodev ) { - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - int pedStatus; /// @param pedStatus Status return from call to enable device. - int id; /// @param id Card ID number read from switch on Contec module. + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. + int id; /// @param id Card ID number read from switch on Contec module. - - /// Get index into CDS_HARDWARE struct based on total number of DIO cards found by mapping routine - /// in map.c - devNum = pHardware->doCount; - /// Enable the module - pedStatus = pci_enable_device(diodev); - /// Find the I/O address space for this module. - pci_read_config_dword(diodev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("contec 6464 dio pci2 = 0x%x\n",pci_io_addr); - pHardware->pci_do[devNum] = pci_io_addr-1; - printk("contec32L diospace = 0x%x\n",pHardware->pci_do[devNum]); - /// Read board number switch setting on module - pci_read_config_dword(diodev,PCI_REVISION_ID,&id); - printk("contec dio pci2 card number= 0x%x\n",(id & 0xf)); - /// Break the module into two, 32bit devices ie 64bits will not carry thru read/write and - ///< maintain all of the bit information. - /// Fill in CDS_HARDWARE information for lower 32 bits. - pHardware->doType[devNum] = CON_6464DIO; - pHardware->doCount ++; - pHardware->doInstance[devNum] = pHardware->cDio6464lCount; - pHardware->cDio6464lCount ++; - /// Fill in CDS_HARDWARE information for upper 32 bits. - devNum ++; - pHardware->pci_do[devNum] = (pci_io_addr-1) + 4; - pHardware->doType[devNum] = CON_6464DIO; - pHardware->doCount ++; - pHardware->doInstance[devNum] = pHardware->cDio6464lCount; - pHardware->cDio6464lCount ++; - printk("contec32H diospace = 0x%x\n",pHardware->pci_do[devNum]); - /// Return board ID number. - return(id); + /// Get index into CDS_HARDWARE struct based on total number of DIO cards + /// found by mapping routine in map.c + devNum = pHardware->doCount; + /// Enable the module + pedStatus = pci_enable_device( diodev ); + /// Find the I/O address space for this module. + pci_read_config_dword( diodev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "contec 6464 dio pci2 = 0x%x\n", pci_io_addr ); + pHardware->pci_do[ devNum ] = pci_io_addr - 1; + printk( "contec32L diospace = 0x%x\n", pHardware->pci_do[ devNum ] ); + /// Read board number switch setting on module + pci_read_config_dword( diodev, PCI_REVISION_ID, &id ); + printk( "contec dio pci2 card number= 0x%x\n", ( id & 0xf ) ); + /// Break the module into two, 32bit devices ie 64bits will not carry thru + /// read/write and + ///< maintain all of the bit information. + /// Fill in CDS_HARDWARE information for lower 32 bits. + pHardware->doType[ devNum ] = CON_6464DIO; + pHardware->doCount++; + pHardware->doInstance[ devNum ] = pHardware->cDio6464lCount; + pHardware->cDio6464lCount++; + /// Fill in CDS_HARDWARE information for upper 32 bits. + devNum++; + pHardware->pci_do[ devNum ] = ( pci_io_addr - 1 ) + 4; + pHardware->doType[ devNum ] = CON_6464DIO; + pHardware->doCount++; + pHardware->doInstance[ devNum ] = pHardware->cDio6464lCount; + pHardware->cDio6464lCount++; + printk( "contec32H diospace = 0x%x\n", pHardware->pci_do[ devNum ] ); + /// Return board ID number. + return ( id ); } // ***************************************************************************** /// \brief Routine to write to CONTEC PCIe-64 DIO modules -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. /// @param[in] data Data to be written to the module. // ***************************************************************************** -unsigned int contec6464WriteOutputRegister(CDS_HARDWARE *pHardware, int modNum, unsigned int data) +unsigned int +contec6464WriteOutputRegister( CDS_HARDWARE* pHardware, + int modNum, + unsigned int data ) { - outl(data,pHardware->pci_do[modNum] + 8); - return data; + outl( data, pHardware->pci_do[ modNum ] + 8 ); + return data; } // ***************************************************************************** -/// \brief Routine to read back the output register of CONTEC PCIe-64 DIO modules. -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// \brief Routine to read back the output register of CONTEC PCIe-64 DIO +/// modules. +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. // ***************************************************************************** -unsigned int contec6464ReadOutputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +contec6464ReadOutputRegister( CDS_HARDWARE* pHardware, int modNum ) { - unsigned int out; - // - out = inl(pHardware->pci_do[modNum] + 8); - return out; + unsigned int out; + // + out = inl( pHardware->pci_do[ modNum ] + 8 ); + return out; } // ***************************************************************************** /// \brief Routine to read the input register of CONTEC PCIe-64 DIO modules. -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. /// @param[in] modNum Which instance of the module is to be addressed. // ***************************************************************************** -unsigned int contec6464ReadInputRegister(CDS_HARDWARE *pHardware, int modNum) +unsigned int +contec6464ReadInputRegister( CDS_HARDWARE* pHardware, int modNum ) { - unsigned int out; - out = inl(pHardware->pci_do[modNum]); - return out; + unsigned int out; + out = inl( pHardware->pci_do[ modNum ] ); + return out; } - diff --git a/src/include/drv/dac_info.c b/src/include/drv/dac_info.c index 14200fde8..5a8c5ca26 100644 --- a/src/include/drv/dac_info.c +++ b/src/include/drv/dac_info.c @@ -1,36 +1,41 @@ -inline int dac_status_update(dacInfo_t *); +inline int dac_status_update( dacInfo_t* ); -inline int dac_status_update(dacInfo_t *dacinfo) +inline int +dac_status_update( dacInfo_t* dacinfo ) { - int ii,jj; - int status = 0; + int ii, jj; + int status = 0; + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + if ( dacOF[ jj ] ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_OVERFLOW_BIT ); + status |= FE_ERROR_OVERFLOW; + ; + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_OVERFLOW_BIT; + dacOF[ jj ] = 0; + if ( dacChanErr[ jj ] ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_TIMING_BIT ); + } + else + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_TIMING_BIT; + dacChanErr[ jj ] = 0; + for ( ii = 0; ii < MAX_DAC_CHN_PER_MOD; ii++ ) + { - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(dacOF[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_OVERFLOW_BIT); - status |= FE_ERROR_OVERFLOW;; - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_OVERFLOW_BIT; - dacOF[jj] = 0; - if(dacChanErr[jj]) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_TIMING_BIT); - } - else pLocalEpics->epicsOutput.statDac[jj] |= DAC_TIMING_BIT; - dacChanErr[jj] = 0; - for(ii=0;ii<MAX_DAC_CHN_PER_MOD;ii++) - { - - if (pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] > OVERFLOW_CNTR_LIMIT) { - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] = 0; + if ( pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] > + OVERFLOW_CNTR_LIMIT ) + { + pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ] = 0; } - pLocalEpics->epicsOutput.overflowDac[jj][ii] = dacinfo->overflowDac[jj][ii]; - dacinfo->overflowDac[jj][ii] = 0; - } - } - return status; + pLocalEpics->epicsOutput.overflowDac[ jj ][ ii ] = + dacinfo->overflowDac[ jj ][ ii ]; + dacinfo->overflowDac[ jj ][ ii ] = 0; + } + } + return status; } - diff --git a/src/include/drv/daqLib.c b/src/include/drv/daqLib.c index cc4703c19..c9775957b 100644 --- a/src/include/drv/daqLib.c +++ b/src/include/drv/daqLib.c @@ -1,45 +1,58 @@ /*! \file daqLib.c * \brief File contains routines to support DAQ on realtime systems. \n * \author R.Bork, A. Ivanov -*/ - -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. -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. -volatile char *pEpicsIntData; ///< Pointer to EPICS integer type data in shared memory. -volatile char *pEpicsDblData; ///< Pointer to EPICS double type data in shared memory. + */ + +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. +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. +volatile char* + pEpicsIntData; ///< Pointer to EPICS integer type data in shared memory. +volatile char* + pEpicsDblData; ///< Pointer to EPICS double type data in shared memory. unsigned int curDaqBlockSize; ///< Total DAQ data rate diag // Added to get EPICS data for RCG V2.8 -volatile char *pEpicsInt; // Pointer to current DAQ data in shared memory. -volatile char *pEpicsInt1; -volatile float *pEpicsFloat; // Pointer to current DAQ data in shared memory. -volatile double *pEpicsDblData1; - -int daqConfig(volatile DAQ_INFO_BLOCK *, volatile DAQ_INFO_BLOCK *, volatile char *); -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[], volatile char *); - -inline double htond(double in) { - double retVal; - char *p = (char *)&retVal; - char *i = (char *)∈ - p[0] = i[7]; - p[1] = i[6]; - p[2] = i[5]; - p[3] = i[4]; - - p[4] = i[3]; - p[5] = i[2]; - p[6] = i[1]; - p[7] = i[0]; - - return retVal; +volatile char* pEpicsInt; // Pointer to current DAQ data in shared memory. +volatile char* pEpicsInt1; +volatile float* pEpicsFloat; // Pointer to current DAQ data in shared memory. +volatile double* pEpicsDblData1; + +int + daqConfig( volatile DAQ_INFO_BLOCK*, volatile DAQ_INFO_BLOCK*, volatile char* ); +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[], + volatile char* ); + +inline double +htond( double in ) +{ + double retVal; + char* p = (char*)&retVal; + char* i = (char*)∈ + p[ 0 ] = i[ 7 ]; + p[ 1 ] = i[ 6 ]; + p[ 2 ] = i[ 5 ]; + p[ 3 ] = i[ 4 ]; + + p[ 4 ] = i[ 3 ]; + p[ 5 ] = i[ 2 ]; + p[ 6 ] = i[ 1 ]; + p[ 7 ] = i[ 0 ]; + + return retVal; } /* ******************************************************************** */ @@ -47,869 +60,1004 @@ inline double htond(double in) { /* ******************************************************************** */ /// @author R.Bork, A. Ivanov\n /// @brief This function provides for reading GDS TP/EXC and writing DAQ -///data. \n +/// data. \n /// @detail For additional information in LIGO DCC, see <a -///href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=8037">T0900638 -///CDS Real-time DAQ Software</a> +/// href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=8037">T0900638 +/// CDS Real-time DAQ Software</a> /// @param[in] flag Initialization flag (1=Init call, 0 = -///run) -/// @param[in] dcuId DAQ Data unit ID - unique within a control -///system -/// @param[in] daqRange Struct defining fron end valid test point -///and exc ranges. +/// run) +/// @param[in] dcuId DAQ Data unit ID - unique within a +///control system +/// @param[in] daqRange Struct defining fron end valid test +///point and exc ranges. /// @param[in] sysRate Data rate of the code / 16 /// @param[in] *pFloatData[] Pointer to TP data not associated with -///filter modules. +/// filter modules. /// @param[in] *dspPtr Pointer to array of filter module data. /// @param[in] netStatus Status of DAQ network /// @param[out] gdsMonitor[] Array to return values of GDS TP/EXC -///selections. -/// @param[out] excSignals[] Array to write EXC signals not associated -///with filter modules. +/// selections. +/// @param[out] excSignals[] Array to write EXC signals not +///associated with filter modules. /// @return Total size of data transmitted in KB/sec. -int daqWrite(int flag, int dcuId, DAQ_RANGE daqRange, int sysRate, - double *pFloatData[], FILT_MOD *dspPtr, int netStatus, - int gdsMonitor[], double excSignal[], volatile char *pEpics) { - int ii, jj, kk; /* Loop counters. */ - int status; /* Return value from called routines. */ - unsigned int mydatatype; - double dWord; /* Temp value for storage of DAQ values */ - static int daqBlockNum; /* 1-16, tracks DAQ cycle. */ - static int daqXmitBlockNum; /* 1-16, tracks shmem DAQ block to write to. - */ - static int excBlockNum; /* 1-16, tracks EXC block to read from. */ - static int excDataSize; - static DAQ_XFER_INFO xferInfo; - static DAQ_LKUP_TABLE localTable[DCU_MAX_CHANNELS]; - static DAQ_LKUP_TABLE excTable[DCU_MAX_CHANNELS]; - static volatile char *pWriteBuffer; /* Ptr to swing buff to write data +int +daqWrite( int flag, + int dcuId, + DAQ_RANGE daqRange, + int sysRate, + double* pFloatData[], + FILT_MOD* dspPtr, + int netStatus, + int gdsMonitor[], + double excSignal[], + volatile char* pEpics ) +{ + int ii, jj, kk; /* Loop counters. */ + int status; /* Return value from called routines. */ + unsigned int mydatatype; + double dWord; /* Temp value for storage of DAQ values */ + static int daqBlockNum; /* 1-16, tracks DAQ cycle. */ + static int daqXmitBlockNum; /* 1-16, tracks shmem DAQ block to write to. + */ + static int excBlockNum; /* 1-16, tracks EXC block to read from. */ + static int excDataSize; + static DAQ_XFER_INFO xferInfo; + static DAQ_LKUP_TABLE localTable[ DCU_MAX_CHANNELS ]; + static DAQ_LKUP_TABLE excTable[ DCU_MAX_CHANNELS ]; + static volatile char* pWriteBuffer; /* Ptr to swing buff to write data */ - static int phase; /* 0-1, switches swing buffers. */ - static int daqSlot; /* 0-sysRate, data slot to write data */ - static int excSlot; /* 0-sysRate, slot to read exc data */ - static DAQ_INFO_BLOCK dataInfo; /* Local DAQ config info buffer. */ - static int tpStart; /* Marks address of first TP data */ - static volatile GDS_CNTRL_BLOCK - *gdsPtr; /* Ptr to shm to pass TP info to DAQ */ - static volatile char *exciteDataPtr; /* Ptr to EXC data in shmem. */ - static int validTp = 0; /* Number of valid GDS sigs selected. */ - static int validTpNet = 0; /* Number of valid GDS sigs selected. */ - static int validEx; /* EXC signal set status indicator. */ - static int - tpNum[DAQ_GDS_MAX_TP_ALLOWED]; /* TP/EXC selects to send to FB. */ - static int tpNumNet - [DAQ_GDS_MAX_TP_ALLOWED]; /* TP/EXC selects to send to FB. */ - static int totalChans; /* DAQ + TP + EXC chans selected. */ - int *statusPtr; - volatile float *dataPtr; /* Ptr to excitation chan data. */ - int exChanOffset; /* shmem offset to next EXC value. */ - int tpx; - static int buf_size; - int i; - int ltSlot; - unsigned int exc; - unsigned int tpn; - int slot; - 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 + static int phase; /* 0-1, switches swing buffers. */ + static int daqSlot; /* 0-sysRate, data slot to write data */ + static int excSlot; /* 0-sysRate, slot to read exc data */ + static DAQ_INFO_BLOCK dataInfo; /* Local DAQ config info buffer. */ + static int tpStart; /* Marks address of first TP data */ + static volatile GDS_CNTRL_BLOCK* + gdsPtr; /* Ptr to shm to pass TP info to DAQ */ + static volatile char* exciteDataPtr; /* Ptr to EXC data in shmem. */ + static int validTp = 0; /* Number of valid GDS sigs selected. */ + static int validTpNet = 0; /* Number of valid GDS sigs selected. */ + static int validEx; /* EXC signal set status indicator. */ + static int tpNum[ DAQ_GDS_MAX_TP_ALLOWED ]; /* TP/EXC selects to send to FB. + */ + static int tpNumNet[ DAQ_GDS_MAX_TP_ALLOWED ]; /* TP/EXC selects to send to + FB. */ + static int totalChans; /* DAQ + TP + EXC chans selected. */ + int* statusPtr; + volatile float* dataPtr; /* Ptr to excitation chan data. */ + int exChanOffset; /* shmem offset to next EXC value. */ + int tpx; + static int buf_size; + int i; + int ltSlot; + unsigned int exc; + unsigned int tpn; + int slot; + 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 #ifdef CORE_BIQUAD - // BIQUAD Decimation filter coefficient definitions. - // dCOEFF 2x - // ************************************************************************* - static double dCoeff2x[13] = { - 0.02717257186578, -0.1159055409088, -0.40753832312918, 2.66236735378793, - 3.37073457156755, -0.49505157452475, -1.10461941102831, 1.40184470311617, - 1.79227686661261, -0.74143396593712, -1.62740819248313, 0.72188475979666, - 0.83591053325065}; - - // dCOEFF 4x - // ************************************************************************* - static double dCoeff4x[13] = { - 0.00426219526013, 0.46640482430571, -0.10620935923005, 2.50932081620118, - 2.93670663266542, 0.43602772908265, -0.31016854747127, 0.75143527373544, - 1.00523899718152, 0.44571894955428, -0.47692045639835, 0.36664098129003, - 0.4440015753374}; - - // dCOEFF 8x - // ************************************************************************* - static double dCoeff8x[13] = { - 0.00162185538923, 0.73342532779703, -0.02862365091314, 1.44110125961504, - 1.67905228090487, 0.77657563380963, -0.08304311675394, 0.18851328163424, - 0.32889453107067, 0.83213081484618, -0.12573495191273, 0.0940911979108501, - 0.13622543115194}; - - // dCOEFF 16x - // ************************************************************************* - static double dCoeff16x[13] = { - 0.00112590539483, 0.86616831686611, -0.00753654634986012, - 0.48586805026482, 0.61216318704885, 0.90508101474565, - -0.0215349711544799, 0.0149886842581499, 0.08837269835802, - 0.94631370100442, -0.0320417955561, 0.0141281606027401, - 0.0357726640422202}; - - // dCOEFF 32x - // ************************************************************************* - static double dCoeff32x[13] = { - 0.00102945292275, 0.93288074072411, -0.00194092797014001, - 0.10751900551591, 0.17269733682166, 0.9570539169953, - -0.00548573773340011, -0.0149997987966302, 0.0224605464746699, - 0.98100244642901, -0.00807148639261013, -0.00189235941040011, - 0.00903370776797985}; - - // dCOEFF 64x - // ************************************************************************* - static double dCoeff64x[13] = { - 0.00101894798776, 0.96638168022541, -0.000492974627960052, - 0.01147570619135, 0.04460105133798, 0.97969775930388, - -0.00138449271550001, -0.0132857101503898, 0.00563203783023014, - 0.99249184543014, -0.0020244997813601, -0.00322227927422025, - 0.00226137551427974}; - - // dCOEFF 128x - // ************************************************************************* - static double dCoeff128x[13] = { - 0.00102359688929, 0.98317523053482, -0.000124254191099959, - -0.00545789721985002, 0.01124261805423, 0.9901470788001, - -0.000347773996469902, -0.00809690612593994, 0.00140824107749005, - 0.9967468102523, -0.000506888877139899, -0.00218112074794985, - 0.000565180122610309}; - - // dCOEFF 256x - // ************************************************************************* - static double dCoeff256x[13] = { - 0.00102849104272, 0.99158359864769, -3.11926170200039e-05, - -0.00556878740432998, 0.00281642133096005, 0.99514878857652, - -8.7150981279982e-05, -0.00441208984599983, 0.000351970596200069, - 0.99849900371282, -0.000126813612729926, -0.00123294150072994, - 0.000141241173720053}; + // BIQUAD Decimation filter coefficient definitions. + // dCOEFF 2x + // ************************************************************************* + static double dCoeff2x[ 13 ] = { 0.02717257186578, -0.1159055409088, + -0.40753832312918, 2.66236735378793, + 3.37073457156755, -0.49505157452475, + -1.10461941102831, 1.40184470311617, + 1.79227686661261, -0.74143396593712, + -1.62740819248313, 0.72188475979666, + 0.83591053325065 }; + + // dCOEFF 4x + // ************************************************************************* + static double dCoeff4x[ 13 ] = { + 0.00426219526013, 0.46640482430571, -0.10620935923005, 2.50932081620118, + 2.93670663266542, 0.43602772908265, -0.31016854747127, 0.75143527373544, + 1.00523899718152, 0.44571894955428, -0.47692045639835, 0.36664098129003, + 0.4440015753374 + }; + + // dCOEFF 8x + // ************************************************************************* + static double dCoeff8x[ 13 ] = { 0.00162185538923, 0.73342532779703, + -0.02862365091314, 1.44110125961504, + 1.67905228090487, 0.77657563380963, + -0.08304311675394, 0.18851328163424, + 0.32889453107067, 0.83213081484618, + -0.12573495191273, 0.0940911979108501, + 0.13622543115194 }; + + // dCOEFF 16x + // ************************************************************************* + static double dCoeff16x[ 13 ] = { 0.00112590539483, 0.86616831686611, + -0.00753654634986012, 0.48586805026482, + 0.61216318704885, 0.90508101474565, + -0.0215349711544799, 0.0149886842581499, + 0.08837269835802, 0.94631370100442, + -0.0320417955561, 0.0141281606027401, + 0.0357726640422202 }; + + // dCOEFF 32x + // ************************************************************************* + static double dCoeff32x[ 13 ] = { + 0.00102945292275, 0.93288074072411, -0.00194092797014001, + 0.10751900551591, 0.17269733682166, 0.9570539169953, + -0.00548573773340011, -0.0149997987966302, 0.0224605464746699, + 0.98100244642901, -0.00807148639261013, -0.00189235941040011, + 0.00903370776797985 + }; + + // dCOEFF 64x + // ************************************************************************* + static double dCoeff64x[ 13 ] = { + 0.00101894798776, 0.96638168022541, -0.000492974627960052, + 0.01147570619135, 0.04460105133798, 0.97969775930388, + -0.00138449271550001, -0.0132857101503898, 0.00563203783023014, + 0.99249184543014, -0.0020244997813601, -0.00322227927422025, + 0.00226137551427974 + }; + + // dCOEFF 128x + // ************************************************************************* + static double dCoeff128x[ 13 ] = { + 0.00102359688929, 0.98317523053482, -0.000124254191099959, + -0.00545789721985002, 0.01124261805423, 0.9901470788001, + -0.000347773996469902, -0.00809690612593994, 0.00140824107749005, + 0.9967468102523, -0.000506888877139899, -0.00218112074794985, + 0.000565180122610309 + }; + + // dCOEFF 256x + // ************************************************************************* + static double dCoeff256x[ 13 ] = { + 0.00102849104272, 0.99158359864769, -3.11926170200039e-05, + -0.00556878740432998, 0.00281642133096005, 0.99514878857652, + -8.7150981279982e-05, -0.00441208984599983, 0.000351970596200069, + 0.99849900371282, -0.000126813612729926, -0.00123294150072994, + 0.000141241173720053 + }; #else - // SOS Decimation filter coefficient definitions. - // dCOEFF 2x - // ************************************************************************* - static double dCoeff2x[13] = {0.02717257186578, - -0.8840944590912, - 0.29163278222038, - 1.77827289469673, - 1, - -0.50494842547525, - 0.60956783650356, - 0.89689627764092, - 1, - -0.25856603406288, - 0.88597422654601, - 0.46331872573378, - 1}; - - // dCOEFF 4x - // ************************************************************************* - static double dCoeff4x[13] = {0.00426219526013, - -1.46640482430571, - 0.57261418353576, - 1.04291599189547, - 1, - -1.43602772908265, - 0.74619627655392, - -0.68459245534721, - 1, - -1.44571894955428, - 0.92263940595263, - -1.07907796826425, - 1}; - - // dCOEFF 8x - // ************************************************************************* - static double dCoeff8x[13] = {0.00162185538923, - -1.73342532779703, - 0.76204897871017, - -0.29232406818199, - 1, - -1.77657563380963, - 0.85961875056357, - -1.58806235217539, - 1, - -1.83213081484618, - 0.95786576675891, - -1.73803961693533, - 1}; - - // dCOEFF 16x - // ************************************************************************* - static double dCoeff16x[13] = {0.00112590539483, - -1.86616831686611, - 0.87370486321597, - -1.38030026660129, - 1, - -1.90508101474565, - 0.92661598590013, - -1.8900923304875, - 1, - -1.94631370100442, - 0.97835549656052, - -1.93218554040168, - 1}; - - // dCOEFF 32x - // ************************************************************************* - static double dCoeff32x[13] = {0.00102945292275, - -1.93288074072411, - 0.93482166869425, - -1.8253617352082, - 1, - -1.9570539169953, - 0.9625396547287, - -1.97205371579193, - 1, - -1.98100244642901, - 0.98907393282162, - -1.98289480583941, - 1}; - - // dCOEFF 64x - // ************************************************************************* - static double dCoeff64x[13] = {0.00101894798776, - -1.96638168022541, - 0.96687465485337, - -1.95490597403406, - 1, - -1.97969775930388, - 0.98108225201938, - -1.99298346945427, - 1, - -1.99249184543014, - 0.9945163452115, - -1.99571412470436, - 1}; - - // dCOEFF 128x - // ************************************************************************* - static double dCoeff128x[13] = {0.00102359688929, - -1.98317523053482, - 0.98329948472592, - -1.98863312775467, - 1, - -1.9901470788001, - 0.99049485279657, - -1.99824398492604, - 1, - -1.9967468102523, - 0.99725369912944, - -1.99892793100025, - 1}; - - // dCOEFF 256x - // ************************************************************************* - static double dCoeff256x[13] = {0.00102849104272, - -1.99158359864769, - 0.99161479126471, - -1.99715238605202, - 1, - -1.99514878857652, - 0.9952359395578, - -1.99956087842252, - 1, - -1.99849900371282, - 0.99862581732555, - -1.99973194521355, - 1}; + // SOS Decimation filter coefficient definitions. + // dCOEFF 2x + // ************************************************************************* + static double dCoeff2x[ 13 ] = { 0.02717257186578, + -0.8840944590912, + 0.29163278222038, + 1.77827289469673, + 1, + -0.50494842547525, + 0.60956783650356, + 0.89689627764092, + 1, + -0.25856603406288, + 0.88597422654601, + 0.46331872573378, + 1 }; + + // dCOEFF 4x + // ************************************************************************* + static double dCoeff4x[ 13 ] = { 0.00426219526013, + -1.46640482430571, + 0.57261418353576, + 1.04291599189547, + 1, + -1.43602772908265, + 0.74619627655392, + -0.68459245534721, + 1, + -1.44571894955428, + 0.92263940595263, + -1.07907796826425, + 1 }; + + // dCOEFF 8x + // ************************************************************************* + static double dCoeff8x[ 13 ] = { 0.00162185538923, + -1.73342532779703, + 0.76204897871017, + -0.29232406818199, + 1, + -1.77657563380963, + 0.85961875056357, + -1.58806235217539, + 1, + -1.83213081484618, + 0.95786576675891, + -1.73803961693533, + 1 }; + + // dCOEFF 16x + // ************************************************************************* + static double dCoeff16x[ 13 ] = { 0.00112590539483, + -1.86616831686611, + 0.87370486321597, + -1.38030026660129, + 1, + -1.90508101474565, + 0.92661598590013, + -1.8900923304875, + 1, + -1.94631370100442, + 0.97835549656052, + -1.93218554040168, + 1 }; + + // dCOEFF 32x + // ************************************************************************* + static double dCoeff32x[ 13 ] = { 0.00102945292275, + -1.93288074072411, + 0.93482166869425, + -1.8253617352082, + 1, + -1.9570539169953, + 0.9625396547287, + -1.97205371579193, + 1, + -1.98100244642901, + 0.98907393282162, + -1.98289480583941, + 1 }; + + // dCOEFF 64x + // ************************************************************************* + static double dCoeff64x[ 13 ] = { 0.00101894798776, + -1.96638168022541, + 0.96687465485337, + -1.95490597403406, + 1, + -1.97969775930388, + 0.98108225201938, + -1.99298346945427, + 1, + -1.99249184543014, + 0.9945163452115, + -1.99571412470436, + 1 }; + + // dCOEFF 128x + // ************************************************************************* + static double dCoeff128x[ 13 ] = { 0.00102359688929, + -1.98317523053482, + 0.98329948472592, + -1.98863312775467, + 1, + -1.9901470788001, + 0.99049485279657, + -1.99824398492604, + 1, + -1.9967468102523, + 0.99725369912944, + -1.99892793100025, + 1 }; + + // dCOEFF 256x + // ************************************************************************* + static double dCoeff256x[ 13 ] = { 0.00102849104272, + -1.99158359864769, + 0.99161479126471, + -1.99715238605202, + 1, + -1.99514878857652, + 0.9952359395578, + -1.99956087842252, + 1, + -1.99849900371282, + 0.99862581732555, + -1.99973194521355, + 1 }; #endif - // History buffers for decimation IIR filters - static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY]; - - // ************************************************************************************** - /// If flag input is 1, then this is a startup initialization request from - /// controller code. - if (flag == DAQ_CONNECT) /* Initialize DAQ connection */ - { - - /* First block to write out is last from previous second */ - phase = 0; - daqBlockNum = (DAQ_NUM_DATA_BLOCKS - 1); - daqXmitBlockNum = 0; - excBlockNum = 0; - - /// ** INITIALIZATION **************\n - daqSlot = -1; - excSlot = 0; - - /// \> CDS standard IIR filters will be used for decimation filtering from - /// the native application rate down to DAQ sample rate. \n - /// \>\> Need to clear the decimation filter histories. - for (ii = 0; ii < DCU_MAX_CHANNELS; ii++) - for (jj = 0; jj < MAX_HISTRY; jj++) - dHistory[ii][jj] = 0.0; - - /// \> Setup Pointers to the various shared memories:\n - /// ---- Assign Ptr to data shared memory to network driver (mx_stream) \n - daqShmPtr = _daq_shm + CDS_DAQ_NET_DATA_OFFSET; - buf_size = DAQ_DCU_BLOCK_SIZE * 2; - pWriteBuffer = (volatile char *)daqShmPtr; - 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); - - /// ---- 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 - gdsPtr = (GDS_CNTRL_BLOCK *)(_epics_shm + DAQ_GDS_BLOCK_ADD); - // Set pointer to EXC data in shmem. - if (sysRate < DAQ_16K_SAMPLE_SIZE) { - exciteDataPtr = (char *)(_epics_shm + DATA_OFFSET_DCU(DCU_ID_EX_2K)); - } else { - exciteDataPtr = (char *)(_epics_shm + DATA_OFFSET_DCU(DCU_ID_EX_16K)); - } - excDataSize = 4 + 4 * sysRate; - - // Clear the reconfiguration flag in shmem. - pInfo->reconfig = 0; - - // Configure data channels - // ***************************************************** - // Return error if configuration is incorrect. - /// \> Load DAQ configuration info from memory shared with EPICS - if ((xferInfo.crcLength = daqConfig(&dataInfo, pInfo, pEpics)) == -1) - return (-1); - - /// \> Load local table information with channel info - if ((status = loadLocalTable(&xferInfo, localTable, sysRate, &dataInfo, - &daqRange)) == -1) - return (-1); - - // Set the start of TP data after DAQ data. - tpStart = xferInfo.offsetAccum; - totalChans = dataInfo.numChans; - - /// \> Clear out the GDS TP selections. - if (sysRate < DAQ_16K_SAMPLE_SIZE) - tpx = 3; - else - tpx = 2; - for (ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++) - gdsPtr->tp[tpx][0][ii] = 0; - if (sysRate < DAQ_16K_SAMPLE_SIZE) - tpx = 1; - else - tpx = 0; - for (ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++) - gdsPtr->tp[tpx][0][ii] = 0; - - /// \> Clear the GDS TP lookup table - for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) { - tpNum[i] = 0; - tpNumNet[i] = 0; - } - validTp = 0; - validTpNet = 0; - - // printf("at connect TPnum[0]=%d\n", tpNum[0]); - } /// End DAQ CONNECT INITIALIZATION ****************************** - - /* ******************************************************************************** - */ - /* Write Data to FB ******************************************* - */ - /* ******************************************************************************** - */ - /// If flag=0, data is to be acquired. This is called every code cycle by - /// controller.c - /// ** Data Acquisition Mode - /// ******************************************************** - if (flag == DAQ_WRITE) { - /// \> Calc data offset into current write swing buffer - daqSlot = (daqSlot + 1) % sysRate; - - /// \> Write data into local swing buffer - for (ii = 0; ii < totalChans; ii++) { - - dWord = 0; - /// \> 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 */ - { - switch (localTable[ii].sigNum) { - case 0: - dWord = dspPtr->data[localTable[ii].fmNum].filterInput; - break; - case 1: - dWord = dspPtr->data[localTable[ii].fmNum].inputTestpoint; - break; - case 2: - dWord = dspPtr->data[localTable[ii].fmNum].testpoint; - break; - default: - dWord = 0.0; - break; - } - } else if (localTable[ii].type == DAQ_SRC_NFM_TP) - /* Data is from non filter module testpoint */ - { - dWord = *(pFloatData[localTable[ii].sigNum]); - } else if (localTable[ii].type == DAQ_SRC_FM_EXC) - /* Data is from filter module excitation */ - { - dWord = dspPtr->data[localTable[ii].fmNum].exciteInput; - } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) { - // Extra excitation - dWord = excSignal[localTable[ii].fmNum]; - } + // History buffers for decimation IIR filters + static double dHistory[ DCU_MAX_CHANNELS ][ MAX_HISTRY ]; -/// \> Perform decimation filtering, if required. -#ifdef CORE_BIQUAD -#define iir_filter iir_filter_biquad -#endif - if (dataInfo.tp[ii].dataType != DAQ_DATATYPE_32BIT_UINT) { - if (localTable[ii].decFactor == 2) - dWord = iir_filter(dWord, &dCoeff2x[0], DTAPS, &dHistory[ii][0]); - if (localTable[ii].decFactor == 4) - dWord = iir_filter(dWord, &dCoeff4x[0], DTAPS, &dHistory[ii][0]); - if (localTable[ii].decFactor == 8) - dWord = iir_filter(dWord, &dCoeff8x[0], DTAPS, &dHistory[ii][0]); - if (localTable[ii].decFactor == 16) - dWord = iir_filter(dWord, &dCoeff16x[0], DTAPS, &dHistory[ii][0]); - if (localTable[ii].decFactor == 32) - dWord = iir_filter(dWord, &dCoeff32x[0], DTAPS, &dHistory[ii][0]); - if (localTable[ii].decFactor == 64) - dWord = iir_filter(dWord, &dCoeff64x[0], DTAPS, &dHistory[ii][0]); - if (localTable[ii].decFactor == 128) - dWord = iir_filter(dWord, &dCoeff128x[0], DTAPS, &dHistory[ii][0]); - if (localTable[ii].decFactor == 256) - dWord = iir_filter(dWord, &dCoeff256x[0], DTAPS, &dHistory[ii][0]); - } -#ifdef CORE_BIQUAD -#undef iir_filter -#endif + // ************************************************************************************** + /// If flag input is 1, then this is a startup initialization request from + /// controller code. + if ( flag == DAQ_CONNECT ) /* Initialize DAQ connection */ + { - /// \> Write fast data into the swing buffer. - if ((daqSlot % localTable[ii].decFactor) == 0) { - mydatatype = dataInfo.tp[ii].dataType; - switch (mydatatype) { - case DAQ_DATATYPE_16BIT_INT: - // Write short data; (XOR 1) here provides sample swapping - ((short *)(pWriteBuffer + - localTable[ii] - .offset))[(daqSlot / localTable[ii].decFactor) ^ 1] = - (short)dWord; - break; - case DAQ_DATATYPE_DOUBLE: - ((double *)(pWriteBuffer + - localTable[ii] - .offset))[daqSlot / localTable[ii].decFactor] = dWord; - break; - case DAQ_DATATYPE_32BIT_UINT: - // Write a 32-bit int (downcast from the double passed) - if (localTable[ii].decFactor == 1) - ((unsigned int *)(pWriteBuffer + localTable[ii].offset)) - [daqSlot / localTable[ii].decFactor] = ((unsigned int)dWord); - else - ((unsigned int *)(pWriteBuffer + localTable[ii].offset)) - [daqSlot / localTable[ii].decFactor] = - ((unsigned int)dWord) & *((unsigned int *)(dHistory[ii])); - break; - case DAQ_DATATYPE_32BIT_INT: - ((int *)(pWriteBuffer + localTable[ii].offset))[daqSlot] = (int)dWord; - break; - default: - // Write a 32-bit float (downcast from the double passed) - ((float *)(pWriteBuffer + - localTable[ii] - .offset))[daqSlot / localTable[ii].decFactor] = - (float)dWord; - break; + /* First block to write out is last from previous second */ + phase = 0; + daqBlockNum = ( DAQ_NUM_DATA_BLOCKS - 1 ); + daqXmitBlockNum = 0; + excBlockNum = 0; + + /// ** INITIALIZATION **************\n + daqSlot = -1; + excSlot = 0; + + /// \> CDS standard IIR filters will be used for decimation + ///filtering from + /// the native application rate down to DAQ sample rate. \n + /// \>\> Need to clear the decimation filter histories. + for ( ii = 0; ii < DCU_MAX_CHANNELS; ii++ ) + for ( jj = 0; jj < MAX_HISTRY; jj++ ) + dHistory[ ii ][ jj ] = 0.0; + + /// \> Setup Pointers to the various shared memories:\n + /// ---- Assign Ptr to data shared memory to network driver (mx_stream) + /// \n + daqShmPtr = _daq_shm + CDS_DAQ_NET_DATA_OFFSET; + buf_size = DAQ_DCU_BLOCK_SIZE * 2; + pWriteBuffer = (volatile char*)daqShmPtr; + 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 ); + + /// ---- 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 + gdsPtr = (GDS_CNTRL_BLOCK*)( _epics_shm + DAQ_GDS_BLOCK_ADD ); + // Set pointer to EXC data in shmem. + if ( sysRate < DAQ_16K_SAMPLE_SIZE ) + { + exciteDataPtr = + (char*)( _epics_shm + DATA_OFFSET_DCU( DCU_ID_EX_2K ) ); } - } else if (dataInfo.tp[ii].dataType == DAQ_DATATYPE_32BIT_UINT) { - if ((daqSlot % localTable[ii].decFactor) == 1) - *((unsigned int *)(dHistory[ii])) = (unsigned int)dWord; else - *((unsigned int *)(dHistory[ii])) &= (unsigned int)dWord; - } - } /* end swing buffer write loop */ - - /// \> Write EPICS data into swing buffer at 16Hz. - if (daqSlot == DAQ_XFER_CYCLE_INT) { - /// \>\> On 16Hz boundary: \n - /// - ---- Write EPICS integer values to beginning of local write buffer - - if (dataInfo.cpyepics2times) { - memcpy((void *)pWriteBuffer, (void *)pEpicsIntData, dataInfo.cpyIntSize[0]); - pEpicsInt = (char *)pWriteBuffer; - pEpicsInt += dataInfo.cpyIntSize[0]; - pEpicsInt1 = pEpicsIntData + dataInfo.cpyIntSize[0] + 4; - memcpy((void *)pEpicsInt, (void *)pEpicsInt1, dataInfo.cpyIntSize[1]); - } else { - memcpy((void *)pWriteBuffer, (void *)pEpicsIntData, dataInfo.cpyIntSize[0]); - } - } - if (daqSlot == DAQ_XFER_CYCLE_DBL) { - /// - ---- Write EPICS double values as float values after EPICS integer - /// type data. - pEpicsDblData1 = (double *)pEpicsDblData; - pEpicsFloat = (float *)pWriteBuffer; - pEpicsFloat += dataInfo.numEpicsInts; - for (ii = 0; ii < dataInfo.numEpicsFloats; ii++) { - *pEpicsFloat = (float)*pEpicsDblData1; - pEpicsFloat++; - pEpicsDblData1++; - } - } - if ((daqSlot >= DAQ_XFER_CYCLE_FMD) && - (daqSlot < dataInfo.numEpicsFiltXfers)) { - /// \>\> On 16Hz boundary + 1 (or more) cycle(s): \n - /// - ---- Write filter module EPICS values as floats - jj = DAQ_XFER_FMD_PER_CYCLE * (daqSlot - DAQ_XFER_CYCLE_FMD); - if (daqSlot == (dataInfo.numEpicsFiltXfers - 1)) { - kk = jj + dataInfo.numEpicsFiltsLast; - } else { - kk = jj + DAQ_XFER_FMD_PER_CYCLE; - } - // printf("Cycle = %d jj = %d kk = %d\n",daqSlot,jj,kk); - for (ii = jj; ii < kk; ii++) { - *pEpicsFloat = (float)dspPtr->inputs[ii].offset; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->inputs[ii].outgain; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->inputs[ii].limiter; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->inputs[ii].gain_ramp_time; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->inputs[ii].swReq; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->inputs[ii].swMask; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->data[ii].filterInput; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->data[ii].exciteInput; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->data[ii].output16Hz; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->data[ii].output; - pEpicsFloat++; - *pEpicsFloat = (float)dspPtr->data[ii].swStatus; - pEpicsFloat++; - } - } - - /// \> Read in any selected EXC signals. \n - /// --- NOTE: EXC signals have to be read and loaded in advance by 1 cycle - /// ie must be loaded and - /// available to the realtime application when the next code cycle is - /// initiated. - excSlot = (excSlot + 1) % sysRate; - // if(validEx) - validEx = 0; - { - // Go through all test points - for (ii = dataInfo.numChans; ii < totalChans; ii++) { - // Do not pickup any testpoints (type 0 or 1) - if (localTable[ii].type < DAQ_SRC_FM_EXC) - continue; - - exChanOffset = localTable[ii].sigNum * excDataSize; - statusPtr = (int *)(exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + - exChanOffset); - if (*statusPtr == 0) { - validEx = FE_ERROR_EXC_SET; - dataPtr = (float *)(exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + - exChanOffset + excSlot * 4 + 4); - if (localTable[ii].type == DAQ_SRC_FM_EXC) { - dspPtr->data[localTable[ii].fmNum].exciteInput = *dataPtr; - } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) { - // extra excitation - excSignal[localTable[ii].fmNum] = *dataPtr; - } + { + exciteDataPtr = + (char*)( _epics_shm + DATA_OFFSET_DCU( DCU_ID_EX_16K ) ); } - // else dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0; - else { - if (localTable[ii].type == DAQ_SRC_FM_EXC) { - dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0; - } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) { - // extra excitation - excSignal[localTable[ii].fmNum] = 0.0; - } - } - } - } + excDataSize = 4 + 4 * sysRate; - /// \> Move to the next 1/16 EXC signal data block if end of 16Hz block - if (excSlot == (sysRate - 1)) - excBlockNum = (excBlockNum + 1) % DAQ_NUM_DATA_BLOCKS; + // Clear the reconfiguration flag in shmem. + pInfo->reconfig = 0; - /// \> If last cycle of a 16Hz block: - if (daqSlot == (sysRate - 1)) - /* Done with 1/16 second DAQ data block */ + // Configure data channels + // ***************************************************** + // Return error if configuration is incorrect. + /// \> Load DAQ configuration info from memory shared with EPICS + if ( ( xferInfo.crcLength = daqConfig( &dataInfo, pInfo, pEpics ) ) == + -1 ) + return ( -1 ); + + /// \> Load local table information with channel info + if ( ( status = loadLocalTable( + &xferInfo, localTable, sysRate, &dataInfo, &daqRange ) ) == + -1 ) + return ( -1 ); + + // Set the start of TP data after DAQ data. + tpStart = xferInfo.offsetAccum; + totalChans = dataInfo.numChans; + + /// \> Clear out the GDS TP selections. + if ( sysRate < DAQ_16K_SAMPLE_SIZE ) + tpx = 3; + else + tpx = 2; + for ( ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++ ) + gdsPtr->tp[ tpx ][ 0 ][ ii ] = 0; + if ( sysRate < DAQ_16K_SAMPLE_SIZE ) + tpx = 1; + else + tpx = 0; + for ( ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++ ) + gdsPtr->tp[ tpx ][ 0 ][ ii ] = 0; + + /// \> Clear the GDS TP lookup table + for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ ) + { + tpNum[ i ] = 0; + tpNumNet[ i ] = 0; + } + validTp = 0; + validTpNet = 0; + + // printf("at connect TPnum[0]=%d\n", tpNum[0]); + } /// End DAQ CONNECT INITIALIZATION ****************************** + + /* ******************************************************************************** + */ + /* Write Data to FB + * ******************************************* + */ + /* ******************************************************************************** + */ + /// If flag=0, data is to be acquired. This is called every code cycle by + /// controller.c + /// ** Data Acquisition Mode + /// ******************************************************** + if ( flag == DAQ_WRITE ) { + /// \> Calc data offset into current write swing buffer + daqSlot = ( daqSlot + 1 ) % sysRate; + + /// \> Write data into local swing buffer + for ( ii = 0; ii < totalChans; ii++ ) + { + + dWord = 0; + /// \> 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 */ + { + switch ( localTable[ ii ].sigNum ) + { + case 0: + dWord = dspPtr->data[ localTable[ ii ].fmNum ].filterInput; + break; + case 1: + dWord = + dspPtr->data[ localTable[ ii ].fmNum ].inputTestpoint; + break; + case 2: + dWord = dspPtr->data[ localTable[ ii ].fmNum ].testpoint; + break; + default: + dWord = 0.0; + break; + } + } + else if ( localTable[ ii ].type == DAQ_SRC_NFM_TP ) + /* Data is from non filter module testpoint */ + { + dWord = *( pFloatData[ localTable[ ii ].sigNum ] ); + } + else if ( localTable[ ii ].type == DAQ_SRC_FM_EXC ) + /* Data is from filter module excitation */ + { + dWord = dspPtr->data[ localTable[ ii ].fmNum ].exciteInput; + } + else if ( localTable[ ii ].type == DAQ_SRC_NFM_EXC ) + { + // Extra excitation + dWord = excSignal[ localTable[ ii ].fmNum ]; + } - /// - -- Fill in the IPC table for DAQ network driver (mx_stream) \n - dipc->dcuId = dcuId; /// - ------ DCU id of this system - dipc->crc = - xferInfo.fileCrc; /// - ------ Checksum of the configuration file - dipc->dataBlockSize = - xferInfo.totalSizeNet; /// - ------ Actual data size - /// - ------ Data block number - dipc->bp[daqXmitBlockNum].cycle = daqXmitBlockNum; - /// - ------ Data block CRC - dipc->bp[daqXmitBlockNum].crc = xferInfo.crcLength; - /// - ------ Timestamp GPS Second - dipc->bp[daqXmitBlockNum].timeSec = (unsigned int)cycle_gps_time; - /// - ------ Timestamp GPS nanoSecond - Actually cycle number - dipc->bp[daqXmitBlockNum].timeNSec = (unsigned int)daqXmitBlockNum; - - /// - ------ Write test point info to DAQ net shared memory - tpPtr->count = validTpNet | validEx; - memcpy(tpPtr->tpNum, tpNumNet, sizeof(tpNumNet[0]) * validTp); - - // As the last step set the cycle counter - // 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) - - /// - -- Increment the 1/16 sec block counter - daqBlockNum = (daqBlockNum + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - daqXmitBlockNum = (daqXmitBlockNum + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - - /// - -- Set data write ptr to next block in shmem - pWriteBuffer = (char *)daqShmPtr; - pWriteBuffer += buf_size * daqXmitBlockNum; - - // - -- Check for reconfig request at start of each second - if ((pInfo->reconfig == 1) && (daqBlockNum == 0)) { - // printf("New daq config\n"); - pInfo->reconfig = 0; - // Configure EPICS data channels - xferInfo.crcLength = daqConfig(&dataInfo, pInfo, pEpics); - if (xferInfo.crcLength) { - status = loadLocalTable(&xferInfo, localTable, sysRate, &dataInfo, - &daqRange); - // Clear decimation filter history - for (ii = 0; ii < dataInfo.numChans; ii++) { - for (jj = 0; jj < MAX_HISTRY; jj++) - dHistory[ii][jj] = 0.0; - } - - tpStart = xferInfo.offsetAccum; - totalChans = dataInfo.numChans; - } - } - /// - -- 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. - - if (daqBlockNum == 15) { - // Offset by one into the TP/EXC tables for the 2K systems - unsigned int _2k_sys_offs = sysRate < DAQ_16K_SAMPLE_SIZE; - - // Helper function to search the lists - // Clears the found number from the lists - // tpnum and excnum lists of numbers do not intersect - inline int in_the_lists(unsigned int tp, unsigned int slot) { - int i; - for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) { - if (tpnum[i] == tp) - return (tpnum[i] = 0, 1); - if (excnum[i] == tp) { - // Check if the excitation is still in the same slot - if (i != excTable[slot].offset) - return 0; - return (excnum[i] = 0, 1); +/// \> Perform decimation filtering, if required. +#ifdef CORE_BIQUAD +#define iir_filter iir_filter_biquad +#endif + if ( dataInfo.tp[ ii ].dataType != DAQ_DATATYPE_32BIT_UINT ) + { + if ( localTable[ ii ].decFactor == 2 ) + dWord = iir_filter( + dWord, &dCoeff2x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 4 ) + dWord = iir_filter( + dWord, &dCoeff4x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 8 ) + dWord = iir_filter( + dWord, &dCoeff8x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 16 ) + dWord = iir_filter( + dWord, &dCoeff16x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 32 ) + dWord = iir_filter( + dWord, &dCoeff32x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 64 ) + dWord = iir_filter( + dWord, &dCoeff64x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 128 ) + dWord = iir_filter( + dWord, &dCoeff128x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 256 ) + dWord = iir_filter( + dWord, &dCoeff256x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); } - } - return 0; - } +#ifdef CORE_BIQUAD +#undef iir_filter +#endif - // Helper function to find an empty slot in the localTable - inline unsigned int empty_slot(void) { - int i; - for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) { - if (tpNum[i] == 0) - return i; - } - return -1; + /// \> Write fast data into the swing buffer. + if ( ( daqSlot % localTable[ ii ].decFactor ) == 0 ) + { + mydatatype = dataInfo.tp[ ii ].dataType; + switch ( mydatatype ) + { + case DAQ_DATATYPE_16BIT_INT: + // Write short data; (XOR 1) here provides sample swapping + ( (short*)( pWriteBuffer + localTable[ ii ].offset ) ) + [ ( daqSlot / localTable[ ii ].decFactor ) ^ 1 ] = + (short)dWord; + break; + case DAQ_DATATYPE_DOUBLE: + ( (double*)( pWriteBuffer + localTable[ ii ].offset ) ) + [ daqSlot / localTable[ ii ].decFactor ] = dWord; + break; + case DAQ_DATATYPE_32BIT_UINT: + // Write a 32-bit int (downcast from the double passed) + if ( localTable[ ii ].decFactor == 1 ) + ( (unsigned int*)( pWriteBuffer + + localTable[ ii ].offset ) ) + [ daqSlot / localTable[ ii ].decFactor ] = + ( (unsigned int)dWord ); + else + ( (unsigned int*)( pWriteBuffer + + localTable[ ii ].offset ) ) + [ daqSlot / localTable[ ii ].decFactor ] = + ( (unsigned int)dWord ) & + *( (unsigned int*)( dHistory[ ii ] ) ); + break; + case DAQ_DATATYPE_32BIT_INT: + ( (int*)( pWriteBuffer + + localTable[ ii ].offset ) )[ daqSlot ] = + (int)dWord; + break; + default: + // Write a 32-bit float (downcast from the double passed) + ( (float*)( pWriteBuffer + localTable[ ii ].offset ) ) + [ daqSlot / localTable[ ii ].decFactor ] = (float)dWord; + break; + } + } + else if ( dataInfo.tp[ ii ].dataType == DAQ_DATATYPE_32BIT_UINT ) + { + if ( ( daqSlot % localTable[ ii ].decFactor ) == 1 ) + *( (unsigned int*)( dHistory[ ii ] ) ) = + (unsigned int)dWord; + else + *( (unsigned int*)( dHistory[ ii ] ) ) &= + (unsigned int)dWord; + } + } /* end swing buffer write loop */ + + /// \> Write EPICS data into swing buffer at 16Hz. + if ( daqSlot == DAQ_XFER_CYCLE_INT ) + { + /// \>\> On 16Hz boundary: \n + /// - ---- Write EPICS integer values to beginning of local write + /// buffer + + if ( dataInfo.cpyepics2times ) + { + memcpy( (void*)pWriteBuffer, + (void*)pEpicsIntData, + dataInfo.cpyIntSize[ 0 ] ); + pEpicsInt = (char*)pWriteBuffer; + pEpicsInt += dataInfo.cpyIntSize[ 0 ]; + pEpicsInt1 = pEpicsIntData + dataInfo.cpyIntSize[ 0 ] + 4; + memcpy( (void*)pEpicsInt, + (void*)pEpicsInt1, + dataInfo.cpyIntSize[ 1 ] ); + } + else + { + memcpy( (void*)pWriteBuffer, + (void*)pEpicsIntData, + dataInfo.cpyIntSize[ 0 ] ); + } } - - // Copy TP/EXC tables into my local memory - // Had to change from memcpy to for loop for Debian 10. - for (ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++) - excnum[ii] = gdsPtr->tp[_2k_sys_offs][0][ii]; - for (ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++) - tpnum[ii] = gdsPtr->tp[(2 + _2k_sys_offs)][0][ii]; - - /// - ------ Search and clear deselected test points - for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) { - if (tpNum[i] == 0) - continue; - if (!in_the_lists(tpNum[i], i)) { - tpNum[i] = 0; // Removed test point is cleared now - ltSlot = dataInfo.numChans + i; - - // If we are clearing an EXC signal, reset filter module input - if (localTable[ltSlot].type == DAQ_SRC_FM_EXC) { - dspPtr->data[excTable[i].fmNum].exciteInput = 0.0; - excTable[i].sigNum = 0; - } else if (localTable[ltSlot].type == DAQ_SRC_NFM_EXC) { - // Extra excitation - excSignal[excTable[i].fmNum] = 0.0; - excTable[i].sigNum = 0; + if ( daqSlot == DAQ_XFER_CYCLE_DBL ) + { + /// - ---- Write EPICS double values as float values after EPICS + /// integer type data. + pEpicsDblData1 = (double*)pEpicsDblData; + pEpicsFloat = (float*)pWriteBuffer; + pEpicsFloat += dataInfo.numEpicsInts; + for ( ii = 0; ii < dataInfo.numEpicsFloats; ii++ ) + { + *pEpicsFloat = (float)*pEpicsDblData1; + pEpicsFloat++; + pEpicsDblData1++; } - - localTable[ltSlot].type = 0; - localTable[ltSlot].sysNum = 0; - localTable[ltSlot].fmNum = 0; - localTable[ltSlot].sigNum = 0; - localTable[ltSlot].decFactor = 1; - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - } } - - // tpnum and excnum lists now have only the new test points - // Insert these new numbers into empty localTable slots - for (i = 0; i < (2 * DAQ_GDS_MAX_TP_ALLOWED); i++) { - exc = 0; - // Do test points first - if (i < DAQ_GDS_MAX_TP_ALLOWED) { - if (tpnum[i] == 0) - continue; - tpn = tpnum[i]; - } else { - if (excnum[i - DAQ_GDS_MAX_TP_ALLOWED] == 0) - continue; - tpn = excnum[i - DAQ_GDS_MAX_TP_ALLOWED]; - exc = 1; - ii = i - DAQ_GDS_MAX_TP_ALLOWED; - } - - // printf("tpn=%d at %d\n", tpn, i); - slot = empty_slot(); - if (slot < 0) { - // No more slots left, table's full - break; - } - - // localTable slot (shifted by the number of DAQ channels) - ltSlot = dataInfo.numChans + slot; - - // Populate the slot with the information - if (!exc) { - if (tpn >= daqRange.filtTpMin && tpn < daqRange.filtTpMax) { - jj = tpn - daqRange.filtTpMin; - localTable[ltSlot].type = DAQ_SRC_FM_TP; - localTable[ltSlot].sysNum = jj / daqRange.filtTpSize; - jj -= localTable[ltSlot].sysNum * daqRange.filtTpSize; - localTable[ltSlot].fmNum = jj / DAQ_NUM_FM_TP; - localTable[ltSlot].sigNum = jj % DAQ_NUM_FM_TP; - localTable[ltSlot].decFactor = 1; - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - - // if (slot < 24) gdsMonitor[slot] = tpn; - gdsPtr->tp[2 + _2k_sys_offs][1][slot] = 0; - tpNum[slot] = tpn; - - } else if (tpn >= daqRange.xTpMin && tpn < daqRange.xTpMax) { - jj = tpn - daqRange.xTpMin; - localTable[ltSlot].type = DAQ_SRC_NFM_TP; - localTable[ltSlot].sigNum = jj; - localTable[ltSlot].decFactor = 1; - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - gdsPtr->tp[2 + _2k_sys_offs][1][slot] = 0; - tpNum[slot] = tpn; + if ( ( daqSlot >= DAQ_XFER_CYCLE_FMD ) && + ( daqSlot < dataInfo.numEpicsFiltXfers ) ) + { + /// \>\> On 16Hz boundary + 1 (or more) cycle(s): \n + /// - ---- Write filter module EPICS values as floats + jj = DAQ_XFER_FMD_PER_CYCLE * ( daqSlot - DAQ_XFER_CYCLE_FMD ); + if ( daqSlot == ( dataInfo.numEpicsFiltXfers - 1 ) ) + { + kk = jj + dataInfo.numEpicsFiltsLast; + } + else + { + kk = jj + DAQ_XFER_FMD_PER_CYCLE; } - } else { - - if (tpn >= daqRange.filtExMin && tpn < daqRange.filtExMax) { - jj = tpn - daqRange.filtExMin; - localTable[ltSlot].type = DAQ_SRC_FM_EXC; - localTable[ltSlot].sysNum = - jj / daqRange.filtExSize; // filtExSize = MAX_MODULES - localTable[ltSlot].fmNum = jj % daqRange.filtExSize; - localTable[ltSlot].sigNum = ii; - localTable[ltSlot].decFactor = 1; - - excTable[slot].sigNum = tpn; - excTable[slot].sysNum = localTable[ltSlot].sysNum; - excTable[slot].fmNum = localTable[ltSlot].fmNum; - excTable[slot].offset = i - DAQ_GDS_MAX_TP_ALLOWED; - - // Save the index into the TPman table - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - - gdsPtr->tp[_2k_sys_offs][1][slot] = 0; - tpNum[slot] = tpn; - - } else if (tpn >= daqRange.xExMin && tpn < daqRange.xExMax) { - jj = tpn - daqRange.xExMin; - localTable[ltSlot].type = DAQ_SRC_NFM_EXC; - localTable[ltSlot].sysNum = 0; // filtExSize = MAX_MODULES - localTable[ltSlot].fmNum = jj; - // localTable[ltSlot].sigNum = slot; - localTable[ltSlot].sigNum = ii; - localTable[ltSlot].decFactor = 1; - - excTable[slot].sigNum = tpn; - excTable[slot].sysNum = localTable[ltSlot].sysNum; - excTable[slot].fmNum = localTable[ltSlot].fmNum; - excTable[slot].offset = i - DAQ_GDS_MAX_TP_ALLOWED; - - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - // if (slot < 8) gdsMonitor[slot + 24] = tpn; - gdsPtr->tp[_2k_sys_offs][1][slot] = 0; - tpNum[slot] = tpn; + // printf("Cycle = %d jj = %d kk = %d\n",daqSlot,jj,kk); + for ( ii = jj; ii < kk; ii++ ) + { + *pEpicsFloat = (float)dspPtr->inputs[ ii ].offset; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].outgain; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].limiter; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].gain_ramp_time; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].swReq; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].swMask; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].filterInput; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].exciteInput; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].output16Hz; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].output; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].swStatus; + pEpicsFloat++; } - } } - /// - ------ Calculate total number of test points to transmit - totalChans = dataInfo.numChans; // Set to the DAQ channels number - validTp = 0; - num_tps = 0; - - // Skip empty slots at the end - for (i = DAQ_GDS_MAX_TP_ALLOWED - 1; i >= 0; i--) { - if (tpNum[i]) { - num_tps = i + 1; - break; - } - } - totalChans += num_tps; - validTp = num_tps; - - /// - ------ Calculate the total transmission size (DAQ +TP) - xferInfo.totalSize = xferInfo.crcLength + validTp * sysRate * 4; - - // Assign offsets into the localTable - xferInfo.offsetAccum = tpStart; - for (i = 0; i < validTp; i++) { - localTable[dataInfo.numChans + i].offset = xferInfo.offsetAccum; - xferInfo.offsetAccum += sysRate * 4; - if (i < 32) - gdsMonitor[i] = tpNum[i]; + /// \> Read in any selected EXC signals. \n + /// --- NOTE: EXC signals have to be read and loaded in advance by 1 + /// cycle ie must be loaded and available to the realtime application + /// when the next code cycle is initiated. + excSlot = ( excSlot + 1 ) % sysRate; + // if(validEx) + validEx = 0; + { + // Go through all test points + for ( ii = dataInfo.numChans; ii < totalChans; ii++ ) + { + // Do not pickup any testpoints (type 0 or 1) + if ( localTable[ ii ].type < DAQ_SRC_FM_EXC ) + continue; + + exChanOffset = localTable[ ii ].sigNum * excDataSize; + statusPtr = + (int*)( exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + + exChanOffset ); + if ( *statusPtr == 0 ) + { + validEx = FE_ERROR_EXC_SET; + dataPtr = (float*)( exciteDataPtr + + excBlockNum * DAQ_DCU_BLOCK_SIZE + + exChanOffset + excSlot * 4 + 4 ); + if ( localTable[ ii ].type == DAQ_SRC_FM_EXC ) + { + dspPtr->data[ localTable[ ii ].fmNum ].exciteInput = + *dataPtr; + } + else if ( localTable[ ii ].type == DAQ_SRC_NFM_EXC ) + { + // extra excitation + excSignal[ localTable[ ii ].fmNum ] = *dataPtr; + } + } + // else dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0; + else + { + if ( localTable[ ii ].type == DAQ_SRC_FM_EXC ) + { + dspPtr->data[ localTable[ ii ].fmNum ].exciteInput = + 0.0; + } + else if ( localTable[ ii ].type == DAQ_SRC_NFM_EXC ) + { + // extra excitation + excSignal[ localTable[ ii ].fmNum ] = 0.0; + } + } + } } - for (i = validTp; i < 32; i++) - gdsMonitor[i] = 0; - - } /* End normal check for new TP numbers */ - - // 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++) - tpNumNet[ii] = tpNum[ii]; - validTpNet = validTp; - xferInfo.totalSizeNet = xferInfo.totalSize; - } + /// \> Move to the next 1/16 EXC signal data block if end of 16Hz block + if ( excSlot == ( sysRate - 1 ) ) + excBlockNum = ( excBlockNum + 1 ) % DAQ_NUM_DATA_BLOCKS; + + /// \> If last cycle of a 16Hz block: + if ( daqSlot == ( sysRate - 1 ) ) + /* Done with 1/16 second DAQ data block */ + { + + /// - -- Fill in the IPC table for DAQ network driver (mx_stream) \n + dipc->dcuId = dcuId; /// - ------ DCU id of this system + dipc->crc = + xferInfo + .fileCrc; /// - ------ Checksum of the configuration file + dipc->dataBlockSize = + xferInfo.totalSizeNet; /// - ------ Actual data size + /// - ------ Data block number + dipc->bp[ daqXmitBlockNum ].cycle = daqXmitBlockNum; + /// - ------ Data block CRC + dipc->bp[ daqXmitBlockNum ].crc = xferInfo.crcLength; + /// - ------ Timestamp GPS Second + dipc->bp[ daqXmitBlockNum ].timeSec = (unsigned int)cycle_gps_time; + /// - ------ Timestamp GPS nanoSecond - Actually cycle number + dipc->bp[ daqXmitBlockNum ].timeNSec = + (unsigned int)daqXmitBlockNum; + + /// - ------ Write test point info to DAQ net shared memory + tpPtr->count = validTpNet | validEx; + memcpy( tpPtr->tpNum, tpNumNet, sizeof( tpNumNet[ 0 ] ) * validTp ); + + // As the last step set the cycle counter + // 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) + + /// - -- Increment the 1/16 sec block counter + daqBlockNum = ( daqBlockNum + 1 ) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; + daqXmitBlockNum = + ( daqXmitBlockNum + 1 ) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; + + /// - -- Set data write ptr to next block in shmem + pWriteBuffer = (char*)daqShmPtr; + pWriteBuffer += buf_size * daqXmitBlockNum; + + // - -- Check for reconfig request at start of each second + if ( ( pInfo->reconfig == 1 ) && ( daqBlockNum == 0 ) ) + { + // printf("New daq config\n"); + pInfo->reconfig = 0; + // Configure EPICS data channels + xferInfo.crcLength = daqConfig( &dataInfo, pInfo, pEpics ); + if ( xferInfo.crcLength ) + { + status = loadLocalTable( + &xferInfo, localTable, sysRate, &dataInfo, &daqRange ); + // Clear decimation filter history + for ( ii = 0; ii < dataInfo.numChans; ii++ ) + { + for ( jj = 0; jj < MAX_HISTRY; jj++ ) + dHistory[ ii ][ jj ] = 0.0; + } + + tpStart = xferInfo.offsetAccum; + totalChans = dataInfo.numChans; + } + } + /// - -- 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. + + if ( daqBlockNum == 15 ) + { + // Offset by one into the TP/EXC tables for the 2K systems + unsigned int _2k_sys_offs = sysRate < DAQ_16K_SAMPLE_SIZE; + + // Helper function to search the lists + // Clears the found number from the lists + // tpnum and excnum lists of numbers do not intersect + inline int in_the_lists( unsigned int tp, unsigned int slot ) + { + int i; + for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ ) + { + if ( tpnum[ i ] == tp ) + return ( tpnum[ i ] = 0, 1 ); + if ( excnum[ i ] == tp ) + { + // Check if the excitation is still in the same slot + if ( i != excTable[ slot ].offset ) + return 0; + return ( excnum[ i ] = 0, 1 ); + } + } + return 0; + } + + // Helper function to find an empty slot in the localTable + inline unsigned int empty_slot( void ) + { + int i; + for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ ) + { + if ( tpNum[ i ] == 0 ) + return i; + } + return -1; + } + + // Copy TP/EXC tables into my local memory + // Had to change from memcpy to for loop for Debian 10. + for ( ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++ ) + excnum[ ii ] = gdsPtr->tp[ _2k_sys_offs ][ 0 ][ ii ]; + for ( ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++ ) + tpnum[ ii ] = gdsPtr->tp[ ( 2 + _2k_sys_offs ) ][ 0 ][ ii ]; + + /// - ------ Search and clear deselected test points + for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ ) + { + if ( tpNum[ i ] == 0 ) + continue; + if ( !in_the_lists( tpNum[ i ], i ) ) + { + tpNum[ i ] = 0; // Removed test point is cleared now + ltSlot = dataInfo.numChans + i; + + // If we are clearing an EXC signal, reset filter module + // input + if ( localTable[ ltSlot ].type == DAQ_SRC_FM_EXC ) + { + dspPtr->data[ excTable[ i ].fmNum ].exciteInput = + 0.0; + excTable[ i ].sigNum = 0; + } + else if ( localTable[ ltSlot ].type == DAQ_SRC_NFM_EXC ) + { + // Extra excitation + excSignal[ excTable[ i ].fmNum ] = 0.0; + excTable[ i ].sigNum = 0; + } + + localTable[ ltSlot ].type = 0; + localTable[ ltSlot ].sysNum = 0; + localTable[ ltSlot ].fmNum = 0; + localTable[ ltSlot ].sigNum = 0; + localTable[ ltSlot ].decFactor = 1; + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + } + } + + // tpnum and excnum lists now have only the new test points + // Insert these new numbers into empty localTable slots + for ( i = 0; i < ( 2 * DAQ_GDS_MAX_TP_ALLOWED ); i++ ) + { + exc = 0; + // Do test points first + if ( i < DAQ_GDS_MAX_TP_ALLOWED ) + { + if ( tpnum[ i ] == 0 ) + continue; + tpn = tpnum[ i ]; + } + else + { + if ( excnum[ i - DAQ_GDS_MAX_TP_ALLOWED ] == 0 ) + continue; + tpn = excnum[ i - DAQ_GDS_MAX_TP_ALLOWED ]; + exc = 1; + ii = i - DAQ_GDS_MAX_TP_ALLOWED; + } + + // printf("tpn=%d at %d\n", tpn, i); + slot = empty_slot( ); + if ( slot < 0 ) + { + // No more slots left, table's full + break; + } + + // localTable slot (shifted by the number of DAQ channels) + ltSlot = dataInfo.numChans + slot; + + // Populate the slot with the information + if ( !exc ) + { + if ( tpn >= daqRange.filtTpMin && + tpn < daqRange.filtTpMax ) + { + jj = tpn - daqRange.filtTpMin; + localTable[ ltSlot ].type = DAQ_SRC_FM_TP; + localTable[ ltSlot ].sysNum = + jj / daqRange.filtTpSize; + jj -= localTable[ ltSlot ].sysNum * + daqRange.filtTpSize; + localTable[ ltSlot ].fmNum = jj / DAQ_NUM_FM_TP; + localTable[ ltSlot ].sigNum = jj % DAQ_NUM_FM_TP; + localTable[ ltSlot ].decFactor = 1; + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + + // if (slot < 24) gdsMonitor[slot] = tpn; + gdsPtr->tp[ 2 + _2k_sys_offs ][ 1 ][ slot ] = 0; + tpNum[ slot ] = tpn; + } + else if ( tpn >= daqRange.xTpMin && + tpn < daqRange.xTpMax ) + { + jj = tpn - daqRange.xTpMin; + localTable[ ltSlot ].type = DAQ_SRC_NFM_TP; + localTable[ ltSlot ].sigNum = jj; + localTable[ ltSlot ].decFactor = 1; + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + gdsPtr->tp[ 2 + _2k_sys_offs ][ 1 ][ slot ] = 0; + tpNum[ slot ] = tpn; + } + } + else + { + + if ( tpn >= daqRange.filtExMin && + tpn < daqRange.filtExMax ) + { + jj = tpn - daqRange.filtExMin; + localTable[ ltSlot ].type = DAQ_SRC_FM_EXC; + localTable[ ltSlot ].sysNum = jj / + daqRange.filtExSize; // filtExSize = MAX_MODULES + localTable[ ltSlot ].fmNum = + jj % daqRange.filtExSize; + localTable[ ltSlot ].sigNum = ii; + localTable[ ltSlot ].decFactor = 1; + + excTable[ slot ].sigNum = tpn; + excTable[ slot ].sysNum = + localTable[ ltSlot ].sysNum; + excTable[ slot ].fmNum = localTable[ ltSlot ].fmNum; + excTable[ slot ].offset = + i - DAQ_GDS_MAX_TP_ALLOWED; + + // Save the index into the TPman table + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + + gdsPtr->tp[ _2k_sys_offs ][ 1 ][ slot ] = 0; + tpNum[ slot ] = tpn; + } + else if ( tpn >= daqRange.xExMin && + tpn < daqRange.xExMax ) + { + jj = tpn - daqRange.xExMin; + localTable[ ltSlot ].type = DAQ_SRC_NFM_EXC; + localTable[ ltSlot ].sysNum = + 0; // filtExSize = MAX_MODULES + localTable[ ltSlot ].fmNum = jj; + // localTable[ltSlot].sigNum = slot; + localTable[ ltSlot ].sigNum = ii; + localTable[ ltSlot ].decFactor = 1; + + excTable[ slot ].sigNum = tpn; + excTable[ slot ].sysNum = + localTable[ ltSlot ].sysNum; + excTable[ slot ].fmNum = localTable[ ltSlot ].fmNum; + excTable[ slot ].offset = + i - DAQ_GDS_MAX_TP_ALLOWED; + + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + // if (slot < 8) gdsMonitor[slot + 24] = tpn; + gdsPtr->tp[ _2k_sys_offs ][ 1 ][ slot ] = 0; + tpNum[ slot ] = tpn; + } + } + } + + /// - ------ Calculate total number of test points to transmit + totalChans = + dataInfo.numChans; // Set to the DAQ channels number + validTp = 0; + num_tps = 0; + + // Skip empty slots at the end + for ( i = DAQ_GDS_MAX_TP_ALLOWED - 1; i >= 0; i-- ) + { + if ( tpNum[ i ] ) + { + num_tps = i + 1; + break; + } + } + totalChans += num_tps; + validTp = num_tps; + + /// - ------ Calculate the total transmission size (DAQ +TP) + xferInfo.totalSize = xferInfo.crcLength + validTp * sysRate * 4; + + // Assign offsets into the localTable + xferInfo.offsetAccum = tpStart; + for ( i = 0; i < validTp; i++ ) + { + localTable[ dataInfo.numChans + i ].offset = + xferInfo.offsetAccum; + xferInfo.offsetAccum += sysRate * 4; + if ( i < 32 ) + gdsMonitor[ i ] = tpNum[ i ]; + } + + for ( i = validTp; i < 32; i++ ) + gdsMonitor[ i ] = 0; + + } /* End normal check for new TP numbers */ + + // 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++ ) + tpNumNet[ ii ] = tpNum[ ii ]; + validTpNet = validTp; + xferInfo.totalSizeNet = xferInfo.totalSize; + } - } /* End done 16Hz Cycle */ + } /* End done 16Hz Cycle */ - } /* End case write */ + } /* End case write */ - /// \> Return the FE total DAQ data rate */ - return ((xferInfo.totalSize * DAQ_NUM_DATA_BLOCKS_PER_SECOND) / 1000); + /// \> Return the FE total DAQ data rate */ + return ( ( xferInfo.totalSize * DAQ_NUM_DATA_BLOCKS_PER_SECOND ) / 1000 ); } // ************************************************************************************** @@ -921,119 +1069,130 @@ int daqWrite(int flag, int dcuId, DAQ_RANGE daqRange, int sysRate, /// @param[in] pEpics Pointer to beginning of EPICS data. /// @return Size, in bytes, of DAQ data. // ************************************************************************************** -int daqConfig(volatile DAQ_INFO_BLOCK *dataInfo, volatile DAQ_INFO_BLOCK *pInfo, volatile char *pEpics) { - int ii, jj; // Loop counters - int epicsIntXferSize = 0; // Size, in bytes, of EPICS integer type data. - int dataLength = 0; // Total size, in bytes, of data to be sent - int status = 0; - int mydatatype; - - /// \> Verify correct channel count before proceeding. \n - /// - ---- Required to be at least one and not more than DCU_MAX_CHANNELS. - status = pInfo->numChans; - // if((status < 1) || (status > DCU_MAX_CHANNELS)) - if (status > DCU_MAX_CHANNELS) { - // printf("Invalid num daq chans = %d\n",status); - return (-1); - } - - /// \> Get the number of fast channels to be acquired - dataInfo->numChans = pInfo->numChans; - - /// \> Setup EPICS channel information/pointers - dataInfo->numEpicsInts = pInfo->numEpicsInts; - dataInfo->numEpicsFloats = pInfo->numEpicsFloats; - dataInfo->numEpicsFilts = pInfo->numEpicsFilts; - dataInfo->numEpicsTotal = pInfo->numEpicsTotal; - /// \> Determine how many filter modules are to have their data transferred - /// per cycle. - /// - ---- This is to balance load (CPU time) across several cycles if number - /// of filter modules > 100 - dataInfo->numEpicsFiltXfers = MAX_MODULES / DAQ_XFER_FMD_PER_CYCLE; - dataInfo->numEpicsFiltsLast = DAQ_XFER_FMD_PER_CYCLE; - if (MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE) { - dataInfo->numEpicsFiltXfers++; - dataInfo->numEpicsFiltsLast = (MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE); - } - dataInfo->numEpicsFiltXfers += DAQ_XFER_CYCLE_FMD; - pEpicsIntData = pEpics; - epicsIntXferSize = dataInfo->numEpicsInts * 4; - - dataInfo->epicsdblDataOffset = 0; - dataInfo->cpyepics2times = 0; - dataInfo->cpyIntSize[0] = dataInfo->numEpicsInts * 4; - dataInfo->cpyIntSize[1] = 0; - - ii = (sizeof(CDS_EPICS_OUT) / 4); - jj = dataInfo->numEpicsInts - ii; - // printf("Have %d CDS epics integer and %d USR epics integer - // channels\n",ii,jj); - ii *= 4; - jj *= 4; - - /// \> Look for memory holes ie integer types not ending on 8 byte boundary. - /// Need to check both standard CDS struct and User channels - /// - ---- If either doesn't end on 8 byte boundary, then a 4 byte hole will - /// appear - /// before the double type data in shared memory. - if (ii % 8) { - // printf("Have int mem hole after CDS %d %d \n",ii,jj); - dataInfo->epicsdblDataOffset += 4; - } - if (jj % 8) { - // printf("Have int mem hole after user %d %d \n",ii,jj); - dataInfo->epicsdblDataOffset += 4; - } - if ((ii % 8) && (jj > 0)) { - /// - ---- If standard CDS struct doesn't end on 8 byte boundary, then - /// have 4 byte mem hole after CDS data - /// This will require 2 memcpys of integer data to get 8 byte alignment for - /// xfer to DAQ buffer.. - dataInfo->cpyIntSize[0] = ii; - dataInfo->cpyIntSize[1] = jj; - dataInfo->cpyepics2times = 1; - // dataInfo->epicsdblDataOffset += 4; - // printf("Have mem holes after CDS %d %d \nNeed to cpy ints twice - size 1 - // = %d size 2 = %d - // \n",ii,jj,dataInfo->cpyIntSize[0],dataInfo->cpyIntSize[1]); - } - - /// \> Set the pointer to start of EPICS double type data in shared memory. \n - /// - ---- Ptr to double type data is at EPICS integer start + EPICS integer - /// size + Memory holes - pEpicsDblData = - (pEpicsIntData + epicsIntXferSize + dataInfo->epicsdblDataOffset); - - // Send EPICS data diags to dmesg - // printf("DAQ EPICS INT DATA is at 0x%lx with size - // %d\n",(long)pEpicsIntData,epicsIntXferSize); - // printf("DAQ EPICS FLT DATA is at 0x%lx\n",(long)pEpicsDblData); - // printf("DAQ EPICS: Int = %d Flt = %d Filters = %d Total = %d Fast = - // %d\n",dataInfo->numEpicsInts,dataInfo->numEpicsFloats,dataInfo->numEpicsFilts, - // dataInfo->numEpicsTotal, dataInfo->numChans); - // printf("DAQ EPICS: Number of Filter Module Xfers = %d last = - // %d\n",dataInfo->numEpicsFiltXfers,dataInfo->numEpicsFiltsLast); - /// \> Initialize CRC length with EPICS data size. - dataLength = 4 * dataInfo->numEpicsTotal; - // printf("crc length epics = %d\n",dataLength); - - /// \> Get the DAQ configuration information for all fast DAQ channels and - /// calc a crc checksum length - for (ii = 0; ii < dataInfo->numChans; ii++) { - dataInfo->tp[ii].tpnum = pInfo->tp[ii].tpnum; - dataInfo->tp[ii].dataType = pInfo->tp[ii].dataType; - dataInfo->tp[ii].dataRate = pInfo->tp[ii].dataRate; - mydatatype = dataInfo->tp[ii].dataType; - dataLength += DAQ_DATA_TYPE_SIZE(mydatatype) * dataInfo->tp[ii].dataRate / - DAQ_NUM_DATA_BLOCKS; - // if(mydatatype == 5) printf("Found double - // %d\n",DAQ_DATA_TYPE_SIZE(mydatatype)); - } - /// \> Set DAQ bytes/sec global, which is output to EPICS by controller.c - curDaqBlockSize = dataLength * DAQ_NUM_DATA_BLOCKS_PER_SECOND; - - /// \> RETURN dataLength, used in other code for CRC checksum byte count - return (dataLength); +int +daqConfig( volatile DAQ_INFO_BLOCK* dataInfo, + volatile DAQ_INFO_BLOCK* pInfo, + volatile char* pEpics ) +{ + int ii, jj; // Loop counters + int epicsIntXferSize = 0; // Size, in bytes, of EPICS integer type data. + int dataLength = 0; // Total size, in bytes, of data to be sent + int status = 0; + int mydatatype; + + /// \> Verify correct channel count before proceeding. \n + /// - ---- Required to be at least one and not more than DCU_MAX_CHANNELS. + status = pInfo->numChans; + // if((status < 1) || (status > DCU_MAX_CHANNELS)) + if ( status > DCU_MAX_CHANNELS ) + { + // printf("Invalid num daq chans = %d\n",status); + return ( -1 ); + } + + /// \> Get the number of fast channels to be acquired + dataInfo->numChans = pInfo->numChans; + + /// \> Setup EPICS channel information/pointers + dataInfo->numEpicsInts = pInfo->numEpicsInts; + dataInfo->numEpicsFloats = pInfo->numEpicsFloats; + dataInfo->numEpicsFilts = pInfo->numEpicsFilts; + dataInfo->numEpicsTotal = pInfo->numEpicsTotal; + /// \> Determine how many filter modules are to have their data transferred + /// per cycle. + /// - ---- This is to balance load (CPU time) across several cycles if + /// number of filter modules > 100 + dataInfo->numEpicsFiltXfers = MAX_MODULES / DAQ_XFER_FMD_PER_CYCLE; + dataInfo->numEpicsFiltsLast = DAQ_XFER_FMD_PER_CYCLE; + if ( MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE ) + { + dataInfo->numEpicsFiltXfers++; + dataInfo->numEpicsFiltsLast = ( MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE ); + } + dataInfo->numEpicsFiltXfers += DAQ_XFER_CYCLE_FMD; + pEpicsIntData = pEpics; + epicsIntXferSize = dataInfo->numEpicsInts * 4; + + dataInfo->epicsdblDataOffset = 0; + dataInfo->cpyepics2times = 0; + dataInfo->cpyIntSize[ 0 ] = dataInfo->numEpicsInts * 4; + dataInfo->cpyIntSize[ 1 ] = 0; + + ii = ( sizeof( CDS_EPICS_OUT ) / 4 ); + jj = dataInfo->numEpicsInts - ii; + // printf("Have %d CDS epics integer and %d USR epics integer + // channels\n",ii,jj); + ii *= 4; + jj *= 4; + + /// \> Look for memory holes ie integer types not ending on 8 byte + /// boundary. Need to check both standard CDS struct and User channels + /// - ---- If either doesn't end on 8 byte boundary, then a 4 byte hole will + /// appear + /// before the double type data in shared memory. + if ( ii % 8 ) + { + // printf("Have int mem hole after CDS %d %d \n",ii,jj); + dataInfo->epicsdblDataOffset += 4; + } + if ( jj % 8 ) + { + // printf("Have int mem hole after user %d %d \n",ii,jj); + dataInfo->epicsdblDataOffset += 4; + } + if ( ( ii % 8 ) && ( jj > 0 ) ) + { + /// - ---- If standard CDS struct doesn't end on 8 byte boundary, then + /// have 4 byte mem hole after CDS data + /// This will require 2 memcpys of integer data to get 8 byte alignment + /// for xfer to DAQ buffer.. + dataInfo->cpyIntSize[ 0 ] = ii; + dataInfo->cpyIntSize[ 1 ] = jj; + dataInfo->cpyepics2times = 1; + // dataInfo->epicsdblDataOffset += 4; + // printf("Have mem holes after CDS %d %d \nNeed to cpy ints twice - + // size 1 = %d size 2 = %d + // \n",ii,jj,dataInfo->cpyIntSize[0],dataInfo->cpyIntSize[1]); + } + + /// \> Set the pointer to start of EPICS double type data in shared memory. + /// \n + /// - ---- Ptr to double type data is at EPICS integer start + EPICS integer + /// size + Memory holes + pEpicsDblData = + ( pEpicsIntData + epicsIntXferSize + dataInfo->epicsdblDataOffset ); + + // Send EPICS data diags to dmesg + // printf("DAQ EPICS INT DATA is at 0x%lx with size + // %d\n",(long)pEpicsIntData,epicsIntXferSize); + // printf("DAQ EPICS FLT DATA is at 0x%lx\n",(long)pEpicsDblData); + // printf("DAQ EPICS: Int = %d Flt = %d Filters = %d Total = %d Fast = + // %d\n",dataInfo->numEpicsInts,dataInfo->numEpicsFloats,dataInfo->numEpicsFilts, + // dataInfo->numEpicsTotal, dataInfo->numChans); + // printf("DAQ EPICS: Number of Filter Module Xfers = %d last = + // %d\n",dataInfo->numEpicsFiltXfers,dataInfo->numEpicsFiltsLast); + /// \> Initialize CRC length with EPICS data size. + dataLength = 4 * dataInfo->numEpicsTotal; + // printf("crc length epics = %d\n",dataLength); + + /// \> Get the DAQ configuration information for all fast DAQ channels and + /// calc a crc checksum length + for ( ii = 0; ii < dataInfo->numChans; ii++ ) + { + dataInfo->tp[ ii ].tpnum = pInfo->tp[ ii ].tpnum; + dataInfo->tp[ ii ].dataType = pInfo->tp[ ii ].dataType; + dataInfo->tp[ ii ].dataRate = pInfo->tp[ ii ].dataRate; + mydatatype = dataInfo->tp[ ii ].dataType; + dataLength += DAQ_DATA_TYPE_SIZE( mydatatype ) * + dataInfo->tp[ ii ].dataRate / DAQ_NUM_DATA_BLOCKS; + // if(mydatatype == 5) printf("Found double + // %d\n",DAQ_DATA_TYPE_SIZE(mydatatype)); + } + /// \> Set DAQ bytes/sec global, which is output to EPICS by controller.c + curDaqBlockSize = dataLength * DAQ_NUM_DATA_BLOCKS_PER_SECOND; + + /// \> RETURN dataLength, used in other code for CRC checksum byte count + return ( dataLength ); } // ************************************************************************************** @@ -1041,106 +1200,121 @@ int daqConfig(volatile DAQ_INFO_BLOCK *dataInfo, volatile DAQ_INFO_BLOCK *pInfo, /// @brief This function populates the local DAQ/TP tables. /// @param *pDxi Pointer to struct with data transfer size information. /// @param localTable[] Table to be populated with data pointer -///information +/// information /// @param sysRate Number of code cycles in 1/16 second. /// @param *dataInfo DAQ configuration information -/// @param *daqRange Info on GDS TP number ranges which provides -///type information +/// @param *daqRange Info on GDS TP number ranges which +///provides type information /// @return 0=OK or -1=FAIL // ************************************************************************************** -int loadLocalTable(DAQ_XFER_INFO *pDxi, DAQ_LKUP_TABLE localTable[], - int sysRate, DAQ_INFO_BLOCK *dataInfo, DAQ_RANGE *daqRange) { - int ii, jj; - int mydatatype; - - /// \> Get the .INI file crc checksum to pass to DAQ Framebuilders for config - /// checking */ - pDxi->fileCrc = pInfo->configFileCRC; - /// \> Calculate the number of bytes to xfer on each call, based on total - /// number - /// of bytes to write each 1/16sec and the front end data rate - /// (2048/16384Hz) - pDxi->xferSize1 = pDxi->crcLength / sysRate; - pDxi->totalSize = pDxi->crcLength; - pDxi->totalSizeNet = pDxi->crcLength; - - /// \> Find first memory location for fast data in read/write swing buffers. - pDxi->offsetAccum = 4 * dataInfo->numEpicsTotal; - localTable[0].offset = pDxi->offsetAccum; - - /// \> Fill in the local lookup table for finding data. - /// - (Need to develop a table of offset pointers to load data into swing - /// buffers) \n - /// - (This is based on decimation factors and data size.) - for (ii = 0; ii < dataInfo->numChans; ii++) { - 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); - return (-1); - } else { - /// - ---- Load decimation factor - localTable[ii].decFactor = - sysRate / (dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS); - } - - /// - ---- Calc offset into swing buffer for writing data - mydatatype = dataInfo->tp[ii].dataType; - pDxi->offsetAccum += - (sysRate / localTable[ii].decFactor * DAQ_DATA_TYPE_SIZE(mydatatype)); - - localTable[ii + 1].offset = pDxi->offsetAccum; - /// - ---- Need to determine if data is from a filter module TP or non-FM - /// TP and tag accordingly - if ((dataInfo->tp[ii].tpnum >= daqRange->filtTpMin) && - (dataInfo->tp[ii].tpnum < daqRange->filtTpMax)) - /* This is a filter module testpoint */ - { - jj = dataInfo->tp[ii].tpnum - daqRange->filtTpMin; - /* Mark as coming from a filter module testpoint */ - localTable[ii].type = DAQ_SRC_FM_TP; - /* Mark which system filter module is in */ - localTable[ii].sysNum = jj / daqRange->filtTpSize; - jj -= localTable[ii].sysNum * daqRange->filtTpSize; - /* Mark which filter module within a system */ - localTable[ii].fmNum = jj / DAQ_NUM_FM_TP; - /* Mark which of three testpoints to store */ - localTable[ii].sigNum = jj % DAQ_NUM_FM_TP; - } else if ((dataInfo->tp[ii].tpnum >= daqRange->filtExMin) && - (dataInfo->tp[ii].tpnum < daqRange->filtExMax)) - /* This is a filter module excitation input */ - { - /* Mark as coming from a filter module excitation input */ - localTable[ii].type = DAQ_SRC_FM_EXC; - /* Mark filter module number */ - localTable[ii].fmNum = dataInfo->tp[ii].tpnum - daqRange->filtExMin; - } else if ((dataInfo->tp[ii].tpnum >= daqRange->xTpMin) && - (dataInfo->tp[ii].tpnum < daqRange->xTpMax)) - /* This testpoint is not part of a filter module */ - { - jj = dataInfo->tp[ii].tpnum - daqRange->xTpMin; - /* Mark as a non filter module testpoint */ - localTable[ii].type = DAQ_SRC_NFM_TP; - /* Mark the offset into the local data buffer */ - localTable[ii].sigNum = jj; - } - else if ((dataInfo->tp[ii].tpnum >= daqRange->xExMin) && - (dataInfo->tp[ii].tpnum < daqRange->xExMax)) - /* This exc testpoint is not part of a filter module */ +int +loadLocalTable( DAQ_XFER_INFO* pDxi, + DAQ_LKUP_TABLE localTable[], + int sysRate, + DAQ_INFO_BLOCK* dataInfo, + DAQ_RANGE* daqRange ) +{ + int ii, jj; + int mydatatype; + + /// \> Get the .INI file crc checksum to pass to DAQ Framebuilders for + /// config checking */ + pDxi->fileCrc = pInfo->configFileCRC; + /// \> Calculate the number of bytes to xfer on each call, based on total + /// number + /// of bytes to write each 1/16sec and the front end data rate + /// (2048/16384Hz) + pDxi->xferSize1 = pDxi->crcLength / sysRate; + pDxi->totalSize = pDxi->crcLength; + pDxi->totalSizeNet = pDxi->crcLength; + + /// \> Find first memory location for fast data in read/write swing buffers. + pDxi->offsetAccum = 4 * dataInfo->numEpicsTotal; + localTable[ 0 ].offset = pDxi->offsetAccum; + + /// \> Fill in the local lookup table for finding data. + /// - (Need to develop a table of offset pointers to load data into swing + /// buffers) \n + /// - (This is based on decimation factors and data size.) + for ( ii = 0; ii < dataInfo->numChans; ii++ ) { - jj = dataInfo->tp[ii].tpnum - daqRange->xExMin; - /* Mark as a non filter module testpoint */ - localTable[ii].type = DAQ_SRC_NFM_EXC; - /* Mark the offset into the local data buffer */ - localTable[ii].fmNum = jj; - localTable[ii].sigNum = jj; - } else { - // printf("Invalid chan num found %d = %d\n",ii,dataInfo->tp[ii].tpnum); - return (-1); + 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); + return ( -1 ); + } + else + { + /// - ---- Load decimation factor + localTable[ ii ].decFactor = + sysRate / ( dataInfo->tp[ ii ].dataRate / DAQ_NUM_DATA_BLOCKS ); + } + + /// - ---- Calc offset into swing buffer for writing data + mydatatype = dataInfo->tp[ ii ].dataType; + pDxi->offsetAccum += ( sysRate / localTable[ ii ].decFactor * + DAQ_DATA_TYPE_SIZE( mydatatype ) ); + + localTable[ ii + 1 ].offset = pDxi->offsetAccum; + /// - ---- Need to determine if data is from a filter module TP or + /// non-FM TP and tag accordingly + if ( ( dataInfo->tp[ ii ].tpnum >= daqRange->filtTpMin ) && + ( dataInfo->tp[ ii ].tpnum < daqRange->filtTpMax ) ) + /* This is a filter module testpoint */ + { + jj = dataInfo->tp[ ii ].tpnum - daqRange->filtTpMin; + /* Mark as coming from a filter module testpoint */ + localTable[ ii ].type = DAQ_SRC_FM_TP; + /* Mark which system filter module is in */ + localTable[ ii ].sysNum = jj / daqRange->filtTpSize; + jj -= localTable[ ii ].sysNum * daqRange->filtTpSize; + /* Mark which filter module within a system */ + localTable[ ii ].fmNum = jj / DAQ_NUM_FM_TP; + /* Mark which of three testpoints to store */ + localTable[ ii ].sigNum = jj % DAQ_NUM_FM_TP; + } + else if ( ( dataInfo->tp[ ii ].tpnum >= daqRange->filtExMin ) && + ( dataInfo->tp[ ii ].tpnum < daqRange->filtExMax ) ) + /* This is a filter module excitation input */ + { + /* Mark as coming from a filter module excitation input */ + localTable[ ii ].type = DAQ_SRC_FM_EXC; + /* Mark filter module number */ + localTable[ ii ].fmNum = + dataInfo->tp[ ii ].tpnum - daqRange->filtExMin; + } + else if ( ( dataInfo->tp[ ii ].tpnum >= daqRange->xTpMin ) && + ( dataInfo->tp[ ii ].tpnum < daqRange->xTpMax ) ) + /* This testpoint is not part of a filter module */ + { + jj = dataInfo->tp[ ii ].tpnum - daqRange->xTpMin; + /* Mark as a non filter module testpoint */ + localTable[ ii ].type = DAQ_SRC_NFM_TP; + /* Mark the offset into the local data buffer */ + localTable[ ii ].sigNum = jj; + } + else if ( ( dataInfo->tp[ ii ].tpnum >= daqRange->xExMin ) && + ( dataInfo->tp[ ii ].tpnum < daqRange->xExMax ) ) + /* This exc testpoint is not part of a filter module */ + { + jj = dataInfo->tp[ ii ].tpnum - daqRange->xExMin; + /* Mark as a non filter module testpoint */ + localTable[ ii ].type = DAQ_SRC_NFM_EXC; + /* Mark the offset into the local data buffer */ + localTable[ ii ].fmNum = jj; + localTable[ ii ].sigNum = jj; + } + else + { + // printf("Invalid chan num found %d = + // %d\n",ii,dataInfo->tp[ii].tpnum); + return ( -1 ); + } + // printf("Table %d Offset = %d Type = + // %d\n",ii,localTable[ii].offset,dataInfo->tp[ii].dataType); } - // printf("Table %d Offset = %d Type = - // %d\n",ii,localTable[ii].offset,dataInfo->tp[ii].dataType); - } - return (0); - /// \> RETURN 0=OK or -1=FAIL + return ( 0 ); + /// \> RETURN 0=OK or -1=FAIL } diff --git a/src/include/drv/daqLibZmq.c b/src/include/drv/daqLibZmq.c index 001c14ecb..2858a151c 100644 --- a/src/include/drv/daqLibZmq.c +++ b/src/include/drv/daqLibZmq.c @@ -1,342 +1,502 @@ -/*! \file daqLib.c +/*! \file daqLib.c * \brief File contains routines to support DAQ on realtime systems. \n * \author R.Bork, A. Ivanov -*/ - -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. -char *pEpicsIntData; ///< Pointer to EPICS integer type data in shared memory. -char *pEpicsDblData; ///< Pointer to EPICS double type data in shared memory. -unsigned int curDaqBlockSize; ///< Total DAQ data rate diag + */ + +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. +char* pEpicsIntData; ///< Pointer to EPICS integer type data in shared memory. +char* pEpicsDblData; ///< Pointer to EPICS double type data in shared memory. +unsigned int curDaqBlockSize; ///< Total DAQ data rate diag // Added to get EPICS data for RCG V2.8 -char *pEpicsInt; // Pointer to current DAQ data in shared memory. -char *pEpicsInt1; -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) { +char* pEpicsInt; // Pointer to current DAQ data in shared memory. +char* pEpicsInt1; +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 ) +{ double retVal; - char* p = (char*)&retVal; - char* i = (char*)∈ - p[0] = i[7]; - p[1] = i[6]; - p[2] = i[5]; - p[3] = i[4]; - - p[4] = i[3]; - p[5] = i[2]; - p[6] = i[1]; - p[7] = i[0]; + char* p = (char*)&retVal; + char* i = (char*)∈ + p[ 0 ] = i[ 7 ]; + p[ 1 ] = i[ 6 ]; + p[ 2 ] = i[ 5 ]; + p[ 3 ] = i[ 4 ]; + + p[ 4 ] = i[ 3 ]; + p[ 5 ] = i[ 2 ]; + p[ 6 ] = i[ 1 ]; + p[ 7 ] = i[ 0 ]; return retVal; } - - - - /* ******************************************************************** */ /* Routine to connect and write to LIGO DAQ system */ /* ******************************************************************** */ /// @author R.Bork, A. Ivanov\n -/// @brief This function provides for reading GDS TP/EXC and writing DAQ data. \n -/// @detail For additional information in LIGO DCC, see <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=8037">T0900638 CDS Real-time DAQ Software</a> -/// @param[in] flag Initialization flag (1=Init call, 0 = run) -/// @param[in] dcuId DAQ Data unit ID - unique within a control system -/// @param[in] daqRange Struct defining fron end valid test point and exc ranges. +/// @brief This function provides for reading GDS TP/EXC and writing DAQ +///data. \n +/// @detail For additional information in LIGO DCC, see <a +///href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=8037">T0900638 +///CDS Real-time DAQ Software</a> +/// @param[in] flag Initialization flag (1=Init call, 0 = +///run) +/// @param[in] dcuId DAQ Data unit ID - unique within a control +///system +/// @param[in] daqRange Struct defining fron end valid test point +///and exc ranges. /// @param[in] sysRate Data rate of the code / 16 -/// @param[in] *pFloatData[] Pointer to TP data not associated with filter modules. +/// @param[in] *pFloatData[] Pointer to TP data not associated with +///filter modules. /// @param[in] *dspPtr Pointer to array of filter module data. /// @param[in] netStatus Status of DAQ network -/// @param[out] gdsMonitor[] Array to return values of GDS TP/EXC selections. -/// @param[out] excSignals[] Array to write EXC signals not associated with filter modules. +/// @param[out] gdsMonitor[] Array to return values of GDS TP/EXC +///selections. +/// @param[out] excSignals[] Array to write EXC signals not associated +///with filter modules. /// @return Total size of data transmitted in KB/sec. -int daqWrite(int flag, - int dcuId, - DAQ_RANGE daqRange, - int sysRate, - double *pFloatData[], - FILT_MOD *dspPtr, - int netStatus, - int gdsMonitor[], - double excSignal[], - char *pEpics) +int +daqWrite( int flag, + int dcuId, + DAQ_RANGE daqRange, + int sysRate, + double* pFloatData[], + FILT_MOD* dspPtr, + int netStatus, + int gdsMonitor[], + double excSignal[], + char* pEpics ) { -int ii,jj,kk; /* Loop counters. */ -int status; /* Return value from called routines. */ -unsigned int mydatatype; -double dWord; /* Temp value for storage of DAQ values */ -static int daqBlockNum; /* 1-16, tracks DAQ cycle. */ -static int daqXmitBlockNum; /* 1-16, tracks shmem DAQ block to write to. */ -static int excBlockNum; /* 1-16, tracks EXC block to read from. */ -static int excDataSize; -static DAQ_XFER_INFO xferInfo; -static int xferDone; -static char *pDaqBuffer[DAQ_NUM_SWING_BUFFERS]; /* Pointers to local swing buffers. */ -static DAQ_LKUP_TABLE localTable[DCU_MAX_CHANNELS]; -static DAQ_LKUP_TABLE excTable[DCU_MAX_CHANNELS]; -static volatile char *pWriteBuffer; /* Ptr to swing buff to write data */ -static int phase; /* 0-1, switches swing buffers. */ -static int daqSlot; /* 0-sysRate, data slot to write data */ -static int excSlot; /* 0-sysRate, slot to read exc data */ -char *bufPtr; /* Ptr to data for crc calculation. */ -static unsigned int crcTest; /* Continuous calc of CRC. */ -static unsigned int crcSend; /* CRC sent to FB. */ -static DAQ_INFO_BLOCK dataInfo; /* Local DAQ config info buffer. */ -static int tpStart; /* Marks address of first TP data */ -static volatile GDS_CNTRL_BLOCK *gdsPtr; /* Ptr to shm to pass TP info to DAQ */ -static volatile char *exciteDataPtr; /* Ptr to EXC data in shmem. */ -static int validTp = 0; /* Number of valid GDS sigs selected. */ -static int validTpNet = 0; /* Number of valid GDS sigs selected. */ -static int validEx; /* EXC signal set status indicator. */ -static int tpNum[DAQ_GDS_MAX_TP_ALLOWED]; /* TP/EXC selects to send to FB. */ -static int tpNumNet[DAQ_GDS_MAX_TP_ALLOWED]; /* TP/EXC selects to send to FB. */ -static int totalChans; /* DAQ + TP + EXC chans selected. */ -int *statusPtr; -volatile float *dataPtr; /* Ptr to excitation chan data. */ -int exChanOffset; /* shmem offset to next EXC value. */ -int tpx; -static int buf_size; -int i; -int ltSlot; -unsigned int exc; -unsigned int tpn; -int slot; -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; + int ii, jj, kk; /* Loop counters. */ + int status; /* Return value from called routines. */ + unsigned int mydatatype; + double dWord; /* Temp value for storage of DAQ values */ + static int daqBlockNum; /* 1-16, tracks DAQ cycle. */ + static int + daqXmitBlockNum; /* 1-16, tracks shmem DAQ block to write to. */ + static int excBlockNum; /* 1-16, tracks EXC block to read from. */ + static int excDataSize; + static DAQ_XFER_INFO xferInfo; + static int xferDone; + static char* pDaqBuffer[ DAQ_NUM_SWING_BUFFERS ]; /* Pointers to local swing + buffers. */ + static DAQ_LKUP_TABLE localTable[ DCU_MAX_CHANNELS ]; + static DAQ_LKUP_TABLE excTable[ DCU_MAX_CHANNELS ]; + static volatile char* + pWriteBuffer; /* Ptr to swing buff to write data */ + static int phase; /* 0-1, switches swing buffers. */ + static int daqSlot; /* 0-sysRate, data slot to write data */ + static int excSlot; /* 0-sysRate, slot to read exc data */ + char* bufPtr; /* Ptr to data for crc calculation. */ + static unsigned int crcTest; /* Continuous calc of CRC. */ + static unsigned int crcSend; /* CRC sent to FB. */ + static DAQ_INFO_BLOCK dataInfo; /* Local DAQ config info buffer. */ + static int tpStart; /* Marks address of first TP data */ + static volatile GDS_CNTRL_BLOCK* + gdsPtr; /* Ptr to shm to pass TP info to DAQ */ + static volatile char* exciteDataPtr; /* Ptr to EXC data in shmem. */ + static int validTp = 0; /* Number of valid GDS sigs selected. */ + static int validTpNet = 0; /* Number of valid GDS sigs selected. */ + static int validEx; /* EXC signal set status indicator. */ + static int tpNum[ DAQ_GDS_MAX_TP_ALLOWED ]; /* TP/EXC selects to send to FB. + */ + static int tpNumNet[ DAQ_GDS_MAX_TP_ALLOWED ]; /* TP/EXC selects to send to + FB. */ + static int totalChans; /* DAQ + TP + EXC chans selected. */ + int* statusPtr; + volatile float* dataPtr; /* Ptr to excitation chan data. */ + int exChanOffset; /* shmem offset to next EXC value. */ + int tpx; + static int buf_size; + int i; + int ltSlot; + unsigned int exc; + unsigned int tpn; + int slot; + 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. -// dCOEFF 2x ************************************************************************* -static double dCoeff2x[13] = {0.02717257186578, - -0.1159055409088, -0.40753832312918, 2.66236735378793, 3.37073457156755, - -0.49505157452475, -1.10461941102831, 1.40184470311617, 1.79227686661261, - -0.74143396593712, -1.62740819248313, 0.72188475979666, 0.83591053325065}; - -// dCOEFF 4x ************************************************************************* -static double dCoeff4x[13] = {0.00426219526013, - 0.46640482430571, -0.10620935923005, 2.50932081620118, 2.93670663266542, - 0.43602772908265, -0.31016854747127, 0.75143527373544, 1.00523899718152, - 0.44571894955428, -0.47692045639835, 0.36664098129003, 0.4440015753374}; - -// dCOEFF 8x ************************************************************************* -static double dCoeff8x[13] = {0.00162185538923, - 0.73342532779703, -0.02862365091314, 1.44110125961504, 1.67905228090487, - 0.77657563380963, -0.08304311675394, 0.18851328163424, 0.32889453107067, - 0.83213081484618, -0.12573495191273, 0.0940911979108501, 0.13622543115194}; - -// dCOEFF 16x ************************************************************************* -static double dCoeff16x[13] = {0.00112590539483, - 0.86616831686611, -0.00753654634986012, 0.48586805026482, 0.61216318704885, - 0.90508101474565, -0.0215349711544799, 0.0149886842581499, 0.08837269835802, - 0.94631370100442, -0.0320417955561, 0.0141281606027401, 0.0357726640422202}; - -// dCOEFF 32x ************************************************************************* -static double dCoeff32x[13] = {0.00102945292275, - 0.93288074072411, -0.00194092797014001, 0.10751900551591, 0.17269733682166, - 0.9570539169953, -0.00548573773340011, -0.0149997987966302, 0.0224605464746699, - 0.98100244642901, -0.00807148639261013, -0.00189235941040011, 0.00903370776797985}; - -// dCOEFF 64x ************************************************************************* -static double dCoeff64x[13] = {0.00101894798776, - 0.96638168022541, -0.000492974627960052, 0.01147570619135, 0.04460105133798, - 0.97969775930388, -0.00138449271550001, -0.0132857101503898, 0.00563203783023014, - 0.99249184543014, -0.0020244997813601, -0.00322227927422025, 0.00226137551427974}; - -// dCOEFF 128x ************************************************************************* -static double dCoeff128x[13] = {0.00102359688929, - 0.98317523053482, -0.000124254191099959, -0.00545789721985002, 0.01124261805423, - 0.9901470788001, -0.000347773996469902, -0.00809690612593994, 0.00140824107749005, - 0.9967468102523, -0.000506888877139899, -0.00218112074794985, 0.000565180122610309}; - -// dCOEFF 256x ************************************************************************* -static double dCoeff256x[13] = {0.00102849104272, - 0.99158359864769, -3.11926170200039e-05, -0.00556878740432998, 0.00281642133096005, - 0.99514878857652, -8.7150981279982e-05, -0.00441208984599983, 0.000351970596200069, - 0.99849900371282, -0.000126813612729926, -0.00123294150072994, 0.000141241173720053}; + // BIQUAD Decimation filter coefficient definitions. + // dCOEFF 2x + // ************************************************************************* + static double dCoeff2x[ 13 ] = { 0.02717257186578, -0.1159055409088, + -0.40753832312918, 2.66236735378793, + 3.37073457156755, -0.49505157452475, + -1.10461941102831, 1.40184470311617, + 1.79227686661261, -0.74143396593712, + -1.62740819248313, 0.72188475979666, + 0.83591053325065 }; + + // dCOEFF 4x + // ************************************************************************* + static double dCoeff4x[ 13 ] = { + 0.00426219526013, 0.46640482430571, -0.10620935923005, 2.50932081620118, + 2.93670663266542, 0.43602772908265, -0.31016854747127, 0.75143527373544, + 1.00523899718152, 0.44571894955428, -0.47692045639835, 0.36664098129003, + 0.4440015753374 + }; + + // dCOEFF 8x + // ************************************************************************* + static double dCoeff8x[ 13 ] = { 0.00162185538923, 0.73342532779703, + -0.02862365091314, 1.44110125961504, + 1.67905228090487, 0.77657563380963, + -0.08304311675394, 0.18851328163424, + 0.32889453107067, 0.83213081484618, + -0.12573495191273, 0.0940911979108501, + 0.13622543115194 }; + + // dCOEFF 16x + // ************************************************************************* + static double dCoeff16x[ 13 ] = { 0.00112590539483, 0.86616831686611, + -0.00753654634986012, 0.48586805026482, + 0.61216318704885, 0.90508101474565, + -0.0215349711544799, 0.0149886842581499, + 0.08837269835802, 0.94631370100442, + -0.0320417955561, 0.0141281606027401, + 0.0357726640422202 }; + + // dCOEFF 32x + // ************************************************************************* + static double dCoeff32x[ 13 ] = { + 0.00102945292275, 0.93288074072411, -0.00194092797014001, + 0.10751900551591, 0.17269733682166, 0.9570539169953, + -0.00548573773340011, -0.0149997987966302, 0.0224605464746699, + 0.98100244642901, -0.00807148639261013, -0.00189235941040011, + 0.00903370776797985 + }; + + // dCOEFF 64x + // ************************************************************************* + static double dCoeff64x[ 13 ] = { + 0.00101894798776, 0.96638168022541, -0.000492974627960052, + 0.01147570619135, 0.04460105133798, 0.97969775930388, + -0.00138449271550001, -0.0132857101503898, 0.00563203783023014, + 0.99249184543014, -0.0020244997813601, -0.00322227927422025, + 0.00226137551427974 + }; + + // dCOEFF 128x + // ************************************************************************* + static double dCoeff128x[ 13 ] = { + 0.00102359688929, 0.98317523053482, -0.000124254191099959, + -0.00545789721985002, 0.01124261805423, 0.9901470788001, + -0.000347773996469902, -0.00809690612593994, 0.00140824107749005, + 0.9967468102523, -0.000506888877139899, -0.00218112074794985, + 0.000565180122610309 + }; + + // dCOEFF 256x + // ************************************************************************* + static double dCoeff256x[ 13 ] = { + 0.00102849104272, 0.99158359864769, -3.11926170200039e-05, + -0.00556878740432998, 0.00281642133096005, 0.99514878857652, + -8.7150981279982e-05, -0.00441208984599983, 0.000351970596200069, + 0.99849900371282, -0.000126813612729926, -0.00123294150072994, + 0.000141241173720053 + }; #else -// SOS Decimation filter coefficient definitions. -// dCOEFF 2x ************************************************************************* -static double dCoeff2x[13] = {0.02717257186578, - -0.8840944590912, 0.29163278222038, 1.77827289469673, 1, - -0.50494842547525, 0.60956783650356, 0.89689627764092, 1, - -0.25856603406288, 0.88597422654601, 0.46331872573378, 1}; - -// dCOEFF 4x ************************************************************************* -static double dCoeff4x[13] = {0.00426219526013, - -1.46640482430571, 0.57261418353576, 1.04291599189547, 1, - -1.43602772908265, 0.74619627655392, -0.68459245534721, 1, - -1.44571894955428, 0.92263940595263, -1.07907796826425, 1}; - -// dCOEFF 8x ************************************************************************* -static double dCoeff8x[13] = {0.00162185538923, - -1.73342532779703, 0.76204897871017, -0.29232406818199, 1, - -1.77657563380963, 0.85961875056357, -1.58806235217539, 1, - -1.83213081484618, 0.95786576675891, -1.73803961693533, 1}; - -// dCOEFF 16x ************************************************************************* -static double dCoeff16x[13] = {0.00112590539483, - -1.86616831686611, 0.87370486321597, -1.38030026660129, 1, - -1.90508101474565, 0.92661598590013, -1.8900923304875, 1, - -1.94631370100442, 0.97835549656052, -1.93218554040168, 1}; - -// dCOEFF 32x ************************************************************************* -static double dCoeff32x[13] = {0.00102945292275, - -1.93288074072411, 0.93482166869425, -1.8253617352082, 1, - -1.9570539169953, 0.9625396547287, -1.97205371579193, 1, - -1.98100244642901, 0.98907393282162, -1.98289480583941, 1}; - -// dCOEFF 64x ************************************************************************* -static double dCoeff64x[13] = {0.00101894798776, - -1.96638168022541, 0.96687465485337, -1.95490597403406, 1, - -1.97969775930388, 0.98108225201938, -1.99298346945427, 1, - -1.99249184543014, 0.9945163452115, -1.99571412470436, 1}; - -// dCOEFF 128x ************************************************************************* -static double dCoeff128x[13] = {0.00102359688929, - -1.98317523053482, 0.98329948472592, -1.98863312775467, 1, - -1.9901470788001, 0.99049485279657, -1.99824398492604, 1, - -1.9967468102523, 0.99725369912944, -1.99892793100025, 1}; - -// dCOEFF 256x ************************************************************************* -static double dCoeff256x[13] = {0.00102849104272, - -1.99158359864769, 0.99161479126471, -1.99715238605202, 1, - -1.99514878857652, 0.9952359395578, -1.99956087842252, 1, - -1.99849900371282, 0.99862581732555, -1.99973194521355, 1}; + // SOS Decimation filter coefficient definitions. + // dCOEFF 2x + // ************************************************************************* + static double dCoeff2x[ 13 ] = { 0.02717257186578, + -0.8840944590912, + 0.29163278222038, + 1.77827289469673, + 1, + -0.50494842547525, + 0.60956783650356, + 0.89689627764092, + 1, + -0.25856603406288, + 0.88597422654601, + 0.46331872573378, + 1 }; + + // dCOEFF 4x + // ************************************************************************* + static double dCoeff4x[ 13 ] = { 0.00426219526013, + -1.46640482430571, + 0.57261418353576, + 1.04291599189547, + 1, + -1.43602772908265, + 0.74619627655392, + -0.68459245534721, + 1, + -1.44571894955428, + 0.92263940595263, + -1.07907796826425, + 1 }; + + // dCOEFF 8x + // ************************************************************************* + static double dCoeff8x[ 13 ] = { 0.00162185538923, + -1.73342532779703, + 0.76204897871017, + -0.29232406818199, + 1, + -1.77657563380963, + 0.85961875056357, + -1.58806235217539, + 1, + -1.83213081484618, + 0.95786576675891, + -1.73803961693533, + 1 }; + + // dCOEFF 16x + // ************************************************************************* + static double dCoeff16x[ 13 ] = { 0.00112590539483, + -1.86616831686611, + 0.87370486321597, + -1.38030026660129, + 1, + -1.90508101474565, + 0.92661598590013, + -1.8900923304875, + 1, + -1.94631370100442, + 0.97835549656052, + -1.93218554040168, + 1 }; + + // dCOEFF 32x + // ************************************************************************* + static double dCoeff32x[ 13 ] = { 0.00102945292275, + -1.93288074072411, + 0.93482166869425, + -1.8253617352082, + 1, + -1.9570539169953, + 0.9625396547287, + -1.97205371579193, + 1, + -1.98100244642901, + 0.98907393282162, + -1.98289480583941, + 1 }; + + // dCOEFF 64x + // ************************************************************************* + static double dCoeff64x[ 13 ] = { 0.00101894798776, + -1.96638168022541, + 0.96687465485337, + -1.95490597403406, + 1, + -1.97969775930388, + 0.98108225201938, + -1.99298346945427, + 1, + -1.99249184543014, + 0.9945163452115, + -1.99571412470436, + 1 }; + + // dCOEFF 128x + // ************************************************************************* + static double dCoeff128x[ 13 ] = { 0.00102359688929, + -1.98317523053482, + 0.98329948472592, + -1.98863312775467, + 1, + -1.9901470788001, + 0.99049485279657, + -1.99824398492604, + 1, + -1.9967468102523, + 0.99725369912944, + -1.99892793100025, + 1 }; + + // dCOEFF 256x + // ************************************************************************* + static double dCoeff256x[ 13 ] = { 0.00102849104272, + -1.99158359864769, + 0.99161479126471, + -1.99715238605202, + 1, + -1.99514878857652, + 0.9952359395578, + -1.99956087842252, + 1, + -1.99849900371282, + 0.99862581732555, + -1.99973194521355, + 1 }; #endif -// History buffers for decimation IIR filters -static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY]; - - - - -// ************************************************************************************** -/// If flag input is 1, then this is a startup initialization request from controller code. - if(flag == DAQ_CONNECT) /* Initialize DAQ connection */ - { - - /* First block to write out is last from previous second */ - phase = 0; - daqBlockNum = (DAQ_NUM_DATA_BLOCKS - 1); - daqXmitBlockNum = 0; - excBlockNum = 0; - - /// ** INITIALIZATION **************\n - daqSlot = -1; - excSlot = 0; - - /// \> CDS standard IIR filters will be used for decimation filtering from - /// the native application rate down to DAQ sample rate. \n - /// \>\> Need to clear the decimation filter histories. - for(ii=0;ii<DCU_MAX_CHANNELS;ii++) - for(jj=0;jj<MAX_HISTRY;jj++) - dHistory[ii][jj] = 0.0; - - /// \> Setup Pointers to the various shared memories:\n - /// ---- Assign Ptr to data shared memory to network driver (mx_stream) \n - daqShmPtr = _daq_shm + CDS_DAQ_NET_DATA_OFFSET; - buf_size = DAQ_DCU_BLOCK_SIZE*2; - pWriteBuffer = (volatile char *)daqShmPtr; - 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 - gdsPtr = (GDS_CNTRL_BLOCK *)(_epics_shm + DAQ_GDS_BLOCK_ADD); - // Set pointer to EXC data in shmem. - if(sysRate < DAQ_16K_SAMPLE_SIZE) - { - exciteDataPtr = (char *)(_epics_shm + DATA_OFFSET_DCU(DCU_ID_EX_2K)); - } - else { - exciteDataPtr = (char *)(_epics_shm + DATA_OFFSET_DCU(DCU_ID_EX_16K)); - } - excDataSize = 4 + 4 * sysRate; - + // History buffers for decimation IIR filters + static double dHistory[ DCU_MAX_CHANNELS ][ MAX_HISTRY ]; - // Clear the reconfiguration flag in shmem. - pInfo->reconfig = 0; - - // Configure data channels ***************************************************** - // Return error if configuration is incorrect. - /// \> Load DAQ configuration info from memory shared with EPICS - if((xferInfo.crcLength = daqConfig(&dataInfo,pInfo,pEpics)) == -1) return(-1); - - /// \> 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; - - /// \> Clear out the GDS TP selections. - if (sysRate < DAQ_16K_SAMPLE_SIZE) tpx = 3; else tpx = 2; - for (ii=0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++) gdsPtr->tp[tpx][0][ii] = 0; - if(sysRate < DAQ_16K_SAMPLE_SIZE) tpx = 1; else tpx = 0; - for (ii=0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++) gdsPtr->tp[tpx][0][ii] = 0; + // ************************************************************************************** + /// If flag input is 1, then this is a startup initialization request from + /// controller code. + if ( flag == DAQ_CONNECT ) /* Initialize DAQ connection */ + { - /// \> Clear the GDS TP lookup table - for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) { - tpNum[i] = 0; - tpNumNet[i] = 0; - } - validTp = 0; - validTpNet = 0; - - //printf("at connect TPnum[0]=%d\n", tpNum[0]); - } /// End DAQ CONNECT INITIALIZATION ****************************** - -/* ******************************************************************************** */ -/* Write Data to FB ******************************************* */ -/* ******************************************************************************** */ -/// If flag=0, data is to be acquired. This is called every code cycle by controller.c -/// ** Data Acquisition Mode ******************************************************** - if(flag == DAQ_WRITE) - { - /// \> Calc data offset into current write swing buffer - daqSlot = (daqSlot + 1) % sysRate; - gdsOffset = (float *) gdsDataPtr;; - gdsOffset += daqSlot; + /* First block to write out is last from previous second */ + phase = 0; + daqBlockNum = ( DAQ_NUM_DATA_BLOCKS - 1 ); + daqXmitBlockNum = 0; + excBlockNum = 0; + + /// ** INITIALIZATION **************\n + daqSlot = -1; + excSlot = 0; + + /// \> CDS standard IIR filters will be used for decimation + ///filtering from + /// the native application rate down to DAQ sample rate. \n + /// \>\> Need to clear the decimation filter histories. + for ( ii = 0; ii < DCU_MAX_CHANNELS; ii++ ) + for ( jj = 0; jj < MAX_HISTRY; jj++ ) + dHistory[ ii ][ jj ] = 0.0; + + /// \> Setup Pointers to the various shared memories:\n + /// ---- Assign Ptr to data shared memory to network driver (mx_stream) + /// \n + daqShmPtr = _daq_shm + CDS_DAQ_NET_DATA_OFFSET; + buf_size = DAQ_DCU_BLOCK_SIZE * 2; + pWriteBuffer = (volatile char*)daqShmPtr; + 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 + gdsPtr = (GDS_CNTRL_BLOCK*)( _epics_shm + DAQ_GDS_BLOCK_ADD ); + // Set pointer to EXC data in shmem. + if ( sysRate < DAQ_16K_SAMPLE_SIZE ) + { + exciteDataPtr = + (char*)( _epics_shm + DATA_OFFSET_DCU( DCU_ID_EX_2K ) ); + } + else + { + exciteDataPtr = + (char*)( _epics_shm + DATA_OFFSET_DCU( DCU_ID_EX_16K ) ); + } + excDataSize = 4 + 4 * sysRate; + + // Clear the reconfiguration flag in shmem. + pInfo->reconfig = 0; + + // Configure data channels + // ***************************************************** Return error if + // configuration is incorrect. + /// \> Load DAQ configuration info from memory shared with EPICS + if ( ( xferInfo.crcLength = daqConfig( &dataInfo, pInfo, pEpics ) ) == + -1 ) + return ( -1 ); + + /// \> 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; + + /// \> Clear out the GDS TP selections. + if ( sysRate < DAQ_16K_SAMPLE_SIZE ) + tpx = 3; + else + tpx = 2; + for ( ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++ ) + gdsPtr->tp[ tpx ][ 0 ][ ii ] = 0; + if ( sysRate < DAQ_16K_SAMPLE_SIZE ) + tpx = 1; + else + tpx = 0; + for ( ii = 0; ii < DAQ_GDS_MAX_TP_ALLOWED; ii++ ) + gdsPtr->tp[ tpx ][ 0 ][ ii ] = 0; + + /// \> Clear the GDS TP lookup table + for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ ) + { + tpNum[ i ] = 0; + tpNumNet[ i ] = 0; + } + validTp = 0; + validTpNet = 0; + + // printf("at connect TPnum[0]=%d\n", tpNum[0]); + } /// End DAQ CONNECT INITIALIZATION ****************************** + + /* ******************************************************************************** + */ + /* Write Data to FB ******************************************* + */ + /* ******************************************************************************** + */ + /// If flag=0, data is to be acquired. This is called every code cycle by + /// controller.c + /// ** Data Acquisition Mode + /// ******************************************************** + if ( flag == DAQ_WRITE ) + { + /// \> 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 */ @@ -357,547 +517,695 @@ static double dHistory[DCU_MAX_CHANNELS][MAX_HISTRY]; } #endif - - /// \> Write data into local swing buffer - for(ii=0;ii<totalChans;ii++) - { - - 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 */ - { - switch(localTable[ii].sigNum) - { - case 0: - dWord = dspPtr->data[localTable[ii].fmNum].filterInput; - break; - case 1: - dWord = dspPtr->data[localTable[ii].fmNum].inputTestpoint; - break; - case 2: - dWord = dspPtr->data[localTable[ii].fmNum].testpoint; - break; - default: - dWord = 0.0; - break; - } - } - else if(localTable[ii].type == DAQ_SRC_NFM_TP) - /* Data is from non filter module testpoint */ - { - dWord = *(pFloatData[localTable[ii].sigNum]); - } - else if(localTable[ii].type == DAQ_SRC_FM_EXC) - /* Data is from filter module excitation */ - { - dWord = dspPtr->data[localTable[ii].fmNum].exciteInput; - } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) { - // Extra excitation - dWord = excSignal[localTable[ii].fmNum]; - } - - /// \> Perform decimation filtering, if required. + /// \> Write data into local swing buffer + for ( ii = 0; ii < totalChans; ii++ ) + { + + 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 */ + { + switch ( localTable[ ii ].sigNum ) + { + case 0: + dWord = dspPtr->data[ localTable[ ii ].fmNum ].filterInput; + break; + case 1: + dWord = + dspPtr->data[ localTable[ ii ].fmNum ].inputTestpoint; + break; + case 2: + dWord = dspPtr->data[ localTable[ ii ].fmNum ].testpoint; + break; + default: + dWord = 0.0; + break; + } + } + else if ( localTable[ ii ].type == DAQ_SRC_NFM_TP ) + /* Data is from non filter module testpoint */ + { + dWord = *( pFloatData[ localTable[ ii ].sigNum ] ); + } + else if ( localTable[ ii ].type == DAQ_SRC_FM_EXC ) + /* Data is from filter module excitation */ + { + dWord = dspPtr->data[ localTable[ ii ].fmNum ].exciteInput; + } + else if ( localTable[ ii ].type == DAQ_SRC_NFM_EXC ) + { + // Extra excitation + dWord = excSignal[ localTable[ ii ].fmNum ]; + } + + /// \> Perform decimation filtering, if required. #ifdef CORE_BIQUAD #define iir_filter iir_filter_biquad #endif - if(dataInfo.tp[ii].dataType != DAQ_DATATYPE_32BIT_UINT) - { - if(localTable[ii].decFactor == 2) dWord = iir_filter(dWord,&dCoeff2x[0],DTAPS,&dHistory[ii][0]); - if(localTable[ii].decFactor == 4) dWord = iir_filter(dWord,&dCoeff4x[0],DTAPS,&dHistory[ii][0]); - if(localTable[ii].decFactor == 8) dWord = iir_filter(dWord,&dCoeff8x[0],DTAPS,&dHistory[ii][0]); - if(localTable[ii].decFactor == 16) dWord = iir_filter(dWord,&dCoeff16x[0],DTAPS,&dHistory[ii][0]); - if(localTable[ii].decFactor == 32) dWord = iir_filter(dWord,&dCoeff32x[0],DTAPS,&dHistory[ii][0]); - if(localTable[ii].decFactor == 64) dWord = iir_filter(dWord,&dCoeff64x[0],DTAPS,&dHistory[ii][0]); - if(localTable[ii].decFactor == 128) dWord = iir_filter(dWord,&dCoeff128x[0],DTAPS,&dHistory[ii][0]); - if(localTable[ii].decFactor == 256) dWord = iir_filter(dWord,&dCoeff256x[0],DTAPS,&dHistory[ii][0]); - } + if ( dataInfo.tp[ ii ].dataType != DAQ_DATATYPE_32BIT_UINT ) + { + if ( localTable[ ii ].decFactor == 2 ) + dWord = iir_filter( + dWord, &dCoeff2x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 4 ) + dWord = iir_filter( + dWord, &dCoeff4x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 8 ) + dWord = iir_filter( + dWord, &dCoeff8x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 16 ) + dWord = iir_filter( + dWord, &dCoeff16x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 32 ) + dWord = iir_filter( + dWord, &dCoeff32x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 64 ) + dWord = iir_filter( + dWord, &dCoeff64x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 128 ) + dWord = iir_filter( + dWord, &dCoeff128x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + if ( localTable[ ii ].decFactor == 256 ) + dWord = iir_filter( + dWord, &dCoeff256x[ 0 ], DTAPS, &dHistory[ ii ][ 0 ] ); + } #ifdef CORE_BIQUAD #undef iir_filter #endif - /// \> Write fast data into the swing buffer. - if ((daqSlot % localTable[ii].decFactor) == 0) { - mydatatype = dataInfo.tp[ii].dataType; - switch(mydatatype) { - case DAQ_DATATYPE_16BIT_INT: - // Write short data; (XOR 1) here provides sample swapping - ((short *)(pWriteBuffer + localTable[ii].offset))[(daqSlot/localTable[ii].decFactor)^1] = (short)dWord; - break; - case DAQ_DATATYPE_DOUBLE: - ((double *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor] = dWord; - break; - case DAQ_DATATYPE_32BIT_UINT: - // Write a 32-bit int (downcast from the double passed) - if (localTable[ii].decFactor == 1) - ((unsigned int *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor] = ((unsigned int)dWord); - else - ((unsigned int *)(pWriteBuffer + localTable[ii].offset))[daqSlot/localTable[ii].decFactor] - = ((unsigned int)dWord) & *((unsigned int *)(dHistory[ii])); - break; - case DAQ_DATATYPE_32BIT_INT: - ((int *)(pWriteBuffer + localTable[ii].offset))[daqSlot] = (int)dWord; - break; - default: - // Write a 32-bit float (downcast from the double passed) - 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) { - if ((daqSlot % localTable[ii].decFactor) == 1) - *((unsigned int *)(dHistory[ii])) = (unsigned int)dWord; - else - *((unsigned int *)(dHistory[ii])) &= (unsigned int)dWord; - } - } /* end swing buffer write loop */ - -/// \> Write EPICS data into swing buffer at 16Hz. -if(daqSlot == DAQ_XFER_CYCLE_INT) -{ -/// \>\> On 16Hz boundary: \n -/// - ---- Write EPICS integer values to beginning of local write buffer - - if(dataInfo.cpyepics2times) - { - memcpy(pWriteBuffer,pEpicsIntData,dataInfo.cpyIntSize[0]); - pEpicsInt = pWriteBuffer; - pEpicsInt += dataInfo.cpyIntSize[0]; - pEpicsInt1 = pEpicsIntData + dataInfo.cpyIntSize[0] + 4; - memcpy(pEpicsInt,pEpicsInt1,dataInfo.cpyIntSize[1]); - } else { - memcpy(pWriteBuffer,pEpicsIntData,dataInfo.cpyIntSize[0]); - } - -} -if(daqSlot == DAQ_XFER_CYCLE_DBL) -{ -/// - ---- Write EPICS double values as float values after EPICS integer type data. - pEpicsDblData1 = (double *)pEpicsDblData; - pEpicsFloat = (float *)pWriteBuffer; - pEpicsFloat += dataInfo.numEpicsInts; - for(ii=0;ii<dataInfo.numEpicsFloats;ii++) - { - *pEpicsFloat = (float)*pEpicsDblData1; - pEpicsFloat ++; - pEpicsDblData1 ++; - } -} -if((daqSlot >= DAQ_XFER_CYCLE_FMD) && (daqSlot < dataInfo.numEpicsFiltXfers)) -{ -/// \>\> On 16Hz boundary + 1 (or more) cycle(s): \n -/// - ---- Write filter module EPICS values as floats - jj = DAQ_XFER_FMD_PER_CYCLE * (daqSlot - DAQ_XFER_CYCLE_FMD); - if(daqSlot == (dataInfo.numEpicsFiltXfers - 1)) - { - kk = jj + dataInfo.numEpicsFiltsLast; - } else { - kk = jj + DAQ_XFER_FMD_PER_CYCLE; - } - // printf("Cycle = %d jj = %d kk = %d\n",daqSlot,jj,kk); - for(ii=jj;ii<kk;ii++) - { - *pEpicsFloat = (float)dspPtr->inputs[ii].offset; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->inputs[ii].outgain;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->inputs[ii].limiter;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->inputs[ii].gain_ramp_time;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->inputs[ii].swReq;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->inputs[ii].swMask;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->data[ii].filterInput;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->data[ii].exciteInput;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->data[ii].output16Hz;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->data[ii].output;; - pEpicsFloat ++; - *pEpicsFloat = (float)dspPtr->data[ii].swStatus;; - pEpicsFloat ++; - } -} - - - /// \> Read in any selected EXC signals. \n - /// --- NOTE: EXC signals have to be read and loaded in advance by 1 cycle ie must be loaded and - /// available to the realtime application when the next code cycle is initiated. - excSlot = (excSlot + 1) % sysRate; - //if(validEx) - validEx = 0; - { - // Go through all test points - for(ii=dataInfo.numChans;ii<totalChans;ii++) - { - // Do not pickup any testpoints (type 0 or 1) - if (localTable[ii].type < DAQ_SRC_FM_EXC) continue; - - exChanOffset = localTable[ii].sigNum * excDataSize; - statusPtr = (int *)(exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + exChanOffset); - if(*statusPtr == 0) - { - validEx = FE_ERROR_EXC_SET; - dataPtr = (float *)(exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + exChanOffset + - excSlot * 4 + 4); - if(localTable[ii].type == DAQ_SRC_FM_EXC) - { - dspPtr->data[localTable[ii].fmNum].exciteInput = *dataPtr; - } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) { - // extra excitation - excSignal[localTable[ii].fmNum] = *dataPtr; - } - } - // else dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0; - else { - if(localTable[ii].type == DAQ_SRC_FM_EXC) - { - dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0; - } else if (localTable[ii].type == DAQ_SRC_NFM_EXC) { - // extra excitation - excSignal[localTable[ii].fmNum] = 0.0; - } - } - } - } - - /// \> Move to the next 1/16 EXC signal data block if end of 16Hz block - if(excSlot == (sysRate - 1)) excBlockNum = (excBlockNum + 1) % DAQ_NUM_DATA_BLOCKS; - - /// \> If last cycle of a 16Hz block: - if(daqSlot == (sysRate - 1)) - /* Done with 1/16 second DAQ data block */ - { - - /// - -- Fill in the IPC table for DAQ network driver (mx_stream) \n - dipc->dcuId = dcuId; /// - ------ DCU id of this system - dipc->crc = xferInfo.fileCrc; /// - ------ Checksum of the configuration file - dipc->dataBlockSize = xferInfo.totalSizeNet; /// - ------ Actual data size - /// - ------ Data block number - dipc->bp[daqXmitBlockNum].cycle = daqXmitBlockNum; - /// - ------ Data block CRC - dipc->bp[daqXmitBlockNum].crc = xferInfo.crcLength; - /// - ------ Timestamp GPS Second - dipc->bp[daqXmitBlockNum].timeSec = (unsigned int) cycle_gps_time; - /// - ------ Timestamp GPS nanoSecond - Actually cycle number - dipc->bp[daqXmitBlockNum].timeNSec = (unsigned int)daqXmitBlockNum; - - /// - ------ Write test point info to DAQ net shared memory - tpPtr->count = validTpNet | validEx; - memcpy(tpPtr->tpNum, tpNumNet, sizeof(tpNumNet[0]) * validTp); - - // As the last step set the cycle counter - // 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; - daqXmitBlockNum = (daqXmitBlockNum + 1) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; - - /// - -- Set data write ptr to next block in shmem - 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)) - { - printf("New daq config\n"); - pInfo->reconfig = 0; - // Configure EPICS data channels - xferInfo.crcLength = daqConfig(&dataInfo,pInfo,pEpics); - if(xferInfo.crcLength) - { - status = loadLocalTable(&xferInfo,localTable,sysRate,&dataInfo,&daqRange); - // Clear decimation filter history - for(ii=0;ii<dataInfo.numChans;ii++) - { - for(jj=0;jj<MAX_HISTRY;jj++) dHistory[ii][jj] = 0.0; - } - - tpStart = xferInfo.offsetAccum; - 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. - - if(daqBlockNum == 15) - { - // Offset by one into the TP/EXC tables for the 2K systems - unsigned int _2k_sys_offs = sysRate < DAQ_16K_SAMPLE_SIZE; - - // Helper function to search the lists - // Clears the found number from the lists - // tpnum and excnum lists of numbers do not intersect - inline int in_the_lists(unsigned int tp, unsigned int slot) { - int i; - for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++){ - if (tpnum[i] == tp) return (tpnum[i] = 0, 1); - if (excnum[i] == tp) { - // Check if the excitation is still in the same slot - if (i != excTable[slot].offset) return 0; - return (excnum[i] = 0, 1); + /// \> Write fast data into the swing buffer. + if ( ( daqSlot % localTable[ ii ].decFactor ) == 0 ) + { + mydatatype = dataInfo.tp[ ii ].dataType; + switch ( mydatatype ) + { + case DAQ_DATATYPE_16BIT_INT: + // Write short data; (XOR 1) here provides sample swapping + ( (short*)( pWriteBuffer + localTable[ ii ].offset ) ) + [ ( daqSlot / localTable[ ii ].decFactor ) ^ 1 ] = + (short)dWord; + break; + case DAQ_DATATYPE_DOUBLE: + ( (double*)( pWriteBuffer + localTable[ ii ].offset ) ) + [ daqSlot / localTable[ ii ].decFactor ] = dWord; + break; + case DAQ_DATATYPE_32BIT_UINT: + // Write a 32-bit int (downcast from the double passed) + if ( localTable[ ii ].decFactor == 1 ) + ( (unsigned int*)( pWriteBuffer + + localTable[ ii ].offset ) ) + [ daqSlot / localTable[ ii ].decFactor ] = + ( (unsigned int)dWord ); + else + ( (unsigned int*)( pWriteBuffer + + localTable[ ii ].offset ) ) + [ daqSlot / localTable[ ii ].decFactor ] = + ( (unsigned int)dWord ) & + *( (unsigned int*)( dHistory[ ii ] ) ); + break; + case DAQ_DATATYPE_32BIT_INT: + ( (int*)( pWriteBuffer + + localTable[ ii ].offset ) )[ daqSlot ] = + (int)dWord; + break; + default: + // Write a 32-bit float (downcast from the double passed) + 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 ) + { + if ( ( daqSlot % localTable[ ii ].decFactor ) == 1 ) + *( (unsigned int*)( dHistory[ ii ] ) ) = + (unsigned int)dWord; + else + *( (unsigned int*)( dHistory[ ii ] ) ) &= + (unsigned int)dWord; + } + } /* end swing buffer write loop */ + + /// \> Write EPICS data into swing buffer at 16Hz. + if ( daqSlot == DAQ_XFER_CYCLE_INT ) + { + /// \>\> On 16Hz boundary: \n + /// - ---- Write EPICS integer values to beginning of local write + /// buffer + + if ( dataInfo.cpyepics2times ) + { + memcpy( pWriteBuffer, pEpicsIntData, dataInfo.cpyIntSize[ 0 ] ); + pEpicsInt = pWriteBuffer; + pEpicsInt += dataInfo.cpyIntSize[ 0 ]; + pEpicsInt1 = pEpicsIntData + dataInfo.cpyIntSize[ 0 ] + 4; + memcpy( pEpicsInt, pEpicsInt1, dataInfo.cpyIntSize[ 1 ] ); + } + else + { + memcpy( pWriteBuffer, pEpicsIntData, dataInfo.cpyIntSize[ 0 ] ); + } + } + if ( daqSlot == DAQ_XFER_CYCLE_DBL ) + { + /// - ---- Write EPICS double values as float values after EPICS + /// integer type data. + pEpicsDblData1 = (double*)pEpicsDblData; + pEpicsFloat = (float*)pWriteBuffer; + pEpicsFloat += dataInfo.numEpicsInts; + for ( ii = 0; ii < dataInfo.numEpicsFloats; ii++ ) + { + *pEpicsFloat = (float)*pEpicsDblData1; + pEpicsFloat++; + pEpicsDblData1++; + } + } + if ( ( daqSlot >= DAQ_XFER_CYCLE_FMD ) && + ( daqSlot < dataInfo.numEpicsFiltXfers ) ) + { + /// \>\> On 16Hz boundary + 1 (or more) cycle(s): \n + /// - ---- Write filter module EPICS values as floats + jj = DAQ_XFER_FMD_PER_CYCLE * ( daqSlot - DAQ_XFER_CYCLE_FMD ); + if ( daqSlot == ( dataInfo.numEpicsFiltXfers - 1 ) ) + { + kk = jj + dataInfo.numEpicsFiltsLast; + } + else + { + kk = jj + DAQ_XFER_FMD_PER_CYCLE; + } + // printf("Cycle = %d jj = %d kk = %d\n",daqSlot,jj,kk); + for ( ii = jj; ii < kk; ii++ ) + { + *pEpicsFloat = (float)dspPtr->inputs[ ii ].offset; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].outgain; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].limiter; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].gain_ramp_time; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].swReq; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->inputs[ ii ].swMask; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].filterInput; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].exciteInput; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].output16Hz; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].output; + ; + pEpicsFloat++; + *pEpicsFloat = (float)dspPtr->data[ ii ].swStatus; + ; + pEpicsFloat++; + } + } + + /// \> Read in any selected EXC signals. \n + /// --- NOTE: EXC signals have to be read and loaded in advance by 1 + /// cycle ie must be loaded and available to the realtime application + /// when the next code cycle is initiated. + excSlot = ( excSlot + 1 ) % sysRate; + // if(validEx) + validEx = 0; + { + // Go through all test points + for ( ii = dataInfo.numChans; ii < totalChans; ii++ ) + { + // Do not pickup any testpoints (type 0 or 1) + if ( localTable[ ii ].type < DAQ_SRC_FM_EXC ) + continue; + + exChanOffset = localTable[ ii ].sigNum * excDataSize; + statusPtr = + (int*)( exciteDataPtr + excBlockNum * DAQ_DCU_BLOCK_SIZE + + exChanOffset ); + if ( *statusPtr == 0 ) + { + validEx = FE_ERROR_EXC_SET; + dataPtr = (float*)( exciteDataPtr + + excBlockNum * DAQ_DCU_BLOCK_SIZE + + exChanOffset + excSlot * 4 + 4 ); + if ( localTable[ ii ].type == DAQ_SRC_FM_EXC ) + { + dspPtr->data[ localTable[ ii ].fmNum ].exciteInput = + *dataPtr; + } + else if ( localTable[ ii ].type == DAQ_SRC_NFM_EXC ) + { + // extra excitation + excSignal[ localTable[ ii ].fmNum ] = *dataPtr; + } + } + // else dspPtr->data[localTable[ii].fmNum].exciteInput = 0.0; + else + { + if ( localTable[ ii ].type == DAQ_SRC_FM_EXC ) + { + dspPtr->data[ localTable[ ii ].fmNum ].exciteInput = + 0.0; + } + else if ( localTable[ ii ].type == DAQ_SRC_NFM_EXC ) + { + // extra excitation + excSignal[ localTable[ ii ].fmNum ] = 0.0; + } + } + } + } + + /// \> Move to the next 1/16 EXC signal data block if end of 16Hz block + if ( excSlot == ( sysRate - 1 ) ) + excBlockNum = ( excBlockNum + 1 ) % DAQ_NUM_DATA_BLOCKS; + + /// \> If last cycle of a 16Hz block: + if ( daqSlot == ( sysRate - 1 ) ) + /* Done with 1/16 second DAQ data block */ + { + + /// - -- Fill in the IPC table for DAQ network driver (mx_stream) \n + dipc->dcuId = dcuId; /// - ------ DCU id of this system + dipc->crc = + xferInfo + .fileCrc; /// - ------ Checksum of the configuration file + dipc->dataBlockSize = + xferInfo.totalSizeNet; /// - ------ Actual data size + /// - ------ Data block number + dipc->bp[ daqXmitBlockNum ].cycle = daqXmitBlockNum; + /// - ------ Data block CRC + dipc->bp[ daqXmitBlockNum ].crc = xferInfo.crcLength; + /// - ------ Timestamp GPS Second + dipc->bp[ daqXmitBlockNum ].timeSec = (unsigned int)cycle_gps_time; + /// - ------ Timestamp GPS nanoSecond - Actually cycle number + dipc->bp[ daqXmitBlockNum ].timeNSec = + (unsigned int)daqXmitBlockNum; + + /// - ------ Write test point info to DAQ net shared memory + tpPtr->count = validTpNet | validEx; + memcpy( tpPtr->tpNum, tpNumNet, sizeof( tpNumNet[ 0 ] ) * validTp ); + + // As the last step set the cycle counter + // 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; + daqXmitBlockNum = + ( daqXmitBlockNum + 1 ) % DAQ_NUM_DATA_BLOCKS_PER_SECOND; + + /// - -- Set data write ptr to next block in shmem + 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 ) ) + { + printf( "New daq config\n" ); + pInfo->reconfig = 0; + // Configure EPICS data channels + xferInfo.crcLength = daqConfig( &dataInfo, pInfo, pEpics ); + if ( xferInfo.crcLength ) + { + status = loadLocalTable( + &xferInfo, localTable, sysRate, &dataInfo, &daqRange ); + // Clear decimation filter history + for ( ii = 0; ii < dataInfo.numChans; ii++ ) + { + for ( jj = 0; jj < MAX_HISTRY; jj++ ) + dHistory[ ii ][ jj ] = 0.0; + } + + tpStart = xferInfo.offsetAccum; + 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. + + if ( daqBlockNum == 15 ) + { + // Offset by one into the TP/EXC tables for the 2K systems + unsigned int _2k_sys_offs = sysRate < DAQ_16K_SAMPLE_SIZE; + + // Helper function to search the lists + // Clears the found number from the lists + // tpnum and excnum lists of numbers do not intersect + inline int in_the_lists( unsigned int tp, unsigned int slot ) + { + int i; + for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ ) + { + if ( tpnum[ i ] == tp ) + return ( tpnum[ i ] = 0, 1 ); + if ( excnum[ i ] == tp ) + { + // Check if the excitation is still in the same slot + if ( i != excTable[ slot ].offset ) + return 0; + return ( excnum[ i ] = 0, 1 ); + } + } + return 0; + } + + // Helper function to find an empty slot in the localTable + inline unsigned int empty_slot( void ) + { + int i; + for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ ) + { + if ( tpNum[ i ] == 0 ) + return i; + } + 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 ) ); + memcpy( tpnum, + (const void*)( gdsPtr->tp[ 2 + _2k_sys_offs ][ 0 ] ), + sizeof( tpnum ) ); + + /// - ------ Search and clear deselected test points + for ( i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++ ) + { + if ( tpNum[ i ] == 0 ) + continue; + if ( !in_the_lists( tpNum[ i ], i ) ) + { + tpNum[ i ] = 0; // Removed test point is cleared now + ltSlot = dataInfo.numChans + i; + + // If we are clearing an EXC signal, reset filter module + // input + if ( localTable[ ltSlot ].type == DAQ_SRC_FM_EXC ) + { + dspPtr->data[ excTable[ i ].fmNum ].exciteInput = + 0.0; + excTable[ i ].sigNum = 0; + } + else if ( localTable[ ltSlot ].type == DAQ_SRC_NFM_EXC ) + { + // Extra excitation + excSignal[ excTable[ i ].fmNum ] = 0.0; + excTable[ i ].sigNum = 0; } - } - return 0; - } - - // Helper function to find an empty slot in the localTable - inline unsigned int empty_slot(void) { - int i; - for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) { - if (tpNum[i] == 0) return i; - } - 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)); - memcpy(tpnum, (const void *)(gdsPtr->tp[2 + _2k_sys_offs][0]), sizeof(tpnum)); - - /// - ------ Search and clear deselected test points - for (i = 0; i < DAQ_GDS_MAX_TP_ALLOWED; i++) { - if (tpNum[i] == 0) continue; - if (!in_the_lists(tpNum[i], i)) { - tpNum[i] = 0; // Removed test point is cleared now - ltSlot = dataInfo.numChans + i; - - // If we are clearing an EXC signal, reset filter module input - if (localTable[ltSlot].type == DAQ_SRC_FM_EXC) { - dspPtr->data[excTable[i].fmNum].exciteInput = 0.0; - excTable[i].sigNum = 0; - } else if (localTable[ltSlot].type == DAQ_SRC_NFM_EXC) { - // Extra excitation - excSignal[excTable[i].fmNum] = 0.0; - excTable[i].sigNum = 0; - } - - localTable[ltSlot].type = DAQ_SRC_NOOP; - localTable[ltSlot].sysNum = 0; - localTable[ltSlot].fmNum = 0; - localTable[ltSlot].sigNum = 0; - localTable[ltSlot].decFactor = 1; - 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 - for (i = 0; i < (2 * DAQ_GDS_MAX_TP_ALLOWED); i++) { - exc = 0; - // Do test points first - if (i < DAQ_GDS_MAX_TP_ALLOWED) { - if (tpnum[i] == 0) continue; - tpn = tpnum[i]; - } else { - if (excnum[i - DAQ_GDS_MAX_TP_ALLOWED] == 0) continue; - tpn = excnum[i - DAQ_GDS_MAX_TP_ALLOWED]; - exc = 1; - ii = i - DAQ_GDS_MAX_TP_ALLOWED; - } - - //printf("tpn=%d at %d\n", tpn, i); - slot = empty_slot(); - if (slot < 0) { - // No more slots left, table's full - break; - } - - // localTable slot (shifted by the number of DAQ channels) - ltSlot = dataInfo.numChans + slot; - - // 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; - jj -= localTable[ltSlot].sysNum * daqRange.filtTpSize; - localTable[ltSlot].fmNum = jj / DAQ_NUM_FM_TP; - localTable[ltSlot].sigNum = jj % DAQ_NUM_FM_TP; - localTable[ltSlot].decFactor = 1; - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - - //if (slot < 24) gdsMonitor[slot] = tpn; - gdsPtr->tp[2 + _2k_sys_offs][1][slot] = 0; - 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; - localTable[ltSlot].decFactor = 1; - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - gdsPtr->tp[2 + _2k_sys_offs][1][slot] = 0; - tpNum[slot] = tpn; - - } - } 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 - localTable[ltSlot].fmNum = jj % daqRange.filtExSize; - localTable[ltSlot].sigNum = ii; - localTable[ltSlot].decFactor = 1; - - excTable[slot].sigNum = tpn; - excTable[slot].sysNum = localTable[ltSlot].sysNum; - excTable[slot].fmNum = localTable[ltSlot].fmNum; - excTable[slot].offset = i - DAQ_GDS_MAX_TP_ALLOWED; - - // Save the index into the TPman table - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - - gdsPtr->tp[_2k_sys_offs][1][slot] = 0; - 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 - localTable[ltSlot].fmNum = jj; - // localTable[ltSlot].sigNum = slot; - localTable[ltSlot].sigNum = ii; - localTable[ltSlot].decFactor = 1; - - excTable[slot].sigNum = tpn; - excTable[slot].sysNum = localTable[ltSlot].sysNum; - excTable[slot].fmNum = localTable[ltSlot].fmNum; - excTable[slot].offset = i - DAQ_GDS_MAX_TP_ALLOWED; - - dataInfo.tp[ltSlot].dataType = DAQ_DATATYPE_FLOAT; - // if (slot < 8) gdsMonitor[slot + 24] = tpn; - gdsPtr->tp[_2k_sys_offs][1][slot] = 0; - tpNum[slot] = tpn; - } - } - } - - /// - ------ Calculate total number of test points to transmit - totalChans = dataInfo.numChans; // Set to the DAQ channels number - validTp = 0; - num_tps = 0; - - // Skip empty slots at the end - for (i = DAQ_GDS_MAX_TP_ALLOWED-1; i >= 0; i--) { - if (tpNum[i]) { - num_tps = i + 1; - break; - } - } - totalChans += num_tps; - validTp = num_tps; - - /// - ------ Calculate the total transmission size (DAQ +TP) - xferInfo.totalSize = xferInfo.crcLength + validTp * sysRate * 4; - - - // Assign offsets into the localTable - xferInfo.offsetAccum = tpStart; - for (i = 0; i < validTp; i++) { - localTable[dataInfo.numChans + i].offset = xferInfo.offsetAccum; - xferInfo.offsetAccum += sysRate * 4; - if (i < 32) gdsMonitor[i] = tpNum[i]; - } - - for (i = validTp; i < 32; i++) gdsMonitor[i] = 0; - - } /* End normal check for new TP numbers */ - - // 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++) { - tpNumNet[ii] = tpNum[ii]; - // if(tpNum[ii] != 0) validTpNet ++; - } - // validTpNet = validTp; - xferInfo.totalSizeNet = xferInfo.crcLength; - } - - } /* End done 16Hz Cycle */ - - } /* End case write */ - - /// \> Return the FE total DAQ data rate */ - return((xferInfo.totalSize*DAQ_NUM_DATA_BLOCKS_PER_SECOND)/1000); + localTable[ ltSlot ].type = DAQ_SRC_NOOP; + localTable[ ltSlot ].sysNum = 0; + localTable[ ltSlot ].fmNum = 0; + localTable[ ltSlot ].sigNum = 0; + localTable[ ltSlot ].decFactor = 1; + 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 + for ( i = 0; i < ( 2 * DAQ_GDS_MAX_TP_ALLOWED ); i++ ) + { + exc = 0; + // Do test points first + if ( i < DAQ_GDS_MAX_TP_ALLOWED ) + { + if ( tpnum[ i ] == 0 ) + continue; + tpn = tpnum[ i ]; + } + else + { + if ( excnum[ i - DAQ_GDS_MAX_TP_ALLOWED ] == 0 ) + continue; + tpn = excnum[ i - DAQ_GDS_MAX_TP_ALLOWED ]; + exc = 1; + ii = i - DAQ_GDS_MAX_TP_ALLOWED; + } + + // printf("tpn=%d at %d\n", tpn, i); + slot = empty_slot( ); + if ( slot < 0 ) + { + // No more slots left, table's full + break; + } + + // localTable slot (shifted by the number of DAQ channels) + ltSlot = dataInfo.numChans + slot; + + // 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; + jj -= localTable[ ltSlot ].sysNum * + daqRange.filtTpSize; + localTable[ ltSlot ].fmNum = jj / DAQ_NUM_FM_TP; + localTable[ ltSlot ].sigNum = jj % DAQ_NUM_FM_TP; + localTable[ ltSlot ].decFactor = 1; + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + + // if (slot < 24) gdsMonitor[slot] = tpn; + gdsPtr->tp[ 2 + _2k_sys_offs ][ 1 ][ slot ] = 0; + 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; + localTable[ ltSlot ].decFactor = 1; + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + gdsPtr->tp[ 2 + _2k_sys_offs ][ 1 ][ slot ] = 0; + tpNum[ slot ] = tpn; + } + } + 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 + localTable[ ltSlot ].fmNum = + jj % daqRange.filtExSize; + localTable[ ltSlot ].sigNum = ii; + localTable[ ltSlot ].decFactor = 1; + + excTable[ slot ].sigNum = tpn; + excTable[ slot ].sysNum = + localTable[ ltSlot ].sysNum; + excTable[ slot ].fmNum = localTable[ ltSlot ].fmNum; + excTable[ slot ].offset = + i - DAQ_GDS_MAX_TP_ALLOWED; + + // Save the index into the TPman table + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + + gdsPtr->tp[ _2k_sys_offs ][ 1 ][ slot ] = 0; + 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 + localTable[ ltSlot ].fmNum = jj; + // localTable[ltSlot].sigNum = slot; + localTable[ ltSlot ].sigNum = ii; + localTable[ ltSlot ].decFactor = 1; + + excTable[ slot ].sigNum = tpn; + excTable[ slot ].sysNum = + localTable[ ltSlot ].sysNum; + excTable[ slot ].fmNum = localTable[ ltSlot ].fmNum; + excTable[ slot ].offset = + i - DAQ_GDS_MAX_TP_ALLOWED; + + dataInfo.tp[ ltSlot ].dataType = DAQ_DATATYPE_FLOAT; + // if (slot < 8) gdsMonitor[slot + 24] = tpn; + gdsPtr->tp[ _2k_sys_offs ][ 1 ][ slot ] = 0; + tpNum[ slot ] = tpn; + } + } + } + + /// - ------ Calculate total number of test points to transmit + totalChans = + dataInfo.numChans; // Set to the DAQ channels number + validTp = 0; + num_tps = 0; + + // Skip empty slots at the end + for ( i = DAQ_GDS_MAX_TP_ALLOWED - 1; i >= 0; i-- ) + { + if ( tpNum[ i ] ) + { + num_tps = i + 1; + break; + } + } + totalChans += num_tps; + validTp = num_tps; + + /// - ------ Calculate the total transmission size (DAQ +TP) + xferInfo.totalSize = xferInfo.crcLength + validTp * sysRate * 4; + + // Assign offsets into the localTable + xferInfo.offsetAccum = tpStart; + for ( i = 0; i < validTp; i++ ) + { + localTable[ dataInfo.numChans + i ].offset = + xferInfo.offsetAccum; + xferInfo.offsetAccum += sysRate * 4; + if ( i < 32 ) + gdsMonitor[ i ] = tpNum[ i ]; + } + + for ( i = validTp; i < 32; i++ ) + gdsMonitor[ i ] = 0; + + } /* End normal check for new TP numbers */ + + // 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++ ) + { + tpNumNet[ ii ] = tpNum[ ii ]; + // if(tpNum[ii] != 0) validTpNet ++; + } + // validTpNet = validTp; + xferInfo.totalSizeNet = xferInfo.crcLength; + } + + } /* End done 16Hz Cycle */ + + } /* End case write */ + + /// \> Return the FE total DAQ data rate */ + return ( ( xferInfo.totalSize * DAQ_NUM_DATA_BLOCKS_PER_SECOND ) / 1000 ); } // ************************************************************************************** // 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); - +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 ); } // ************************************************************************************** @@ -909,43 +1217,43 @@ int gdsConfig(GDS_INFO_BLOCK *localtable, GDS_INFO_BLOCK *shmtable) { /// @param[in] pEpics Pointer to beginning of EPICS data. /// @return Size, in bytes, of DAQ data. // ************************************************************************************** -int daqConfig( DAQ_INFO_BLOCK *dataInfo, - DAQ_INFO_BLOCK *pInfo, - char *pEpics - ) +int +daqConfig( DAQ_INFO_BLOCK* dataInfo, DAQ_INFO_BLOCK* pInfo, char* pEpics ) { -int ii,jj; // Loop counters -int epicsIntXferSize = 0; // Size, in bytes, of EPICS integer type data. -int dataLength = 0; // Total size, in bytes, of data to be sent -int status = 0; -int mydatatype; - -/// \> Verify correct channel count before proceeding. \n -/// - ---- Required to be at least one and not more than DCU_MAX_CHANNELS. + int ii, jj; // Loop counters + int epicsIntXferSize = 0; // Size, in bytes, of EPICS integer type data. + int dataLength = 0; // Total size, in bytes, of data to be sent + int status = 0; + int mydatatype; + + /// \> Verify correct channel count before proceeding. \n + /// - ---- Required to be at least one and not more than DCU_MAX_CHANNELS. status = pInfo->numChans; // if((status < 1) || (status > DCU_MAX_CHANNELS)) - if(status > DCU_MAX_CHANNELS) - { - printf("Invalid num daq chans = %d\n",status); - return(-1); + if ( status > DCU_MAX_CHANNELS ) + { + printf( "Invalid num daq chans = %d\n", status ); + return ( -1 ); } - /// \> Get the number of fast channels to be acquired + /// \> Get the number of fast channels to be acquired dataInfo->numChans = pInfo->numChans; -/// \> Setup EPICS channel information/pointers + /// \> Setup EPICS channel information/pointers dataInfo->numEpicsInts = pInfo->numEpicsInts; dataInfo->numEpicsFloats = pInfo->numEpicsFloats; dataInfo->numEpicsFilts = pInfo->numEpicsFilts; dataInfo->numEpicsTotal = pInfo->numEpicsTotal; -/// \> Determine how many filter modules are to have their data transferred per cycle. -/// - ---- This is to balance load (CPU time) across several cycles if number of filter modules > 100 - dataInfo->numEpicsFiltXfers = MAX_MODULES/DAQ_XFER_FMD_PER_CYCLE; + /// \> Determine how many filter modules are to have their data transferred + /// per cycle. + /// - ---- This is to balance load (CPU time) across several cycles if + /// number of filter modules > 100 + dataInfo->numEpicsFiltXfers = MAX_MODULES / DAQ_XFER_FMD_PER_CYCLE; dataInfo->numEpicsFiltsLast = DAQ_XFER_FMD_PER_CYCLE; - if(MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE) + if ( MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE ) { - dataInfo->numEpicsFiltXfers ++; - dataInfo->numEpicsFiltsLast = (MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE); + dataInfo->numEpicsFiltXfers++; + dataInfo->numEpicsFiltsLast = ( MAX_MODULES % DAQ_XFER_FMD_PER_CYCLE ); } dataInfo->numEpicsFiltXfers += DAQ_XFER_CYCLE_FMD; pEpicsIntData = pEpics; @@ -953,101 +1261,134 @@ int mydatatype; dataInfo->epicsdblDataOffset = 0; dataInfo->cpyepics2times = 0; - dataInfo->cpyIntSize[0] = dataInfo->numEpicsInts * 4; - dataInfo->cpyIntSize[1] = 0; + dataInfo->cpyIntSize[ 0 ] = dataInfo->numEpicsInts * 4; + dataInfo->cpyIntSize[ 1 ] = 0; - ii = (sizeof(CDS_EPICS_OUT) / 4); + ii = ( sizeof( CDS_EPICS_OUT ) / 4 ); jj = dataInfo->numEpicsInts - ii; - printf("Have %d CDS epics integer and %d USR epics integer channels\n",ii,jj); + printf( "Have %d CDS epics integer and %d USR epics integer channels\n", + ii, + jj ); ii *= 4; jj *= 4; - /// \> Look for memory holes ie integer types not ending on 8 byte boundary. - /// Need to check both standard CDS struct and User channels - /// - ---- If either doesn't end on 8 byte boundary, then a 4 byte hole will appear - /// before the double type data in shared memory. - if(ii % 8) { - printf("Have int mem hole after CDS %d %d \n",ii,jj); + /// \> Look for memory holes ie integer types not ending on 8 byte + /// boundary. Need to check both standard CDS struct and User channels + /// - ---- If either doesn't end on 8 byte boundary, then a 4 byte hole will + /// appear before the double type data in shared memory. + if ( ii % 8 ) + { + printf( "Have int mem hole after CDS %d %d \n", ii, jj ); dataInfo->epicsdblDataOffset += 4; } - if(jj % 8) { - printf("Have int mem hole after user %d %d \n",ii,jj); + if ( jj % 8 ) + { + printf( "Have int mem hole after user %d %d \n", ii, jj ); dataInfo->epicsdblDataOffset += 4; } - if ((ii%8) &&(jj>0)) { + if ( ( ii % 8 ) && ( jj > 0 ) ) + { /// - ---- If standard CDS struct doesn't end on 8 byte boundary, then /// have 4 byte mem hole after CDS data - /// This will require 2 memcpys of integer data to get 8 byte alignment for xfer to DAQ buffer.. - dataInfo->cpyIntSize[0] = ii; - dataInfo->cpyIntSize[1] = jj; - dataInfo->cpyepics2times = 1; + /// This will require 2 memcpys of integer data to get 8 byte alignment + /// for xfer to DAQ buffer.. + dataInfo->cpyIntSize[ 0 ] = ii; + dataInfo->cpyIntSize[ 1 ] = jj; + dataInfo->cpyepics2times = 1; // dataInfo->epicsdblDataOffset += 4; - printf("Have mem holes after CDS %d %d \nNeed to cpy ints twice - size 1 = %d size 2 = %d \n",ii,jj,dataInfo->cpyIntSize[0],dataInfo->cpyIntSize[1]); + printf( "Have mem holes after CDS %d %d \nNeed to cpy ints twice - " + "size 1 = %d size 2 = %d \n", + ii, + jj, + dataInfo->cpyIntSize[ 0 ], + dataInfo->cpyIntSize[ 1 ] ); } - /// \> Set the pointer to start of EPICS double type data in shared memory. \n - /// - ---- Ptr to double type data is at EPICS integer start + EPICS integer size + Memory holes - pEpicsDblData = (pEpicsIntData + epicsIntXferSize + dataInfo->epicsdblDataOffset); + /// \> Set the pointer to start of EPICS double type data in shared memory. + /// \n + /// - ---- Ptr to double type data is at EPICS integer start + EPICS integer + /// size + Memory holes + pEpicsDblData = + ( pEpicsIntData + epicsIntXferSize + dataInfo->epicsdblDataOffset ); // Send EPICS data diags to dmesg - printf("DAQ EPICS INT DATA is at 0x%lx with size %d\n",(long)pEpicsIntData,epicsIntXferSize); - printf("DAQ EPICS FLT DATA is at 0x%lx\n",(long)pEpicsDblData); - printf("DAQ EPICS: Int = %d Flt = %d Filters = %d Total = %d Fast = %d\n",dataInfo->numEpicsInts,dataInfo->numEpicsFloats,dataInfo->numEpicsFilts, dataInfo->numEpicsTotal, dataInfo->numChans); - printf("DAQ EPICS: Number of Filter Module Xfers = %d last = %d\n",dataInfo->numEpicsFiltXfers,dataInfo->numEpicsFiltsLast); + printf( "DAQ EPICS INT DATA is at 0x%lx with size %d\n", + (long)pEpicsIntData, + epicsIntXferSize ); + printf( "DAQ EPICS FLT DATA is at 0x%lx\n", (long)pEpicsDblData ); + printf( "DAQ EPICS: Int = %d Flt = %d Filters = %d Total = %d Fast = %d\n", + dataInfo->numEpicsInts, + dataInfo->numEpicsFloats, + dataInfo->numEpicsFilts, + dataInfo->numEpicsTotal, + dataInfo->numChans ); + printf( "DAQ EPICS: Number of Filter Module Xfers = %d last = %d\n", + dataInfo->numEpicsFiltXfers, + dataInfo->numEpicsFiltsLast ); /// \> Initialize CRC length with EPICS data size. dataLength = 4 * dataInfo->numEpicsTotal; - printf("crc length epics = %d\n",dataLength); + printf( "crc length epics = %d\n", dataLength ); - /// \> Get the DAQ configuration information for all fast DAQ channels and calc a crc checksum length - for(ii=0;ii<dataInfo->numChans;ii++) + /// \> 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; - mydatatype = dataInfo->tp[ii].dataType; - dataLength += DAQ_DATA_TYPE_SIZE(mydatatype) * dataInfo->tp[ii].dataRate / DAQ_NUM_DATA_BLOCKS; - if(mydatatype == 5) printf("Found double %d\n",DAQ_DATA_TYPE_SIZE(mydatatype)); + 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; + mydatatype = dataInfo->tp[ ii ].dataType; + dataLength += DAQ_DATA_TYPE_SIZE( mydatatype ) * + dataInfo->tp[ ii ].dataRate / DAQ_NUM_DATA_BLOCKS; + if ( mydatatype == 5 ) + printf( "Found double %d\n", DAQ_DATA_TYPE_SIZE( mydatatype ) ); } /// \> Set DAQ bytes/sec global, which is output to EPICS by controller.c curDaqBlockSize = dataLength * DAQ_NUM_DATA_BLOCKS_PER_SECOND; /// \> RETURN dataLength, used in other code for CRC checksum byte count - return(dataLength); - + return ( dataLength ); } // ************************************************************************************** /// @author R.Bork\n /// @brief This function populates the local DAQ/TP tables. /// @param *pDxi Pointer to struct with data transfer size information. -/// @param localTable[] Table to be populated with data pointer information +/// @param localTable[] Table to be populated with data pointer +///information /// @param sysRate Number of code cycles in 1/16 second. /// @param *dataInfo DAQ configuration information -/// @param *daqRange Info on GDS TP number ranges which provides type information +/// @param *daqRange Info on GDS TP number ranges which provides +///type information /// @return 0=OK or -1=FAIL // ************************************************************************************** -int loadLocalTable(DAQ_XFER_INFO *pDxi, - DAQ_LKUP_TABLE localTable[], - int sysRate, - DAQ_INFO_BLOCK *dataInfo, - DAQ_RANGE *daqRange - ) +int +loadLocalTable( DAQ_XFER_INFO* pDxi, + DAQ_LKUP_TABLE localTable[], + int sysRate, + DAQ_INFO_BLOCK* dataInfo, + DAQ_RANGE* daqRange ) { -int ii,jj; -int mydatatype; - + int ii, jj; + int mydatatype; - /// \> Get the .INI file crc checksum to pass to DAQ Framebuilders for config checking */ + /// \> Get the .INI file crc checksum to pass to DAQ Framebuilders for + /// config checking */ pDxi->fileCrc = pInfo->configFileCRC; - /// \> Calculate the number of bytes to xfer on each call, based on total number - /// of bytes to write each 1/16sec and the front end data rate (2048/16384Hz) - pDxi->xferSize1 = pDxi->crcLength/sysRate; + /// \> Calculate the number of bytes to xfer on each call, based on total + /// number + /// of bytes to write each 1/16sec and the front end data rate + /// (2048/16384Hz) + pDxi->xferSize1 = pDxi->crcLength / sysRate; pDxi->totalSize = pDxi->crcLength; pDxi->totalSizeNet = pDxi->crcLength; - printf (" xfer sizes = %d %d %d %d \n",sysRate,pDxi->xferSize1,pDxi->totalSize,pDxi->crcLength); - + printf( " xfer sizes = %d %d %d %d \n", + sysRate, + pDxi->xferSize1, + pDxi->totalSize, + pDxi->crcLength ); + #if 0 /// \> Maintain 8 byte data boundaries for writing data, particularly important /// when DMA xfers are used on 5565 RFM modules. Note that this usually results @@ -1057,88 +1398,102 @@ int mydatatype; printf("DAQ resized %d\n", pDxi->xferSize1); #endif - /// \> Find first memory location for fast data in read/write swing buffers. + /// \> Find first memory location for fast data in read/write swing buffers. pDxi->offsetAccum = 4 * dataInfo->numEpicsTotal; - localTable[0].offset = pDxi->offsetAccum; + localTable[ 0 ].offset = pDxi->offsetAccum; - /// \> Fill in the local lookup table for finding data. - /// - (Need to develop a table of offset pointers to load data into swing buffers) \n - /// - (This is based on decimation factors and data size.) -for(ii=0;ii<dataInfo->numChans;ii++) + /// \> Fill in the local lookup table for finding data. + /// - (Need to develop a table of offset pointers to load data into swing + /// buffers) \n + /// - (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); - return(-1); - } else { - /// - ---- 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; - pDxi->offsetAccum += (sysRate/localTable[ii].decFactor * DAQ_DATA_TYPE_SIZE(mydatatype)); - - localTable[ii+1].offset = pDxi->offsetAccum; - /// - ---- Need to determine if data is from a filter module TP or non-FM TP and tag accordingly - if((dataInfo->tp[ii].tpnum >= daqRange->filtTpMin) && - (dataInfo->tp[ii].tpnum < daqRange->filtTpMax)) - /* This is a filter module testpoint */ - { - jj = dataInfo->tp[ii].tpnum - daqRange->filtTpMin; - /* Mark as coming from a filter module testpoint */ - localTable[ii].type = DAQ_SRC_FM_TP; - /* Mark which system filter module is in */ - localTable[ii].sysNum = jj / daqRange->filtTpSize; - jj -= localTable[ii].sysNum * daqRange->filtTpSize; - /* Mark which filter module within a system */ - localTable[ii].fmNum = jj / DAQ_NUM_FM_TP; - /* Mark which of three testpoints to store */ - localTable[ii].sigNum = jj % DAQ_NUM_FM_TP; - } - else if((dataInfo->tp[ii].tpnum >= daqRange->filtExMin) && - (dataInfo->tp[ii].tpnum < daqRange->filtExMax)) - /* This is a filter module excitation input */ - { - /* Mark as coming from a filter module excitation input */ - localTable[ii].type = DAQ_SRC_FM_EXC; - /* Mark filter module number */ - localTable[ii].fmNum = dataInfo->tp[ii].tpnum - daqRange->filtExMin; - } - else if((dataInfo->tp[ii].tpnum >= daqRange->xTpMin) && - (dataInfo->tp[ii].tpnum < daqRange->xTpMax)) - /* This testpoint is not part of a filter module */ - { - jj = dataInfo->tp[ii].tpnum - daqRange->xTpMin; - /* Mark as a non filter module testpoint */ - localTable[ii].type = DAQ_SRC_NFM_TP; - /* Mark the offset into the local data buffer */ - localTable[ii].sigNum = jj; - } - // :TODO: this is broken, needs some work to make extra EXC work. - else if((dataInfo->tp[ii].tpnum >= daqRange->xExMin) && - (dataInfo->tp[ii].tpnum < daqRange->xExMax)) - /* This exc testpoint is not part of a filter module */ - { - jj = dataInfo->tp[ii].tpnum - daqRange->xExMin; - /* Mark as a non filter module testpoint */ - localTable[ii].type = DAQ_SRC_NFM_EXC; - /* Mark the offset into the local data buffer */ - localTable[ii].fmNum = jj; - localTable[ii].sigNum = jj; - } - else - { - printf("Invalid chan num found %d = %d\n",ii,dataInfo->tp[ii].tpnum); - return(-1); - } - // printf("Table %d Offset = %d Type = %d\n",ii,localTable[ii].offset,dataInfo->tp[ii].dataType); -} -return(0); -/// \> RETURN 0=OK or -1=FAIL - + // 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 ); + return ( -1 ); + } + else + { + /// - ---- 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; + pDxi->offsetAccum += ( sysRate / localTable[ ii ].decFactor * + DAQ_DATA_TYPE_SIZE( mydatatype ) ); + + localTable[ ii + 1 ].offset = pDxi->offsetAccum; + /// - ---- Need to determine if data is from a filter module TP or + /// non-FM TP and tag accordingly + if ( ( dataInfo->tp[ ii ].tpnum >= daqRange->filtTpMin ) && + ( dataInfo->tp[ ii ].tpnum < daqRange->filtTpMax ) ) + /* This is a filter module testpoint */ + { + jj = dataInfo->tp[ ii ].tpnum - daqRange->filtTpMin; + /* Mark as coming from a filter module testpoint */ + localTable[ ii ].type = DAQ_SRC_FM_TP; + /* Mark which system filter module is in */ + localTable[ ii ].sysNum = jj / daqRange->filtTpSize; + jj -= localTable[ ii ].sysNum * daqRange->filtTpSize; + /* Mark which filter module within a system */ + localTable[ ii ].fmNum = jj / DAQ_NUM_FM_TP; + /* Mark which of three testpoints to store */ + localTable[ ii ].sigNum = jj % DAQ_NUM_FM_TP; + } + else if ( ( dataInfo->tp[ ii ].tpnum >= daqRange->filtExMin ) && + ( dataInfo->tp[ ii ].tpnum < daqRange->filtExMax ) ) + /* This is a filter module excitation input */ + { + /* Mark as coming from a filter module excitation input */ + localTable[ ii ].type = DAQ_SRC_FM_EXC; + /* Mark filter module number */ + localTable[ ii ].fmNum = + dataInfo->tp[ ii ].tpnum - daqRange->filtExMin; + } + else if ( ( dataInfo->tp[ ii ].tpnum >= daqRange->xTpMin ) && + ( dataInfo->tp[ ii ].tpnum < daqRange->xTpMax ) ) + /* This testpoint is not part of a filter module */ + { + jj = dataInfo->tp[ ii ].tpnum - daqRange->xTpMin; + /* Mark as a non filter module testpoint */ + localTable[ ii ].type = DAQ_SRC_NFM_TP; + /* Mark the offset into the local data buffer */ + localTable[ ii ].sigNum = jj; + } + // :TODO: this is broken, needs some work to make extra EXC work. + else if ( ( dataInfo->tp[ ii ].tpnum >= daqRange->xExMin ) && + ( dataInfo->tp[ ii ].tpnum < daqRange->xExMax ) ) + /* This exc testpoint is not part of a filter module */ + { + jj = dataInfo->tp[ ii ].tpnum - daqRange->xExMin; + /* Mark as a non filter module testpoint */ + localTable[ ii ].type = DAQ_SRC_NFM_EXC; + /* Mark the offset into the local data buffer */ + localTable[ ii ].fmNum = jj; + localTable[ ii ].sigNum = jj; + } + else + { + printf( "Invalid chan num found %d = %d\n", + ii, + dataInfo->tp[ ii ].tpnum ); + return ( -1 ); + } + // printf("Table %d Offset = %d Type = + // %d\n",ii,localTable[ii].offset,dataInfo->tp[ii].dataType); + } + return ( 0 ); + /// \> RETURN 0=OK or -1=FAIL } diff --git a/src/include/drv/epicsXfer.c b/src/include/drv/epicsXfer.c index 2d3b1f36f..492e956de 100644 --- a/src/include/drv/epicsXfer.c +++ b/src/include/drv/epicsXfer.c @@ -11,29 +11,30 @@ /// @param[in] *dspCoeff Pointer to process memory fm coeff data. /// @param[in] *pCoeff Pointer to shared memory fm coeff data. /************************************************************************/ -inline void updateEpics(int subcycle, - FILT_MOD *dsp, - FILT_MOD *pDsp, - COEF *dspCoeff, - VME_COEF *pCoeff) +inline void +updateEpics( int subcycle, + FILT_MOD* dsp, + FILT_MOD* pDsp, + COEF* dspCoeff, + VME_COEF* pCoeff ) { -int ii; + int ii; - ii = subcycle; - if((ii >= 0) && (ii < MAX_MODULES)) - { - checkFiltReset(ii, dsp, pDsp, dspCoeff, MAX_MODULES, pCoeff); + ii = subcycle; + if ( ( ii >= 0 ) && ( ii < MAX_MODULES ) ) + { + checkFiltReset( ii, dsp, pDsp, dspCoeff, MAX_MODULES, pCoeff ); // dsp->inputs[ii].opSwitchE = pDsp->inputs[ii].opSwitchE; - pDsp->data[ii].filterInput = dsp->data[ii].filterInput; - pDsp->data[ii].exciteInput = dsp->data[ii].exciteInput; - pDsp->data[ii].output16Hz = dsp->data[ii].output16Hz; - pDsp->data[ii].output = dsp->data[ii].output; - pDsp->data[ii].testpoint = dsp->data[ii].testpoint; - pDsp->data[ii].swStatus = dsp->data[ii].swStatus; - pDsp->inputs[ii].opSwitchP = dsp->inputs[ii].opSwitchP; + pDsp->data[ ii ].filterInput = dsp->data[ ii ].filterInput; + pDsp->data[ ii ].exciteInput = dsp->data[ ii ].exciteInput; + pDsp->data[ ii ].output16Hz = dsp->data[ ii ].output16Hz; + pDsp->data[ ii ].output = dsp->data[ ii ].output; + pDsp->data[ ii ].testpoint = dsp->data[ ii ].testpoint; + pDsp->data[ ii ].swStatus = dsp->data[ ii ].swStatus; + pDsp->inputs[ ii ].opSwitchP = dsp->inputs[ ii ].opSwitchP; // dsp->inputs[ii].limiter = pDsp->inputs[ii].limiter; - pDsp->inputs[ii].mask = dsp->inputs[ii].mask; - pDsp->inputs[ii].control = dsp->inputs[ii].control; + pDsp->inputs[ ii ].mask = dsp->inputs[ ii ].mask; + pDsp->inputs[ ii ].control = dsp->inputs[ ii ].control; #if 0 if (dsp->inputs[ii].mask & 0x20000000) { /* Offset controlled by the FE */ pDsp->inputs[ii].offset = dsp->inputs[ii].offset; @@ -51,88 +52,100 @@ int ii; dsp->inputs[ii].gain_ramp_time = pDsp->inputs[ii].gain_ramp_time; } #endif - } + } } -inline void updateFmSetpoints( - FILT_MOD *dsp, - FILT_MOD *pDsp, - COEF *dspCoeff, - VME_COEF *pCoeff) +inline void +updateFmSetpoints( FILT_MOD* dsp, + FILT_MOD* pDsp, + COEF* dspCoeff, + VME_COEF* pCoeff ) { -int ii; - - for(ii=0;ii<MAX_MODULES;ii++) - { - dsp->inputs[ii].opSwitchE = pDsp->inputs[ii].opSwitchE; - dsp->inputs[ii].limiter = pDsp->inputs[ii].limiter; - if (dsp->inputs[ii].mask & 0x20000000) { /* Offset controlled by the FE */ - pDsp->inputs[ii].offset = dsp->inputs[ii].offset; - } else { - dsp->inputs[ii].offset = pDsp->inputs[ii].offset; - } - if (dsp->inputs[ii].mask & 0x40000000) { /* Gain controlled by the FE */ - pDsp->inputs[ii].outgain = dsp->inputs[ii].outgain; - } else { - dsp->inputs[ii].outgain = pDsp->inputs[ii].outgain; - } - if (dsp->inputs[ii].mask & 0x80000000) { /* Ramp time controlled by the FE */ - pDsp->inputs[ii].gain_ramp_time = dsp->inputs[ii].gain_ramp_time; - } else { - dsp->inputs[ii].gain_ramp_time = pDsp->inputs[ii].gain_ramp_time; - } - } - + int ii; + + for ( ii = 0; ii < MAX_MODULES; ii++ ) + { + dsp->inputs[ ii ].opSwitchE = pDsp->inputs[ ii ].opSwitchE; + dsp->inputs[ ii ].limiter = pDsp->inputs[ ii ].limiter; + if ( dsp->inputs[ ii ].mask & 0x20000000 ) + { /* Offset controlled by the FE */ + pDsp->inputs[ ii ].offset = dsp->inputs[ ii ].offset; + } + else + { + dsp->inputs[ ii ].offset = pDsp->inputs[ ii ].offset; + } + if ( dsp->inputs[ ii ].mask & 0x40000000 ) + { /* Gain controlled by the FE */ + pDsp->inputs[ ii ].outgain = dsp->inputs[ ii ].outgain; + } + else + { + dsp->inputs[ ii ].outgain = pDsp->inputs[ ii ].outgain; + } + if ( dsp->inputs[ ii ].mask & 0x80000000 ) + { /* Ramp time controlled by the FE */ + pDsp->inputs[ ii ].gain_ramp_time = + dsp->inputs[ ii ].gain_ramp_time; + } + else + { + dsp->inputs[ ii ].gain_ramp_time = + pDsp->inputs[ ii ].gain_ramp_time; + } + } } - /// Check for process stop command from EPICS /// @param[in] subcycle Present code cycle /// @param[in] *plocalEpics Pointer to EPICS data in shared memory -inline int checkEpicsReset(int subcycle, CDS_EPICS *plocalEpics){ - int ii; - - ii = subcycle; +inline int +checkEpicsReset( int subcycle, CDS_EPICS* plocalEpics ) +{ + int ii; - if ((ii==MAX_MODULES) && (plocalEpics->epicsInput.vmeReset)) { - return(1); - } + ii = subcycle; - return(0); + if ( ( ii == MAX_MODULES ) && ( plocalEpics->epicsInput.vmeReset ) ) + { + return ( 1 ); + } + return ( 0 ); } /// Perform gain ramping -int gainRamp(float gainReq, int rampTime, int id, float *gain, int gainRate) +int +gainRamp( float gainReq, int rampTime, int id, float* gain, int gainRate ) { -static int dir[40]; -static float inc[40]; -static float gainFinal[40]; -static float gainOut[40]; - - if (rampTime <= 0) return 0; - - if(gainFinal[id] != gainReq) - { - inc[id] = rampTime * gainRate; - inc[id] = (gainReq - gainOut[id]) / inc[id]; - if(inc[id] <= 0.0) dir[id] = 0; - else dir[id] = 1; - gainFinal[id] = gainReq; - } - if(gainFinal[id] == gainOut[id]) - { - *gain = gainOut[id]; - return(0); - } - gainOut[id] += inc[id]; - if((dir[id] == 1) && (gainOut[id] >= gainFinal[id])) - gainOut[id] = gainFinal[id]; - if((dir[id] == 0) && (gainOut[id] <= gainFinal[id])) - gainOut[id] = gainFinal[id]; - *gain = gainOut[id]; - return(1); + static int dir[ 40 ]; + static float inc[ 40 ]; + static float gainFinal[ 40 ]; + static float gainOut[ 40 ]; + + if ( rampTime <= 0 ) + return 0; + + if ( gainFinal[ id ] != gainReq ) + { + inc[ id ] = rampTime * gainRate; + inc[ id ] = ( gainReq - gainOut[ id ] ) / inc[ id ]; + if ( inc[ id ] <= 0.0 ) + dir[ id ] = 0; + else + dir[ id ] = 1; + gainFinal[ id ] = gainReq; + } + if ( gainFinal[ id ] == gainOut[ id ] ) + { + *gain = gainOut[ id ]; + return ( 0 ); + } + gainOut[ id ] += inc[ id ]; + if ( ( dir[ id ] == 1 ) && ( gainOut[ id ] >= gainFinal[ id ] ) ) + gainOut[ id ] = gainFinal[ id ]; + if ( ( dir[ id ] == 0 ) && ( gainOut[ id ] <= gainFinal[ id ] ) ) + gainOut[ id ] = gainFinal[ id ]; + *gain = gainOut[ id ]; + return ( 1 ); } - - - diff --git a/src/include/drv/fm10Gen.c b/src/include/drv/fm10Gen.c index 64ad475b7..56002e93a 100644 --- a/src/include/drv/fm10Gen.c +++ b/src/include/drv/fm10Gen.c @@ -1,38 +1,40 @@ -/*----------------------------------------------------------------------------- */ +/*----------------------------------------------------------------------------- + */ /* */ -/* ------------------- */ +/* ------------------- */ /* */ -/* LIGO */ +/* LIGO */ /* */ -/* THE LASER INTERFEROMETER GRAVITATIONAL WAVE OBSERVATORY. */ +/* THE LASER INTERFEROMETER GRAVITATIONAL WAVE OBSERVATORY. */ /* */ -/* (C) The LIGO Project, 2005. */ +/* (C) The LIGO Project, 2005. */ /* */ /* */ -/* File: fm10Gen.c */ -/* Description: */ -/* CDS generic code for calculating IIR filters. */ +/* File: fm10Gen.c */ +/* Description: */ +/* CDS generic code for calculating IIR filters. */ /* */ -/* California Institute of Technology */ -/* LIGO Project MS 18-34 */ -/* Pasadena CA 91125 */ +/* California Institute of Technology */ +/* LIGO Project MS 18-34 */ +/* Pasadena CA 91125 */ /* */ -/* Massachusetts Institute of Technology */ -/* LIGO Project MS 20B-145 */ -/* Cambridge MA 01239 */ +/* Massachusetts Institute of Technology */ +/* LIGO Project MS 20B-145 */ +/* Cambridge MA 01239 */ /* */ -/*----------------------------------------------------------------------------- */ +/*----------------------------------------------------------------------------- + */ /// @file fm10Gen.c /// @brief This file contains the routines for performing the real-time /// IIR/FIR filter calculations. \n -/// Further information is provided in the LIGO DCC -/// <a href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7687">T0900606 CDS Standard IIR Filter Module Software</a> - +/// Further information is provided in the LIGO DCC +/// <a +///href="https://dcc.ligo.org/cgi-bin/private/DocDB/ShowDocument?docid=7687">T0900606 +///CDS Standard IIR Filter Module Software</a> #include "fm10Gen.h" - /* Switching register bits */ #define OPSWITCH_INPUT_ENABLE 0x4 #define OPSWITCH_OFFSET_ENABLE 0x8 @@ -42,169 +44,180 @@ #define OPSWITCH_HOLD_ENABLE 0x8000000 /// Quick look up table for power of 2 calcs -const UINT32 pow2_in[10] = {0x10,0x40,0x100,0x400,0x1000,0x4000,0x10000, - 0x40000,0x100000,0x400000}; +const UINT32 pow2_in[ 10 ] = { 0x10, 0x40, 0x100, 0x400, 0x1000, + 0x4000, 0x10000, 0x40000, 0x100000, 0x400000 }; /// Quick look up table for power of 2 calcs -const UINT32 pow2_out[10] = {0x20,0x80,0x200,0x800,0x2000,0x8000,0x20000, - 0x80000,0x200000,0x800000}; +const UINT32 pow2_out[ 10 ] = { 0x20, 0x80, 0x200, 0x800, 0x2000, + 0x8000, 0x20000, 0x80000, 0x200000, 0x800000 }; /// Quick look up table for filter module switch decoding -const UINT32 fltrConst[17] = {16, 64, 256, 1024, 4096, 16384, - 65536, 262144, 1048576, 4194304, - 0x4, 0x8, 0x4000000,0x1000000,0x1, /* in sw, off sw, out sw , limit sw*/ - 0x2000000,0x8000000 - }; - -#if defined(SERVO16K) || defined(SERVO512K) || defined(SERVO32K) || defined(SERVO64K) || defined(SERVO128K) || defined(SERVO256K) || defined(SERVO1024K) -double sixteenKAvgCoeff[9] = {1.9084759e-12, - -1.99708675982420, 0.99709029700517, 2.00000005830747, 1.00000000739582, - -1.99878510620232, 0.99879373895648, 1.99999994169253, 0.99999999260419}; +const UINT32 + fltrConst[ 17 ] = { 16, 64, 256, 1024, 4096, 16384, + 65536, 262144, 1048576, 4194304, 0x4, 0x8, + 0x4000000, 0x1000000, 0x1, /* in sw, off sw, out sw , + limit sw*/ + 0x2000000, 0x8000000 }; + +#if defined( SERVO16K ) || defined( SERVO512K ) || defined( SERVO32K ) || \ + defined( SERVO64K ) || defined( SERVO128K ) || defined( SERVO256K ) || \ + defined( SERVO1024K ) +double sixteenKAvgCoeff[ 9 ] = { 1.9084759e-12, -1.99708675982420, + 0.99709029700517, 2.00000005830747, + 1.00000000739582, -1.99878510620232, + 0.99879373895648, 1.99999994169253, + 0.99999999260419 }; #endif -#if defined(SERVO2K) || defined(SERVO4K) -double twoKAvgCoeff[9] = {7.705446e-9, - -1.97673337437048, 0.97695747524900, 2.00000006227141, 1.00000000659235, - -1.98984125831661, 0.99039139954634, 1.99999993772859, 0.99999999340765}; +#if defined( SERVO2K ) || defined( SERVO4K ) +double twoKAvgCoeff[ 9 ] = { 7.705446e-9, -1.97673337437048, + 0.97695747524900, 2.00000006227141, + 1.00000000659235, -1.98984125831661, + 0.99039139954634, 1.99999993772859, + 0.99999999340765 }; #endif #ifdef SERVO16K #define avgCoeff sixteenKAvgCoeff -#elif defined(SERVO32K) || defined(SERVO64K) || defined(SERVO128K) || defined(SERVO256K) +#elif defined( SERVO32K ) || defined( SERVO64K ) || defined( SERVO128K ) || \ + defined( SERVO256K ) #define avgCoeff sixteenKAvgCoeff -#elif defined(SERVO1024K) +#elif defined( SERVO1024K ) #define avgCoeff sixteenKAvgCoeff -#elif defined(SERVO512K) +#elif defined( SERVO512K ) #define avgCoeff sixteenKAvgCoeff -#elif defined(SERVO2K) +#elif defined( SERVO2K ) #define avgCoeff twoKAvgCoeff -#elif defined(SERVO4K) +#elif defined( SERVO4K ) #define avgCoeff twoKAvgCoeff -#elif defined(SERVO5HZ) +#elif defined( SERVO5HZ ) #else #error need to define 2k or 16k or mixed #endif #ifdef SERVO1024K - #define FE_RATE 1048576 +#define FE_RATE 1048576 #endif #ifdef SERVO512K - #define FE_RATE 524288 +#define FE_RATE 524288 #endif #ifdef SERVO256K - #define FE_RATE 262144 +#define FE_RATE 262144 #endif #ifdef SERVO64K - #define FE_RATE 65536 +#define FE_RATE 65536 #endif #ifdef SERVO32K - #define FE_RATE 32768 +#define FE_RATE 32768 #endif #ifdef SERVO16K - #define FE_RATE 16384 +#define FE_RATE 16384 #endif #ifdef SERVO4K - #define FE_RATE 4096 +#define FE_RATE 4096 #endif #ifdef SERVO2K - #define FE_RATE 2048 +#define FE_RATE 2048 #endif - /// New tRamp.c gain ramping strcuture -RampParamState gain_ramp[MAX_MODULES][10]; - +RampParamState gain_ramp[ MAX_MODULES ][ 10 ]; /// New tRamp.c gain offset strcuture -RampParamState offset_ramp[MAX_MODULES][10]; +RampParamState offset_ramp[ MAX_MODULES ][ 10 ]; -/// @brief Perform IIR filtering sample by sample on doubles. +/// @brief Perform IIR filtering sample by sample on doubles. /// Implements cascaded direct form II second order sections. /// @param[in] input New input sample -/// @param[in] *coef Pointer to filter coefficient data with size 4*n + 1 (gain) +/// @param[in] *coef Pointer to filter coefficient data with size 4*n + 1 +///(gain) /// @param[in] n Number of second order sections in filter definition /// @param[in,out] *history Pointer to filter history data of size 2*n /// @return Result of filter calculation -inline double iir_filter(double input,double *coef,int n,double *history){ - - int i; - double *coef_ptr; - double *hist1_ptr,*hist2_ptr; - double output,new_hist,history1,history2; - - coef_ptr = coef; /* coefficient pointer */ - - hist1_ptr = history; /* first history */ - hist2_ptr = hist1_ptr + 1; /* next history */ - - output = input * (*coef_ptr++); /* overall input scale factor */ - - for(i = 0 ; i < n ; i++) { - - history1 = *hist1_ptr; /* history values */ - history2 = *hist2_ptr; - - - output = output - history1 * (*coef_ptr++); - new_hist = output - history2 * (*coef_ptr++); /* poles */ - - output = new_hist + history1 * (*coef_ptr++); - output = output + history2 * (*coef_ptr++); /* zeros */ - - *hist2_ptr++ = *hist1_ptr; - *hist1_ptr++ = new_hist; - hist1_ptr++; - hist2_ptr++; - - } - - return(output); +inline double +iir_filter( double input, double* coef, int n, double* history ) +{ + + int i; + double* coef_ptr; + double *hist1_ptr, *hist2_ptr; + double output, new_hist, history1, history2; + + coef_ptr = coef; /* coefficient pointer */ + + hist1_ptr = history; /* first history */ + hist2_ptr = hist1_ptr + 1; /* next history */ + + output = input * ( *coef_ptr++ ); /* overall input scale factor */ + + for ( i = 0; i < n; i++ ) + { + + history1 = *hist1_ptr; /* history values */ + history2 = *hist2_ptr; + + output = output - history1 * ( *coef_ptr++ ); + new_hist = output - history2 * ( *coef_ptr++ ); /* poles */ + + output = new_hist + history1 * ( *coef_ptr++ ); + output = output + history2 * ( *coef_ptr++ ); /* zeros */ + + *hist2_ptr++ = *hist1_ptr; + *hist1_ptr++ = new_hist; + hist1_ptr++; + hist2_ptr++; + } + + return ( output ); } /* Biquad form IIR */ -/// @brief Perform IIR filtering sample by sample on doubles. +/// @brief Perform IIR filtering sample by sample on doubles. /// Implements Biquad form calculations. /// @param[in] input New input sample -/// @param[in] *coef Pointer to filter coefficient data with size 4*n + 1 (gain) +/// @param[in] *coef Pointer to filter coefficient data with size 4*n + 1 +///(gain) /// @param[in] n Number of second order sections in filter definition /// @param[in,out] *history Pointer to filter history data of size 2*n /// @return Result of filter calculation -inline double iir_filter_biquad(double input,double *coef,int n,double *history){ - - int i; - double *coef_ptr; - double *hist1_ptr,*hist2_ptr; - double output,new_w, new_u, w, u, a11, a12, c1, c2; - - coef_ptr = coef; /* coefficient pointer */ - - hist1_ptr = history; /* first history */ - hist2_ptr = hist1_ptr + 1; /* next history */ - - output = input * (*coef_ptr++); /* overall input scale factor */ - - for(i = 0 ; i < n ; i++) { - - w = *hist1_ptr; - u = *hist2_ptr; - - a11 = *coef_ptr++; - a12 = *coef_ptr++; - c1 = *coef_ptr++; - c2 = *coef_ptr++; - - new_w = output + a11 * w + a12 * u; - output = output + w * c1 + u * c2; - new_u = w + u; - - *hist1_ptr++ = new_w; - *hist2_ptr++ = new_u; - hist1_ptr++; - hist2_ptr++; - - } - - //if((output < 1e-28) && (output > -1e-28)) output = 0.0; - return(output); +inline double +iir_filter_biquad( double input, double* coef, int n, double* history ) +{ + + int i; + double* coef_ptr; + double *hist1_ptr, *hist2_ptr; + double output, new_w, new_u, w, u, a11, a12, c1, c2; + + coef_ptr = coef; /* coefficient pointer */ + + hist1_ptr = history; /* first history */ + hist2_ptr = hist1_ptr + 1; /* next history */ + + output = input * ( *coef_ptr++ ); /* overall input scale factor */ + + for ( i = 0; i < n; i++ ) + { + + w = *hist1_ptr; + u = *hist2_ptr; + + a11 = *coef_ptr++; + a12 = *coef_ptr++; + c1 = *coef_ptr++; + c2 = *coef_ptr++; + + new_w = output + a11 * w + a12 * u; + output = output + w * c1 + u * c2; + new_u = w + u; + + *hist1_ptr++ = new_w; + *hist2_ptr++ = new_u; + hist1_ptr++; + hist2_ptr++; + } + + // if((output < 1e-28) && (output > -1e-28)) output = 0.0; + return ( output ); } #ifdef FIR_FILTERS @@ -215,63 +228,67 @@ inline double iir_filter_biquad(double input,double *coef,int n,double *history) /// @param[in] n Number of taps /// @param[in,out] *history Pointer to filter history data /// @return Result of FIR filter calculation -inline double fir_filter(double input, double *coef, int n, double *history) +inline double +fir_filter( double input, double* coef, int n, double* history ) { - int i; - double *hist_ptr,*hist1_ptr,*coef_ptr; - double output; + int i; + double *hist_ptr, *hist1_ptr, *coef_ptr; + double output; hist_ptr = history; - hist1_ptr = hist_ptr; /* use for history update */ - coef_ptr = coef + n - 1; /* point to last coef */ - -/* form output accumulation */ - output = *hist_ptr++ * (*coef_ptr--); - for(i = 2 ; i < n ; i++) { - *hist1_ptr++ = *hist_ptr; /* update history array */ - output += (*hist_ptr++) * (*coef_ptr--); + hist1_ptr = hist_ptr; /* use for history update */ + coef_ptr = coef + n - 1; /* point to last coef */ + + /* form output accumulation */ + output = *hist_ptr++ * ( *coef_ptr-- ); + for ( i = 2; i < n; i++ ) + { + *hist1_ptr++ = *hist_ptr; /* update history array */ + output += ( *hist_ptr++ ) * ( *coef_ptr-- ); } - output += input * (*coef_ptr); /* input tap */ - *hist1_ptr = input; /* last history */ + output += input * ( *coef_ptr ); /* input tap */ + *hist1_ptr = input; /* last history */ - return(output); + return ( output ); } #endif - #ifdef SERVO16K const int rate = 16384; -#elif defined(SERVO5HZ) +#elif defined( SERVO5HZ ) const int rate = 5; -#elif defined(SERVO2K) +#elif defined( SERVO2K ) const int rate = 2048; -#elif defined(SERVO4K) +#elif defined( SERVO4K ) const int rate = 4096; -#elif defined(SERVO32K) +#elif defined( SERVO32K ) const int rate = 32768; -#elif defined(SERVO64K) -const int rate = (2*32768); -#elif defined(SERVO128K) -const int rate = (4*32768); -#elif defined(SERVO256K) -const int rate = (8*32768); -#elif defined(SERVO512K) -const int rate = (16*32768); -#elif defined(SERVO1024K) -const int rate = (32*32768); +#elif defined( SERVO64K ) +const int rate = ( 2 * 32768 ); +#elif defined( SERVO128K ) +const int rate = ( 4 * 32768 ); +#elif defined( SERVO256K ) +const int rate = ( 8 * 32768 ); +#elif defined( SERVO512K ) +const int rate = ( 16 * 32768 ); +#elif defined( SERVO1024K ) +const int rate = ( 32 * 32768 ); #endif /* Convert opSwitchE bits into the 16-bit FiltCtrl2 Ctrl output format */ inline unsigned int -filtCtrlBitConvert(unsigned int v) { - unsigned int val = 0; - int i; - for (i = 0; i < 17; i++) { - if (v & fltrConst[i]) val |= 1<<i; - } - return val; +filtCtrlBitConvert( unsigned int v ) +{ + unsigned int val = 0; + int i; + for ( i = 0; i < 17; i++ ) + { + if ( v & fltrConst[ i ] ) + val |= 1 << i; + } + return val; } - + /************************************************************************/ /************************************************************************/ /// @brief Read in filter coeffs from shared memory on code initialization. @@ -280,63 +297,81 @@ filtCtrlBitConvert(unsigned int v) { /// @param[in] bF Start filter number /// @param[in] sF End filter number /// @param[in] *pRfmCoeff Pointer to coeffs in shared memory -inline int readCoefVme(COEF *filtC,FILT_MOD *fmt, int bF, int sF, volatile VME_COEF *pRfmCoeff) +inline int +readCoefVme( + COEF* filtC, FILT_MOD* fmt, int bF, int sF, volatile VME_COEF* pRfmCoeff ) { - int ii,jj,kk; + int ii, jj, kk; #ifdef FIR_FILTERS - int l; - for(jj = 0; jj < MAX_FIR_MODULES; jj++) - for (kk = 0; kk < FILTERS; kk++) - for (l = 0; l < MAX_FIR_COEFFS; l++) - filtC->firFiltCoeff[jj][kk][l] = pRfmCoeff->firFiltCoeff[jj][kk][l]; + int l; + for ( jj = 0; jj < MAX_FIR_MODULES; jj++ ) + for ( kk = 0; kk < FILTERS; kk++ ) + for ( l = 0; l < MAX_FIR_COEFFS; l++ ) + filtC->firFiltCoeff[ jj ][ kk ][ l ] = + pRfmCoeff->firFiltCoeff[ jj ][ kk ][ l ]; #endif - for(ii=bF;ii<sF;ii++) - { - filtC->coeffs[ii].biquad = pRfmCoeff->vmeCoeffs[ii].biquad; - //if(filtC->coeffs[ii].biquad) printf("Found a BQF filter %d\n",ii); - for(jj=0;jj<FILTERS;jj++) + for ( ii = bF; ii < sF; ii++ ) { - if(pRfmCoeff->vmeCoeffs[ii].filtSections[jj]) - { - filtC->coeffs[ii].filterType[jj] = pRfmCoeff->vmeCoeffs[ii].filterType[jj]; + filtC->coeffs[ ii ].biquad = pRfmCoeff->vmeCoeffs[ ii ].biquad; + // if(filtC->coeffs[ii].biquad) printf("Found a BQF filter %d\n",ii); + for ( jj = 0; jj < FILTERS; jj++ ) + { + if ( pRfmCoeff->vmeCoeffs[ ii ].filtSections[ jj ] ) + { + filtC->coeffs[ ii ].filterType[ jj ] = + pRfmCoeff->vmeCoeffs[ ii ].filterType[ jj ]; #ifdef FIR_FILTERS - if (filtC->coeffs[ii].filterType[jj] < 0 || filtC->coeffs[ii].filterType[jj] > MAX_FIR_MODULES) { - filtC->coeffs[ii].filterType[jj] = 0; - // printk("Corrupted data coming from Epics: module=%d filter=%d filterType=%d\n", - // ii, jj, pRfmCoeff->vmeCoeffs[ii].filterType[jj]); - return 1; - } + if ( filtC->coeffs[ ii ].filterType[ jj ] < 0 || + filtC->coeffs[ ii ].filterType[ jj ] > MAX_FIR_MODULES ) + { + filtC->coeffs[ ii ].filterType[ jj ] = 0; + // printk("Corrupted data coming from Epics: module=%d + // filter=%d filterType=%d\n", + // ii, jj, pRfmCoeff->vmeCoeffs[ii].filterType[jj]); + return 1; + } #endif - filtC->coeffs[ii].filtSections[jj] =pRfmCoeff->vmeCoeffs[ii].filtSections[jj]; - filtC->coeffs[ii].sType[jj] = pRfmCoeff->vmeCoeffs[ii].sType[jj]; - fmt->inputs[ii].rmpcmp[jj] = pRfmCoeff->vmeCoeffs[ii].ramp[jj]; - fmt->inputs[ii].timeout[jj] = pRfmCoeff->vmeCoeffs[ii].timout[jj]; - - if (filtC->coeffs[ii].filterType[jj] == 0) { - if (filtC->coeffs[ii].filtSections[jj] > 10) { - // printk("Corrupted Epics data: module=%d filter=%d filterType=%d filtSections=%d\n", - // ii, jj, pRfmCoeff->vmeCoeffs[ii].filterType[jj], - // filtC->coeffs[ii].filtSections[jj]); - return 1; - } - for(kk=0;kk<filtC->coeffs[ii].filtSections[jj]*4+1;kk++) { - filtC->coeffs[ii].filtCoeff[jj][kk] = pRfmCoeff->vmeCoeffs[ii].filtCoeff[jj][kk]; - } - } - } + filtC->coeffs[ ii ].filtSections[ jj ] = + pRfmCoeff->vmeCoeffs[ ii ].filtSections[ jj ]; + filtC->coeffs[ ii ].sType[ jj ] = + pRfmCoeff->vmeCoeffs[ ii ].sType[ jj ]; + fmt->inputs[ ii ].rmpcmp[ jj ] = + pRfmCoeff->vmeCoeffs[ ii ].ramp[ jj ]; + fmt->inputs[ ii ].timeout[ jj ] = + pRfmCoeff->vmeCoeffs[ ii ].timout[ jj ]; + + if ( filtC->coeffs[ ii ].filterType[ jj ] == 0 ) + { + if ( filtC->coeffs[ ii ].filtSections[ jj ] > 10 ) + { + // printk("Corrupted Epics data: module=%d filter=%d + // filterType=%d filtSections=%d\n", ii, jj, + // pRfmCoeff->vmeCoeffs[ii].filterType[jj], + // filtC->coeffs[ii].filtSections[jj]); + return 1; + } + for ( kk = 0; + kk < filtC->coeffs[ ii ].filtSections[ jj ] * 4 + 1; + kk++ ) + { + filtC->coeffs[ ii ].filtCoeff[ jj ][ kk ] = + pRfmCoeff->vmeCoeffs[ ii ].filtCoeff[ jj ][ kk ]; + } + } + } + } } - } - return 0; + return 0; } - /**************************************************/ /* Read in new coeffs while running - - One filter bank at a time. - - One SOS at a time. */ + - One filter bank at a time. + - One SOS at a time. */ /**************************************************/ -/// @brief Read in filter coeffs from shared memory while code is running ie filter reload initiated. +/// @brief Read in filter coeffs from shared memory while code is running ie +/// filter reload initiated. /// @param[in,out] *filtC Pointer to coeffs in local memory /// @param[in] *fmt Pointer to filter data in local memory /// @param[in] modNum1 ID number of the filter module @@ -344,187 +379,267 @@ inline int readCoefVme(COEF *filtC,FILT_MOD *fmt, int bF, int sF, volatile VME_C /// @param[in] cycle Code cycle number /// @param[in] *pRfmCoeff Pointer to coeffs in shared memory /// @param[in] *changed Pointer to filter coef change flag memory. -int readCoefVme2(COEF *filtC,FILT_MOD *fmt, int modNum1, int filtNum, int cycle, volatile VME_COEF *pRfmCoeff, int *changed) +int +readCoefVme2( COEF* filtC, + FILT_MOD* fmt, + int modNum1, + int filtNum, + int cycle, + volatile VME_COEF* pRfmCoeff, + int* changed ) { - unsigned int ii, kk, jj; + unsigned int ii, kk, jj; #ifdef FIR_FILTERS - unsigned int hh; + unsigned int hh; #endif - double temp; - static VME_FM_OP_COEF localCoeff; - + double temp; + static VME_FM_OP_COEF localCoeff; #ifdef FIR_FILTERS -# define MAX_UPDATE_CYCLE (MAX_FIR_SO_SECTIONS+1) - static double localFirFiltCoeff[FILTERS][MAX_FIR_COEFFS]; +#define MAX_UPDATE_CYCLE ( MAX_FIR_SO_SECTIONS + 1 ) + static double localFirFiltCoeff[ FILTERS ][ MAX_FIR_COEFFS ]; #else -# define MAX_UPDATE_CYCLE (MAX_SO_SECTIONS+1) +#define MAX_UPDATE_CYCLE ( MAX_SO_SECTIONS + 1 ) #endif - int type = pRfmCoeff->vmeCoeffs[modNum1].filterType[filtNum]; + int type = pRfmCoeff->vmeCoeffs[ modNum1 ].filterType[ filtNum ]; #ifdef FIR_FILTERS - if (type < 0 || type > MAX_FIR_MODULES) { - // printk("Vme2 bad Epics filter type: module=%d filter=%d filterType=%d\n", - // modNum1, filtNum, type); - } + if ( type < 0 || type > MAX_FIR_MODULES ) + { + // printk("Vme2 bad Epics filter type: module=%d filter=%d + // filterType=%d\n", modNum1, filtNum, type); + } #endif - // printf("readCoefVme2: module=%d filter=%d filterType=%d\n", modNum1, filtNum, type); - - ii = 0; - if (cycle == 0) { - for (ii = 0; ii < 10; ii++) changed[ii] = 0; - ii = pRfmCoeff->vmeCoeffs[modNum1].filtSections[filtNum]; - if (filtNum == 0) localCoeff.crc = 0; - localCoeff.crc = crc_ptr((char *)&ii, sizeof(int), localCoeff.crc); - if (((ii>0) && (ii<11)) || ((ii>10) && (type>0))) - { - //printf("vme2: module=%d filter=%d type=%d\n", modNum1, filtNum, type); - localCoeff.filtSections[filtNum] = ii; - localCoeff.filterType[filtNum] = type; - localCoeff.sType[filtNum] = pRfmCoeff->vmeCoeffs[modNum1].sType[filtNum]; - localCoeff.ramp[filtNum] = pRfmCoeff->vmeCoeffs[modNum1].ramp[filtNum]; - localCoeff.timout[filtNum] = pRfmCoeff->vmeCoeffs[modNum1].timout[filtNum]; - localCoeff.crc = crc_ptr ((char *)&(localCoeff.sType[filtNum]), sizeof(int), localCoeff.crc); - localCoeff.crc = crc_ptr ((char *)&(localCoeff.ramp[filtNum]), sizeof(int), localCoeff.crc); - localCoeff.crc = crc_ptr ((char *)&(localCoeff.timout[filtNum]), sizeof(int), localCoeff.crc); - ii = 1; - } - else - { - //printf("vme2:off module=%d filter=%d type=%d\n", modNum1, filtNum, type); - /* Turn filter status readback off */ - fmt->inputs[modNum1].opSwitchP &= ~pow2_out[filtNum]; - filtC->coeffs[modNum1].filtSections[filtNum] = 0; - filtC->coeffs[modNum1].filterType[filtNum] = 0; - for (ii = 0; ii < 10; ii++) changed[ii] = 1; - localCoeff.filtSections[filtNum] = 0; - ii = MAX_UPDATE_CYCLE; - } - } else if (cycle > 0 && cycle < MAX_UPDATE_CYCLE ) { - if (cycle == 1) { - if (type > 0) { + // printf("readCoefVme2: module=%d filter=%d filterType=%d\n", modNum1, + // filtNum, type); + + ii = 0; + if ( cycle == 0 ) + { + for ( ii = 0; ii < 10; ii++ ) + changed[ ii ] = 0; + ii = pRfmCoeff->vmeCoeffs[ modNum1 ].filtSections[ filtNum ]; + if ( filtNum == 0 ) + localCoeff.crc = 0; + localCoeff.crc = crc_ptr( (char*)&ii, sizeof( int ), localCoeff.crc ); + if ( ( ( ii > 0 ) && ( ii < 11 ) ) || ( ( ii > 10 ) && ( type > 0 ) ) ) + { + // printf("vme2: module=%d filter=%d type=%d\n", modNum1, filtNum, + // type); + localCoeff.filtSections[ filtNum ] = ii; + localCoeff.filterType[ filtNum ] = type; + localCoeff.sType[ filtNum ] = + pRfmCoeff->vmeCoeffs[ modNum1 ].sType[ filtNum ]; + localCoeff.ramp[ filtNum ] = + pRfmCoeff->vmeCoeffs[ modNum1 ].ramp[ filtNum ]; + localCoeff.timout[ filtNum ] = + pRfmCoeff->vmeCoeffs[ modNum1 ].timout[ filtNum ]; + localCoeff.crc = crc_ptr( (char*)&( localCoeff.sType[ filtNum ] ), + sizeof( int ), + localCoeff.crc ); + localCoeff.crc = crc_ptr( (char*)&( localCoeff.ramp[ filtNum ] ), + sizeof( int ), + localCoeff.crc ); + localCoeff.crc = crc_ptr( (char*)&( localCoeff.timout[ filtNum ] ), + sizeof( int ), + localCoeff.crc ); + ii = 1; + } + else + { + // printf("vme2:off module=%d filter=%d type=%d\n", modNum1, + // filtNum, type); + /* Turn filter status readback off */ + fmt->inputs[ modNum1 ].opSwitchP &= ~pow2_out[ filtNum ]; + filtC->coeffs[ modNum1 ].filtSections[ filtNum ] = 0; + filtC->coeffs[ modNum1 ].filterType[ filtNum ] = 0; + for ( ii = 0; ii < 10; ii++ ) + changed[ ii ] = 1; + localCoeff.filtSections[ filtNum ] = 0; + ii = MAX_UPDATE_CYCLE; + } + } + else if ( cycle > 0 && cycle < MAX_UPDATE_CYCLE ) + { + if ( cycle == 1 ) + { + if ( type > 0 ) + { #ifdef FIR_FILTERS - /* FIR filter */ - temp = pRfmCoeff->firFiltCoeff[type-1][filtNum][0]; - if (filtC->firFiltCoeff[type-1][filtNum][0] != temp) changed[filtNum]++; - localFirFiltCoeff[filtNum][0] = temp; - localCoeff.crc = crc_ptr ((char *)&temp, sizeof(double), localCoeff.crc); - //printf("gain = %f\n", temp); + /* FIR filter */ + temp = pRfmCoeff->firFiltCoeff[ type - 1 ][ filtNum ][ 0 ]; + if ( filtC->firFiltCoeff[ type - 1 ][ filtNum ][ 0 ] != temp ) + changed[ filtNum ]++; + localFirFiltCoeff[ filtNum ][ 0 ] = temp; + localCoeff.crc = + crc_ptr( (char*)&temp, sizeof( double ), localCoeff.crc ); + // printf("gain = %f\n", temp); #endif - } else { - /* Assign filter gain value */ - temp = pRfmCoeff->vmeCoeffs[modNum1].filtCoeff[filtNum][0]; - if (filtC->coeffs[modNum1].filtCoeff[filtNum][0] != temp) changed[filtNum]++; - //if (localCoeff.filtCoeff[filtNum][0] != temp) changed[filtNum]++; - localCoeff.filtCoeff[filtNum][0] = temp; - localCoeff.crc = crc_ptr ((char *)&(localCoeff.filtCoeff[filtNum][0]), sizeof(double), localCoeff.crc); - } - } - { - /* Assign second-order sections */ - int to = cycle * 4 + 1; - for (kk = to - 4; kk < to; kk++) { - if (type > 0) { + } + else + { + /* Assign filter gain value */ + temp = + pRfmCoeff->vmeCoeffs[ modNum1 ].filtCoeff[ filtNum ][ 0 ]; + if ( filtC->coeffs[ modNum1 ].filtCoeff[ filtNum ][ 0 ] != + temp ) + changed[ filtNum ]++; + // if (localCoeff.filtCoeff[filtNum][0] != temp) + // changed[filtNum]++; + localCoeff.filtCoeff[ filtNum ][ 0 ] = temp; + localCoeff.crc = + crc_ptr( (char*)&( localCoeff.filtCoeff[ filtNum ][ 0 ] ), + sizeof( double ), + localCoeff.crc ); + } + } + { + /* Assign second-order sections */ + int to = cycle * 4 + 1; + for ( kk = to - 4; kk < to; kk++ ) + { + if ( type > 0 ) + { #ifdef FIR_FILTERS - /* FIR filter */ - temp = pRfmCoeff->firFiltCoeff[type-1][filtNum][kk]; - if (filtC->firFiltCoeff[type-1][filtNum][kk] != temp) changed[filtNum]++; - localFirFiltCoeff[filtNum][kk] = temp; - localCoeff.crc = crc_ptr ((char *)&temp, sizeof(double), localCoeff.crc); - //printf("%f ", temp); + /* FIR filter */ + temp = pRfmCoeff->firFiltCoeff[ type - 1 ][ filtNum ][ kk ]; + if ( filtC->firFiltCoeff[ type - 1 ][ filtNum ][ kk ] != + temp ) + changed[ filtNum ]++; + localFirFiltCoeff[ filtNum ][ kk ] = temp; + localCoeff.crc = crc_ptr( + (char*)&temp, sizeof( double ), localCoeff.crc ); + // printf("%f ", temp); #endif - } else { - temp = pRfmCoeff->vmeCoeffs[modNum1].filtCoeff[filtNum][kk]; - if (filtC->coeffs[modNum1].filtCoeff[filtNum][kk] != temp) changed[filtNum]++; - //if (localCoeff.filtCoeff[filtNum][kk] != temp) changed[filtNum]++; - localCoeff.filtCoeff[filtNum][kk] = temp; - localCoeff.crc = crc_ptr ((char *)&(localCoeff.filtCoeff[filtNum][kk]), sizeof(double), localCoeff.crc); - } - } - //if (type > 0) printf("\n"); - if (localCoeff.filtSections[filtNum] > cycle) ii = cycle + 1; - else ii = MAX_UPDATE_CYCLE; - } - } else if (cycle == MAX_UPDATE_CYCLE) { - /* Make sure all numbers check out OK */ - if (filtNum == 9) { /* Last filter loaded in this filter bank */ - unsigned int vme_crc = pRfmCoeff->vmeCoeffs[modNum1].crc; - if (localCoeff.crc != vme_crc) { - // printk("vme_crc = 0x%x; local crc = 0x%x\n", vme_crc, localCoeff.crc); - // return -1; - } - } - if(localCoeff.filtSections[filtNum]) - { - - /* Reset filter history only if its coefficients modified */ - for(jj=0;jj<FILTERS;jj++) { - if (changed[jj]) { - if (type) { /* FIR filter */ + } + else + { + temp = pRfmCoeff->vmeCoeffs[ modNum1 ] + .filtCoeff[ filtNum ][ kk ]; + if ( filtC->coeffs[ modNum1 ].filtCoeff[ filtNum ][ kk ] != + temp ) + changed[ filtNum ]++; + // if (localCoeff.filtCoeff[filtNum][kk] != temp) + // changed[filtNum]++; + localCoeff.filtCoeff[ filtNum ][ kk ] = temp; + localCoeff.crc = crc_ptr( + (char*)&( localCoeff.filtCoeff[ filtNum ][ kk ] ), + sizeof( double ), + localCoeff.crc ); + } + } + // if (type > 0) printf("\n"); + if ( localCoeff.filtSections[ filtNum ] > cycle ) + ii = cycle + 1; + else + ii = MAX_UPDATE_CYCLE; + } + } + else if ( cycle == MAX_UPDATE_CYCLE ) + { + /* Make sure all numbers check out OK */ + if ( filtNum == 9 ) + { /* Last filter loaded in this filter bank */ + unsigned int vme_crc = pRfmCoeff->vmeCoeffs[ modNum1 ].crc; + if ( localCoeff.crc != vme_crc ) + { + // printk("vme_crc = 0x%x; local crc = 0x%x\n", vme_crc, + // localCoeff.crc); return -1; + } + } + if ( localCoeff.filtSections[ filtNum ] ) + { + + /* Reset filter history only if its coefficients modified */ + for ( jj = 0; jj < FILTERS; jj++ ) + { + if ( changed[ jj ] ) + { + if ( type ) + { /* FIR filter */ #ifdef FIR_FILTERS - for (kk = 0; kk < FIR_POLYPHASE_SIZE; kk++) - for (hh = 0; hh < FIR_TAPS; hh++) - filtC->firHistory[type-1][jj][kk][hh] = 0.0; + for ( kk = 0; kk < FIR_POLYPHASE_SIZE; kk++ ) + for ( hh = 0; hh < FIR_TAPS; hh++ ) + filtC + ->firHistory[ type - 1 ][ jj ][ kk ][ hh ] = + 0.0; #endif - } else { - for(kk=0;kk<MAX_HISTRY;kk++) - filtC->coeffs[modNum1].filtHist[jj][kk] = 0.0; - } - } - } - - /* Do not clear decimation history when filters are reloaded */ + } + else + { + for ( kk = 0; kk < MAX_HISTRY; kk++ ) + filtC->coeffs[ modNum1 ].filtHist[ jj ][ kk ] = 0.0; + } + } + } + + /* Do not clear decimation history when filters are reloaded */ #if 0 /* Clear decimation history */ for(jj = 0; jj < 8; jj++) filtC->coeffs[modNum1].decHist[jj] = 0; #endif - filtC->coeffs[modNum1].filtSections[filtNum] = localCoeff.filtSections[filtNum]; - filtC->coeffs[modNum1].filterType[filtNum] = localCoeff.filterType[filtNum]; - filtC->coeffs[modNum1].sType[filtNum] = localCoeff.sType[filtNum]; - fmt->inputs[modNum1].rmpcmp[filtNum] = localCoeff.ramp[filtNum]; - fmt->inputs[modNum1].timeout[filtNum] = localCoeff.timout[filtNum]; - if (type > 0) { + filtC->coeffs[ modNum1 ].filtSections[ filtNum ] = + localCoeff.filtSections[ filtNum ]; + filtC->coeffs[ modNum1 ].filterType[ filtNum ] = + localCoeff.filterType[ filtNum ]; + filtC->coeffs[ modNum1 ].sType[ filtNum ] = + localCoeff.sType[ filtNum ]; + fmt->inputs[ modNum1 ].rmpcmp[ filtNum ] = + localCoeff.ramp[ filtNum ]; + fmt->inputs[ modNum1 ].timeout[ filtNum ] = + localCoeff.timout[ filtNum ]; + if ( type > 0 ) + { #ifdef FIR_FILTERS - for(kk=0;kk<filtC->coeffs[modNum1].filtSections[filtNum]*4+1;kk++) - filtC->firFiltCoeff[type-1][filtNum][kk] = localFirFiltCoeff[filtNum][kk]; + for ( kk = 0; kk < + filtC->coeffs[ modNum1 ].filtSections[ filtNum ] * 4 + 1; + kk++ ) + filtC->firFiltCoeff[ type - 1 ][ filtNum ][ kk ] = + localFirFiltCoeff[ filtNum ][ kk ]; #endif - } else { - // filtC->biquad = localCoeff.biquad; - for(kk=0;kk<filtC->coeffs[modNum1].filtSections[filtNum]*4+1;kk++) - filtC->coeffs[modNum1].filtCoeff[filtNum][kk] = localCoeff.filtCoeff[filtNum][kk]; - } - } - ii = 0; - } else { - ii = 0; + } + else + { + // filtC->biquad = localCoeff.biquad; + for ( kk = 0; kk < + filtC->coeffs[ modNum1 ].filtSections[ filtNum ] * 4 + 1; + kk++ ) + filtC->coeffs[ modNum1 ].filtCoeff[ filtNum ][ kk ] = + localCoeff.filtCoeff[ filtNum ][ kk ]; + } + } + ii = 0; } - return(ii); + else + { + ii = 0; + } + return ( ii ); #undef MAX_UPDATE_CYCLE } -/// Filter module update globals -struct filtResetId { - int fmResetCoeff; - int fmResetCounter; - int fmSubCounter; - FILT_MOD *fmResetDsp; - int changed[FILTERS]; -} filtResetId[FILTERS] = { - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}}, - {0,0,0,0,{0,0,0,0,0,0,0,0,0,0}} -}; +/// Filter module update globals +struct filtResetId +{ + int fmResetCoeff; + int fmResetCounter; + int fmSubCounter; + FILT_MOD* fmResetDsp; + int changed[ FILTERS ]; +} filtResetId[ FILTERS ] = { { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }, + { 0, 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } }; /***************************************/ /* Check for history resets or new coeffs for filter banks */ @@ -537,74 +652,105 @@ struct filtResetId { /// @param[in] totMod Total number of filter modules /// @param[in] *pRfmCoeff Pointer to filter coefs in shared memory. /// @param[in] id System ID number (old HEPI only). -inline void checkFiltResetId(int bankNum, FILT_MOD *pL, volatile FILT_MOD *dspVme, COEF *pC, int totMod, volatile VME_COEF *pRfmCoeff, int id) +inline void +checkFiltResetId( int bankNum, + FILT_MOD* pL, + volatile FILT_MOD* dspVme, + COEF* pC, + int totMod, + volatile VME_COEF* pRfmCoeff, + int id ) { - int jj,kk; + int jj, kk; #ifdef FIR_FILTERS - int hh; + int hh; #endif - int status; - - if (id < 0 || id > 9) return; - - if (filtResetId[id].fmResetCoeff) { - /* Coeff reset in progress */ - if (filtResetId[id].fmResetDsp == pL) { /* Coeff reset is done for this subsystem */ - /* printf("Coeff reset done\n"); */ - filtResetId[id].fmSubCounter = readCoefVme2(pC, pL, (filtResetId[id].fmResetCoeff - 1), filtResetId[id].fmResetCounter, filtResetId[id].fmSubCounter, pRfmCoeff, filtResetId[id].changed); - if (filtResetId[id].fmSubCounter == -1) { - dspVme->coef_load_error = -1; - filtResetId[id].fmResetCoeff = 0; - filtResetId[id].fmResetCounter = 0; - } else if (filtResetId[id].fmSubCounter == 0) { - filtResetId[id].fmResetCounter ++; - if (filtResetId[id].fmResetCounter >= FILTERS) { - filtResetId[id].fmResetCounter = 0; - dspVme->coef_load_error = filtResetId[id].fmResetCoeff; - /* printf("dspVme->coef_load_error = %d\n", dspVme->coef_load_error ); */ - filtResetId[id].fmResetCoeff = 0; - } - } - } else /* Do nothing if this is a call for another subsystem */ - ; - } else if (bankNum >=0 && bankNum < totMod) { - /* Check for Reset History request */ - status = (dspVme->inputs[bankNum].rset & 0x3); - if(status) - { - /* Reset the flag */ - dspVme->inputs[bankNum].rset = 0; - } - - /* Filter history reset request */ - if(status & 2) - { - /* Clear out filter bank histories */ - for(jj=0;jj<FILTERS;jj++) { + int status; + + if ( id < 0 || id > 9 ) + return; + + if ( filtResetId[ id ].fmResetCoeff ) + { + /* Coeff reset in progress */ + if ( filtResetId[ id ].fmResetDsp == pL ) + { /* Coeff reset is done for this subsystem */ + /* printf("Coeff reset done\n"); */ + filtResetId[ id ].fmSubCounter = + readCoefVme2( pC, + pL, + ( filtResetId[ id ].fmResetCoeff - 1 ), + filtResetId[ id ].fmResetCounter, + filtResetId[ id ].fmSubCounter, + pRfmCoeff, + filtResetId[ id ].changed ); + if ( filtResetId[ id ].fmSubCounter == -1 ) + { + dspVme->coef_load_error = -1; + filtResetId[ id ].fmResetCoeff = 0; + filtResetId[ id ].fmResetCounter = 0; + } + else if ( filtResetId[ id ].fmSubCounter == 0 ) + { + filtResetId[ id ].fmResetCounter++; + if ( filtResetId[ id ].fmResetCounter >= FILTERS ) + { + filtResetId[ id ].fmResetCounter = 0; + dspVme->coef_load_error = filtResetId[ id ].fmResetCoeff; + /* printf("dspVme->coef_load_error = %d\n", + * dspVme->coef_load_error ); */ + filtResetId[ id ].fmResetCoeff = 0; + } + } + } + else /* Do nothing if this is a call for another subsystem */ + ; + } + else if ( bankNum >= 0 && bankNum < totMod ) + { + /* Check for Reset History request */ + status = ( dspVme->inputs[ bankNum ].rset & 0x3 ); + if ( status ) + { + /* Reset the flag */ + dspVme->inputs[ bankNum ].rset = 0; + } + + /* Filter history reset request */ + if ( status & 2 ) + { + /* Clear out filter bank histories */ + for ( jj = 0; jj < FILTERS; jj++ ) + { #ifdef FIR_FILTERS - int type = pC->coeffs[bankNum].filterType[jj]; - if (type > 0) { - for (kk = 0; kk < FIR_POLYPHASE_SIZE; kk++) - for (hh = 0; hh < FIR_TAPS; hh++) - pC->firHistory[type-1][jj][kk][hh] = 0.0; - } else + int type = pC->coeffs[ bankNum ].filterType[ jj ]; + if ( type > 0 ) + { + for ( kk = 0; kk < FIR_POLYPHASE_SIZE; kk++ ) + for ( hh = 0; hh < FIR_TAPS; hh++ ) + pC->firHistory[ type - 1 ][ jj ][ kk ][ hh ] = 0.0; + } + else #endif - for(kk=0;kk<MAX_HISTRY;kk++) - pC->coeffs[bankNum].filtHist[jj][kk] = 0.0; - } - - /* Clear decimation history */ - for(jj = 0; jj < 8; jj++) - pC->coeffs[bankNum].decHist[jj] = 0; - } - - /* Check if new coeffs */ - if (status & 1) { - /* printf("New coeff request; bank=%d \n", bankNum); */ - filtResetId[id].fmResetCoeff = bankNum + 1; - filtResetId[id].fmResetDsp = pL; - } else filtResetId[id].fmResetCoeff = 0; - } + for ( kk = 0; kk < MAX_HISTRY; kk++ ) + pC->coeffs[ bankNum ].filtHist[ jj ][ kk ] = 0.0; + } + + /* Clear decimation history */ + for ( jj = 0; jj < 8; jj++ ) + pC->coeffs[ bankNum ].decHist[ jj ] = 0; + } + + /* Check if new coeffs */ + if ( status & 1 ) + { + /* printf("New coeff request; bank=%d \n", bankNum); */ + filtResetId[ id ].fmResetCoeff = bankNum + 1; + filtResetId[ id ].fmResetDsp = pL; + } + else + filtResetId[ id ].fmResetCoeff = 0; + } } /// @brief Calls checkFiltResetId with dummy sys id of 0 @@ -614,8 +760,15 @@ inline void checkFiltResetId(int bankNum, FILT_MOD *pL, volatile FILT_MOD *dspVm /// @param[in,out] *pC Pointer to filter coefs in local memory. /// @param[in] totMod Total number of filter modules /// @param[in] *pRfmCoeff Pointer to filter coefs in shared memory. -inline void checkFiltReset(int bankNum, FILT_MOD *pL, volatile FILT_MOD *dspVme, COEF *pC, int totMod, volatile VME_COEF *pRfmCoeff) { - checkFiltResetId(bankNum, pL, dspVme, pC, totMod, pRfmCoeff, 0); +inline void +checkFiltReset( int bankNum, + FILT_MOD* pL, + volatile FILT_MOD* dspVme, + COEF* pC, + int totMod, + volatile VME_COEF* pRfmCoeff ) +{ + checkFiltResetId( bankNum, pL, dspVme, pC, totMod, pRfmCoeff, 0 ); } /// @brief Initialize filter module variables on code startup @@ -625,60 +778,65 @@ inline void checkFiltReset(int bankNum, FILT_MOD *pL, volatile FILT_MOD *dspVme, /// @param[in] totMod Total number of filter modules /// @param[in] *pRfmCoeff Pointer to filter coeffs in shared memory /// @param[in] id System id (old HEPI only) -inline int -initVarsId(FILT_MOD *pL, - volatile FILT_MOD *pV, - COEF *pC, - int totMod, - volatile VME_COEF *pRfmCoeff, - int id) /* System id (HEPI) */ +inline int initVarsId( FILT_MOD* pL, + volatile FILT_MOD* pV, + COEF* pC, + int totMod, + volatile VME_COEF* pRfmCoeff, + int id ) /* System id (HEPI) */ { - int ii,kk,hh; + int ii, kk, hh; #ifdef FIR_FILTERS - int ll; + int ll; - for (ii = 0; ii < MAX_FIR_MODULES; ii++) - for (kk = 0; kk < FILTERS; kk++) - for (ll = 0; ll < FIR_POLYPHASE_SIZE; ll++) - for (hh = 0; hh < FIR_TAPS; hh++) - pC->firHistory[ii][kk][ll][hh] = 0.0; + for ( ii = 0; ii < MAX_FIR_MODULES; ii++ ) + for ( kk = 0; kk < FILTERS; kk++ ) + for ( ll = 0; ll < FIR_POLYPHASE_SIZE; ll++ ) + for ( hh = 0; hh < FIR_TAPS; hh++ ) + pC->firHistory[ ii ][ kk ][ ll ][ hh ] = 0.0; #endif - /*Initialize all the variables */ - for(ii=0;ii<totMod;ii++){ - - for(kk=0;kk<FILTERS;kk++){ - /*set History*/ - for(hh=0;hh<MAX_HISTRY;hh++){ - pC->coeffs[ii].filtHist[kk][hh] = 0; - } - - pL->inputs[ii].cnt[kk] = 0; - } + /*Initialize all the variables */ + for ( ii = 0; ii < totMod; ii++ ) + { - /*set decimation history*/ - for(hh=0;hh<8;hh++){ - pC->coeffs[ii].decHist[hh] = 0; + for ( kk = 0; kk < FILTERS; kk++ ) + { + /*set History*/ + for ( hh = 0; hh < MAX_HISTRY; hh++ ) + { + pC->coeffs[ ii ].filtHist[ kk ][ hh ] = 0; + } + + pL->inputs[ ii ].cnt[ kk ] = 0; + } + + /*set decimation history*/ + for ( hh = 0; hh < 8; hh++ ) + { + pC->coeffs[ ii ].decHist[ hh ] = 0; + } + + /*set switch/offsets/gains/limits*/ + pL->inputs[ ii ].opSwitchE = pV->inputs[ ii ].opSwitchE; + + pL->inputs[ ii ].opSwitchP = 0; + pL->inputs[ ii ].rset = 0; + pL->inputs[ ii ].offset = pV->inputs[ ii ].offset; + pL->inputs[ ii ].outgain = pV->inputs[ ii ].outgain; + pL->inputs[ ii ].limiter = pV->inputs[ ii ].limiter; + pL->inputs[ ii ].gain_ramp_time = pV->inputs[ ii ].gain_ramp_time; + RampParamInit( &offset_ramp[ ii ][ id ], + ( pL->inputs[ ii ].opSwitchE & OPSWITCH_OFFSET_ENABLE ) + ? pL->inputs[ ii ].offset + : 0.0, + FE_RATE ); + RampParamInit( + &gain_ramp[ ii ][ id ], pL->inputs[ ii ].outgain, FE_RATE ); } - - /*set switch/offsets/gains/limits*/ - pL->inputs[ii].opSwitchE = - pV->inputs[ii].opSwitchE; - - pL->inputs[ii].opSwitchP = 0; - pL->inputs[ii].rset = 0; - pL->inputs[ii].offset = pV->inputs[ii].offset; - pL->inputs[ii].outgain = pV->inputs[ii].outgain; - pL->inputs[ii].limiter = pV->inputs[ii].limiter; - pL->inputs[ii].gain_ramp_time = pV->inputs[ii].gain_ramp_time; - RampParamInit(&offset_ramp[ii][id], - (pL->inputs[ii].opSwitchE & OPSWITCH_OFFSET_ENABLE)?pL->inputs[ii].offset:0.0, - FE_RATE); - RampParamInit(&gain_ramp[ii][id],pL->inputs[ii].outgain,FE_RATE); - } - - return readCoefVme(pC, pL, 0, totMod, pRfmCoeff); + + return readCoefVme( pC, pL, 0, totMod, pRfmCoeff ); } /// @brief Calls initVarsId with dummy sys id of 0 @@ -688,13 +846,18 @@ initVarsId(FILT_MOD *pL, /// @param[in] totMod Total number of filter modules /// @param[in] *pRfmCoeff Pointer to filter coeffs in shared memory inline int -initVars(FILT_MOD *pL, volatile FILT_MOD *pV, COEF *pC, int totMod, - volatile VME_COEF *pRfmCoeff) { - return initVarsId(pL, pV, pC, totMod, pRfmCoeff, 0); +initVars( FILT_MOD* pL, + volatile FILT_MOD* pV, + COEF* pC, + int totMod, + volatile VME_COEF* pRfmCoeff ) +{ + return initVarsId( pL, pV, pC, totMod, pRfmCoeff, 0 ); } -/* This module added to hanle all input, calculations and outputs as doubles. This module also - incorporates the input module, done separately above for older systems. */ +/* This module added to hanle all input, calculations and outputs as doubles. + This module also incorporates the input module, done separately above for + older systems. */ /* Mask logic table: * M-mask; C-control input; S0-current bit state; S1-new bit state @@ -704,12 +867,13 @@ initVars(FILT_MOD *pL, volatile FILT_MOD *pV, COEF *pC, int totMod, 0 1 0 0 1 0 0 0 1 1 0 1 - 0 0 1 1 - 0 1 1 1 - 1 0 1 0 - 1 1 1 1 + 0 0 1 1 + 0 1 1 1 + 1 0 1 0 + 1 1 1 1 */ -/// @brief This function is called by filterModuleD, or, in the case of FMC2 parts, user code directly to +/// @brief This function is called by filterModuleD, or, in the case of FMC2 +/// parts, user code directly to ///< perform CDS standard filter module calculations. /// @param[in,out] *pFilt Filter Module Data /// @param[in] *pC Filter module coefficients @@ -722,300 +886,404 @@ initVars(FILT_MOD *pL, volatile FILT_MOD *pV, COEF *pC, int totMod, /// @param[in] ramp_in Ramping time from user model. /// @return Output of IIR/FIR filter calculations. double -filterModuleD2(FILT_MOD *pFilt, /* Filter module data */ - COEF *pC, /* Filter coefficients */ - int modNum, /* Filter module number */ - double filterInput, /* Input data sample (output from funtcion inputModule()) */ - int fltrCtrlVal, /* Filter control value */ - int mask, /* Mask of bits to act upon */ - double offset_in, - double gain_in, - double ramp_in) +filterModuleD2( FILT_MOD* pFilt, /* Filter module data */ + COEF* pC, /* Filter coefficients */ + int modNum, /* Filter module number */ + double filterInput, /* Input data sample (output from funtcion + inputModule()) */ + int fltrCtrlVal, /* Filter control value */ + int mask, /* Mask of bits to act upon */ + double offset_in, + double gain_in, + double ramp_in ) { - int ix; - UINT32 opSwitchE; - int ii, jj, kk, ramp, timeout; - int sw, sw_out, sType, sw_in; - double filtData; - float avg, compare; - double output; - double fmInput; - int id = 0; /* System number (HEPI) */ - extern int cycleNum; - - /* Do the shift to match the bits in the the opSwitchE variable so I can do "==" comparisons */ - UINT32 opSwitchP = pFilt->inputs[modNum].opSwitchP >> 1; - - fltrCtrlVal &= 0xffff; /* Limit to the 16 bits */ - - /* decode arrays for operator switches */ - if (mask != 0 && (fltrCtrlVal >= 0)) { - UINT32 fltrSwitch = 0; - UINT32 epicsExclude = 0; - if (mask > 0) { - for (ix = 0; ix < 13; ix++) { - if (mask & (1<<ix)) { - // Keep the current bit value - // - if (opSwitchP & fltrConst[ix]) fltrSwitch |= fltrConst[ix]; - // Change only if bit-mask is set - // - if (fltrCtrlVal%2 == 1) { - fltrSwitch |= fltrConst[ix]; - } else { - fltrSwitch &= ~fltrConst[ix]; - } - epicsExclude |= fltrConst[ix]; - } - fltrCtrlVal = fltrCtrlVal>>1; - } - // Assign offset, gain and ramp value bits (last 3 bits in 16-bit control input) - epicsExclude |= (mask & 0xe000) << 16; - - if (mask & 0x2000) pFilt->inputs[modNum].offset = offset_in; /* Assign local offset */ - if (mask & 0x4000) pFilt->inputs[modNum].outgain = gain_in; - if (mask & 0x8000) pFilt->inputs[modNum].gain_ramp_time = ramp_in; - } - pFilt->inputs[modNum].mask = epicsExclude; - pFilt->inputs[modNum].control = fltrSwitch; - opSwitchE = (pFilt->inputs[modNum].opSwitchE & ~epicsExclude) | fltrSwitch; - pFilt->inputs[modNum].opSwitchE = opSwitchE; - } - else { - pFilt->inputs[modNum].mask = 0; - pFilt->inputs[modNum].control = 0; - opSwitchE = pFilt->inputs[modNum].opSwitchE; - } - - fmInput = 0; - - /* Load the filter input testpoint to the input value. */ - pFilt->data[modNum].filterInput = (filterInput + fmInput); - - /* Add excitation signal to input value. */ - fmInput += (double)pFilt->data[modNum].exciteInput; - - /* If input is turned on, add the filterInput value. */ - if (pFilt->inputs[modNum].opSwitchE & OPSWITCH_INPUT_ENABLE) - fmInput += filterInput; - pFilt->data[modNum].inputTestpoint = fmInput; - - /* If the offset is enabled, add the filter module offset value. */ - if (pFilt->inputs[modNum].opSwitchE & OPSWITCH_OFFSET_ENABLE) { - //fmInput += pFilt->inputs[modNum].offset; - - if (pFilt->inputs[modNum].offset != offset_ramp[modNum][id].req) { - RampParamLoad(&offset_ramp[modNum][id],pFilt->inputs[modNum].offset,pFilt->inputs[modNum].gain_ramp_time,rate); - pFilt->inputs[modNum].opSwitchP |= 0x20000000; + int ix; + UINT32 opSwitchE; + int ii, jj, kk, ramp, timeout; + int sw, sw_out, sType, sw_in; + double filtData; + float avg, compare; + double output; + double fmInput; + int id = 0; /* System number (HEPI) */ + extern int cycleNum; + + /* Do the shift to match the bits in the the opSwitchE variable so I can do + * "==" comparisons */ + UINT32 opSwitchP = pFilt->inputs[ modNum ].opSwitchP >> 1; + + fltrCtrlVal &= 0xffff; /* Limit to the 16 bits */ + + /* decode arrays for operator switches */ + if ( mask != 0 && ( fltrCtrlVal >= 0 ) ) + { + UINT32 fltrSwitch = 0; + UINT32 epicsExclude = 0; + if ( mask > 0 ) + { + for ( ix = 0; ix < 13; ix++ ) + { + if ( mask & ( 1 << ix ) ) + { + // Keep the current bit value + // + if ( opSwitchP & fltrConst[ ix ] ) + fltrSwitch |= fltrConst[ ix ]; + // Change only if bit-mask is set + // + if ( fltrCtrlVal % 2 == 1 ) + { + fltrSwitch |= fltrConst[ ix ]; + } + else + { + fltrSwitch &= ~fltrConst[ ix ]; + } + epicsExclude |= fltrConst[ ix ]; + } + fltrCtrlVal = fltrCtrlVal >> 1; + } + // Assign offset, gain and ramp value bits (last 3 bits in 16-bit + // control input) + epicsExclude |= ( mask & 0xe000 ) << 16; + + if ( mask & 0x2000 ) + pFilt->inputs[ modNum ].offset = + offset_in; /* Assign local offset */ + if ( mask & 0x4000 ) + pFilt->inputs[ modNum ].outgain = gain_in; + if ( mask & 0x8000 ) + pFilt->inputs[ modNum ].gain_ramp_time = ramp_in; + } + pFilt->inputs[ modNum ].mask = epicsExclude; + pFilt->inputs[ modNum ].control = fltrSwitch; + opSwitchE = + ( pFilt->inputs[ modNum ].opSwitchE & ~epicsExclude ) | fltrSwitch; + pFilt->inputs[ modNum ].opSwitchE = opSwitchE; } - } else { - if (0.0 != offset_ramp[modNum][id].req) { - RampParamLoad(&offset_ramp[modNum][id], 0.0, pFilt->inputs[modNum].gain_ramp_time,rate); - pFilt->inputs[modNum].opSwitchP |= 0x20000000; + else + { + pFilt->inputs[ modNum ].mask = 0; + pFilt->inputs[ modNum ].control = 0; + opSwitchE = pFilt->inputs[ modNum ].opSwitchE; } - } - if (offset_ramp[modNum][id].isRamping == 0) { - pFilt->inputs[modNum].opSwitchP &= ~0x20000000; - } - fmInput += RampParamUpdate(&offset_ramp[modNum][id]); - /* Apply Filtering */ + fmInput = 0; - /* Loop through all filters */ - for (ii=0; ii<FILTERS; ii++) { - /* Do not do anything for any filter with zero filter sections */ - if (!pC->coeffs[modNum].filtSections[ii]) continue; + /* Load the filter input testpoint to the input value. */ + pFilt->data[ modNum ].filterInput = ( filterInput + fmInput ); - sw = opSwitchE & pow2_in[ii]; /* Epics screen filter on/off request bit */ - sw_out = opSwitchP & pow2_in[ii]; /* Pentium output ack bit (opSwitchP was right shifted by 1) */ + /* Add excitation signal to input value. */ + fmInput += (double)pFilt->data[ modNum ].exciteInput; - /* Filter switching type */ - sType = pC->coeffs[modNum].sType[ii]; + /* If input is turned on, add the filterInput value. */ + if ( pFilt->inputs[ modNum ].opSwitchE & OPSWITCH_INPUT_ENABLE ) + fmInput += filterInput; + pFilt->data[ modNum ].inputTestpoint = fmInput; - /* If sType is type 1X, the input will always go to filter to be calculated */ - /* If sType is type 2X, then the input will be zero if output is turned off */ - /* If sType is type 22, then the input will go to filter if filter is turning on (ramping up)*/ - sw_in = sType < 20 || sw_out || (sType == 22 && sw); + /* If the offset is enabled, add the filter module offset value. */ + if ( pFilt->inputs[ modNum ].opSwitchE & OPSWITCH_OFFSET_ENABLE ) + { + // fmInput += pFilt->inputs[modNum].offset; + + if ( pFilt->inputs[ modNum ].offset != offset_ramp[ modNum ][ id ].req ) + { + RampParamLoad( &offset_ramp[ modNum ][ id ], + pFilt->inputs[ modNum ].offset, + pFilt->inputs[ modNum ].gain_ramp_time, + rate ); + pFilt->inputs[ modNum ].opSwitchP |= 0x20000000; + } + } + else + { + if ( 0.0 != offset_ramp[ modNum ][ id ].req ) + { + RampParamLoad( &offset_ramp[ modNum ][ id ], + 0.0, + pFilt->inputs[ modNum ].gain_ramp_time, + rate ); + pFilt->inputs[ modNum ].opSwitchP |= 0x20000000; + } + } + if ( offset_ramp[ modNum ][ id ].isRamping == 0 ) + { + pFilt->inputs[ modNum ].opSwitchP &= ~0x20000000; + } + fmInput += RampParamUpdate( &offset_ramp[ modNum ][ id ] ); + + /* Apply Filtering */ + + /* Loop through all filters */ + for ( ii = 0; ii < FILTERS; ii++ ) + { + /* Do not do anything for any filter with zero filter sections */ + if ( !pC->coeffs[ modNum ].filtSections[ ii ] ) + continue; + + sw = opSwitchE & + pow2_in[ ii ]; /* Epics screen filter on/off request bit */ + sw_out = opSwitchP & pow2_in[ ii ]; /* Pentium output ack bit (opSwitchP + was right shifted by 1) */ + + /* Filter switching type */ + sType = pC->coeffs[ modNum ].sType[ ii ]; + + /* If sType is type 1X, the input will always go to filter to be + * calculated */ + /* If sType is type 2X, then the input will be zero if output is turned + * off */ + /* If sType is type 22, then the input will go to filter if filter is + * turning on (ramping up)*/ + sw_in = sType < 20 || sw_out || ( sType == 22 && sw ); #ifdef FIR_FILTERS - int filterType = pC->coeffs[modNum].filterType[ii]; - if (filterType) { - extern int cycleNum; + int filterType = pC->coeffs[ modNum ].filterType[ ii ]; + if ( filterType ) + { + extern int cycleNum; #ifdef SERVO2K - int firNum = (cycleNum / 32) % 32; + int firNum = ( cycleNum / 32 ) % 32; #endif #ifdef SERVO4K - int firNum = (cycleNum / 32) % 64; + int firNum = ( cycleNum / 32 ) % 64; #endif - //int firNum = cycleNum % 32; - //printf("cycleNum=%d; firNum=%d\n", cycleNum, firNum); - - /* FIR filter */ - --filterType; - if (cycleNum % 32) filtData = pC->prevFirOutput[filterType]; - else { - if (filterType >=0 && filterType < MAX_FIR_MODULES) { - double input = fmInput * pC->firFiltCoeff[filterType][ii][0]; /* overall input scale factor */ - filtData = fir_filter(sw_in?input:0, - &(pC->firFiltCoeff[filterType][ii][1]), - pC->coeffs[modNum].filtSections[ii]*4, - &(pC->firHistory[filterType][ii][firNum][0])); - pC->prevFirOutput[filterType] = filtData; - } else { - filtData = filterType; - // printk("module %d; filter %d; filterType = %d\n", modNum, ii, filterType); - } - } - } else + // int firNum = cycleNum % 32; + // printf("cycleNum=%d; firNum=%d\n", cycleNum, firNum); + + /* FIR filter */ + --filterType; + if ( cycleNum % 32 ) + filtData = pC->prevFirOutput[ filterType ]; + else + { + if ( filterType >= 0 && filterType < MAX_FIR_MODULES ) + { + double input = fmInput * + pC->firFiltCoeff[ filterType ][ ii ] + [ 0 ]; /* overall input scale factor */ + filtData = fir_filter( + sw_in ? input : 0, + &( pC->firFiltCoeff[ filterType ][ ii ][ 1 ] ), + pC->coeffs[ modNum ].filtSections[ ii ] * 4, + &( pC->firHistory[ filterType ][ ii ][ firNum ] + [ 0 ] ) ); + pC->prevFirOutput[ filterType ] = filtData; + } + else + { + filtData = filterType; + // printk("module %d; filter %d; filterType = %d\n", modNum, + // ii, filterType); + } + } + } + else #endif - /* Calculate filter */ - if (pC->coeffs[modNum].biquad) - filtData = iir_filter_biquad(sw_in?fmInput:0, - pC->coeffs[modNum].filtCoeff[ii], - pC->coeffs[modNum].filtSections[ii], - pC->coeffs[modNum].filtHist[ii]); - else - filtData = iir_filter(sw_in?fmInput:0, - pC->coeffs[modNum].filtCoeff[ii], - pC->coeffs[modNum].filtSections[ii], - pC->coeffs[modNum].filtHist[ii]); - - if (sw == sw_out) { /* No switching */ - if (sw) fmInput = filtData; /* Use the filtered value if the filter is turned on */ - } else { /* Switching request */ - int sTypeMod10 = sType%10; - /* Process filter switching according to output type [1-3] */ - switch (sTypeMod10) { - case 1: /* Instantenious switch */ - /* Turn output on/off according to the request */ - if ((sw_out = sw)) fmInput = filtData; /* Use the filtered value if the filter is turned on */ - break; - case 2: /* Ramp in/out filter output */ - ramp = pFilt->inputs[modNum].rmpcmp[ii]; /* Ramp slope coefficient */ - kk = pFilt->inputs[modNum].cnt[ii]; /* Ramp count */ - /* printf("kk=%d; ramp=%d; sw=%d; sw_out=%d\n", kk, ramp, sw, sw_out); */ - - if (kk == ramp) { /* Done ramping */ - /* Turn output on/off according to the request */ - if ((sw_out = sw)) fmInput = filtData; /* Use the filtered value if the filter is turned on */ - kk = 0; - } else { /* Ramping will be done */ - if (kk) { /* Currently ramping */ - double t = (double)kk / (double)ramp; /* Slope */ - if (sw) /* Turn on request */ - fmInput = (1.0 - t) * fmInput + t * filtData; - else /* Turn off request */ - fmInput = t * fmInput + (1.0 - t) * filtData; - } else { /* Start to ramp */ - if (sw) /* Turn on request */ - ; /* At the start of turning on ramp input goes to output (filter bypassed) */ - else /* Turn off request */ - fmInput = filtData; /* At the start of turning off the ramp is at filter output */ - } - kk++; - } - pFilt->inputs[modNum].cnt[ii] = kk; - break; - case 3: /* Comparator */ - case 4: /* Zero crossing */ - ramp = pFilt->inputs[modNum].rmpcmp[ii]; /* Filter comparison range */ - timeout = pFilt->inputs[modNum].timeout[ii]; /* Comparison timeout number */ - kk = pFilt->inputs[modNum].cnt[ii]; /* comparison count */ - if (sTypeMod10 == 3) compare = fmInput - filtData; /* Comparator looks at the filter in/out diff */ - else compare = sw_out? filtData: fmInput; /* Use the filtered value if waiting to switch off */ - if (compare < .0) compare = -compare; - - ++kk; - if (kk >= timeout || compare <= (float)ramp) { /* If timed out or the difference is in the range */ - /* Turn output on/off according to the request */ - if ((sw_out = sw)) fmInput = filtData; /* Use the filtered value if the filter is turned on */ - kk = 0; - } else { /* Waiting for the match or the timeout */ - if (sw_out) fmInput = filtData; /* Use the filtered value if waiting to switch off */ - } - pFilt->inputs[modNum].cnt[ii] = kk; - break; - default: - fmInput = 777; - break; - } - - if (sw == sw_out) { /* If turning the filter on/off NOW */ - /* Clear history buffer if filter is turned off NOW */ - /* History is cleared one time only */ - if (!sw) { /* Turn off request */ - for(jj=0;jj<MAX_HISTRY;jj++) - pC->coeffs[modNum].filtHist[ii][jj] = 0.0; - - } - - /* Send back the readback switches when there is change */ - if (sw_out) { /* switch is on, turn it on */ - pFilt->inputs[modNum].opSwitchP |= pow2_out[ii]; - } else { /* switch is off, turn it off */ - pFilt->inputs[modNum].opSwitchP &= ~pow2_out[ii]; - } - } - } - } - - /* Calculate output values */ - { - - if (pFilt->inputs[modNum].outgain != gain_ramp[modNum][id].req) { - RampParamLoad(&gain_ramp[modNum][id],pFilt->inputs[modNum].outgain,pFilt->inputs[modNum].gain_ramp_time,rate); - pFilt->inputs[modNum].opSwitchP |= 0x10000000; - } - if (gain_ramp[modNum][id].isRamping == 0) { - pFilt->inputs[modNum].opSwitchP &= ~0x10000000; - } - - output = fmInput * RampParamUpdate(&gain_ramp[modNum][id]); - if(output > 1e20) output = 1e20; - - /* Limiting */ - /* If the limit switch is on, limit the output accordingly. */ - if (opSwitchE & OPSWITCH_LIMITER_ENABLE) { - if(output > pFilt->inputs[modNum].limiter) - output = pFilt->inputs[modNum].limiter; - else if(output < -pFilt->inputs[modNum].limiter) - output = -pFilt->inputs[modNum].limiter; + /* Calculate filter */ + if ( pC->coeffs[ modNum ].biquad ) + filtData = + iir_filter_biquad( sw_in ? fmInput : 0, + pC->coeffs[ modNum ].filtCoeff[ ii ], + pC->coeffs[ modNum ].filtSections[ ii ], + pC->coeffs[ modNum ].filtHist[ ii ] ); + else + filtData = iir_filter( sw_in ? fmInput : 0, + pC->coeffs[ modNum ].filtCoeff[ ii ], + pC->coeffs[ modNum ].filtSections[ ii ], + pC->coeffs[ modNum ].filtHist[ ii ] ); + + if ( sw == sw_out ) + { /* No switching */ + if ( sw ) + fmInput = filtData; /* Use the filtered value if the filter is + turned on */ + } + else + { /* Switching request */ + int sTypeMod10 = sType % 10; + /* Process filter switching according to output type [1-3] */ + switch ( sTypeMod10 ) + { + case 1: /* Instantenious switch */ + /* Turn output on/off according to the request */ + if ( ( sw_out = sw ) ) + fmInput = filtData; /* Use the filtered value if the filter + is turned on */ + break; + case 2: /* Ramp in/out filter output */ + ramp = pFilt->inputs[ modNum ] + .rmpcmp[ ii ]; /* Ramp slope coefficient */ + kk = pFilt->inputs[ modNum ].cnt[ ii ]; /* Ramp count */ + /* printf("kk=%d; ramp=%d; sw=%d; sw_out=%d\n", kk, ramp, sw, + * sw_out); */ + + if ( kk == ramp ) + { /* Done ramping */ + /* Turn output on/off according to the request */ + if ( ( sw_out = sw ) ) + fmInput = filtData; /* Use the filtered value if the + filter is turned on */ + kk = 0; + } + else + { /* Ramping will be done */ + if ( kk ) + { /* Currently ramping */ + double t = (double)kk / (double)ramp; /* Slope */ + if ( sw ) /* Turn on request */ + fmInput = ( 1.0 - t ) * fmInput + t * filtData; + else /* Turn off request */ + fmInput = t * fmInput + ( 1.0 - t ) * filtData; + } + else + { /* Start to ramp */ + if ( sw ) /* Turn on request */ + ; /* At the start of turning on ramp input goes to + output (filter bypassed) */ + else /* Turn off request */ + fmInput = + filtData; /* At the start of turning off the + ramp is at filter output */ + } + kk++; + } + pFilt->inputs[ modNum ].cnt[ ii ] = kk; + break; + case 3: /* Comparator */ + case 4: /* Zero crossing */ + ramp = pFilt->inputs[ modNum ] + .rmpcmp[ ii ]; /* Filter comparison range */ + timeout = pFilt->inputs[ modNum ] + .timeout[ ii ]; /* Comparison timeout number */ + kk = pFilt->inputs[ modNum ].cnt[ ii ]; /* comparison count */ + if ( sTypeMod10 == 3 ) + compare = fmInput - filtData; /* Comparator looks at the + filter in/out diff */ + else + compare = sw_out ? filtData + : fmInput; /* Use the filtered value if + waiting to switch off */ + if ( compare < .0 ) + compare = -compare; + + ++kk; + if ( kk >= timeout || compare <= (float)ramp ) + { /* If timed out or the difference is in the range */ + /* Turn output on/off according to the request */ + if ( ( sw_out = sw ) ) + fmInput = filtData; /* Use the filtered value if the + filter is turned on */ + kk = 0; + } + else + { /* Waiting for the match or the timeout */ + if ( sw_out ) + fmInput = filtData; /* Use the filtered value if waiting + to switch off */ + } + pFilt->inputs[ modNum ].cnt[ ii ] = kk; + break; + default: + fmInput = 777; + break; + } + + if ( sw == sw_out ) + { /* If turning the filter on/off NOW */ + /* Clear history buffer if filter is turned off NOW */ + /* History is cleared one time only */ + if ( !sw ) + { /* Turn off request */ + for ( jj = 0; jj < MAX_HISTRY; jj++ ) + pC->coeffs[ modNum ].filtHist[ ii ][ jj ] = 0.0; + } + + /* Send back the readback switches when there is change */ + if ( sw_out ) + { /* switch is on, turn it on */ + pFilt->inputs[ modNum ].opSwitchP |= pow2_out[ ii ]; + } + else + { /* switch is off, turn it off */ + pFilt->inputs[ modNum ].opSwitchP &= ~pow2_out[ ii ]; + } + } + } } - /* Set Output Test Point */ - pFilt->data[modNum].testpoint = output; - pFilt->data[modNum].swStatus = filtCtrlBitConvert(opSwitchE); - - /* Test Output Switch and output hold on/off */ - if (opSwitchE & OPSWITCH_HOLD_ENABLE) { - /* Assign output to last held value. */ - output = pFilt->data[modNum].output; - ; /* Other outputs are not assigned, hence they are held */ - } else { - if (opSwitchE & OPSWITCH_OUTPUT_ENABLE) { - pFilt->data[modNum].output = output; - - /* Decimation */ - if (opSwitchE & OPSWITCH_DECIMATE_ENABLE) - { - avg = iir_filter(output, avgCoeff, 2, pC->coeffs[modNum].decHist); - pFilt->data[modNum].output16Hz = avg; - } - else - pFilt->data[modNum].output16Hz = output; - } else { - pFilt->data[modNum].output = 0; - pFilt->data[modNum].output16Hz = 0; - output = 0.0; - } + /* Calculate output values */ + { + + if ( pFilt->inputs[ modNum ].outgain != gain_ramp[ modNum ][ id ].req ) + { + RampParamLoad( &gain_ramp[ modNum ][ id ], + pFilt->inputs[ modNum ].outgain, + pFilt->inputs[ modNum ].gain_ramp_time, + rate ); + pFilt->inputs[ modNum ].opSwitchP |= 0x10000000; + } + if ( gain_ramp[ modNum ][ id ].isRamping == 0 ) + { + pFilt->inputs[ modNum ].opSwitchP &= ~0x10000000; + } + + output = fmInput * RampParamUpdate( &gain_ramp[ modNum ][ id ] ); + if ( output > 1e20 ) + output = 1e20; + + /* Limiting */ + /* If the limit switch is on, limit the output accordingly. */ + if ( opSwitchE & OPSWITCH_LIMITER_ENABLE ) + { + if ( output > pFilt->inputs[ modNum ].limiter ) + output = pFilt->inputs[ modNum ].limiter; + else if ( output < -pFilt->inputs[ modNum ].limiter ) + output = -pFilt->inputs[ modNum ].limiter; + } + + /* Set Output Test Point */ + pFilt->data[ modNum ].testpoint = output; + pFilt->data[ modNum ].swStatus = filtCtrlBitConvert( opSwitchE ); + + /* Test Output Switch and output hold on/off */ + if ( opSwitchE & OPSWITCH_HOLD_ENABLE ) + { + /* Assign output to last held value. */ + output = pFilt->data[ modNum ].output; + ; /* Other outputs are not assigned, hence they are held */ + } + else + { + if ( opSwitchE & OPSWITCH_OUTPUT_ENABLE ) + { + pFilt->data[ modNum ].output = output; + + /* Decimation */ + if ( opSwitchE & OPSWITCH_DECIMATE_ENABLE ) + { + avg = iir_filter( + output, avgCoeff, 2, pC->coeffs[ modNum ].decHist ); + pFilt->data[ modNum ].output16Hz = avg; + } + else + pFilt->data[ modNum ].output16Hz = output; + } + else + { + pFilt->data[ modNum ].output = 0; + pFilt->data[ modNum ].output16Hz = 0; + output = 0.0; + } + } } - } - return output; + return output; } -/// @brief This function is called by user apps using standard IIR/FIR filters.. -///< This function in turn calls filterModuleD2 to actually perform the calcs, with dummy -///< vars added. +/// @brief This function is called by user apps using standard IIR/FIR +/// filters.. +///< This function in turn calls filterModuleD2 to actually perform the calcs, +///< with dummy vars added. /// @param[in,out] *pFilt Filter Module Data /// @param[in] *pC Filter module coefficients /// @param[in] modNum Filter module ID number @@ -1024,15 +1292,22 @@ filterModuleD2(FILT_MOD *pFilt, /* Filter module data */ /// @param[in] mask Control mask /// @return Output of IIR/FIR filter calculations. inline double -filterModuleD(FILT_MOD *pFilt, /* Filter module data */ - COEF *pC, /* Filter coefficients */ - int modNum, /* Filter module number */ - double filterInput, /* Input data sample (output from funtcion inputModule()) */ - int fltrCtrlVal, /* Filter control value */ - int mask) /* Mask of bits to act upon */ +filterModuleD( FILT_MOD* pFilt, /* Filter module data */ + COEF* pC, /* Filter coefficients */ + int modNum, /* Filter module number */ + double filterInput, /* Input data sample (output from funtcion + inputModule()) */ + int fltrCtrlVal, /* Filter control value */ + int mask ) /* Mask of bits to act upon */ { - /* Limit control to the 10 bits */ - return filterModuleD2(pFilt, pC, modNum, filterInput, fltrCtrlVal & 0x3ff, mask & 0x3ff, 0., 0., 0.); + /* Limit control to the 10 bits */ + return filterModuleD2( pFilt, + pC, + modNum, + filterInput, + fltrCtrlVal & 0x3ff, + mask & 0x3ff, + 0., + 0., + 0. ); } - - diff --git a/src/include/drv/gsc16ai64.c b/src/include/drv/gsc16ai64.c index 9bfcdc743..9550d0cfe 100644 --- a/src/include/drv/gsc16ai64.c +++ b/src/include/drv/gsc16ai64.c @@ -1,98 +1,109 @@ /// \file gsc16ai64.c -/// \brief File contains the initialization routine and various register read/write -///< operations for the General Standards 16bit, 32 channel ADC modules. \n -///< For board info, see -///< <a href="http://www.generalstandards.com/view-products2.php?BD_family=16ai64ssc">GSC 16AI64SSC Manual</a> +/// \brief File contains the initialization routine and various register +///read/write +///< operations for the General Standards 16bit, 32 channel ADC modules. +///<\n +///< For board info, see +///< <a +///< href="http://www.generalstandards.com/view-products2.php?BD_family=16ai64ssc">GSC +///< 16AI64SSC Manual</a> #include "gsc16ai64.h" -volatile PLX_9056_DMA *adcDma[MAX_ADC_MODULES]; ///< DMA struct for GSA ADC -dma_addr_t adc_dma_handle[MAX_ADC_MODULES]; ///< PCI add of ADC DMA memory -volatile GSA_ADC_REG *adcPtr[MAX_ADC_MODULES]; ///< Ptr to ADC registers */ +volatile PLX_9056_DMA* adcDma[ MAX_ADC_MODULES ]; ///< DMA struct for GSA ADC +dma_addr_t adc_dma_handle[ MAX_ADC_MODULES ]; ///< PCI add of ADC DMA memory +volatile GSA_ADC_REG* adcPtr[ MAX_ADC_MODULES ]; ///< Ptr to ADC registers */ // ***************************************************************************** /// \brief Routine to initialize GSC 16bit, 32 channel ADC modules -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @param[in] *adcdev PCI address information passed by the mapping code in map.c +/// @param[in] *adcdev PCI address information passed by the mapping code in +/// map.c /// @return Status from board enable command. // ***************************************************************************** -int gsc16ai64Init(CDS_HARDWARE *pHardware, struct pci_dev *adcdev) +int +gsc16ai64Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev ) { - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - char *_adc_add; /// @param *_adc_add ADC register address space - int pedStatus; /// @param pedStatus Status return from call to enable device. + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + char* _adc_add; /// @param *_adc_add ADC register address space + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. + /// Get index into CDS_HARDWARE struct based on total number of ADC cards + /// found by mapping routine in map.c + devNum = pHardware->adcCount; + /// Enable the module. + pedStatus = pci_enable_device( adcdev ); + /// Enable device to be DMA master. + pci_set_master( adcdev ); + /// Get the PLX chip address + pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "pci0 = 0x%x\n", pci_io_addr ); + /// Map module DMA space directly to computer memory space. + _adc_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + /// Map the module DMA control registers via PLX chip registers + adcDma[ devNum ] = (PLX_9056_DMA*)_adc_add; + if ( devNum == 0 ) + plxIcr = (PLX_9056_INTCTRL*)_adc_add; - /// Get index into CDS_HARDWARE struct based on total number of ADC cards found by mapping routine - /// in map.c - devNum = pHardware->adcCount; - /// Enable the module. - pedStatus = pci_enable_device(adcdev); - /// Enable device to be DMA master. - pci_set_master(adcdev); - /// Get the PLX chip address - pci_read_config_dword(adcdev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("pci0 = 0x%x\n",pci_io_addr); - /// Map module DMA space directly to computer memory space. - _adc_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - /// Map the module DMA control registers via PLX chip registers - adcDma[devNum] = (PLX_9056_DMA *)_adc_add; - if(devNum == 0) plxIcr = (PLX_9056_INTCTRL *)_adc_add; + /// Get the ADC register address + pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + printk( "pci2 = 0x%x\n", pci_io_addr ); + /// Map the module control register so local memory space. + _adc_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + printk( "ADC I/O address=0x%x 0x%lx\n", pci_io_addr, (long)_adc_add ); + /// Set global ptr to control register memory space. + adcPtr[ devNum ] = (GSA_ADC_REG*)_adc_add; - /// Get the ADC register address - pci_read_config_dword(adcdev,PCI_BASE_ADDRESS_2,&pci_io_addr); - printk("pci2 = 0x%x\n",pci_io_addr); - /// Map the module control register so local memory space. - _adc_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - printk("ADC I/O address=0x%x 0x%lx\n", pci_io_addr,(long)_adc_add); - /// Set global ptr to control register memory space. - adcPtr[devNum] = (GSA_ADC_REG *)_adc_add; - - printk("BCR = 0x%x\n",adcPtr[devNum]->BCR); - /// Reset the ADC board - adcPtr[devNum]->BCR |= GSAI_RESET; - do{ - }while((adcPtr[devNum]->BCR & GSAI_RESET) != 0); - - /// Write in a sync word - adcPtr[devNum]->SMUW = 0x0000; - adcPtr[devNum]->SMLW = 0x0000; - - /// Set ADC to 64 channel = 32 differential channels - adcPtr[devNum]->BCR |= (GSAI_FULL_DIFFERENTIAL); + printk( "BCR = 0x%x\n", adcPtr[ devNum ]->BCR ); + /// Reset the ADC board + adcPtr[ devNum ]->BCR |= GSAI_RESET; + do + { + } while ( ( adcPtr[ devNum ]->BCR & GSAI_RESET ) != 0 ); - #ifdef ADC_EXTERNAL_SYNC - adcPtr[devNum]->BCR |= (GSAI_ENABLE_X_SYNC); - adcPtr[devNum]->AUX_SIO |= 0x80; - #endif + /// Write in a sync word + adcPtr[ devNum ]->SMUW = 0x0000; + adcPtr[ devNum ]->SMLW = 0x0000; + /// Set ADC to 64 channel = 32 differential channels + adcPtr[ devNum ]->BCR |= ( GSAI_FULL_DIFFERENTIAL ); - /// Set sample rate close to 16384Hz - /// Unit runs with external clock, so this probably not necessary - adcPtr[devNum]->RAG = 0x117D8; - printk("RAG = 0x%x\n",adcPtr[devNum]->RAG); - printk("BCR = 0x%x\n",adcPtr[devNum]->BCR); - adcPtr[devNum]->RAG &= ~(GSAI_SAMPLE_START); - /// Initiate board calibration - adcPtr[devNum]->BCR |= GSAI_AUTO_CAL; - /// Wait for internal calibration to complete. - do { - }while((adcPtr[devNum]->BCR & GSAI_AUTO_CAL) != 0); - adcPtr[devNum]->RAG |= GSAI_SAMPLE_START; - adcPtr[devNum]->IDBC = (GSAI_CLEAR_BUFFER | GSAI_THRESHOLD); - adcPtr[devNum]->SSC = (GSAI_64_CHANNEL | GSAI_EXTERNAL_SYNC); - printk("SSC = 0x%x\n",adcPtr[devNum]->SSC); - printk("IDBC = 0x%x\n",adcPtr[devNum]->IDBC); - /// Fill in CDS_HARDWARE structure with ADC information. - pHardware->pci_adc[devNum] = (long) pci_alloc_consistent(adcdev,0x2000,&adc_dma_handle[devNum]); - pHardware->adcType[devNum] = GSC_16AI64SSA; - pHardware->adcConfig[devNum] = adcPtr[devNum]->ASSC; - pHardware->adcCount ++; - /// Return board enable status. - return(pedStatus); +#ifdef ADC_EXTERNAL_SYNC + adcPtr[ devNum ]->BCR |= ( GSAI_ENABLE_X_SYNC ); + adcPtr[ devNum ]->AUX_SIO |= 0x80; +#endif + /// Set sample rate close to 16384Hz + /// Unit runs with external clock, so this probably not necessary + adcPtr[ devNum ]->RAG = 0x117D8; + printk( "RAG = 0x%x\n", adcPtr[ devNum ]->RAG ); + printk( "BCR = 0x%x\n", adcPtr[ devNum ]->BCR ); + adcPtr[ devNum ]->RAG &= ~( GSAI_SAMPLE_START ); + /// Initiate board calibration + adcPtr[ devNum ]->BCR |= GSAI_AUTO_CAL; + /// Wait for internal calibration to complete. + do + { + } while ( ( adcPtr[ devNum ]->BCR & GSAI_AUTO_CAL ) != 0 ); + adcPtr[ devNum ]->RAG |= GSAI_SAMPLE_START; + adcPtr[ devNum ]->IDBC = ( GSAI_CLEAR_BUFFER | GSAI_THRESHOLD ); + adcPtr[ devNum ]->SSC = ( GSAI_64_CHANNEL | GSAI_EXTERNAL_SYNC ); + printk( "SSC = 0x%x\n", adcPtr[ devNum ]->SSC ); + printk( "IDBC = 0x%x\n", adcPtr[ devNum ]->IDBC ); + /// Fill in CDS_HARDWARE structure with ADC information. + pHardware->pci_adc[ devNum ] = + (long)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] ); + pHardware->adcType[ devNum ] = GSC_16AI64SSA; + pHardware->adcConfig[ devNum ] = adcPtr[ devNum ]->ASSC; + pHardware->adcCount++; + /// Return board enable status. + return ( pedStatus ); } // ***************************************************************************** @@ -100,84 +111,96 @@ int gsc16ai64Init(CDS_HARDWARE *pHardware, struct pci_dev *adcdev) /// @param[in] module ID of ADC board to read. /// @return Status of ADC module DMA DONE bit (0=not complete, 1= complete) // ***************************************************************************** -int gsc16ai64CheckDmaDone(int module) +int +gsc16ai64CheckDmaDone( int module ) { - // Return 0 if DMA not complete - if((adcDma[module]->DMA_CSR & GSAI_DMA_DONE) == 0) return(0); - // Return 1 if DMA is complete - else return(1); + // Return 0 if DMA not complete + if ( ( adcDma[ module ]->DMA_CSR & GSAI_DMA_DONE ) == 0 ) + return ( 0 ); + // Return 1 if DMA is complete + else + return ( 1 ); } // ***************************************************************************** -/// \brief Function if DMA from ADC module is complete. +/// \brief Function if DMA from ADC module is complete. ///< Code will remain in loop until DMA is complete. /// @param[in] module ID of ADC board to read. /// @param[out] data Status of DMA DONE bit. /// @return ADC DMA Status (0=not complete, 16=complete /// Note: This function not presently used. // ***************************************************************************** -int gsc16ai64WaitDmaDone(int module, volatile int *data) +int +gsc16ai64WaitDmaDone( int module, volatile int* data ) { - do{ - }while((adcDma[module]->DMA_CSR & GSAI_DMA_DONE) == 0); - // First channel should be marked with an upper bit set - if (*data == 0) return 0; else return 16; + do + { + } while ( ( adcDma[ module ]->DMA_CSR & GSAI_DMA_DONE ) == 0 ); + // First channel should be marked with an upper bit set + if ( *data == 0 ) + return 0; + else + return 16; } - // ***************************************************************************** /// \brief Function clears ADC buffer and starts acquisition via external clock. ///< Also sets up ADC for Demand DMA mode and set GO bit in DMA Mode Register. -///< NOTE: In normal operation, this code should only be called while the clocks from -///< the timing slave are turned OFF ie during initialization process. +///< NOTE: In normal operation, this code should only be called while the clocks +///< from the timing slave are turned OFF ie during initialization process. /// @param[in] adcCount Total number of ADC modules to start DMA. // ***************************************************************************** -int gsc16ai64Enable(CDS_HARDWARE *pHardware) +int +gsc16ai64Enable( CDS_HARDWARE* pHardware ) { - int ii; - for(ii=0;ii<pHardware->adcCount;ii++) - { - if(pHardware->adcType[ii] == GSC_16AI64SSA) + int ii; + for ( ii = 0; ii < pHardware->adcCount; ii++ ) { - /// Enable demand DMA mode ie auto DMA data to computer memory when - ///< GSAI_THRESHOLD data points in ADC FIFO. - adcPtr[ii]->BCR &= ~(GSAI_DMA_DEMAND_MODE); - /// Set DMA mode and direction in PLX controller chip on module. - adcDma[ii]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR | 0x1000; - /// Enable DMA - adcDma[ii]->DMA_CSR = GSAI_DMA_START; - /// Clear the FIFO and set demand DMA to start after all 32 channels have 1 sample - adcPtr[ii]->IDBC = (GSAI_CLEAR_BUFFER | GSAI_THRESHOLD); - /// Enable sync via external clock input. - adcPtr[ii]->BCR |= GSAI_ENABLE_X_SYNC; + if ( pHardware->adcType[ ii ] == GSC_16AI64SSA ) + { + /// Enable demand DMA mode ie auto DMA data to computer memory when + ///< GSAI_THRESHOLD data points in ADC FIFO. + adcPtr[ ii ]->BCR &= ~( GSAI_DMA_DEMAND_MODE ); + /// Set DMA mode and direction in PLX controller chip on module. + adcDma[ ii ]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR | 0x1000; + /// Enable DMA + adcDma[ ii ]->DMA_CSR = GSAI_DMA_START; + /// Clear the FIFO and set demand DMA to start after all 32 channels + /// have 1 sample + adcPtr[ ii ]->IDBC = ( GSAI_CLEAR_BUFFER | GSAI_THRESHOLD ); + /// Enable sync via external clock input. + adcPtr[ ii ]->BCR |= GSAI_ENABLE_X_SYNC; + } } - } - return(0); + return ( 0 ); } // ***************************************************************************** -int gsc16ai64Enable1PPS(int ii) +int +gsc16ai64Enable1PPS( int ii ) { -/// Enable demand DMA mode ie auto DMA data to computer memory when -///< GSAI_THRESHOLD data points in ADC FIFO. - adcPtr[ii]->BCR &= ~(GSAI_DMA_DEMAND_MODE); - /// Set DMA mode and direction in PLX controller chip on module. - adcDma[ii]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR | 0x1000; - /// Enable DMA - adcDma[ii]->DMA_CSR = GSAI_DMA_START; - /// Clear the FIFO and set demand DMA to start after all 32 channels have 1 sample - adcPtr[ii]->IDBC = (GSAI_CLEAR_BUFFER | GSAI_THRESHOLD); - /// Enable sync via external clock input. - adcPtr[ii]->BCR |= GSAI_ENABLE_X_SYNC; - return(0); + /// Enable demand DMA mode ie auto DMA data to computer memory when + ///< GSAI_THRESHOLD data points in ADC FIFO. + adcPtr[ ii ]->BCR &= ~( GSAI_DMA_DEMAND_MODE ); + /// Set DMA mode and direction in PLX controller chip on module. + adcDma[ ii ]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR | 0x1000; + /// Enable DMA + adcDma[ ii ]->DMA_CSR = GSAI_DMA_START; + /// Clear the FIFO and set demand DMA to start after all 32 channels have 1 + /// sample + adcPtr[ ii ]->IDBC = ( GSAI_CLEAR_BUFFER | GSAI_THRESHOLD ); + /// Enable sync via external clock input. + adcPtr[ ii ]->BCR |= GSAI_ENABLE_X_SYNC; + return ( 0 ); } // ***************************************************************************** /// \brief Function stops ADC acquisition by removing the clocking signal. // ***************************************************************************** -int gsc16ai64AdcStop() +int +gsc16ai64AdcStop( ) { - adcPtr[0]->BCR &= ~(GSAI_ENABLE_X_SYNC); - return(0); + adcPtr[ 0 ]->BCR &= ~( GSAI_ENABLE_X_SYNC ); + return ( 0 ); } // ***************************************************************************** @@ -185,68 +208,73 @@ int gsc16ai64AdcStop() /// @param[in] numAdc The ID number of the ADC module to read. /// @return The number of samples presently in the ADC FIFO. // ***************************************************************************** -int gsc16ai64CheckAdcBuffer(int numAdc) +int +gsc16ai64CheckAdcBuffer( int numAdc ) { - int dataCount; - - dataCount = adcPtr[numAdc]->BUF_SIZE; - return(dataCount); + int dataCount; + dataCount = adcPtr[ numAdc ]->BUF_SIZE; + return ( dataCount ); } - // ***************************************************************************** -/// \brief This routine sets up the ADC DMA registers once on code initialization. +/// \brief This routine sets up the ADC DMA registers once on code +/// initialization. /// @param[in] modNum The ID number of the ADC module to read. // ***************************************************************************** -int gsc16ai64DmaSetup(int modNum) +int +gsc16ai64DmaSetup( int modNum ) { - /// Set DMA mode such that completion does not cause interrupt on bus. - adcDma[modNum]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR; - /// Load PCI address (remapped local memory) to which data is to be delivered. - adcDma[modNum]->DMA0_PCI_ADD = (int)adc_dma_handle[modNum]; - /// Set the PCI address of board where data will be transferred from. - adcDma[modNum]->DMA0_LOC_ADD = GSAI_DMA_LOCAL_ADDR; - /// Set the number of bytes to be transferred. - adcDma[modNum]->DMA0_BTC = GSAI_DMA_BYTE_COUNT; - /// Set the DMA direction ie ADC to computer memory. - adcDma[modNum]->DMA0_DESC = GSAI_DMA_TO_PCI; - return(1); + /// Set DMA mode such that completion does not cause interrupt on bus. + adcDma[ modNum ]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR; + /// Load PCI address (remapped local memory) to which data is to be + /// delivered. + adcDma[ modNum ]->DMA0_PCI_ADD = (int)adc_dma_handle[ modNum ]; + /// Set the PCI address of board where data will be transferred from. + adcDma[ modNum ]->DMA0_LOC_ADD = GSAI_DMA_LOCAL_ADDR; + /// Set the number of bytes to be transferred. + adcDma[ modNum ]->DMA0_BTC = GSAI_DMA_BYTE_COUNT; + /// Set the DMA direction ie ADC to computer memory. + adcDma[ modNum ]->DMA0_DESC = GSAI_DMA_TO_PCI; + return ( 1 ); } // ***************************************************************************** -/// \brief This routine sets up the ADC DMA registers once on code initialization. +/// \brief This routine sets up the ADC DMA registers once on code +/// initialization. /// @param[in] modNum The ID number of the ADC module to read. // ***************************************************************************** -int gsc16ai64DmaSetup32(int modNum) +int +gsc16ai64DmaSetup32( int modNum ) { - /// Set DMA mode such that completion does not cause interrupt on bus. - adcDma[modNum]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR; - /// Load PCI address (remapped local memory) to which data is to be delivered. - adcDma[modNum]->DMA0_PCI_ADD = (int)adc_dma_handle[modNum]; - /// Set the PCI address of board where data will be transferred from. - adcDma[modNum]->DMA0_LOC_ADD = GSAI_DMA_LOCAL_ADDR; - /// Set the number of bytes to be transferred. - adcDma[modNum]->DMA0_BTC = 0x100; - /// Set the DMA direction ie ADC to computer memory. - adcDma[modNum]->DMA0_DESC = GSAI_DMA_TO_PCI; - return(1); + /// Set DMA mode such that completion does not cause interrupt on bus. + adcDma[ modNum ]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR; + /// Load PCI address (remapped local memory) to which data is to be + /// delivered. + adcDma[ modNum ]->DMA0_PCI_ADD = (int)adc_dma_handle[ modNum ]; + /// Set the PCI address of board where data will be transferred from. + adcDma[ modNum ]->DMA0_LOC_ADD = GSAI_DMA_LOCAL_ADDR; + /// Set the number of bytes to be transferred. + adcDma[ modNum ]->DMA0_BTC = 0x100; + /// Set the DMA direction ie ADC to computer memory. + adcDma[ modNum ]->DMA0_DESC = GSAI_DMA_TO_PCI; + return ( 1 ); } - // ***************************************************************************** -/// \brief This routine starts an ADC DMA operation. It must first be setup by +/// \brief This routine starts an ADC DMA operation. It must first be setup by ///< the gsc16ai64DmaSetup routine. /// @param[in] modNum The ID number of the ADC module to read. // ***************************************************************************** -void gsc16ai64DmaEnable(int modNum) +void +gsc16ai64DmaEnable( int modNum ) { - adcDma[modNum]->DMA_CSR = GSAI_DMA_START; + adcDma[ modNum ]->DMA_CSR = GSAI_DMA_START; } #ifdef DIAG_TEST // ***************************************************************************** -/// \brief Test Code +/// \brief Test Code ///< For DIAGS ONLY !!!!!!!! ///< This will change ADC DMA BYTE count @@ -256,9 +284,9 @@ void gsc16ai64DmaEnable(int modNum) ///< In both cases, real-time kernel code should exit with errors to dmesg // ***************************************************************************** -void gsc16ai64DmaBump(int modNum, int bump) +void +gsc16ai64DmaBump( int modNum, int bump ) { - adcDma[modNum]->DMA0_BTC = GSAI_DMA_BYTE_COUNT + bump; + adcDma[ modNum ]->DMA0_BTC = GSAI_DMA_BYTE_COUNT + bump; } #endif - diff --git a/src/include/drv/gsc16ao16.c b/src/include/drv/gsc16ao16.c index 6090cfb48..4f05f9336 100644 --- a/src/include/drv/gsc16ao16.c +++ b/src/include/drv/gsc16ao16.c @@ -1,117 +1,132 @@ /// \file gsc16ao16.c -/// \brief File contains the initialization routine and various register read/write -///< operations for the General Standards 16bit, 16 channel DAC modules. \n -///< For board info, see -///< <a href="http://www.generalstandards.com/view-products2.php?BD_family=16ao16">GSC 16AO16 Manual</a> +/// \brief File contains the initialization routine and various register +/// read/write +///< operations for the General Standards 16bit, 16 channel DAC +///< modules. \n +///< For board info, see +///< <a +///< href="http://www.generalstandards.com/view-products2.php?BD_family=16ao16">GSC +///< 16AO16 Manual</a> #include "gsc16ao16.h" // ***************************************************************************** /// \brief Routine to initialize GSC 16AO16 DAC modules. -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @param[in] *dacdev PCI address information passed by the mapping code in map.c +/// @param[in] *dacdev PCI address information passed by the mapping code in +/// map.c /// @return Status from board enable command. // ***************************************************************************** -int gsc16ao16Init(CDS_HARDWARE *pHardware, struct pci_dev *dacdev) +int +gsc16ao16Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev ) { - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - char *_dac_add; /// @param *_dac_add DAC register address space - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int pedStatus; /// @param pedStatus Status return from call to enable device. - - /// Get index into CDS_HARDWARE struct based on total number of DAC cards found by mapping routine - /// in map.c - devNum = pHardware->dacCount; - /// Enable the device, PCI required - pedStatus = pci_enable_device(dacdev); - /// Register module as Master capable, required for DMA - pci_set_master(dacdev); - /// Get the PLX chip PCI address, it is advertised at address 0 - pci_read_config_dword(dacdev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("pci0 = 0x%x\n",pci_io_addr); - _dac_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - /// Set up a pointer to DMA registers on PLX chip - dacDma[devNum] = (PLX_9056_DMA *)_dac_add; - - /// Get the DAC register address - pci_read_config_dword(dacdev,PCI_BASE_ADDRESS_2,&pci_io_addr); - printk("dac pci2 = 0x%x\n",pci_io_addr); - _dac_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - printk("DAC I/O address=0x%x 0x%lx\n", pci_io_addr,(long)_dac_add); - dacPtr[devNum] = (GSC_DAC_REG *)_dac_add; - - printk("DAC BCR = 0x%x\n",dacPtr[devNum]->BCR); - /// Reset the DAC board and wait for it to finish (3msec) - dacPtr[devNum]->BCR |= GSAO_RESET; - - - do{ - }while((dacPtr[devNum]->BCR & GSAO_RESET) != 0); - - /// Enable 2s complement by clearing offset binary bit - dacPtr[devNum]->BCR = (GSAO_OUT_RANGE_10 | GSAO_SIMULT_OUT); - printk("DAC BCR after init = 0x%x\n",dacPtr[devNum]->BCR); - printk("DAC CSR = 0x%x\n",dacPtr[devNum]->CSR); + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + char* _dac_add; /// @param *_dac_add DAC register address space + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. + + /// Get index into CDS_HARDWARE struct based on total number of DAC cards + /// found by mapping routine in map.c + devNum = pHardware->dacCount; + /// Enable the device, PCI required + pedStatus = pci_enable_device( dacdev ); + /// Register module as Master capable, required for DMA + pci_set_master( dacdev ); + /// Get the PLX chip PCI address, it is advertised at address 0 + pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "pci0 = 0x%x\n", pci_io_addr ); + _dac_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + /// Set up a pointer to DMA registers on PLX chip + dacDma[ devNum ] = (PLX_9056_DMA*)_dac_add; + + /// Get the DAC register address + pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + printk( "dac pci2 = 0x%x\n", pci_io_addr ); + _dac_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + printk( "DAC I/O address=0x%x 0x%lx\n", pci_io_addr, (long)_dac_add ); + dacPtr[ devNum ] = (GSC_DAC_REG*)_dac_add; + + printk( "DAC BCR = 0x%x\n", dacPtr[ devNum ]->BCR ); + /// Reset the DAC board and wait for it to finish (3msec) + dacPtr[ devNum ]->BCR |= GSAO_RESET; + + do + { + } while ( ( dacPtr[ devNum ]->BCR & GSAO_RESET ) != 0 ); + + /// Enable 2s complement by clearing offset binary bit + dacPtr[ devNum ]->BCR = ( GSAO_OUT_RANGE_10 | GSAO_SIMULT_OUT ); + printk( "DAC BCR after init = 0x%x\n", dacPtr[ devNum ]->BCR ); + printk( "DAC CSR = 0x%x\n", dacPtr[ devNum ]->CSR ); #ifdef OVERSAMPLE_DAC - // Larger buffer required when in oversampling mode + // Larger buffer required when in oversampling mode #ifdef SERVO32K - dacPtr[devNum]->BOR = GSAO_FIFO_64; + dacPtr[ devNum ]->BOR = GSAO_FIFO_64; #endif #ifdef SERVO16K - dacPtr[devNum]->BOR = GSAO_FIFO_128; + dacPtr[ devNum ]->BOR = GSAO_FIFO_128; #endif #ifdef SERVO2K - dacPtr[devNum]->BOR = GSAO_FIFO_1024; + dacPtr[ devNum ]->BOR = GSAO_FIFO_1024; #endif #else - /// Set DAC FIFO buffer size. Set to match DAC timing diagnostics. - dacPtr[devNum]->BOR = GSAO_FIFO_256; + /// Set DAC FIFO buffer size. Set to match DAC timing diagnostics. + dacPtr[ devNum ]->BOR = GSAO_FIFO_256; #endif - dacPtr[devNum]->BOR |= GSAO_EXTERN_CLK; - printk("DAC BOR = 0x%x\n",dacPtr[devNum]->BOR); - pHardware->pci_dac[devNum] = - (long) pci_alloc_consistent(dacdev,0x200,&dac_dma_handle[devNum]); - pHardware->dacConfig[devNum] = (int) (dacPtr[devNum]->ASSC); - pHardware->dacType[devNum] = GSC_16AO16; - pHardware->dacCount ++; - - /// Call patch in map.c needed to properly write to native PCIe module version of 16AO16 - set_8111_prefetch(dacdev); - return(pedStatus); + dacPtr[ devNum ]->BOR |= GSAO_EXTERN_CLK; + printk( "DAC BOR = 0x%x\n", dacPtr[ devNum ]->BOR ); + pHardware->pci_dac[ devNum ] = + (long)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] ); + pHardware->dacConfig[ devNum ] = (int)( dacPtr[ devNum ]->ASSC ); + pHardware->dacType[ devNum ] = GSC_16AO16; + pHardware->dacCount++; + + /// Call patch in map.c needed to properly write to native PCIe module + /// version of 16AO16 + set_8111_prefetch( dacdev ); + return ( pedStatus ); } - // ***************************************************************************** /// \brief Function checks if DMA from DAC module is complete. \n ///< Note: This function not presently used. /// @param[in] module ID number of board to be accessed. // ***************************************************************************** -int gsc16ao16DacDmaDone(int module) +int +gsc16ao16DacDmaDone( int module ) { - do{ - }while((dacDma[module]->DMA_CSR & GSAI_DMA_DONE) == 0); - return(1); + do + { + } while ( ( dacDma[ module ]->DMA_CSR & GSAI_DMA_DONE ) == 0 ); + return ( 1 ); } // ***************************************************************************** -/// \brief Function enables all 16AO16 DAC modules to begin receiving external clocking signals. -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// \brief Function enables all 16AO16 DAC modules to begin receiving external +/// clocking signals. +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. // ***************************************************************************** -int gsc16ao16Enable(CDS_HARDWARE *pHardware) +int +gsc16ao16Enable( CDS_HARDWARE* pHardware ) { - int ii; + int ii; - for (ii = 0; ii < pHardware -> dacCount; ii++) - { - if (pHardware->dacType[ii] == GSC_16AO16) { - dacPtr[ii]->BOR |= (GSAO_ENABLE_CLK | GSAO_EXTERN_CLK); - } - } + for ( ii = 0; ii < pHardware->dacCount; ii++ ) + { + if ( pHardware->dacType[ ii ] == GSC_16AO16 ) + { + dacPtr[ ii ]->BOR |= ( GSAO_ENABLE_CLK | GSAO_EXTERN_CLK ); + } + } - return(0); + return ( 0 ); } // @@ -120,69 +135,72 @@ int gsc16ao16Enable(CDS_HARDWARE *pHardware) /// @param[in] numDac ID number of board to be accessed. /// @return DAC FIFO size information. // ***************************************************************************** -int gsc16ao16CheckDacBuffer(int numDac) +int +gsc16ao16CheckDacBuffer( int numDac ) { - int dataCount; - dataCount = (dacPtr[numDac]->BOR >> 12) & 0xf; - return(dataCount); + int dataCount; + dataCount = ( dacPtr[ numDac ]->BOR >> 12 ) & 0xf; + return ( dataCount ); } // ***************************************************************************** /// \brief Clear DAC FIFO. /// @param[in] numDac ID number of board to be accessed. // ***************************************************************************** -int gsc16ao16ClearDacBuffer(int numDac) +int +gsc16ao16ClearDacBuffer( int numDac ) { - dacPtr[numDac]->BOR |= GSAO_CLR_BUFFER; - return(0); + dacPtr[ numDac ]->BOR |= GSAO_CLR_BUFFER; + return ( 0 ); } - // ***************************************************************************** /// \brief This routine sets up the DAC DMA registers. ///< It is only called once to set up the number of bytes to be preloaded into ///< the DAC prior to fe code realtime loop. /// @param[in] modNum ID number of board to be accessed. -/// @param[in] samples Number DAC values to be transferred on each DMA cycle.. +/// @param[in] samples Number DAC values to be transferred on each DMA +/// cycle.. // ***************************************************************************** -int gsc16ao16DmaPreload(int modNum, int samples) +int +gsc16ao16DmaPreload( int modNum, int samples ) { - dacDma[modNum]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR; - dacDma[modNum]->DMA0_PCI_ADD = (int)dac_dma_handle[modNum]; - dacDma[modNum]->DMA0_LOC_ADD = 0x18; - dacDma[modNum]->DMA0_BTC = 0x20 * samples; - dacDma[modNum]->DMA0_DESC = 0x0; - return(1); + dacDma[ modNum ]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR; + dacDma[ modNum ]->DMA0_PCI_ADD = (int)dac_dma_handle[ modNum ]; + dacDma[ modNum ]->DMA0_LOC_ADD = 0x18; + dacDma[ modNum ]->DMA0_BTC = 0x20 * samples; + dacDma[ modNum ]->DMA0_DESC = 0x0; + return ( 1 ); } - // ***************************************************************************** -/// \brief This routine sets up the DAC DMA registers once on code initialization. +/// \brief This routine sets up the DAC DMA registers once on code +/// initialization. /// @param[in] modNum ID number of board to be accessed. // ***************************************************************************** -int gsc16ao16DmaSetup(int modNum) +int +gsc16ao16DmaSetup( int modNum ) { - dacDma[modNum]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR; - dacDma[modNum]->DMA0_PCI_ADD = (int)dac_dma_handle[modNum]; - dacDma[modNum]->DMA0_LOC_ADD = 0x18; + dacDma[ modNum ]->DMA0_MODE = GSAI_DMA_MODE_NO_INTR; + dacDma[ modNum ]->DMA0_PCI_ADD = (int)dac_dma_handle[ modNum ]; + dacDma[ modNum ]->DMA0_LOC_ADD = 0x18; #ifdef OVERSAMPLE_DAC - dacDma[modNum]->DMA0_BTC = 0x40*OVERSAMPLE_TIMES; + dacDma[ modNum ]->DMA0_BTC = 0x40 * OVERSAMPLE_TIMES; #else - dacDma[modNum]->DMA0_BTC = 0x40; + dacDma[ modNum ]->DMA0_BTC = 0x40; #endif - dacDma[modNum]->DMA0_DESC = 0x0; - return(1); + dacDma[ modNum ]->DMA0_DESC = 0x0; + return ( 1 ); } - // ***************************************************************************** /// \brief This routine starts a DMA operation to a DAC module. ///< It must first be setup by the gsc16ao16DmaSetup call. /// @param[in] modNum ID number of board to be accessed. // ***************************************************************************** -void gsc16ao16DmaStart(int modNum) +void +gsc16ao16DmaStart( int modNum ) { - // dacDma[modNum]->DMA0_PCI_ADD = ((int)dac_dma_handle[modNum]); - dacDma[modNum]->DMA_CSR = GSAI_DMA_START; + // dacDma[modNum]->DMA0_PCI_ADD = ((int)dac_dma_handle[modNum]); + dacDma[ modNum ]->DMA_CSR = GSAI_DMA_START; } - diff --git a/src/include/drv/gsc18ai32.c b/src/include/drv/gsc18ai32.c index 88aa85424..2114d23ff 100644 --- a/src/include/drv/gsc18ai32.c +++ b/src/include/drv/gsc18ai32.c @@ -1,108 +1,119 @@ /// \file gsc16ai64.c -/// \brief File contains the initialization routine and various register read/write -///< operations for the General Standards 16bit, 32 channel ADC modules. \n -///< For board info, see -///< <a href="http://www.generalstandards.com/view-products2.php?BD_family=16ai64ssc">GSC 16AI64SSC Manual</a> +/// \brief File contains the initialization routine and various register +///read/write +///< operations for the General Standards 16bit, 32 channel ADC modules. +///<\n +///< For board info, see +///< <a +///< href="http://www.generalstandards.com/view-products2.php?BD_family=16ai64ssc">GSC +///< 16AI64SSC Manual</a> #include "gsc18ai32.h" - // ***************************************************************************** /// \brief Routine to initialize GSC 16bit, 32 channel ADC modules -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @param[in] *adcdev PCI address information passed by the mapping code in map.c +/// @param[in] *adcdev PCI address information passed by the mapping code in +/// map.c /// @return Status from board enable command. // ***************************************************************************** -int gsc18ai32Init(CDS_HARDWARE *pHardware, struct pci_dev *adcdev) +int +gsc18ai32Init( CDS_HARDWARE* pHardware, struct pci_dev* adcdev ) { - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - char *_adc_add; /// @param *_adc_add ADC register address space - int pedStatus; /// @param pedStatus Status return from call to enable device. - volatile GSA_ADC_18BIT_REG *adc18Ptr; - + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + char* _adc_add; /// @param *_adc_add ADC register address space + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. + volatile GSA_ADC_18BIT_REG* adc18Ptr; - /// Get index into CDS_HARDWARE struct based on total number of ADC cards found by mapping routine - /// in map.c - devNum = pHardware->adcCount; - /// Enable the module. - pedStatus = pci_enable_device(adcdev); - /// Enable device to be DMA master. - pci_set_master(adcdev); - /// Get the PLX chip address - pci_read_config_dword(adcdev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("pci0 = 0x%x\n",pci_io_addr); - /// Map module DMA space directly to computer memory space. - _adc_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - /// Map the module DMA control registers via PLX chip registers - adcDma[devNum] = (PLX_9056_DMA *)_adc_add; - if(devNum == 0) plxIcr = (PLX_9056_INTCTRL *)_adc_add; + /// Get index into CDS_HARDWARE struct based on total number of ADC cards + /// found by mapping routine in map.c + devNum = pHardware->adcCount; + /// Enable the module. + pedStatus = pci_enable_device( adcdev ); + /// Enable device to be DMA master. + pci_set_master( adcdev ); + /// Get the PLX chip address + pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "pci0 = 0x%x\n", pci_io_addr ); + /// Map module DMA space directly to computer memory space. + _adc_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + /// Map the module DMA control registers via PLX chip registers + adcDma[ devNum ] = (PLX_9056_DMA*)_adc_add; + if ( devNum == 0 ) + plxIcr = (PLX_9056_INTCTRL*)_adc_add; - /// Get the ADC register address - pci_read_config_dword(adcdev,PCI_BASE_ADDRESS_2,&pci_io_addr); - printk("pci2 = 0x%x\n",pci_io_addr); - /// Map the module control register so local memory space. - _adc_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - printk("ADC 18 I/O address=0x%x 0x%lx\n", pci_io_addr,(long)_adc_add); - /// Set global ptr to control register memory space. - adc18Ptr = (GSA_ADC_18BIT_REG *)_adc_add; - adcPtr[devNum] = (GSA_ADC_REG *)_adc_add; - printk("ADC pointer init at 0x%lx\n",(long)adcPtr[devNum]); + /// Get the ADC register address + pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + printk( "pci2 = 0x%x\n", pci_io_addr ); + /// Map the module control register so local memory space. + _adc_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + printk( "ADC 18 I/O address=0x%x 0x%lx\n", pci_io_addr, (long)_adc_add ); + /// Set global ptr to control register memory space. + adc18Ptr = (GSA_ADC_18BIT_REG*)_adc_add; + adcPtr[ devNum ] = (GSA_ADC_REG*)_adc_add; + printk( "ADC pointer init at 0x%lx\n", (long)adcPtr[ devNum ] ); - printk("BCR = 0x%x\n",adc18Ptr->BCR); - /// Reset the ADC board - adc18Ptr->BCR |= GSAF_RESET; - do{ - }while((adc18Ptr->BCR & GSAF_RESET) != 0); + printk( "BCR = 0x%x\n", adc18Ptr->BCR ); + /// Reset the ADC board + adc18Ptr->BCR |= GSAF_RESET; + do + { + } while ( ( adc18Ptr->BCR & GSAF_RESET ) != 0 ); - /// Write in a sync word - adc18Ptr->SMUW = 0x0000; - adc18Ptr->SMLW = 0x0000; + /// Write in a sync word + adc18Ptr->SMUW = 0x0000; + adc18Ptr->SMLW = 0x0000; - /// Set ADC to 64 channel = 32 differential channels + /// Set ADC to 64 channel = 32 differential channels // Don't need this for this board - #ifdef ADC_EXTERNAL_SYNC - // This is for the external connector use - adc18Ptr->BCR |= (GSAF_ENABLE_X_SYNC); // 0x80 - adc18Ptr->AUX_SIO |= 0x80; - #endif - - - /// Set sample rate close to 16384Hz - /// Unit runs with external clock, so this probably not necessary - adc18Ptr->RAG = 0x117D8; - printk("RAG = 0x%x\n",adc18Ptr->RAG); - printk("BCR = 0x%x\n",adc18Ptr->BCR); - adc18Ptr->RAG &= ~(GSAF_SAMPLE_START); // 0x10000 - /// Initiate board calibration - adc18Ptr->BCR |= GSAF_AUTO_CAL; - /// Wait for internal calibration to complete. - do { - }while((adc18Ptr->BCR & GSAF_AUTO_CAL) != 0); // 0x2000 - adc18Ptr->RAG |= GSAF_SAMPLE_START; // 0x10000 - adc18Ptr->IDBC = (GSAF_CLEAR_BUFFER | GSAF_THRESHOLD); // 0x40000 | 0x001f - adc18Ptr->SSC = (GSAF_32_CHANNEL); // 0x5 Sets 32 channels and external clock - printk("SSC = 0x%x\n",adc18Ptr->SSC); - printk("IDBC = 0x%x\n",adc18Ptr->IDBC); - /// Fill in CDS_HARDWARE structure with ADC information. - pHardware->pci_adc[devNum] = (long) pci_alloc_consistent(adcdev,0x2000,&adc_dma_handle[devNum]); - pHardware->adcType[devNum] = GSC_18AI32SSC1M; - pHardware->adcConfig[devNum] = adc18Ptr->ASSC; - pHardware->adcCount ++; - /// Return board enable status. - return(pedStatus); - +#ifdef ADC_EXTERNAL_SYNC + // This is for the external connector use + adc18Ptr->BCR |= ( GSAF_ENABLE_X_SYNC ); // 0x80 + adc18Ptr->AUX_SIO |= 0x80; +#endif -/* -SSC Register - - Byte 0 = Active channels + lower sample source bit - - 0x5 - - Byte 1 = upper sample source + enable clocking + enable clock divider + burst busy - - 0x20 -*/ + /// Set sample rate close to 16384Hz + /// Unit runs with external clock, so this probably not necessary + adc18Ptr->RAG = 0x117D8; + printk( "RAG = 0x%x\n", adc18Ptr->RAG ); + printk( "BCR = 0x%x\n", adc18Ptr->BCR ); + adc18Ptr->RAG &= ~( GSAF_SAMPLE_START ); // 0x10000 + /// Initiate board calibration + adc18Ptr->BCR |= GSAF_AUTO_CAL; + /// Wait for internal calibration to complete. + do + { + } while ( ( adc18Ptr->BCR & GSAF_AUTO_CAL ) != 0 ); // 0x2000 + adc18Ptr->RAG |= GSAF_SAMPLE_START; // 0x10000 + adc18Ptr->IDBC = ( GSAF_CLEAR_BUFFER | GSAF_THRESHOLD ); // 0x40000 | 0x001f + adc18Ptr->SSC = + ( GSAF_32_CHANNEL ); // 0x5 Sets 32 channels and external clock + printk( "SSC = 0x%x\n", adc18Ptr->SSC ); + printk( "IDBC = 0x%x\n", adc18Ptr->IDBC ); + /// Fill in CDS_HARDWARE structure with ADC information. + pHardware->pci_adc[ devNum ] = + (long)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] ); + pHardware->adcType[ devNum ] = GSC_18AI32SSC1M; + pHardware->adcConfig[ devNum ] = adc18Ptr->ASSC; + pHardware->adcCount++; + /// Return board enable status. + return ( pedStatus ); + /* + SSC Register + - Byte 0 = Active channels + lower sample source bit + - 0x5 + - Byte 1 = upper sample source + enable clocking + enable clock divider + + burst busy + - 0x20 + */ } // ***************************************************************************** @@ -110,60 +121,69 @@ SSC Register /// @param[in] module ID of ADC board to read. /// @return Status of ADC module DMA DONE bit (0=not complete, 1= complete) // ***************************************************************************** -int gsc18ai32CheckDmaDone(int module) +int +gsc18ai32CheckDmaDone( int module ) { - // Return 0 if DMA not complete - if((adcDma[module]->DMA_CSR & GSAF_DMA_DONE) == 0) return(0); - // Return 1 if DMA is complete - else return(1); + // Return 0 if DMA not complete + if ( ( adcDma[ module ]->DMA_CSR & GSAF_DMA_DONE ) == 0 ) + return ( 0 ); + // Return 1 if DMA is complete + else + return ( 1 ); } // ***************************************************************************** -/// \brief Function if DMA from ADC module is complete. +/// \brief Function if DMA from ADC module is complete. ///< Code will remain in loop until DMA is complete. /// @param[in] module ID of ADC board to read. /// @param[out] data Status of DMA DONE bit. /// @return ADC DMA Status (0=not complete, 16=complete /// Note: This function not presently used. // ***************************************************************************** -int gsc18ai32WaitDmaDone(int module, int *data) +int +gsc18ai32WaitDmaDone( int module, int* data ) { - do{ - }while((adcDma[module]->DMA_CSR & GSAF_DMA_DONE) == 0); - // First channel should be marked with an upper bit set - if (*data == 0) return 0; else return 16; + do + { + } while ( ( adcDma[ module ]->DMA_CSR & GSAF_DMA_DONE ) == 0 ); + // First channel should be marked with an upper bit set + if ( *data == 0 ) + return 0; + else + return 16; } - // ***************************************************************************** /// \brief Function clears ADC buffer and starts acquisition via external clock. ///< Also sets up ADC for Demand DMA mode and set GO bit in DMA Mode Register. -///< NOTE: In normal operation, this code should only be called while the clocks from -///< the timing slave are turned OFF ie during initialization process. +///< NOTE: In normal operation, this code should only be called while the clocks +///< from the timing slave are turned OFF ie during initialization process. /// @param[in] adcCount Total number of ADC modules to start DMA. // ***************************************************************************** -int gsc18ai32Enable(CDS_HARDWARE *pHardware) +int +gsc18ai32Enable( CDS_HARDWARE* pHardware ) { - int ii; - volatile GSA_ADC_18BIT_REG *adc18Ptr; - for(ii=0;ii<pHardware->adcCount;ii++) - { - if(pHardware->adcType[ii] == GSC_18AI32SSC1M) + int ii; + volatile GSA_ADC_18BIT_REG* adc18Ptr; + for ( ii = 0; ii < pHardware->adcCount; ii++ ) { - adc18Ptr = (volatile GSA_ADC_18BIT_REG *) adcPtr[ii]; - /// Enable demand DMA mode ie auto DMA data to computer memory when - ///< GSAI_THRESHOLD data points in ADC FIFO. - adc18Ptr->BCR &= ~(GSAF_DMA_DEMAND_MODE); - /// Set DMA mode and direction in PLX controller chip on module. - adcDma[ii]->DMA0_MODE = GSAF_DMA_MODE_NO_INTR | 0x1000; - /// Enable DMA - adcDma[ii]->DMA_CSR = GSAF_DMA_START; - /// Clear the FIFO and set demand DMA to start after all 32 channels have 1 sample - adc18Ptr->IDBC = (GSAF_CLEAR_BUFFER | GSAF_THRESHOLD); - /// Enable sync via external clock input. - adc18Ptr->SSC |= GSAF_ENABLE_CLOCK; + if ( pHardware->adcType[ ii ] == GSC_18AI32SSC1M ) + { + adc18Ptr = (volatile GSA_ADC_18BIT_REG*)adcPtr[ ii ]; + /// Enable demand DMA mode ie auto DMA data to computer memory when + ///< GSAI_THRESHOLD data points in ADC FIFO. + adc18Ptr->BCR &= ~( GSAF_DMA_DEMAND_MODE ); + /// Set DMA mode and direction in PLX controller chip on module. + adcDma[ ii ]->DMA0_MODE = GSAF_DMA_MODE_NO_INTR | 0x1000; + /// Enable DMA + adcDma[ ii ]->DMA_CSR = GSAF_DMA_START; + /// Clear the FIFO and set demand DMA to start after all 32 channels + /// have 1 sample + adc18Ptr->IDBC = ( GSAF_CLEAR_BUFFER | GSAF_THRESHOLD ); + /// Enable sync via external clock input. + adc18Ptr->SSC |= GSAF_ENABLE_CLOCK; + } } - } - return(0); + return ( 0 ); } #if 0 @@ -204,42 +224,45 @@ int gsc18ai32AdcStop() /// @param[in] numAdc The ID number of the ADC module to read. /// @return The number of samples presently in the ADC FIFO. // ***************************************************************************** -int gsc18ai32CheckAdcBuffer(CDS_HARDWARE *pHardware, int numAdc) +int +gsc18ai32CheckAdcBuffer( CDS_HARDWARE* pHardware, int numAdc ) { - volatile GSA_ADC_18BIT_REG *adc18Ptr; - int dataCount = 0; + volatile GSA_ADC_18BIT_REG* adc18Ptr; + int dataCount = 0; - if(pHardware->adcType[numAdc] == GSC_18AI32SSC1M) - { - adc18Ptr = (volatile GSA_ADC_18BIT_REG *) adcPtr[numAdc]; + if ( pHardware->adcType[ numAdc ] == GSC_18AI32SSC1M ) + { + adc18Ptr = (volatile GSA_ADC_18BIT_REG*)adcPtr[ numAdc ]; dataCount = adc18Ptr->BUF_SIZE; - } - return(dataCount); - + } + return ( dataCount ); } - // ***************************************************************************** -/// \brief This routine sets up the ADC DMA registers once on code initialization. +/// \brief This routine sets up the ADC DMA registers once on code +/// initialization. /// @param[in] modNum The ID number of the ADC module to read. // ***************************************************************************** -int gsc18ai32DmaSetup(int modNum) +int +gsc18ai32DmaSetup( int modNum ) { - /// Set DMA mode such that completion does not cause interrupt on bus. - adcDma[modNum]->DMA0_MODE = GSAF_DMA_MODE_NO_INTR; - /// Load PCI address (remapped local memory) to which data is to be delivered. - adcDma[modNum]->DMA0_PCI_ADD = (int)adc_dma_handle[modNum]; - /// Set the PCI address of board where data will be transferred from. - adcDma[modNum]->DMA0_LOC_ADD = GSAF_DMA_LOCAL_ADDR; - /// Set the number of bytes to be transferred. - adcDma[modNum]->DMA0_BTC = GSAF_DMA_BYTE_COUNT; - /// Set the DMA direction ie ADC to computer memory. - adcDma[modNum]->DMA0_DESC = GSAF_DMA_TO_PCI; - return(1); + /// Set DMA mode such that completion does not cause interrupt on bus. + adcDma[ modNum ]->DMA0_MODE = GSAF_DMA_MODE_NO_INTR; + /// Load PCI address (remapped local memory) to which data is to be + /// delivered. + adcDma[ modNum ]->DMA0_PCI_ADD = (int)adc_dma_handle[ modNum ]; + /// Set the PCI address of board where data will be transferred from. + adcDma[ modNum ]->DMA0_LOC_ADD = GSAF_DMA_LOCAL_ADDR; + /// Set the number of bytes to be transferred. + adcDma[ modNum ]->DMA0_BTC = GSAF_DMA_BYTE_COUNT; + /// Set the DMA direction ie ADC to computer memory. + adcDma[ modNum ]->DMA0_DESC = GSAF_DMA_TO_PCI; + return ( 1 ); } // ***************************************************************************** -/// \brief This routine sets up the ADC DMA registers once on code initialization. +/// \brief This routine sets up the ADC DMA registers once on code +/// initialization. /// @param[in] modNum The ID number of the ADC module to read. // ***************************************************************************** #if 0 @@ -259,14 +282,13 @@ int gsc18ai32DmaSetup32(int modNum) } #endif - // ***************************************************************************** -/// \brief This routine starts an ADC DMA operation. It must first be setup by +/// \brief This routine starts an ADC DMA operation. It must first be setup by ///< the gsc16ai64DmaSetup routine. /// @param[in] modNum The ID number of the ADC module to read. // ***************************************************************************** -void gsc18ai32DmaEnable(int modNum) +void +gsc18ai32DmaEnable( int modNum ) { - adcDma[modNum]->DMA_CSR = GSAF_DMA_START; + adcDma[ modNum ]->DMA_CSR = GSAF_DMA_START; } - diff --git a/src/include/drv/gsc18ai6.c b/src/include/drv/gsc18ai6.c index 869443798..ba434b198 100644 --- a/src/include/drv/gsc18ai6.c +++ b/src/include/drv/gsc18ai6.c @@ -1,72 +1,74 @@ #include "gsc18ai6.h" -volatile GSA_FAD_REG *fadcPtr[MAX_ADC_MODULES]; +volatile GSA_FAD_REG* fadcPtr[ MAX_ADC_MODULES ]; // ***************************************************************************** -/// Routine to initialize GSA PMC66_18AISS6C ADC modules +/// Routine to initialize GSA PMC66_18AISS6C ADC modules // ***************************************************************************** -int mapFadc(CDS_HARDWARE *pHardware, - struct pci_dev *adcdev) +int +mapFadc( CDS_HARDWARE* pHardware, struct pci_dev* adcdev ) { - static unsigned int pci_io_addr; - int devNum; - char *_adc_add; /* ADC register address space */ - int pedStatus; + static unsigned int pci_io_addr; + int devNum; + char* _adc_add; /* ADC register address space */ + int pedStatus; - devNum = pHardware->adcCount; - pedStatus = pci_enable_device(adcdev); - pci_set_master(adcdev); - // Get the PLX chip address - pci_read_config_dword(adcdev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("pci0 = 0x%x\n",pci_io_addr); - _adc_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - adcDma[devNum] = (PLX_9056_DMA *)_adc_add; - dacDma[pHardware->dacCount] = (PLX_9056_DMA *)_adc_add; - if(devNum == 0) plxIcr = (PLX_9056_INTCTRL *)_adc_add; + devNum = pHardware->adcCount; + pedStatus = pci_enable_device( adcdev ); + pci_set_master( adcdev ); + // Get the PLX chip address + pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "pci0 = 0x%x\n", pci_io_addr ); + _adc_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + adcDma[ devNum ] = (PLX_9056_DMA*)_adc_add; + dacDma[ pHardware->dacCount ] = (PLX_9056_DMA*)_adc_add; + if ( devNum == 0 ) + plxIcr = (PLX_9056_INTCTRL*)_adc_add; - // Get the ADC register address - pci_read_config_dword(adcdev,PCI_BASE_ADDRESS_2,&pci_io_addr); - printk("pci2 = 0x%x\n",pci_io_addr); - _adc_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - printk("ADC I/O address=0x%x 0x%lx\n", pci_io_addr,(long)_adc_add); - fadcPtr[devNum] = (GSA_FAD_REG *)_adc_add; + // Get the ADC register address + pci_read_config_dword( adcdev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + printk( "pci2 = 0x%x\n", pci_io_addr ); + _adc_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + printk( "ADC I/O address=0x%x 0x%lx\n", pci_io_addr, (long)_adc_add ); + fadcPtr[ devNum ] = (GSA_FAD_REG*)_adc_add; - printk("BCR = 0x%x\n",fadcPtr[devNum]->BCR); - printk("INPUT CONFIG = 0x%x\n",fadcPtr[devNum]->IN_CONF); + printk( "BCR = 0x%x\n", fadcPtr[ devNum ]->BCR ); + printk( "INPUT CONFIG = 0x%x\n", fadcPtr[ devNum ]->IN_CONF ); - // Reset the ADC board - fadcPtr[devNum]->BCR |= GSAF_RESET; - do{ - }while((fadcPtr[devNum]->BCR & GSAF_RESET) != 0); - printk("after reset BCR = 0x%x\n",fadcPtr[devNum]->BCR); - printk("after reset INPUT CONFIG = 0x%x\n",fadcPtr[devNum]->IN_CONF); + // Reset the ADC board + fadcPtr[ devNum ]->BCR |= GSAF_RESET; + do + { + } while ( ( fadcPtr[ devNum ]->BCR & GSAF_RESET ) != 0 ); + printk( "after reset BCR = 0x%x\n", fadcPtr[ devNum ]->BCR ); + printk( "after reset INPUT CONFIG = 0x%x\n", fadcPtr[ devNum ]->IN_CONF ); - fadcPtr[devNum]->IN_CONF |= 1 << 9; - fadcPtr[devNum]->BCR |= 1 << 12; // enable buffer - fadcPtr[devNum]->BCR |= 1 << 13; - printk("final BCR = 0x%x\n",fadcPtr[devNum]->BCR); - printk("final INPUT CONFIG = 0x%x\n",fadcPtr[devNum]->IN_CONF); - pHardware->adcConfig[devNum] = fadcPtr[devNum]->ASSC; - printk("final ASSEMBLY CONFIG = 0x%x\n",pHardware->adcConfig[devNum]); + fadcPtr[ devNum ]->IN_CONF |= 1 << 9; + fadcPtr[ devNum ]->BCR |= 1 << 12; // enable buffer + fadcPtr[ devNum ]->BCR |= 1 << 13; + printk( "final BCR = 0x%x\n", fadcPtr[ devNum ]->BCR ); + printk( "final INPUT CONFIG = 0x%x\n", fadcPtr[ devNum ]->IN_CONF ); + pHardware->adcConfig[ devNum ] = fadcPtr[ devNum ]->ASSC; + printk( "final ASSEMBLY CONFIG = 0x%x\n", pHardware->adcConfig[ devNum ] ); - pHardware->pci_adc[devNum] = - (long)pci_alloc_consistent(adcdev,0x2000,&adc_dma_handle[devNum]); - pHardware->adcType[devNum] = GSC_18AISS6C; - pHardware->adcCount ++; - return(0); + pHardware->pci_adc[ devNum ] = + (long)pci_alloc_consistent( adcdev, 0x2000, &adc_dma_handle[ devNum ] ); + pHardware->adcType[ devNum ] = GSC_18AISS6C; + pHardware->adcCount++; + return ( 0 ); } - // ***************************************************************************** /// Test if ADC has a sample ready. /// Only to be used with 2MS/sec ADC module. // ***************************************************************************** -int checkAdcRdy(int count,int numAdc,int type) +int +checkAdcRdy( int count, int numAdc, int type ) { - int dataCount; + int dataCount; - int i = 0; - switch(type) - { + int i = 0; + switch ( type ) + { #if 0 case GSC_18AI32SSC1M: do { @@ -78,8 +80,8 @@ int checkAdcRdy(int count,int numAdc,int type) }while(dataCount < count); break; #endif - case GSC_16AI64SSA: - dataCount = adcPtr[numAdc]->BUF_SIZE; + case GSC_16AI64SSA: + dataCount = adcPtr[ numAdc ]->BUF_SIZE; #if 0 do { dataCount = adcPtr[numAdc]->BUF_SIZE; @@ -89,21 +91,23 @@ int checkAdcRdy(int count,int numAdc,int type) i++; }while(dataCount < count); #endif - break; - // Default is GSC 2MHz ADC - default: - do { - dataCount = fadcPtr[0]->IN_BUF_SIZE; - if (i == 1000000) { - break; - } - i++; - }while(dataCount < (count / 8)); + break; + // Default is GSC 2MHz ADC + default: + do + { + dataCount = fadcPtr[ 0 ]->IN_BUF_SIZE; + if ( i == 1000000 ) + { break; - } - // If timeout, return error - if (i >= 1000000) return -1; - // gsaAdcDma2(numAdc); - return(dataCount); + } + i++; + } while ( dataCount < ( count / 8 ) ); + break; + } + // If timeout, return error + if ( i >= 1000000 ) + return -1; + // gsaAdcDma2(numAdc); + return ( dataCount ); } - diff --git a/src/include/drv/gsc18ao8.c b/src/include/drv/gsc18ao8.c index abb58ffb3..5b65aa71c 100644 --- a/src/include/drv/gsc18ao8.c +++ b/src/include/drv/gsc18ao8.c @@ -1,153 +1,174 @@ /// \file gsc18ao8.c -/// \brief File contains the initialization routine and various register read/write -///< operations for the General Standards 18bit, 8 channel DAC modules. \n -///< For board info, see -///< <a href="http://www.generalstandards.com/view-products2.php?BD_family=18ao8">GSC 18AO8 Manual</a> +/// \brief File contains the initialization routine and various register +/// read/write +///< operations for the General Standards 18bit, 8 channel DAC +///< modules. \n +///< For board info, see +///< <a +///< href="http://www.generalstandards.com/view-products2.php?BD_family=18ao8">GSC +///< 18AO8 Manual</a> #include "gsc18ao8.h" // ***************************************************************************** /// \brief Routine to initialize GSC 18AO8 DAC modules. -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @param[in] *dacdev PCI address information passed by the mapping code in map.c +/// @param[in] *dacdev PCI address information passed by the mapping code in +/// map.c /// @return Status from board enable command. // ***************************************************************************** -int gsc18ao8Init(CDS_HARDWARE *pHardware, struct pci_dev *dacdev) +int +gsc18ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev ) { - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - char *_dac_add; /// @param *_dac_add DAC register address space - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int pedStatus; /// @param pedStatus Status return from call to enable device. - volatile GSA_18BIT_DAC_REG *dac18bitPtr; /// @param *dac18bitPtr Pointer to DAC control registers. + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + char* _dac_add; /// @param *_dac_add DAC register address space + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. + volatile GSA_18BIT_DAC_REG* + dac18bitPtr; /// @param *dac18bitPtr Pointer to DAC control registers. #ifdef DAC_AUTOCAL - int timer = 0; + int timer = 0; #endif - /// Get index into CDS_HARDWARE struct based on total number of DAC cards found by mapping routine - /// in map.c - devNum = pHardware->dacCount; - /// Enable the device, PCI required - pedStatus = pci_enable_device(dacdev); - /// Register module as Master capable, required for DMA - pci_set_master(dacdev); - /// Get the PLX chip PCI address, it is advertised at address 0 - pci_read_config_dword(dacdev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("pci0 = 0x%x\n",pci_io_addr); - _dac_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - /// Set up a pointer to DMA registers on PLX chip - dacDma[devNum] = (PLX_9056_DMA *)_dac_add; - - /// Get the DAC register address - pci_read_config_dword(dacdev,PCI_BASE_ADDRESS_2,&pci_io_addr); - printk("dac pci2 = 0x%x\n",pci_io_addr); - _dac_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - printk("DAC I/O address=0x%x 0x%lx\n", pci_io_addr,(long)_dac_add); - - dac18bitPtr = (GSA_18BIT_DAC_REG *)_dac_add; - dacPtr[devNum] = (GSC_DAC_REG *)_dac_add; - - printk("DAC BCR = 0x%x\n",dac18bitPtr->BCR); - /// Reset the DAC board and wait for it to finish (3msec) - - dac18bitPtr->BCR |= GSAO_18BIT_RESET; - - do{ - }while((dac18bitPtr->BCR & GSAO_18BIT_RESET) != 0); - - /// Enable 2s complement by clearing offset binary bit - dac18bitPtr->BCR &= ~GSAO_18BIT_OFFSET_BINARY; - dac18bitPtr->BCR |= GSAO_18BIT_SIMULT_OUT; - printk("DAC BCR after init = 0x%x\n",dac18bitPtr->BCR); - printk("DAC OUTPUT CONFIG = 0x%x\n",dac18bitPtr->OUTPUT_CONFIG); - - /// Enable 10 volt output range - dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_10VOLT_RANGE; - // Various bits setup - //dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_ENABLE_EXT_CLOCK; - //dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_EXT_CLOCK_SRC; - //dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_EXT_TRIG_SRC; - dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_DIFF_OUTS; + /// Get index into CDS_HARDWARE struct based on total number of DAC cards + /// found by mapping routine in map.c + devNum = pHardware->dacCount; + /// Enable the device, PCI required + pedStatus = pci_enable_device( dacdev ); + /// Register module as Master capable, required for DMA + pci_set_master( dacdev ); + /// Get the PLX chip PCI address, it is advertised at address 0 + pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "pci0 = 0x%x\n", pci_io_addr ); + _dac_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + /// Set up a pointer to DMA registers on PLX chip + dacDma[ devNum ] = (PLX_9056_DMA*)_dac_add; + + /// Get the DAC register address + pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + printk( "dac pci2 = 0x%x\n", pci_io_addr ); + _dac_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + printk( "DAC I/O address=0x%x 0x%lx\n", pci_io_addr, (long)_dac_add ); + + dac18bitPtr = (GSA_18BIT_DAC_REG*)_dac_add; + dacPtr[ devNum ] = (GSC_DAC_REG*)_dac_add; + + printk( "DAC BCR = 0x%x\n", dac18bitPtr->BCR ); + /// Reset the DAC board and wait for it to finish (3msec) + + dac18bitPtr->BCR |= GSAO_18BIT_RESET; + + do + { + } while ( ( dac18bitPtr->BCR & GSAO_18BIT_RESET ) != 0 ); + + /// Enable 2s complement by clearing offset binary bit + dac18bitPtr->BCR &= ~GSAO_18BIT_OFFSET_BINARY; + dac18bitPtr->BCR |= GSAO_18BIT_SIMULT_OUT; + printk( "DAC BCR after init = 0x%x\n", dac18bitPtr->BCR ); + printk( "DAC OUTPUT CONFIG = 0x%x\n", dac18bitPtr->OUTPUT_CONFIG ); + + /// Enable 10 volt output range + dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_10VOLT_RANGE; + // Various bits setup + // dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_ENABLE_EXT_CLOCK; + // dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_EXT_CLOCK_SRC; + // dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_EXT_TRIG_SRC; + dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_DIFF_OUTS; #ifdef DAC_AUTOCAL - // Start Calibration - dac18bitPtr->BCR |= GSAO_18BIT_AUTOCAL_SET; - do{ - udelay(1000); - timer += 1; - }while((dac18bitPtr->BCR & GSAO_18BIT_AUTOCAL_SET) != 0); - - if(dac18bitPtr->BCR & GSAO_18BIT_AUTOCAL_PASS) - printk("DAC AUTOCAL SUCCESS in %d milliseconds \n",timer); - else - printk("DAC AUTOCAL FAILED in %d milliseconds \n",timer); - printk("DAC OUTPUT CONFIG after init = 0x%x with BCR = 0x%x\n",dac18bitPtr->OUTPUT_CONFIG, dac18bitPtr->BCR); + // Start Calibration + dac18bitPtr->BCR |= GSAO_18BIT_AUTOCAL_SET; + do + { + udelay( 1000 ); + timer += 1; + } while ( ( dac18bitPtr->BCR & GSAO_18BIT_AUTOCAL_SET ) != 0 ); + + if ( dac18bitPtr->BCR & GSAO_18BIT_AUTOCAL_PASS ) + printk( "DAC AUTOCAL SUCCESS in %d milliseconds \n", timer ); + else + printk( "DAC AUTOCAL FAILED in %d milliseconds \n", timer ); + printk( "DAC OUTPUT CONFIG after init = 0x%x with BCR = 0x%x\n", + dac18bitPtr->OUTPUT_CONFIG, + dac18bitPtr->BCR ); #else - printk("DAC OUTPUT CONFIG after init = 0x%x\n",dac18bitPtr->OUTPUT_CONFIG); + printk( "DAC OUTPUT CONFIG after init = 0x%x\n", + dac18bitPtr->OUTPUT_CONFIG ); #endif - // TODO: maybe dac_dma_handle should be a separate variable for 18-bit board? - pHardware->pci_dac[devNum] = - (long) pci_alloc_consistent(dacdev,0x200,&dac_dma_handle[devNum]); - pHardware->dacConfig[devNum] = (int) (dac18bitPtr->ASY_CONFIG); - pHardware->dacType[devNum] = GSC_18AO8; - pHardware->dacCount ++; - - /// Call patch in map.c needed to properly write to native PCIe module version of 16AO16 - set_8111_prefetch(dacdev); - return(pedStatus); + // TODO: maybe dac_dma_handle should be a separate variable for 18-bit + // board? + pHardware->pci_dac[ devNum ] = + (long)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] ); + pHardware->dacConfig[ devNum ] = (int)( dac18bitPtr->ASY_CONFIG ); + pHardware->dacType[ devNum ] = GSC_18AO8; + pHardware->dacCount++; + + /// Call patch in map.c needed to properly write to native PCIe module + /// version of 16AO16 + set_8111_prefetch( dacdev ); + return ( pedStatus ); } // ***************************************************************************** -/// \brief Function enables DAC modules to begin receiving external clocking signals. -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// \brief Function enables DAC modules to begin receiving external clocking +/// signals. +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. // ***************************************************************************** -int gsc18ao8Enable(CDS_HARDWARE *pHardware) +int +gsc18ao8Enable( CDS_HARDWARE* pHardware ) { - int ii; - - for (ii = 0; ii < pHardware -> dacCount; ii++) - { - if (pHardware->dacType[ii] == GSC_18AO8) { - volatile GSA_18BIT_DAC_REG *dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[ii]); - dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_EXT_CLOCK_SRC; - dac18bitPtr->BUF_OUTPUT_OPS |= GSAO_18BIT_ENABLE_CLOCK; - // printk("Triggered 18-bit DAC\n"); - } - } - - return(0); + int ii; + + for ( ii = 0; ii < pHardware->dacCount; ii++ ) + { + if ( pHardware->dacType[ ii ] == GSC_18AO8 ) + { + volatile GSA_18BIT_DAC_REG* dac18bitPtr = + (volatile GSA_18BIT_DAC_REG*)( dacPtr[ ii ] ); + dac18bitPtr->OUTPUT_CONFIG |= GSAO_18BIT_EXT_CLOCK_SRC; + dac18bitPtr->BUF_OUTPUT_OPS |= GSAO_18BIT_ENABLE_CLOCK; + // printk("Triggered 18-bit DAC\n"); + } + } + + return ( 0 ); } - // ***************************************************************************** -/// \brief This routine sets up the DAC DMA registers once on code initialization. +/// \brief This routine sets up the DAC DMA registers once on code +/// initialization. /// @param[in] modNum ID number of board to be accessed. // ***************************************************************************** -int gsc18ao8DmaSetup(int modNum) +int +gsc18ao8DmaSetup( int modNum ) { - dacDma[modNum]->DMA1_MODE = GSAI_DMA_MODE_NO_INTR; - dacDma[modNum]->DMA1_PCI_ADD = (int)dac_dma_handle[modNum]; - dacDma[modNum]->DMA1_LOC_ADD = GSAO_18BIT_DMA_LOCAL_ADDR; + dacDma[ modNum ]->DMA1_MODE = GSAI_DMA_MODE_NO_INTR; + dacDma[ modNum ]->DMA1_PCI_ADD = (int)dac_dma_handle[ modNum ]; + dacDma[ modNum ]->DMA1_LOC_ADD = GSAO_18BIT_DMA_LOCAL_ADDR; #ifdef OVERSAMPLE_DAC - dacDma[modNum]->DMA1_BTC = 0x20*OVERSAMPLE_TIMES; + dacDma[ modNum ]->DMA1_BTC = 0x20 * OVERSAMPLE_TIMES; #else - dacDma[modNum]->DMA1_BTC = 0x20; + dacDma[ modNum ]->DMA1_BTC = 0x20; #endif - dacDma[modNum]->DMA1_DESC = 0x0; - return(1); + dacDma[ modNum ]->DMA1_DESC = 0x0; + return ( 1 ); } - // ***************************************************************************** /// \brief This routine starts a DMA operation to a DAC module. ///< It must first be setup by the gsc18ao8DmaSetup call. // ***************************************************************************** -void gsc18ao8DmaStart(int modNum) +void +gsc18ao8DmaStart( int modNum ) { - // dacDma[modNum]->DMA1_PCI_ADD = ((int)dac_dma_handle[modNum]); - dacDma[modNum]->DMA_CSR = GSAI_DMA1_START; + // dacDma[modNum]->DMA1_PCI_ADD = ((int)dac_dma_handle[modNum]); + dacDma[ modNum ]->DMA_CSR = GSAI_DMA1_START; } - - diff --git a/src/include/drv/gsc20ao8.c b/src/include/drv/gsc20ao8.c index 88281afad..7a18b8a08 100644 --- a/src/include/drv/gsc20ao8.c +++ b/src/include/drv/gsc20ao8.c @@ -1,173 +1,191 @@ /// \file gsc20ao8.c -/// \brief File contains the initialization routine and various register read/write -///< operations for the General Standards 20bit, 8 channel DAC modules. \n -///< For board info, see -///< <a href="http://www.generalstandards.com/view-products2.php?BD_family=18ao8">GSC 18AO8 Manual</a> +/// \brief File contains the initialization routine and various register +/// read/write +///< operations for the General Standards 20bit, 8 channel DAC +///< modules. \n +///< For board info, see +///< <a +///< href="http://www.generalstandards.com/view-products2.php?BD_family=18ao8">GSC +///< 18AO8 Manual</a> #include "gsc20ao8.h" // ***************************************************************************** /// \brief Routine to initialize GSC 20AO8 DAC modules. -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @param[in] *dacdev PCI address information passed by the mapping code in map.c +/// @param[in] *dacdev PCI address information passed by the mapping code in +/// map.c /// @return Status from board enable command. // ***************************************************************************** -int gsc20ao8Init(CDS_HARDWARE *pHardware, struct pci_dev *dacdev) +int +gsc20ao8Init( CDS_HARDWARE* pHardware, struct pci_dev* dacdev ) { - int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding board info. - char *_dac_add; /// @param *_dac_add DAC register address space - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int pedStatus; /// @param pedStatus Status return from call to enable device. - volatile GSA_20BIT_DAC_REG *dac20bitPtr; /// @param *dac20bitPtr Pointer to DAC control registers. - int timer = 0; - - /// Get index into CDS_HARDWARE struct based on total number of DAC cards found by mapping routine - /// in map.c - devNum = pHardware->dacCount; - /// Enable the device, PCI required - pedStatus = pci_enable_device(dacdev); - /// Register module as Master capable, required for DMA - pci_set_master(dacdev); - /// Get the PLX chip PCI address, it is advertised at address 0 - pci_read_config_dword(dacdev,PCI_BASE_ADDRESS_0,&pci_io_addr); - printk("pci0 = 0x%x\n",pci_io_addr); - _dac_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - /// Set up a pointer to DMA registers on PLX chip - dacDma[devNum] = (PLX_9056_DMA *)_dac_add; - - /// Get the DAC register address - pci_read_config_dword(dacdev,PCI_BASE_ADDRESS_2,&pci_io_addr); - // Send some info to dmesg - printk("dac pci2 = 0x%x\n",pci_io_addr); - _dac_add = ioremap_nocache((unsigned long)pci_io_addr, 0x200); - // Send some info to dmesg - printk("DAC I/O address=0x%x 0x%lx\n", pci_io_addr,(long)_dac_add); - - dac20bitPtr = (GSA_20BIT_DAC_REG *)_dac_add; - dacPtr[devNum] = (GSC_DAC_REG *)_dac_add; - - // Send some info to dmesg - printk("DAC BCR = 0x%x\n",dac20bitPtr->BCR); - /// Reset the DAC board and wait for it to finish (3msec) - - dac20bitPtr->BCR |= GSAO_20BIT_RESET; - - timer = 6000; - do{ - udelay(1000); - timer -= 1; - }while((dac20bitPtr->BCR & GSAO_20BIT_RESET) != 0 && - timer > 0 && - dac20bitPtr->PRIMARY_STATUS == 1); - - // printk("DAC PSR after init = 0x%x and timer = %d\n",dac20bitPtr->PRIMARY_STATUS,timer); - - /// Enable 2s complement by clearing offset binary bit - dac20bitPtr->BCR &= ~GSAO_20BIT_OFFSET_BINARY; - // Set simultaneous outputs - dac20bitPtr->BCR |= GSAO_20BIT_SIMULT_OUT; - // Send some info to dmesg - // printk("DAC BCR after init = 0x%x\n",dac20bitPtr->BCR); - // printk("DAC OUTPUT CONFIG = 0x%x\n",dac20bitPtr->OUTPUT_CONFIG); - - /// Enable 10 volt output range - dac20bitPtr->OUTPUT_CONFIG |= GSAO_20BIT_10VOLT_RANGE; - // Set differential outputs - dac20bitPtr->OUTPUT_CONFIG |= GSAO_20BIT_DIFF_OUTS; - // Enable outputs. - dac20bitPtr->BCR |= GSAO_20BIT_OUTPUT_ENABLE; - udelay(1000); - // Set primary status to detect autocal - printk("DAC PSR = 0x%x\n",dac20bitPtr->PRIMARY_STATUS); - dac20bitPtr->PRIMARY_STATUS = 2; - udelay(1000); - printk("DAC PSR after reset = 0x%x\n",dac20bitPtr->PRIMARY_STATUS); - - // Start Calibration - dac20bitPtr->BCR |= GSAO_20BIT_AUTOCAL_SET; - // Wait for autocal to complete - timer = 0; - do{ - udelay(1000); - // printk("DAC PSR in autocal = 0x%x\n",dac20bitPtr->PRIMARY_STATUS); - timer += 1; - }while((dac20bitPtr->BCR & GSAO_20BIT_AUTOCAL_SET) != 0); - - printk("DAC after autocal PSR = 0x%x\n",dac20bitPtr->PRIMARY_STATUS); - if(dac20bitPtr->BCR & GSAO_20BIT_AUTOCAL_PASS) - printk("DAC AUTOCAL SUCCESS in %d milliseconds \n",timer); - else - printk("DAC AUTOCAL FAILED in %d milliseconds \n",timer); - printk("DAC PSR = 0x%x\n",dac20bitPtr->PRIMARY_STATUS); - - // If 20bit DAC, need to enable outputs. - dac20bitPtr->BCR |= GSAO_20BIT_OUTPUT_ENABLE; - printk("DAC OUTPUT CONFIG after init = 0x%x with BCR = 0x%x\n",dac20bitPtr->OUTPUT_CONFIG, dac20bitPtr->BCR); - - pHardware->pci_dac[devNum] = - (long) pci_alloc_consistent(dacdev,0x200,&dac_dma_handle[devNum]); - pHardware->dacConfig[devNum] = (int) (dac20bitPtr->ASY_CONFIG); - - // Return the device type to main code. - pHardware->dacType[devNum] = GSC_20AO8; - pHardware->dacCount ++; - - /// Call patch in map.c needed to properly write to native PCIe module - set_8111_prefetch(dacdev); - return(pedStatus); + int devNum; /// @param devNum Index into CDS_HARDWARE struct for adding + /// board info. + char* _dac_add; /// @param *_dac_add DAC register address space + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int pedStatus; /// @param pedStatus Status return from call to enable + /// device. + volatile GSA_20BIT_DAC_REG* + dac20bitPtr; /// @param *dac20bitPtr Pointer to DAC control registers. + int timer = 0; + + /// Get index into CDS_HARDWARE struct based on total number of DAC cards + /// found by mapping routine in map.c + devNum = pHardware->dacCount; + /// Enable the device, PCI required + pedStatus = pci_enable_device( dacdev ); + /// Register module as Master capable, required for DMA + pci_set_master( dacdev ); + /// Get the PLX chip PCI address, it is advertised at address 0 + pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + printk( "pci0 = 0x%x\n", pci_io_addr ); + _dac_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + /// Set up a pointer to DMA registers on PLX chip + dacDma[ devNum ] = (PLX_9056_DMA*)_dac_add; + + /// Get the DAC register address + pci_read_config_dword( dacdev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + // Send some info to dmesg + printk( "dac pci2 = 0x%x\n", pci_io_addr ); + _dac_add = ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + // Send some info to dmesg + printk( "DAC I/O address=0x%x 0x%lx\n", pci_io_addr, (long)_dac_add ); + + dac20bitPtr = (GSA_20BIT_DAC_REG*)_dac_add; + dacPtr[ devNum ] = (GSC_DAC_REG*)_dac_add; + + // Send some info to dmesg + printk( "DAC BCR = 0x%x\n", dac20bitPtr->BCR ); + /// Reset the DAC board and wait for it to finish (3msec) + + dac20bitPtr->BCR |= GSAO_20BIT_RESET; + + timer = 6000; + do + { + udelay( 1000 ); + timer -= 1; + } while ( ( dac20bitPtr->BCR & GSAO_20BIT_RESET ) != 0 && timer > 0 && + dac20bitPtr->PRIMARY_STATUS == 1 ); + + // printk("DAC PSR after init = 0x%x and timer = + // %d\n",dac20bitPtr->PRIMARY_STATUS,timer); + + /// Enable 2s complement by clearing offset binary bit + dac20bitPtr->BCR &= ~GSAO_20BIT_OFFSET_BINARY; + // Set simultaneous outputs + dac20bitPtr->BCR |= GSAO_20BIT_SIMULT_OUT; + // Send some info to dmesg + // printk("DAC BCR after init = 0x%x\n",dac20bitPtr->BCR); + // printk("DAC OUTPUT CONFIG = 0x%x\n",dac20bitPtr->OUTPUT_CONFIG); + + /// Enable 10 volt output range + dac20bitPtr->OUTPUT_CONFIG |= GSAO_20BIT_10VOLT_RANGE; + // Set differential outputs + dac20bitPtr->OUTPUT_CONFIG |= GSAO_20BIT_DIFF_OUTS; + // Enable outputs. + dac20bitPtr->BCR |= GSAO_20BIT_OUTPUT_ENABLE; + udelay( 1000 ); + // Set primary status to detect autocal + printk( "DAC PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS ); + dac20bitPtr->PRIMARY_STATUS = 2; + udelay( 1000 ); + printk( "DAC PSR after reset = 0x%x\n", dac20bitPtr->PRIMARY_STATUS ); + + // Start Calibration + dac20bitPtr->BCR |= GSAO_20BIT_AUTOCAL_SET; + // Wait for autocal to complete + timer = 0; + do + { + udelay( 1000 ); + // printk("DAC PSR in autocal = 0x%x\n",dac20bitPtr->PRIMARY_STATUS); + timer += 1; + } while ( ( dac20bitPtr->BCR & GSAO_20BIT_AUTOCAL_SET ) != 0 ); + + printk( "DAC after autocal PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS ); + if ( dac20bitPtr->BCR & GSAO_20BIT_AUTOCAL_PASS ) + printk( "DAC AUTOCAL SUCCESS in %d milliseconds \n", timer ); + else + printk( "DAC AUTOCAL FAILED in %d milliseconds \n", timer ); + printk( "DAC PSR = 0x%x\n", dac20bitPtr->PRIMARY_STATUS ); + + // If 20bit DAC, need to enable outputs. + dac20bitPtr->BCR |= GSAO_20BIT_OUTPUT_ENABLE; + printk( "DAC OUTPUT CONFIG after init = 0x%x with BCR = 0x%x\n", + dac20bitPtr->OUTPUT_CONFIG, + dac20bitPtr->BCR ); + + pHardware->pci_dac[ devNum ] = + (long)pci_alloc_consistent( dacdev, 0x200, &dac_dma_handle[ devNum ] ); + pHardware->dacConfig[ devNum ] = (int)( dac20bitPtr->ASY_CONFIG ); + + // Return the device type to main code. + pHardware->dacType[ devNum ] = GSC_20AO8; + pHardware->dacCount++; + + /// Call patch in map.c needed to properly write to native PCIe module + set_8111_prefetch( dacdev ); + return ( pedStatus ); } // ***************************************************************************** -/// \brief Function enables DAC modules to begin receiving external clocking signals. -/// @param[in] *pHardware Pointer to global data structure for storing I/O +/// \brief Function enables DAC modules to begin receiving external clocking +/// signals. +/// @param[in] *pHardware Pointer to global data structure for storing I/O ///< register mapping information. // ***************************************************************************** -int gsc20ao8Enable(CDS_HARDWARE *pHardware) +int +gsc20ao8Enable( CDS_HARDWARE* pHardware ) { - int ii; - - for (ii = 0; ii < pHardware -> dacCount; ii++) - { - if (pHardware->dacType[ii] == GSC_20AO8) { - volatile GSA_20BIT_DAC_REG *dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[ii]); - dac20bitPtr->OUTPUT_CONFIG |= GSAO_20BIT_EXT_CLOCK_SRC; - dac20bitPtr->BUF_OUTPUT_OPS |= GSAO_20BIT_ENABLE_CLOCK; - // printk("Triggered 20-bit DAC\n"); - } - } - - return(0); + int ii; + + for ( ii = 0; ii < pHardware->dacCount; ii++ ) + { + if ( pHardware->dacType[ ii ] == GSC_20AO8 ) + { + volatile GSA_20BIT_DAC_REG* dac20bitPtr = + (volatile GSA_20BIT_DAC_REG*)( dacPtr[ ii ] ); + dac20bitPtr->OUTPUT_CONFIG |= GSAO_20BIT_EXT_CLOCK_SRC; + dac20bitPtr->BUF_OUTPUT_OPS |= GSAO_20BIT_ENABLE_CLOCK; + // printk("Triggered 20-bit DAC\n"); + } + } + + return ( 0 ); } - // ***************************************************************************** -/// \brief This routine sets up the DAC DMA registers once on code initialization. +/// \brief This routine sets up the DAC DMA registers once on code +/// initialization. /// @param[in] modNum ID number of board to be accessed. // ***************************************************************************** -int gsc20ao8DmaSetup(int modNum) +int +gsc20ao8DmaSetup( int modNum ) { - dacDma[modNum]->DMA1_MODE = GSAI_DMA_MODE_NO_INTR; - dacDma[modNum]->DMA1_PCI_ADD = (int)dac_dma_handle[modNum]; - dacDma[modNum]->DMA1_LOC_ADD = GSAO_20BIT_DMA_LOCAL_ADDR; + dacDma[ modNum ]->DMA1_MODE = GSAI_DMA_MODE_NO_INTR; + dacDma[ modNum ]->DMA1_PCI_ADD = (int)dac_dma_handle[ modNum ]; + dacDma[ modNum ]->DMA1_LOC_ADD = GSAO_20BIT_DMA_LOCAL_ADDR; #ifdef OVERSAMPLE_DAC - dacDma[modNum]->DMA1_BTC = 0x20*OVERSAMPLE_TIMES; + dacDma[ modNum ]->DMA1_BTC = 0x20 * OVERSAMPLE_TIMES; #else - dacDma[modNum]->DMA1_BTC = 0x20; + dacDma[ modNum ]->DMA1_BTC = 0x20; #endif - dacDma[modNum]->DMA1_DESC = 0x0; - return(1); + dacDma[ modNum ]->DMA1_DESC = 0x0; + return ( 1 ); } - // ***************************************************************************** /// \brief This routine starts a DMA operation to a DAC module. ///< It must first be setup by the gsc20ao8DmaSetup call. // ***************************************************************************** -void gsc20ao8DmaStart(int modNum) +void +gsc20ao8DmaStart( int modNum ) { - // dacDma[modNum]->DMA1_PCI_ADD = ((int)dac_dma_handle[modNum]); - dacDma[modNum]->DMA_CSR = GSAI_DMA1_START; + // dacDma[modNum]->DMA1_PCI_ADD = ((int)dac_dma_handle[modNum]); + dacDma[ modNum ]->DMA_CSR = GSAI_DMA1_START; } - - diff --git a/src/include/drv/iop_adc_functions.c b/src/include/drv/iop_adc_functions.c index 94815f8fd..fbd17973a 100644 --- a/src/include/drv/iop_adc_functions.c +++ b/src/include/drv/iop_adc_functions.c @@ -195,7 +195,7 @@ iop_adc_read( adcInfo_t* adcinfo, int cpuClk[] ) #ifdef TIME_MASTER pcieTimer->gps_time = timeSec; pcieTimer->cycle = cycleNum; - clflush_cache_range( (void *)&pcieTimer->gps_time, 16 ); + clflush_cache_range( (void*)&pcieTimer->gps_time, 16 ); #endif } else diff --git a/src/include/drv/iop_dac_functions.c b/src/include/drv/iop_dac_functions.c index 93ef385e4..7059d4f3d 100644 --- a/src/include/drv/iop_dac_functions.c +++ b/src/include/drv/iop_dac_functions.c @@ -1,305 +1,385 @@ -inline int iop_dac_init(int []); -inline int iop_dac_preload(volatile GSC_DAC_REG *[]); -inline int iop_dac_write(void); +inline int iop_dac_init( int[] ); +inline int iop_dac_preload( volatile GSC_DAC_REG*[] ); +inline int iop_dac_write( void ); -inline int iop_dac_init(int errorPend[]) +inline int +iop_dac_init( int errorPend[] ) { - int ii,jj; - int status; + int ii, jj; + int status; - /// \> Zero out DAC outputs - for (ii = 0; ii < MAX_DAC_MODULES; ii++) - { - errorPend[ii] = 0; - for (jj = 0; jj < 16; jj++) { - dacOut[ii][jj] = 0.0; - dacOutUsed[ii][jj] = 0; - dacOutBufSize[ii] = 0; - // Zero out DAC channel map in the shared memory - // to be used to check on slaves' channel allocation - ioMemData->dacOutUsed[ii][jj] = 0; + /// \> Zero out DAC outputs + for ( ii = 0; ii < MAX_DAC_MODULES; ii++ ) + { + errorPend[ ii ] = 0; + for ( jj = 0; jj < 16; jj++ ) + { + dacOut[ ii ][ jj ] = 0.0; + dacOutUsed[ ii ][ jj ] = 0; + dacOutBufSize[ ii ] = 0; + // Zero out DAC channel map in the shared memory + // to be used to check on slaves' channel allocation + ioMemData->dacOutUsed[ ii ][ jj ] = 0; + } } - } - for(jj = 0; jj < cdsPciModules.dacCount; jj++) { - pLocalEpics->epicsOutput.statDac[jj] = DAC_FOUND_BIT; - // Arm DAC DMA for full data size - if(cdsPciModules.dacType[jj] == GSC_16AO16) { - status = gsc16ao16DmaSetup(jj); - } else if (cdsPciModules.dacType[jj] == GSC_20AO8){ - status = gsc20ao8DmaSetup(jj); - } else { - status = gsc18ao8DmaSetup(jj); - } - } + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + pLocalEpics->epicsOutput.statDac[ jj ] = DAC_FOUND_BIT; + // Arm DAC DMA for full data size + if ( cdsPciModules.dacType[ jj ] == GSC_16AO16 ) + { + status = gsc16ao16DmaSetup( jj ); + } + else if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + status = gsc20ao8DmaSetup( jj ); + } + else + { + status = gsc18ao8DmaSetup( jj ); + } + } - return 0; + return 0; } - -inline int iop_dac_preload(volatile GSC_DAC_REG *dacReg[]) +inline int +iop_dac_preload( volatile GSC_DAC_REG* dacReg[] ) { -volatile GSA_18BIT_DAC_REG *dac18Ptr; -volatile GSA_20BIT_DAC_REG *dac20Ptr; -volatile GSC_DAC_REG *dac16Ptr; -int ii,jj; + volatile GSA_18BIT_DAC_REG* dac18Ptr; + volatile GSA_20BIT_DAC_REG* dac20Ptr; + volatile GSC_DAC_REG* dac16Ptr; + int ii, jj; - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - dac18Ptr = (volatile GSA_18BIT_DAC_REG *)(dacReg[jj]); - for(ii=0;ii<GSAO_18BIT_PRELOAD;ii++) dac18Ptr->OUTPUT_BUF = 0; - } else if(cdsPciModules.dacType[jj] == GSC_20AO8) { - dac20Ptr = (volatile GSA_20BIT_DAC_REG *)(dacReg[jj]); - for(ii=0;ii<GSAO_20BIT_PRELOAD;ii++) dac20Ptr->OUTPUT_BUF = 0; - }else{ - dac16Ptr = dacReg[jj]; - for(ii=0;ii<GSAO_16BIT_PRELOAD;ii++) dac16Ptr->ODB = 0; - } - } + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) + { + dac18Ptr = (volatile GSA_18BIT_DAC_REG*)( dacReg[ jj ] ); + for ( ii = 0; ii < GSAO_18BIT_PRELOAD; ii++ ) + dac18Ptr->OUTPUT_BUF = 0; + } + else if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + dac20Ptr = (volatile GSA_20BIT_DAC_REG*)( dacReg[ jj ] ); + for ( ii = 0; ii < GSAO_20BIT_PRELOAD; ii++ ) + dac20Ptr->OUTPUT_BUF = 0; + } + else + { + dac16Ptr = dacReg[ jj ]; + for ( ii = 0; ii < GSAO_16BIT_PRELOAD; ii++ ) + dac16Ptr->ODB = 0; + } + } return 0; } -inline int iop_dac_recover(int loops, volatile GSC_DAC_REG *dacReg[]) +inline int +iop_dac_recover( int loops, volatile GSC_DAC_REG* dacReg[] ) { - volatile GSA_18BIT_DAC_REG *dac18Ptr; - volatile GSA_20BIT_DAC_REG *dac20Ptr; - volatile GSC_DAC_REG *dac16Ptr; - int ii,jj,kk; - for(kk=0;kk<loops;kk++) + volatile GSA_18BIT_DAC_REG* dac18Ptr; + volatile GSA_20BIT_DAC_REG* dac20Ptr; + volatile GSC_DAC_REG* dac16Ptr; + int ii, jj, kk; + for ( kk = 0; kk < loops; kk++ ) { - for(jj=0;jj<cdsPciModules.dacCount;jj++) - { - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - dac18Ptr = (volatile GSA_18BIT_DAC_REG *)(dacReg[jj]); - for(ii=0;ii<GSAO_18BIT_CHAN_COUNT;ii++) dac18Ptr->OUTPUT_BUF = dacOutEpics[jj][ii]; - } else if(cdsPciModules.dacType[jj] == GSC_20AO8) { - dac20Ptr = (volatile GSA_20BIT_DAC_REG *)(dacReg[jj]); - for(ii=0;ii<GSAO_20BIT_CHAN_COUNT;ii++) dac20Ptr->OUTPUT_BUF = dacOutEpics[jj][ii]; - }else{ - dac16Ptr = dacReg[jj]; - for(ii=0;ii<GSAO_16BIT_CHAN_COUNT;ii++) dac16Ptr->ODB = dacOutEpics[jj][ii]; - } - } - } + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) + { + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) + { + dac18Ptr = (volatile GSA_18BIT_DAC_REG*)( dacReg[ jj ] ); + for ( ii = 0; ii < GSAO_18BIT_CHAN_COUNT; ii++ ) + dac18Ptr->OUTPUT_BUF = dacOutEpics[ jj ][ ii ]; + } + else if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + dac20Ptr = (volatile GSA_20BIT_DAC_REG*)( dacReg[ jj ] ); + for ( ii = 0; ii < GSAO_20BIT_CHAN_COUNT; ii++ ) + dac20Ptr->OUTPUT_BUF = dacOutEpics[ jj ][ ii ]; + } + else + { + dac16Ptr = dacReg[ jj ]; + for ( ii = 0; ii < GSAO_16BIT_CHAN_COUNT; ii++ ) + dac16Ptr->ODB = dacOutEpics[ jj ][ ii ]; + } + } + } return 0; } -inline int iop_dac_write() +inline int +iop_dac_write( ) { -unsigned int *pDacData; -int ii,jj,mm; -int limit; -int mask; -int num_outs; -int status = 0; + unsigned int* pDacData; + int ii, jj, mm; + int limit; + int mask; + int num_outs; + int status = 0; -/// START OF IOP DAC WRITE ***************************************** \n + /// START OF IOP DAC WRITE ***************************************** \n /// \> If DAC FIFO error, always output zero to DAC modules. \n /// - -- Code will require restart to clear. - // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. + // COMMENT OUT NEX LINE FOR TEST STAND w/bad DAC cards. /// \> Loop thru all DAC modules - if(dacWriteEnable > 4) { - for(jj=0;jj<cdsPciModules.dacCount;jj++) + if ( dacWriteEnable > 4 ) { - /// - -- Point to DAC memory buffer - pDacData = (unsigned int *)(cdsPciModules.pci_dac[jj]); - /// - -- locate the proper DAC memory block - mm = cdsPciModules.dacConfig[jj]; - /// - -- Determine if memory block has been set with the correct cycle count by Slave app. - if(ioMemData->iodata[mm][ioMemCntrDac].cycle == ioClockDac) + for ( jj = 0; jj < cdsPciModules.dacCount; jj++ ) { - dacEnable |= pBits[jj]; - }else { - dacEnable &= ~(pBits[jj]); - dacChanErr[jj] += 1; - } - /// - -- Set overflow limits, data mask, and chan count based on DAC type - limit = OVERFLOW_LIMIT_16BIT; - mask = GSAO_16BIT_MASK; - num_outs = GSAO_16BIT_CHAN_COUNT; - if (cdsPciModules.dacType[jj] == GSC_18AO8) { - limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit - mask = GSAO_18BIT_MASK; - num_outs = GSAO_18BIT_CHAN_COUNT; - } - if (cdsPciModules.dacType[jj] == GSC_20AO8) { - limit = OVERFLOW_LIMIT_20BIT; // 20 bit limit - mask = GSAO_20BIT_MASK; - num_outs = GSAO_20BIT_CHAN_COUNT; - } - /// - -- For each DAC channel - for (ii=0; ii < num_outs; ii++) - { -#ifdef FLIP_SIGNALS - dacOut[jj][ii] *= -1; -#endif - /// - ---- Read DAC output value from shared memory and reset memory to zero - if((!dacChanErr[jj]) && (iopDacEnable)) { - dac_out = ioMemData->iodata[mm][ioMemCntrDac].data[ii]; - /// - --------- Zero out data in case user app dies by next cycle - /// when two or more apps share same DAC module. - ioMemData->iodata[mm][ioMemCntrDac].data[ii] = 0; - } else { - dac_out = 0; - status = 1; + /// - -- Point to DAC memory buffer + pDacData = (unsigned int*)( cdsPciModules.pci_dac[ jj ] ); + /// - -- locate the proper DAC memory block + mm = cdsPciModules.dacConfig[ jj ]; + /// - -- Determine if memory block has been set with the correct + /// cycle count by Slave app. + if ( ioMemData->iodata[ mm ][ ioMemCntrDac ].cycle == ioClockDac ) + { + dacEnable |= pBits[ jj ]; + } + else + { + dacEnable &= ~( pBits[ jj ] ); + dacChanErr[ jj ] += 1; } - /// - ---- Write out ADC duotone signal to first DAC, last channel, - /// if DAC duotone is enabled. - if((dt_diag.dacDuoEnable) && (ii==(num_outs-1)) && (jj == 0)) + /// - -- Set overflow limits, data mask, and chan count based on DAC + /// type + limit = OVERFLOW_LIMIT_16BIT; + mask = GSAO_16BIT_MASK; + num_outs = GSAO_16BIT_CHAN_COUNT; + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) { - dac_out = adcinfo.adcData[0][ADC_DUOTONE_CHAN]; + limit = OVERFLOW_LIMIT_18BIT; // 18 bit limit + mask = GSAO_18BIT_MASK; + num_outs = GSAO_18BIT_CHAN_COUNT; } + if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + limit = OVERFLOW_LIMIT_20BIT; // 20 bit limit + mask = GSAO_20BIT_MASK; + num_outs = GSAO_20BIT_CHAN_COUNT; + } + /// - -- For each DAC channel + for ( ii = 0; ii < num_outs; ii++ ) + { +#ifdef FLIP_SIGNALS + dacOut[ jj ][ ii ] *= -1; +#endif + /// - ---- Read DAC output value from shared memory and reset + /// memory to zero + if ( ( !dacChanErr[ jj ] ) && ( iopDacEnable ) ) + { + dac_out = + ioMemData->iodata[ mm ][ ioMemCntrDac ].data[ ii ]; + /// - --------- Zero out data in case user app dies by next + /// cycle when two or more apps share same DAC module. + ioMemData->iodata[ mm ][ ioMemCntrDac ].data[ ii ] = 0; + } + else + { + dac_out = 0; + status = 1; + } + /// - ---- Write out ADC duotone signal to first DAC, last + /// channel, if DAC duotone is enabled. + if ( ( dt_diag.dacDuoEnable ) && ( ii == ( num_outs - 1 ) ) && + ( jj == 0 ) ) + { + dac_out = adcinfo.adcData[ 0 ][ ADC_DUOTONE_CHAN ]; + } // Code below is only for use in DAQ test system. #ifdef DIAG_TEST - if((ii==0) && (jj == 0)) - { - if(cycleNum < 100) dac_out = limit / 20; - else dac_out = 0; - } - if((ii==0) && (jj == 2)) - { - if(cycleNum < 100) dac_out = limit / 20; - else dac_out = 0; - } + if ( ( ii == 0 ) && ( jj == 0 ) ) + { + if ( cycleNum < 100 ) + dac_out = limit / 20; + else + dac_out = 0; + } + if ( ( ii == 0 ) && ( jj == 2 ) ) + { + if ( cycleNum < 100 ) + dac_out = limit / 20; + else + dac_out = 0; + } #endif - /// - ---- Check output values are within range of DAC \n - /// - --------- If overflow, clip at DAC limits and report errors - if(dac_out > limit || dac_out < -limit) - { - dacinfo.overflowDac[jj][ii] ++; - pLocalEpics->epicsOutput.overflowDacAcc[jj][ii] ++; - overflowAcc ++; - dacOF[jj] = 1; - odcStateWord |= ODC_DAC_OVF;; - if(dac_out > limit) dac_out = limit; - else dac_out = -limit; - } - /// - ---- If DAQKILL tripped, set output to zero. - if(!iopDacEnable) dac_out = 0; - /// - ---- Load last values to EPICS channels for monitoring on GDS_TP screen. - dacOutEpics[jj][ii] = dac_out; + /// - ---- Check output values are within range of DAC \n + /// - --------- If overflow, clip at DAC limits and report + /// errors + if ( dac_out > limit || dac_out < -limit ) + { + dacinfo.overflowDac[ jj ][ ii ]++; + pLocalEpics->epicsOutput.overflowDacAcc[ jj ][ ii ]++; + overflowAcc++; + dacOF[ jj ] = 1; + odcStateWord |= ODC_DAC_OVF; + ; + if ( dac_out > limit ) + dac_out = limit; + else + dac_out = -limit; + } + /// - ---- If DAQKILL tripped, set output to zero. + if ( !iopDacEnable ) + dac_out = 0; + /// - ---- Load last values to EPICS channels for monitoring on + /// GDS_TP screen. + dacOutEpics[ jj ][ ii ] = dac_out; - /// - ---- Load DAC testpoints - floatDacOut[16*jj + ii] = dac_out; + /// - ---- Load DAC testpoints + floatDacOut[ 16 * jj + ii ] = dac_out; - /// - ---- Write to DAC local memory area, for later xmit to DAC module - *pDacData = (unsigned int)(dac_out & mask); - pDacData ++; - } - /// - -- Mark cycle count as having been used -1 \n - /// - --------- Forces slaves to mark this cycle or will not be used again by Master - ioMemData->iodata[mm][ioMemCntrDac].cycle = -1; - /// - -- DMA Write data to DAC module - if(dacWriteEnable > 4) { - if(cdsPciModules.dacType[jj] == GSC_16AO16) { - gsc16ao16DmaStart(jj); - } else if(cdsPciModules.dacType[jj] == GSC_20AO8) { - gsc20ao8DmaStart(jj); - } else { - gsc18ao8DmaStart(jj); - } + /// - ---- Write to DAC local memory area, for later xmit to DAC + /// module + *pDacData = (unsigned int)( dac_out & mask ); + pDacData++; + } + /// - -- Mark cycle count as having been used -1 \n + /// - --------- Forces slaves to mark this cycle or will not be used + /// again by Master + ioMemData->iodata[ mm ][ ioMemCntrDac ].cycle = -1; + /// - -- DMA Write data to DAC module + if ( dacWriteEnable > 4 ) + { + if ( cdsPciModules.dacType[ jj ] == GSC_16AO16 ) + { + gsc16ao16DmaStart( jj ); + } + else if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + gsc20ao8DmaStart( jj ); + } + else + { + gsc18ao8DmaStart( jj ); + } + } } } - } /// \> Increment DAC memory block pointers for next cycle - ioClockDac = (ioClockDac + 1) % IOP_IO_RATE; - ioMemCntrDac = (ioMemCntrDac + 1) % IO_MEMORY_SLOTS; - if(dacWriteEnable < 10) dacWriteEnable ++; -/// END OF IOP DAC WRITE ************************************************* + ioClockDac = ( ioClockDac + 1 ) % IOP_IO_RATE; + ioMemCntrDac = ( ioMemCntrDac + 1 ) % IO_MEMORY_SLOTS; + if ( dacWriteEnable < 10 ) + dacWriteEnable++; + /// END OF IOP DAC WRITE ************************************************* return status; - } - -inline int check_dac_buffers (int cycleNum) +inline int +check_dac_buffers( int cycleNum ) { - volatile GSA_18BIT_DAC_REG *dac18bitPtr; - volatile GSA_20BIT_DAC_REG *dac20bitPtr; - int out_buf_size = 0; - int jj = 0; - int status = 0; + volatile GSA_18BIT_DAC_REG* dac18bitPtr; + volatile GSA_20BIT_DAC_REG* dac20bitPtr; + int out_buf_size = 0; + int jj = 0; + int status = 0; - jj = cycleNum - HKP_DAC_FIFO_CHK; - if(cdsPciModules.dacType[jj] == GSC_18AO8) - { - dac18bitPtr = (volatile GSA_18BIT_DAC_REG *)(dacPtr[jj]); - out_buf_size = dac18bitPtr->OUT_BUF_SIZE; - dacOutBufSize[jj] = out_buf_size; - pLocalEpics->epicsOutput.buffDac[jj] = out_buf_size; - if(!dacTimingError) { - if((out_buf_size < 8) || (out_buf_size > 24)) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_FIFO_BIT); - if(dacTimingErrorPending[jj]) dacTimingError = 1; - dacTimingErrorPending[jj] = 1; - } else { - pLocalEpics->epicsOutput.statDac[jj] |= DAC_FIFO_BIT; - dacTimingErrorPending[jj] = 0; - } - } - if(out_buf_size < 4) { - pLocalEpics->epicsOutput.statDac[jj] |= DAC_FIFO_EMPTY; - } else { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_FIFO_EMPTY); - } - if(out_buf_size > 32) { - pLocalEpics->epicsOutput.statDac[jj] |= DAC_FIFO_FULL; - } else { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_FIFO_FULL); - } - - } - if(cdsPciModules.dacType[jj] == GSC_20AO8) + jj = cycleNum - HKP_DAC_FIFO_CHK; + if ( cdsPciModules.dacType[ jj ] == GSC_18AO8 ) + { + dac18bitPtr = (volatile GSA_18BIT_DAC_REG*)( dacPtr[ jj ] ); + out_buf_size = dac18bitPtr->OUT_BUF_SIZE; + dacOutBufSize[ jj ] = out_buf_size; + pLocalEpics->epicsOutput.buffDac[ jj ] = out_buf_size; + if ( !dacTimingError ) { - dac20bitPtr = (volatile GSA_20BIT_DAC_REG *)(dacPtr[jj]); - out_buf_size = dac20bitPtr->OUT_BUF_SIZE; - dacOutBufSize[jj] = out_buf_size; - pLocalEpics->epicsOutput.buffDac[jj] = out_buf_size; - pLocalEpics->epicsOutput.buffDac[jj] = out_buf_size; - if((out_buf_size > 24)) + if ( ( out_buf_size < 8 ) || ( out_buf_size > 24 ) ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_FIFO_BIT ); + if ( dacTimingErrorPending[ jj ] ) + dacTimingError = 1; + dacTimingErrorPending[ jj ] = 1; + } + else { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_FIFO_BIT); - if(dacTimingErrorPending[jj]) dacTimingError = 1; - dacTimingErrorPending[jj] = 1; - } else { - pLocalEpics->epicsOutput.statDac[jj] |= DAC_FIFO_BIT; - dacTimingErrorPending[jj] = 0; + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_FIFO_BIT; + dacTimingErrorPending[ jj ] = 0; } - } - if(cdsPciModules.dacType[jj] == GSC_16AO16) - { - status = gsc16ao16CheckDacBuffer(jj); - dacOutBufSize[jj] = status; - if(!dacTimingError) { - if(status != 2) - { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_FIFO_BIT); - if(dacTimingErrorPending[jj]) dacTimingError = 1; - dacTimingErrorPending[jj] = 1; - } else { - pLocalEpics->epicsOutput.statDac[jj] |= DAC_FIFO_BIT; - dacTimingErrorPending[jj] = 0; - } - } - if(status & 1) { - pLocalEpics->epicsOutput.statDac[jj] |= DAC_FIFO_EMPTY; - } else { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_FIFO_EMPTY); - } - if(status & 8) { - pLocalEpics->epicsOutput.statDac[jj] |= DAC_FIFO_FULL; - } else { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_FIFO_FULL); - } - if(status & 4) { - pLocalEpics->epicsOutput.statDac[jj] |= DAC_FIFO_HI_QTR; - } else { - pLocalEpics->epicsOutput.statDac[jj] &= ~(DAC_FIFO_HI_QTR); - } - } - return 0; + } + if ( out_buf_size < 4 ) + { + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_FIFO_EMPTY; + } + else + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_FIFO_EMPTY ); + } + if ( out_buf_size > 32 ) + { + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_FIFO_FULL; + } + else + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_FIFO_FULL ); + } + } + if ( cdsPciModules.dacType[ jj ] == GSC_20AO8 ) + { + dac20bitPtr = (volatile GSA_20BIT_DAC_REG*)( dacPtr[ jj ] ); + out_buf_size = dac20bitPtr->OUT_BUF_SIZE; + dacOutBufSize[ jj ] = out_buf_size; + pLocalEpics->epicsOutput.buffDac[ jj ] = out_buf_size; + pLocalEpics->epicsOutput.buffDac[ jj ] = out_buf_size; + if ( ( out_buf_size > 24 ) ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_FIFO_BIT ); + if ( dacTimingErrorPending[ jj ] ) + dacTimingError = 1; + dacTimingErrorPending[ jj ] = 1; + } + else + { + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_FIFO_BIT; + dacTimingErrorPending[ jj ] = 0; + } + } + if ( cdsPciModules.dacType[ jj ] == GSC_16AO16 ) + { + status = gsc16ao16CheckDacBuffer( jj ); + dacOutBufSize[ jj ] = status; + if ( !dacTimingError ) + { + if ( status != 2 ) + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_FIFO_BIT ); + if ( dacTimingErrorPending[ jj ] ) + dacTimingError = 1; + dacTimingErrorPending[ jj ] = 1; + } + else + { + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_FIFO_BIT; + dacTimingErrorPending[ jj ] = 0; + } + } + if ( status & 1 ) + { + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_FIFO_EMPTY; + } + else + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_FIFO_EMPTY ); + } + if ( status & 8 ) + { + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_FIFO_FULL; + } + else + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_FIFO_FULL ); + } + if ( status & 4 ) + { + pLocalEpics->epicsOutput.statDac[ jj ] |= DAC_FIFO_HI_QTR; + } + else + { + pLocalEpics->epicsOutput.statDac[ jj ] &= ~( DAC_FIFO_HI_QTR ); + } + } + return 0; } diff --git a/src/include/drv/seiwd.c b/src/include/drv/seiwd.c index de65eb203..ea61f345e 100644 --- a/src/include/drv/seiwd.c +++ b/src/include/drv/seiwd.c @@ -1,118 +1,144 @@ -/* *********************************************************************************** */ -/* seiwd() */ -/* Main SEI watchdog routine. */ -/* *********************************************************************************** */ +/* *********************************************************************************** + */ +/* seiwd() */ +/* Main SEI watchdog routine. */ +/* *********************************************************************************** + */ -inline int seiwd(float input_sensors[], int max_var[]) +inline int +seiwd( float input_sensors[], int max_var[] ) { -int watchdog_byte; + int watchdog_byte; - watchdog_byte = 0; + watchdog_byte = 0; - /* Compare the STS sensor inputs */ - if(input_sensors[0] > max_var[0]) watchdog_byte |= 0x1; /* Bit 0 */ - if(input_sensors[1] > max_var[0]) watchdog_byte |= 0x2; /* Bit 1 */ - if(input_sensors[2] > max_var[0]) watchdog_byte |= 0x4; /* Bit 2 */ + /* Compare the STS sensor inputs */ + if ( input_sensors[ 0 ] > max_var[ 0 ] ) + watchdog_byte |= 0x1; /* Bit 0 */ + if ( input_sensors[ 1 ] > max_var[ 0 ] ) + watchdog_byte |= 0x2; /* Bit 1 */ + if ( input_sensors[ 2 ] > max_var[ 0 ] ) + watchdog_byte |= 0x4; /* Bit 2 */ - /* Compare the POS V sensor inputs */ - if(input_sensors[3] > max_var[1]) watchdog_byte |= 0x8; /* Bit 3 */ - if(input_sensors[4] > max_var[1]) watchdog_byte |= 0x10; /* Bit 4 */ - if(input_sensors[5] > max_var[1]) watchdog_byte |= 0x20; /* Bit 5 */ - if(input_sensors[6] > max_var[1]) watchdog_byte |= 0x40; /* Bit 6 */ + /* Compare the POS V sensor inputs */ + if ( input_sensors[ 3 ] > max_var[ 1 ] ) + watchdog_byte |= 0x8; /* Bit 3 */ + if ( input_sensors[ 4 ] > max_var[ 1 ] ) + watchdog_byte |= 0x10; /* Bit 4 */ + if ( input_sensors[ 5 ] > max_var[ 1 ] ) + watchdog_byte |= 0x20; /* Bit 5 */ + if ( input_sensors[ 6 ] > max_var[ 1 ] ) + watchdog_byte |= 0x40; /* Bit 6 */ - /* Compare the POS H sensor inputs */ - if(input_sensors[7] > max_var[2]) watchdog_byte |= 0x80; /* Bit 7 */ - if(input_sensors[8] > max_var[2]) watchdog_byte |= 0x100; /* Bit 8 */ - if(input_sensors[9] > max_var[2]) watchdog_byte |= 0x200; /* Bit 9 */ - if(input_sensors[10] > max_var[2]) watchdog_byte |= 0x400; /* Bit 10 */ + /* Compare the POS H sensor inputs */ + if ( input_sensors[ 7 ] > max_var[ 2 ] ) + watchdog_byte |= 0x80; /* Bit 7 */ + if ( input_sensors[ 8 ] > max_var[ 2 ] ) + watchdog_byte |= 0x100; /* Bit 8 */ + if ( input_sensors[ 9 ] > max_var[ 2 ] ) + watchdog_byte |= 0x200; /* Bit 9 */ + if ( input_sensors[ 10 ] > max_var[ 2 ] ) + watchdog_byte |= 0x400; /* Bit 10 */ - /* Compare the GEO V sensor inputs */ - if(input_sensors[11] > max_var[3]) watchdog_byte |= 0x10000; /* Bit 16 */ - if(input_sensors[12] > max_var[3]) watchdog_byte |= 0x20000; /* Bit 17 */ - if(input_sensors[13] > max_var[3]) watchdog_byte |= 0x40000; /* Bit 18 */ - if(input_sensors[14] > max_var[3]) watchdog_byte |= 0x80000; /* Bit 19 */ + /* Compare the GEO V sensor inputs */ + if ( input_sensors[ 11 ] > max_var[ 3 ] ) + watchdog_byte |= 0x10000; /* Bit 16 */ + if ( input_sensors[ 12 ] > max_var[ 3 ] ) + watchdog_byte |= 0x20000; /* Bit 17 */ + if ( input_sensors[ 13 ] > max_var[ 3 ] ) + watchdog_byte |= 0x40000; /* Bit 18 */ + if ( input_sensors[ 14 ] > max_var[ 3 ] ) + watchdog_byte |= 0x80000; /* Bit 19 */ - /* Compare the GEO H sensor inputs */ - if(input_sensors[15] > max_var[4]) watchdog_byte |= 0x100000; /* Bit 20 */ - if(input_sensors[16] > max_var[4]) watchdog_byte |= 0x200000; /* Bit 21 */ - if(input_sensors[17] > max_var[4]) watchdog_byte |= 0x400000; /* Bit 22 */ - if(input_sensors[18] > max_var[4]) watchdog_byte |= 0x800000; /* Bit 23 */ + /* Compare the GEO H sensor inputs */ + if ( input_sensors[ 15 ] > max_var[ 4 ] ) + watchdog_byte |= 0x100000; /* Bit 20 */ + if ( input_sensors[ 16 ] > max_var[ 4 ] ) + watchdog_byte |= 0x200000; /* Bit 21 */ + if ( input_sensors[ 17 ] > max_var[ 4 ] ) + watchdog_byte |= 0x400000; /* Bit 22 */ + if ( input_sensors[ 18 ] > max_var[ 4 ] ) + watchdog_byte |= 0x800000; /* Bit 23 */ - return(watchdog_byte); + return ( watchdog_byte ); } -inline void seiwd1(int cycle, float rawInput[], float filtInput[],SEI_WATCHDOG *wd) +inline void +seiwd1( int cycle, float rawInput[], float filtInput[], SEI_WATCHDOG* wd ) { -int ii,kk,jj; + int ii, kk, jj; - // Get ABS of all input values - for(ii=0;ii<19;ii++) - { - if(rawInput[ii] < 0) rawInput[ii] *= -1; - if(filtInput[ii] < 0) filtInput[ii] *= -1; - } - if(!wd->trip) - { - wd->status[0] = 0; - wd->status[1] = 0; - wd->status[2] = 0; - for(ii=0;ii<3;ii++) - { - if((rawInput[ii] > 32000) || (rawInput[ii] == 0)) - { - wd->senCount[ii] ++; - } - if(filtInput[ii] > wd->filtMax[ii]) - { - wd->filtMax[ii] = filtInput[ii]; - } - kk = ii+3; - if(filtInput[ii] > wd->tripSetF[0]) - { - wd->status[0] |= (0x1 << kk); - } - if(cycle == 0) - { - wd->filtMaxHold[ii] = wd->filtMax[ii]; - wd->filtMax[ii] = 0; - if(wd->senCount[ii] > wd->tripSetR[0]) - { - wd->status[0] |= (0x1 << ii); - } - wd->senCountHold[ii] = wd->senCount[ii]; - wd->senCount[ii] = 0; - } - } - for(jj=0;jj<16;jj++) - { - ii = jj+3; - if((rawInput[ii] > 32000) || (rawInput[ii] == 0)) - { - wd->senCount[ii] ++; - } - if(filtInput[ii] > wd->filtMax[ii]) - { - wd->filtMax[ii] = filtInput[ii]; - } - kk = jj/4+1; - if(filtInput[ii] > wd->tripSetF[kk]) - { - wd->status[2] |= (0x1 << jj); - } - if(cycle == 0) - { - wd->filtMaxHold[ii] = wd->filtMax[ii]; - wd->filtMax[ii] = 0; - if(wd->senCount[ii] > wd->tripSetR[kk]) - { - wd->status[1] |= (0x1 << jj); - } - wd->senCountHold[ii] = wd->senCount[ii]; - wd->senCount[ii] = 0; - } - } - } - if((wd->status[0]) || (wd->status[1]) || (wd->status[2])) wd->trip = 1; - else wd->trip = 0; + // Get ABS of all input values + for ( ii = 0; ii < 19; ii++ ) + { + if ( rawInput[ ii ] < 0 ) + rawInput[ ii ] *= -1; + if ( filtInput[ ii ] < 0 ) + filtInput[ ii ] *= -1; + } + if ( !wd->trip ) + { + wd->status[ 0 ] = 0; + wd->status[ 1 ] = 0; + wd->status[ 2 ] = 0; + for ( ii = 0; ii < 3; ii++ ) + { + if ( ( rawInput[ ii ] > 32000 ) || ( rawInput[ ii ] == 0 ) ) + { + wd->senCount[ ii ]++; + } + if ( filtInput[ ii ] > wd->filtMax[ ii ] ) + { + wd->filtMax[ ii ] = filtInput[ ii ]; + } + kk = ii + 3; + if ( filtInput[ ii ] > wd->tripSetF[ 0 ] ) + { + wd->status[ 0 ] |= ( 0x1 << kk ); + } + if ( cycle == 0 ) + { + wd->filtMaxHold[ ii ] = wd->filtMax[ ii ]; + wd->filtMax[ ii ] = 0; + if ( wd->senCount[ ii ] > wd->tripSetR[ 0 ] ) + { + wd->status[ 0 ] |= ( 0x1 << ii ); + } + wd->senCountHold[ ii ] = wd->senCount[ ii ]; + wd->senCount[ ii ] = 0; + } + } + for ( jj = 0; jj < 16; jj++ ) + { + ii = jj + 3; + if ( ( rawInput[ ii ] > 32000 ) || ( rawInput[ ii ] == 0 ) ) + { + wd->senCount[ ii ]++; + } + if ( filtInput[ ii ] > wd->filtMax[ ii ] ) + { + wd->filtMax[ ii ] = filtInput[ ii ]; + } + kk = jj / 4 + 1; + if ( filtInput[ ii ] > wd->tripSetF[ kk ] ) + { + wd->status[ 2 ] |= ( 0x1 << jj ); + } + if ( cycle == 0 ) + { + wd->filtMaxHold[ ii ] = wd->filtMax[ ii ]; + wd->filtMax[ ii ] = 0; + if ( wd->senCount[ ii ] > wd->tripSetR[ kk ] ) + { + wd->status[ 1 ] |= ( 0x1 << jj ); + } + wd->senCountHold[ ii ] = wd->senCount[ ii ]; + wd->senCount[ ii ] = 0; + } + } + } + if ( ( wd->status[ 0 ] ) || ( wd->status[ 1 ] ) || ( wd->status[ 2 ] ) ) + wd->trip = 1; + else + wd->trip = 0; } - diff --git a/src/include/drv/spectracomGPS.c b/src/include/drv/spectracomGPS.c index 98c5e4904..bd3951b15 100644 --- a/src/include/drv/spectracomGPS.c +++ b/src/include/drv/spectracomGPS.c @@ -1,155 +1,179 @@ /// \file spectracomGPS.c -/// \brief File contains the initialization routine and various register read/write +/// \brief File contains the initialization routine and various register +/// read/write ///< operations for the TSync-PCIe IRIG-B receiver module. \n -///< For board info, see -///< <a href="http://www.spectracomcorp.com/ProductsServices/TimingSynchronization/BuslevelTiming/PCIexpressslotcards/tabid/1296/Default.aspx">Spectracom TSync-PCIe Manual</a> +///< For board info, see +///< <a +///< href="http://www.spectracomcorp.com/ProductsServices/TimingSynchronization/BuslevelTiming/PCIexpressslotcards/tabid/1296/Default.aspx">Spectracom +///< TSync-PCIe Manual</a> #include "spectracomGPS.h" // ***************************************************************************** /// \brief Initialize TSYNC GPS card (model BC635PCI-U) -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @param *gpsdev PCI address information passed by the mapping code in map.c +/// @param *gpsdev PCI address information passed by the mapping code in +///map.c // ***************************************************************************** -static int spectracomGpsInitCheckSync(CDS_HARDWARE *pHardware, struct pci_dev *gpsdev, int *need_sync) +static int +spectracomGpsInitCheckSync( CDS_HARDWARE* pHardware, + struct pci_dev* gpsdev, + int* need_sync ) { - unsigned int i,ii; - static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI card I/O register. - int pedStatus; - unsigned int days,hours,min,sec,msec,usec,nanosec,tsync; - unsigned char *addr1; - TSYNC_REGISTER *myTime; - void *TSYNC_FIFO; /// @param *TSYNC_FIFO Pointer to board uP FIFO - int sync_dummy = 0; - - if (!need_sync) - need_sync = &sync_dummy; - - pedStatus = pci_enable_device(gpsdev); - pci_read_config_dword(gpsdev, PCI_BASE_ADDRESS_0, &pci_io_addr); - pci_io_addr &= 0xfffffff0; - printk("TSYNC PIC BASE 0 address = %x\n", pci_io_addr); - - addr1 = (unsigned char *)ioremap_nocache((unsigned long)pci_io_addr, 0x30); - printk("Remapped 0x%p\n", addr1); - pHardware->gps = (unsigned int *)addr1; - pHardware->gpsType = TSYNC_RCVR; - -// Spectracom IRIG-B Card does not auto detect Year information from IRIG-B fanout unit -// This section writes to the module uP CodeExp register to correct this. -// Delays are required between code lines, as writing to FIFO is slow. -// Sequence was determined by looking at manufacturer driver code. - TSYNC_FIFO = (void *)(addr1 + 384); - iowrite16(0x101,TSYNC_FIFO); - udelay(1000); - iowrite16(0x1000,TSYNC_FIFO); - udelay(1000); - iowrite16(0x72a,TSYNC_FIFO); - udelay(1000); - iowrite16(0x280,TSYNC_FIFO); - udelay(1000); - iowrite16(0x0,TSYNC_FIFO); - udelay(1000); - iowrite16(0x800,TSYNC_FIFO); - udelay(1000); - iowrite16(0x0,TSYNC_FIFO); - udelay(1000); - iowrite16(0x0,TSYNC_FIFO); - udelay(1000); - iowrite16(0x0,TSYNC_FIFO); - udelay(1000); - iowrite16(0x400,TSYNC_FIFO); - udelay(1000); - iowrite16(0xd100,TSYNC_FIFO); - udelay(10000); - udelay(10000); - udelay(10000); -// End Code exp setup -// Need following delay to allow module to change time codes -for(ii=0;ii<500;ii++) udelay(10000); - - myTime = (TSYNC_REGISTER *)addr1; -for(ii=0;ii<2;ii++) -{ - udelay(10000); - i = myTime->SUPER_SEC_LOW; - sec = (i&0xf) + ((i>>4)&0xf) * 10; - min = ((i>>8)&0xf) + ((i>>12)&0xf)*10; - hours = ((i>>16)&0xf) + ((i>>20)&0xf)*10; - days = ((i>>24)&0xf) + ((i>>28)&0xf)*10; - - i = myTime->SUPER_SEC_HIGH; - days += (i&0xf)*100; - - i = myTime->SUB_SEC; - // nanosec = ((i & 0xffff)*5) + (i&0xfff0000); - nanosec = ((i & 0xfffffff)*5); - tsync = (i>>31) & 1; - - - i = myTime->BCD_SEC; - if(i < 1000000000) - { - printk("TSYNC NOT receiving YEAR info, defaulting to by year patch\n"); - *need_sync = 1; - /* Historically we would hardwire a offset here. - * With RCG 3.4 we have moved to configuring this in - * the symmetricom/gpstime driver. - * - * This file is built 2 ways - * 1. as part of the symmetricom/gpstime driver, in which case - * it sets the gpsOffset to 0 (and allows the user - * to configure it). - * 2. as part of an IOP, in which it gets the offset from - * the symmetricom/gpstime driver. - * - * We are leaving the offsets in as comments so that we have a history/example of what was done - */ -/* add offsets for leap-seconds - +15 through 2008 */ -/* add offset at end of 2011 (31536000 normal year) */ -/* Add offset for June 30, 2012 leap second */ -/* add offset at end of 2012 (31622400 leap year) */ -/* add offset at end of 2013 (31536000 normal year) */ - /*pHardware->gpsOffset = 31190400 + 15 + 31536000 + 1 + 31622400 + 31536000;*/ -/* add offset at end of 2014 (31536000 normal year) */ - /*pHardware->gpsOffset = pHardware->gpsOffset + 31536000;*/ -/* 2015 had 365 days plus a July 1, 2015 leap second */ - /*pHardware->gpsOffset += 31536000 + 1;*/ -/* 2016 had 366 days plus a Dec 31, 2016/Jan 1, 2017 leap second */ - /*pHardware->gpsOffset += 31622400 + 1;*/ + unsigned int i, ii; + static unsigned int pci_io_addr; /// @param pci_io_addr Bus address of PCI + /// card I/O register. + int pedStatus; + unsigned int days, hours, min, sec, msec, usec, nanosec, tsync; + unsigned char* addr1; + TSYNC_REGISTER* myTime; + void* TSYNC_FIFO; /// @param *TSYNC_FIFO Pointer to board uP FIFO + int sync_dummy = 0; + + if ( !need_sync ) + need_sync = &sync_dummy; + + pedStatus = pci_enable_device( gpsdev ); + pci_read_config_dword( gpsdev, PCI_BASE_ADDRESS_0, &pci_io_addr ); + pci_io_addr &= 0xfffffff0; + printk( "TSYNC PIC BASE 0 address = %x\n", pci_io_addr ); + + addr1 = (unsigned char*)ioremap_nocache( (unsigned long)pci_io_addr, 0x30 ); + printk( "Remapped 0x%p\n", addr1 ); + pHardware->gps = (unsigned int*)addr1; + pHardware->gpsType = TSYNC_RCVR; + + // Spectracom IRIG-B Card does not auto detect Year information from IRIG-B + // fanout unit This section writes to the module uP CodeExp register to + // correct this. Delays are required between code lines, as writing to FIFO + // is slow. Sequence was determined by looking at manufacturer driver code. + TSYNC_FIFO = (void*)( addr1 + 384 ); + iowrite16( 0x101, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x1000, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x72a, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x280, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x0, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x800, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x0, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x0, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x0, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0x400, TSYNC_FIFO ); + udelay( 1000 ); + iowrite16( 0xd100, TSYNC_FIFO ); + udelay( 10000 ); + udelay( 10000 ); + udelay( 10000 ); + // End Code exp setup + // Need following delay to allow module to change time codes + for ( ii = 0; ii < 500; ii++ ) + udelay( 10000 ); + + myTime = (TSYNC_REGISTER*)addr1; + for ( ii = 0; ii < 2; ii++ ) + { + udelay( 10000 ); + i = myTime->SUPER_SEC_LOW; + sec = ( i & 0xf ) + ( ( i >> 4 ) & 0xf ) * 10; + min = ( ( i >> 8 ) & 0xf ) + ( ( i >> 12 ) & 0xf ) * 10; + hours = ( ( i >> 16 ) & 0xf ) + ( ( i >> 20 ) & 0xf ) * 10; + days = ( ( i >> 24 ) & 0xf ) + ( ( i >> 28 ) & 0xf ) * 10; + + i = myTime->SUPER_SEC_HIGH; + days += ( i & 0xf ) * 100; + + i = myTime->SUB_SEC; + // nanosec = ((i & 0xffff)*5) + (i&0xfff0000); + nanosec = ( ( i & 0xfffffff ) * 5 ); + tsync = ( i >> 31 ) & 1; + + i = myTime->BCD_SEC; + if ( i < 1000000000 ) + { + printk( "TSYNC NOT receiving YEAR info, defaulting to by year " + "patch\n" ); + *need_sync = 1; + /* Historically we would hardwire a offset here. + * With RCG 3.4 we have moved to configuring this in + * the symmetricom/gpstime driver. + * + * This file is built 2 ways + * 1. as part of the symmetricom/gpstime driver, in which case + * it sets the gpsOffset to 0 (and allows the user + * to configure it). + * 2. as part of an IOP, in which it gets the offset from + * the symmetricom/gpstime driver. + * + * We are leaving the offsets in as comments so that we have a + * history/example of what was done + */ + /* add offsets for leap-seconds - +15 through 2008 */ + /* add offset at end of 2011 (31536000 normal year) */ + /* Add offset for June 30, 2012 leap second */ + /* add offset at end of 2012 (31622400 leap year) */ + /* add offset at end of 2013 (31536000 normal year) */ + /*pHardware->gpsOffset = 31190400 + 15 + 31536000 + 1 + 31622400 + + * 31536000;*/ + /* add offset at end of 2014 (31536000 normal year) */ + /*pHardware->gpsOffset = pHardware->gpsOffset + 31536000;*/ + /* 2015 had 365 days plus a July 1, 2015 leap second */ + /*pHardware->gpsOffset += 31536000 + 1;*/ + /* 2016 had 366 days plus a Dec 31, 2016/Jan 1, 2017 leap second */ + /*pHardware->gpsOffset += 31622400 + 1;*/ #ifndef IN_LIGO_GPS_KERNEL_DRIVER - extern long ligo_get_gps_driver_offset(void); - pHardware->gpsOffset = ligo_get_gps_driver_offset(); + extern long ligo_get_gps_driver_offset( void ); + pHardware->gpsOffset = ligo_get_gps_driver_offset( ); #else - pHardware->gpsOffset = 0; + pHardware->gpsOffset = 0; #endif - } else { - *need_sync = 0; - printk("TSYNC receiving YEAR info\n"); - pHardware->gpsOffset = -315964800; - } - sec = i + pHardware->gpsOffset; - i = myTime->BCD_SUB_SEC; - printk("date = %d days %2d:%2d:%2d\n",days,hours,min,sec); - usec = (i&0xf) + ((i>>4)&0xf) *10 + ((i>>8)&0xf) * 100; - msec = ((i>>16)&0xf) + ((i>>20)&0xf) *10 + ((i>>24)&0xf) * 100; - printk("bcd time = %d sec %d milliseconds %d microseconds %d nanosec\n",sec,msec,usec,nanosec); - printk("Board sync = %d\n",tsync); -} - return(0); + } + else + { + *need_sync = 0; + printk( "TSYNC receiving YEAR info\n" ); + pHardware->gpsOffset = -315964800; + } + sec = i + pHardware->gpsOffset; + i = myTime->BCD_SUB_SEC; + printk( "date = %d days %2d:%2d:%2d\n", days, hours, min, sec ); + usec = ( i & 0xf ) + ( ( i >> 4 ) & 0xf ) * 10 + + ( ( i >> 8 ) & 0xf ) * 100; + msec = ( ( i >> 16 ) & 0xf ) + ( ( i >> 20 ) & 0xf ) * 10 + + ( ( i >> 24 ) & 0xf ) * 100; + printk( + "bcd time = %d sec %d milliseconds %d microseconds %d nanosec\n", + sec, + msec, + usec, + nanosec ); + printk( "Board sync = %d\n", tsync ); + } + return ( 0 ); } // ***************************************************************************** /// \brief Initialize TSYNC GPS card (model BC635PCI-U) -/// @param[in,out] *pHardware Pointer to global data structure for storing I/O +/// @param[in,out] *pHardware Pointer to global data structure for storing +/// I/O ///< register mapping information. -/// @param *gpsdev PCI address information passed by the mapping code in map.c +/// @param *gpsdev PCI address information passed by the mapping code in +///map.c // ***************************************************************************** -int spectracomGpsInit(CDS_HARDWARE *pHardware, struct pci_dev *gpsdev) +int +spectracomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev ) { int need_sync_dummy = 0; - return spectracomGpsInitCheckSync(pHardware, gpsdev, &need_sync_dummy); + return spectracomGpsInitCheckSync( pHardware, gpsdev, &need_sync_dummy ); } //*********************************************************************** @@ -158,37 +182,43 @@ int spectracomGpsInit(CDS_HARDWARE *pHardware, struct pci_dev *gpsdev) /// @param[out] *tsyncUsec Pointer to register with microsecond information. /// @return GPS Sync bit (0=No sync 1=Sync) //*********************************************************************** -inline int getGpsTimeTsync(unsigned int *tsyncSec, unsigned int *tsyncUsec) { - TSYNC_REGISTER *timeRead; - unsigned int timeSec,timeNsec,sync; - - if (cdsPciModules.gps) { - timeRead = (TSYNC_REGISTER *)cdsPciModules.gps; - timeSec = timeRead->BCD_SEC; - timeSec += cdsPciModules.gpsOffset; - *tsyncSec = timeSec; - timeNsec = timeRead->SUB_SEC; - *tsyncUsec = ((timeNsec & 0xfffffff) * 5) / 1000; - sync = ((timeNsec >> 31) & 0x1) + 1; - return(sync); - } - return(0); +inline int +getGpsTimeTsync( unsigned int* tsyncSec, unsigned int* tsyncUsec ) +{ + TSYNC_REGISTER* timeRead; + unsigned int timeSec, timeNsec, sync; + + if ( cdsPciModules.gps ) + { + timeRead = (TSYNC_REGISTER*)cdsPciModules.gps; + timeSec = timeRead->BCD_SEC; + timeSec += cdsPciModules.gpsOffset; + *tsyncSec = timeSec; + timeNsec = timeRead->SUB_SEC; + *tsyncUsec = ( ( timeNsec & 0xfffffff ) * 5 ) / 1000; + sync = ( ( timeNsec >> 31 ) & 0x1 ) + 1; + return ( sync ); + } + return ( 0 ); } //*********************************************************************** /// \brief Get current GPS seconds from TSYNC IRIG-B Rcvr //*********************************************************************** -inline unsigned int getGpsSecTsync(void) { -TSYNC_REGISTER *timeRead; - unsigned int timeSec; - - if (cdsPciModules.gps) { - timeRead = (TSYNC_REGISTER *)cdsPciModules.gps; - timeSec = timeRead->BCD_SEC; - timeSec += cdsPciModules.gpsOffset; - return(timeSec); - } - return(0); +inline unsigned int +getGpsSecTsync( void ) +{ + TSYNC_REGISTER* timeRead; + unsigned int timeSec; + + if ( cdsPciModules.gps ) + { + timeRead = (TSYNC_REGISTER*)cdsPciModules.gps; + timeSec = timeRead->BCD_SEC; + timeSec += cdsPciModules.gpsOffset; + return ( timeSec ); + } + return ( 0 ); } //*********************************************************************** @@ -196,17 +226,19 @@ TSYNC_REGISTER *timeRead; /// @param[out] *tsyncUsec Pointer to register with microsecond information. /// @return GPS Sync bit (0=No sync 1=Sync) //*********************************************************************** -inline int getGpsuSecTsync(unsigned int *tsyncUsec) { - TSYNC_REGISTER *timeRead; - unsigned int timeNsec,sync; - - if (cdsPciModules.gps) { - timeRead = (TSYNC_REGISTER *)cdsPciModules.gps; - timeNsec = timeRead->SUB_SEC; - *tsyncUsec = ((timeNsec & 0xfffffff) * 5) / 1000; - sync = ((timeNsec >> 31) & 0x1) + 1; - return(sync); - } - return(0); +inline int +getGpsuSecTsync( unsigned int* tsyncUsec ) +{ + TSYNC_REGISTER* timeRead; + unsigned int timeNsec, sync; + + if ( cdsPciModules.gps ) + { + timeRead = (TSYNC_REGISTER*)cdsPciModules.gps; + timeNsec = timeRead->SUB_SEC; + *tsyncUsec = ( ( timeNsec & 0xfffffff ) * 5 ) / 1000; + sync = ( ( timeNsec >> 31 ) & 0x1 ) + 1; + return ( sync ); + } + return ( 0 ); } - diff --git a/src/include/drv/symmetricomGps.c b/src/include/drv/symmetricomGps.c index 2bc984f70..cf05aeb1f 100644 --- a/src/include/drv/symmetricomGps.c +++ b/src/include/drv/symmetricomGps.c @@ -3,143 +3,164 @@ // ***************************************************************************** /// Initialize Symmetricom GPS card (model BC635PCI-U) // ***************************************************************************** -int symmetricomGpsInit(CDS_HARDWARE *pHardware, struct pci_dev *gpsdev) +int +symmetricomGpsInit( CDS_HARDWARE* pHardware, struct pci_dev* gpsdev ) { - int i; - static unsigned int pci_io_addr; - int pedStatus; - unsigned char *addr1; - unsigned char *addr3; - unsigned int *cmd; - unsigned int *dramRead; - unsigned int time0; - SYMCOM_REGISTER *timeReg; + int i; + static unsigned int pci_io_addr; + int pedStatus; + unsigned char* addr1; + unsigned char* addr3; + unsigned int* cmd; + unsigned int* dramRead; + unsigned int time0; + SYMCOM_REGISTER* timeReg; - pedStatus = pci_enable_device(gpsdev); - pci_read_config_dword(gpsdev, PCI_BASE_ADDRESS_2, &pci_io_addr); - pci_io_addr &= 0xfffffff0; - printk("PIC BASE 2 address = %x\n", pci_io_addr); + pedStatus = pci_enable_device( gpsdev ); + pci_read_config_dword( gpsdev, PCI_BASE_ADDRESS_2, &pci_io_addr ); + pci_io_addr &= 0xfffffff0; + printk( "PIC BASE 2 address = %x\n", pci_io_addr ); - addr1 = (unsigned char *)ioremap_nocache((unsigned long)pci_io_addr, 0x40); - printk("Remapped 0x%p\n", addr1); - pHardware->gps = (unsigned int *)addr1; - pHardware->gpsType = SYMCOM_RCVR; - timeReg = (SYMCOM_REGISTER *) addr1;; + addr1 = (unsigned char*)ioremap_nocache( (unsigned long)pci_io_addr, 0x40 ); + printk( "Remapped 0x%p\n", addr1 ); + pHardware->gps = (unsigned int*)addr1; + pHardware->gpsType = SYMCOM_RCVR; + timeReg = (SYMCOM_REGISTER*)addr1; + ; - pci_read_config_dword(gpsdev, PCI_BASE_ADDRESS_3, &pci_io_addr); - pci_io_addr &= 0xfffffff0; - addr3 = (unsigned char *)ioremap_nocache((unsigned long)pci_io_addr, 0x200); - printk("PIC BASE 3 address = 0x%x\n", pci_io_addr); - printk("PIC BASE 3 address = 0x%p\n", addr3); - dramRead = (unsigned int *)(addr3 + 0x82); - cmd = (unsigned int *)(addr3 + 0x102); - // - // Set write and wait ***************************** - *cmd = 0xf6; // Request model ID - i=0; - timeReg->ACK = 0x1; // Trigger module to capture time - udelay(1000); - timeReg->ACK = 0x80; // Trigger module to capture time - do{ - udelay(1000); + pci_read_config_dword( gpsdev, PCI_BASE_ADDRESS_3, &pci_io_addr ); + pci_io_addr &= 0xfffffff0; + addr3 = + (unsigned char*)ioremap_nocache( (unsigned long)pci_io_addr, 0x200 ); + printk( "PIC BASE 3 address = 0x%x\n", pci_io_addr ); + printk( "PIC BASE 3 address = 0x%p\n", addr3 ); + dramRead = (unsigned int*)( addr3 + 0x82 ); + cmd = (unsigned int*)( addr3 + 0x102 ); + // + // Set write and wait ***************************** + *cmd = 0xf6; // Request model ID + i = 0; + timeReg->ACK = 0x1; // Trigger module to capture time + udelay( 1000 ); + timeReg->ACK = 0x80; // Trigger module to capture time + do + { + udelay( 1000 ); i++; - }while((timeReg->ACK == 0) &&(i<20)); - if(timeReg->ACK) printk("SysCom ack received ID %d !!! 0x%x\n",timeReg->ACK,i); - printk("Model = 0x%x\n",*dramRead); -// End Wait **************************************** - // - // Set write and wait ***************************** - *cmd = 0x4915; // Request model ID - i=0; - timeReg->ACK = 0x1; // Trigger module to capture time - udelay(1000); - timeReg->ACK = 0x80; // Trigger module to capture time - do{ - udelay(1000); + } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) ); + if ( timeReg->ACK ) + printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i ); + printk( "Model = 0x%x\n", *dramRead ); + // End Wait **************************************** + // + // Set write and wait ***************************** + *cmd = 0x4915; // Request model ID + i = 0; + timeReg->ACK = 0x1; // Trigger module to capture time + udelay( 1000 ); + timeReg->ACK = 0x80; // Trigger module to capture time + do + { + udelay( 1000 ); i++; - }while((timeReg->ACK == 0) &&(i<20)); - if(timeReg->ACK) printk("SysCom ack received ID %d !!! 0x%x\n",timeReg->ACK,i); - printk("Model = 0x%x\n",*dramRead); -// End Wait **************************************** - // - // Set write and wait ***************************** - *cmd = 0x4416; // Request model ID - i=0; - timeReg->ACK = 0x1; // Trigger module to capture time - udelay(1000); - timeReg->ACK = 0x80; // Trigger module to capture time - do{ - udelay(1000); + } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) ); + if ( timeReg->ACK ) + printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i ); + printk( "Model = 0x%x\n", *dramRead ); + // End Wait **************************************** + // + // Set write and wait ***************************** + *cmd = 0x4416; // Request model ID + i = 0; + timeReg->ACK = 0x1; // Trigger module to capture time + udelay( 1000 ); + timeReg->ACK = 0x80; // Trigger module to capture time + do + { + udelay( 1000 ); i++; - }while((timeReg->ACK == 0) &&(i<20)); - if(timeReg->ACK) printk("SysCom ack received ID %d !!! 0x%x\n",timeReg->ACK,i); - printk("Model = 0x%x\n",*dramRead); -// End Wait **************************************** - // - // Set write and wait ***************************** - *cmd = 0x1519; // Request model ID - i=0; - timeReg->ACK = 0x1; // Trigger module to capture time - udelay(1000); - timeReg->ACK = 0x80; // Trigger module to capture time - do{ - udelay(1000); + } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) ); + if ( timeReg->ACK ) + printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i ); + printk( "Model = 0x%x\n", *dramRead ); + // End Wait **************************************** + // + // Set write and wait ***************************** + *cmd = 0x1519; // Request model ID + i = 0; + timeReg->ACK = 0x1; // Trigger module to capture time + udelay( 1000 ); + timeReg->ACK = 0x80; // Trigger module to capture time + do + { + udelay( 1000 ); i++; - }while((timeReg->ACK == 0) &&(i<20)); - if(timeReg->ACK) printk("SysCom ack received ID %d !!! 0x%x\n",timeReg->ACK,i); - printk("New Time COde Format = 0x%x\n",*dramRead); -// End Wait **************************************** - // - // Set write and wait ***************************** - *cmd = 0x1619; // Request model ID - i=0; - timeReg->ACK = 0x1; // Trigger module to capture time - udelay(1000); - timeReg->ACK = 0x80; // Trigger module to capture time - do{ - udelay(1000); + } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) ); + if ( timeReg->ACK ) + printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i ); + printk( "New Time COde Format = 0x%x\n", *dramRead ); + // End Wait **************************************** + // + // Set write and wait ***************************** + *cmd = 0x1619; // Request model ID + i = 0; + timeReg->ACK = 0x1; // Trigger module to capture time + udelay( 1000 ); + timeReg->ACK = 0x80; // Trigger module to capture time + do + { + udelay( 1000 ); i++; - }while((timeReg->ACK == 0) &&(i<20)); - if(timeReg->ACK) printk("SysCom ack received ID %d !!! 0x%x\n",timeReg->ACK,i); - printk("New TC Modulation = 0x%x\n",*dramRead); -// End Wait **************************************** + } while ( ( timeReg->ACK == 0 ) && ( i < 20 ) ); + if ( timeReg->ACK ) + printk( "SysCom ack received ID %d !!! 0x%x\n", timeReg->ACK, i ); + printk( "New TC Modulation = 0x%x\n", *dramRead ); + // End Wait **************************************** - for (i = 0; i < 10; i++) { - pHardware->gps[0] = 1; - printk("Current time %ds %dus %dns \n", (pHardware->gps[0x34/4]-252806386), 0xfffff & pHardware->gps[0x30/4], 100 * ((pHardware->gps[0x30/4] >> 20) & 0xf)); - } - pHardware->gps[0] = 1; - time0 = pHardware->gps[0x30/4]; - if (time0 & (1<<24)) printk("Flywheeling, unlocked...\n"); - else printk ("Locked!\n"); - return(0); + for ( i = 0; i < 10; i++ ) + { + pHardware->gps[ 0 ] = 1; + printk( "Current time %ds %dus %dns \n", + ( pHardware->gps[ 0x34 / 4 ] - 252806386 ), + 0xfffff & pHardware->gps[ 0x30 / 4 ], + 100 * ( ( pHardware->gps[ 0x30 / 4 ] >> 20 ) & 0xf ) ); + } + pHardware->gps[ 0 ] = 1; + time0 = pHardware->gps[ 0x30 / 4 ]; + if ( time0 & ( 1 << 24 ) ) + printk( "Flywheeling, unlocked...\n" ); + else + printk( "Locked!\n" ); + return ( 0 ); } -inline void lockGpsTime(void) +inline void +lockGpsTime( void ) { - SYMCOM_REGISTER *timeRead; - timeRead = (SYMCOM_REGISTER *)cdsPciModules.gps; - timeRead->TIMEREQ = 1; // Trigger module to capture time + SYMCOM_REGISTER* timeRead; + timeRead = (SYMCOM_REGISTER*)cdsPciModules.gps; + timeRead->TIMEREQ = 1; // Trigger module to capture time } //*********************************************************************** // Function to read time from Symmetricom IRIG-B Module *********************** //*********************************************************************** -inline int getGpsTime(unsigned int *tsyncSec, unsigned int *tsyncUsec) +inline int +getGpsTime( unsigned int* tsyncSec, unsigned int* tsyncUsec ) { - SYMCOM_REGISTER *timeRead; - unsigned int timeSec,timeNsec,sync; + SYMCOM_REGISTER* timeRead; + unsigned int timeSec, timeNsec, sync; - if (cdsPciModules.gps) { - timeRead = (SYMCOM_REGISTER *)cdsPciModules.gps; - timeSec = timeRead->TIME1; - timeNsec = timeRead->TIME0; - *tsyncSec = timeSec - 315964800; - *tsyncUsec = (timeNsec & 0xfffff); - // Read seconds, microseconds, nanoseconds - sync = !(timeNsec & (1<<24)); - return sync; - } - return (0); + if ( cdsPciModules.gps ) + { + timeRead = (SYMCOM_REGISTER*)cdsPciModules.gps; + timeSec = timeRead->TIME1; + timeNsec = timeRead->TIME0; + *tsyncSec = timeSec - 315964800; + *tsyncUsec = ( timeNsec & 0xfffff ); + // Read seconds, microseconds, nanoseconds + sync = !( timeNsec & ( 1 << 24 ) ); + return sync; + } + return ( 0 ); } - diff --git a/src/include/drv/tRamp.c b/src/include/drv/tRamp.c index 27108427a..ed5ca9e38 100644 --- a/src/include/drv/tRamp.c +++ b/src/include/drv/tRamp.c @@ -2,123 +2,131 @@ /* Time ramp function */ /* Takes in a ramping state */ -inline double RampParamGetVal(RampParamState* state) { - return state->val; -} - -inline int RampParamGetIsRamping(RampParamState* state) { - return state->isRamping; +inline double +RampParamGetVal( RampParamState* state ) +{ + return state->val; } - -inline void RampParamInit(RampParamState* state, double xInit, const int fe_rate) +inline int +RampParamGetIsRamping( RampParamState* state ) { - state->isRamping = 0; - state->val = xInit; - state->dxPrev = 0.0; - - state->req = xInit; - state->dxMax = 0.0; - state->ddxMax = 0.0; - - state->softRatio = 4.0; - state->softVel = 1.36; // how to compute this from softRatio? - state->minAccCycles = 0.05 * fe_rate; + return state->isRamping; } -inline void RampParamLoad(RampParamState* state, double req, double tRamp, const int fe_rate) +inline void +RampParamInit( RampParamState* state, double xInit, const int fe_rate ) { - double inv_nRamp; // 1 / number of ramp cycles - - if( tRamp <= 0.0 ) - { - // no ramp state->isRamping = 0; - state->val = req; + state->val = xInit; state->dxPrev = 0.0; - state->req = req; + state->req = xInit; state->dxMax = 0.0; state->ddxMax = 0.0; - } - else if( state->isRamping || req != state->val ) - { - // setup ramp parameters - inv_nRamp = 1.0 / (fe_rate * tRamp); - state->req = req; - state->dxMax = state->softVel * lfabs(req - state->val) * inv_nRamp; - state->ddxMax = state->softRatio * state->dxMax * inv_nRamp; - - // if currently ramping, allow high accelleration - if( state->isRamping ) - state->ddxMax = lfabs(state->dxMax + state->dxPrev) / state->minAccCycles; - - // start the ramp - state->isRamping = 1; - } + + state->softRatio = 4.0; + state->softVel = 1.36; // how to compute this from softRatio? + state->minAccCycles = 0.05 * fe_rate; } -inline double RampParamUpdate(RampParamState* state) +inline void +RampParamLoad( RampParamState* state, + double req, + double tRamp, + const int fe_rate ) { - double dxReq; // distance to requested value - double dxNow; // current step size - double dxNowAbs; // lfabs(dxNow) - double ddxNow; // current change in step size - double nStop; // steps required to stop (may be non-integer) - double dxStop; // shortest distance required to stop - double dxLand; // current step size to achieve "soft landing" - - // if not ramping, just return - if( !state->isRamping ) - return state->val; - - // requested change - dxReq = state->req - state->val; - - // apply slew limit - if( dxReq > state->dxMax ) - dxNow = state->dxMax; - else if( dxReq < -state->dxMax ) - dxNow = -state->dxMax; - else - dxNow = dxReq; - - // apply accelleration limit - ddxNow = dxNow - state->dxPrev; - if( ddxNow > state->ddxMax ) - dxNow = state->dxPrev + state->ddxMax; - else if( ddxNow < -state->ddxMax ) - dxNow = state->dxPrev - state->ddxMax; - - // enforce "soft landing" - dxNowAbs = lfabs(dxNow); - if( dxNowAbs > state->ddxMax && dxNow * dxReq > 0.0 ) - { - // number of decellerations required to stop - nStop = dxNowAbs / state->ddxMax; - - // distance traveled before stopping - // assuming max decelleration in all subsequent steps - dxStop = dxNow * (1.5 + 0.5 * nStop); - - // dxNow required to make stopping distance = dxReq - // (approximation for dxReq ~ dxStop) - dxLand = dxNow + (dxReq - dxStop) / (1.5 + nStop); - - // if dxLand is slower than dxNow, use it - if( lfabs(dxLand) < dxNowAbs ) - dxNow = dxLand; - } - - // update state - state->isRamping = !(dxNow == 0.0 && state->dxPrev == 0.0); - if( dxNow == dxReq ) - state->val = state->req; - else - state->val += dxNow; - state->dxPrev = dxNow; - - return state->val; + double inv_nRamp; // 1 / number of ramp cycles + + if ( tRamp <= 0.0 ) + { + // no ramp + state->isRamping = 0; + state->val = req; + state->dxPrev = 0.0; + + state->req = req; + state->dxMax = 0.0; + state->ddxMax = 0.0; + } + else if ( state->isRamping || req != state->val ) + { + // setup ramp parameters + inv_nRamp = 1.0 / ( fe_rate * tRamp ); + state->req = req; + state->dxMax = state->softVel * lfabs( req - state->val ) * inv_nRamp; + state->ddxMax = state->softRatio * state->dxMax * inv_nRamp; + + // if currently ramping, allow high accelleration + if ( state->isRamping ) + state->ddxMax = + lfabs( state->dxMax + state->dxPrev ) / state->minAccCycles; + + // start the ramp + state->isRamping = 1; + } } +inline double +RampParamUpdate( RampParamState* state ) +{ + double dxReq; // distance to requested value + double dxNow; // current step size + double dxNowAbs; // lfabs(dxNow) + double ddxNow; // current change in step size + double nStop; // steps required to stop (may be non-integer) + double dxStop; // shortest distance required to stop + double dxLand; // current step size to achieve "soft landing" + + // if not ramping, just return + if ( !state->isRamping ) + return state->val; + + // requested change + dxReq = state->req - state->val; + + // apply slew limit + if ( dxReq > state->dxMax ) + dxNow = state->dxMax; + else if ( dxReq < -state->dxMax ) + dxNow = -state->dxMax; + else + dxNow = dxReq; + + // apply accelleration limit + ddxNow = dxNow - state->dxPrev; + if ( ddxNow > state->ddxMax ) + dxNow = state->dxPrev + state->ddxMax; + else if ( ddxNow < -state->ddxMax ) + dxNow = state->dxPrev - state->ddxMax; + + // enforce "soft landing" + dxNowAbs = lfabs( dxNow ); + if ( dxNowAbs > state->ddxMax && dxNow * dxReq > 0.0 ) + { + // number of decellerations required to stop + nStop = dxNowAbs / state->ddxMax; + + // distance traveled before stopping + // assuming max decelleration in all subsequent steps + dxStop = dxNow * ( 1.5 + 0.5 * nStop ); + + // dxNow required to make stopping distance = dxReq + // (approximation for dxReq ~ dxStop) + dxLand = dxNow + ( dxReq - dxStop ) / ( 1.5 + nStop ); + + // if dxLand is slower than dxNow, use it + if ( lfabs( dxLand ) < dxNowAbs ) + dxNow = dxLand; + } + + // update state + state->isRamping = !( dxNow == 0.0 && state->dxPrev == 0.0 ); + if ( dxNow == dxReq ) + state->val = state->req; + else + state->val += dxNow; + state->dxPrev = dxNow; + return state->val; +} diff --git a/src/include/drv/time_slave_io.c b/src/include/drv/time_slave_io.c index f43000cd9..d9d25f678 100644 --- a/src/include/drv/time_slave_io.c +++ b/src/include/drv/time_slave_io.c @@ -27,7 +27,9 @@ sync2master( volatile TIMING_SIGNAL* timePtr ) if ( loop >= 1000000 ) { return ( -1 ); - } else { + } + else + { return ( timePtr->gps_time ); } } diff --git a/src/include/drv/vmic5565.c b/src/include/drv/vmic5565.c index 701f80840..d32cda9ca 100644 --- a/src/include/drv/vmic5565.c +++ b/src/include/drv/vmic5565.c @@ -1,8 +1,12 @@ /// \file vmic5565.c -/// \brief File contains the initialization routine and various register read/write -///< operations for the Gefanuc PCIe-5565RC reflected memory modules. \n -///< For board info, see -///< <a href="http://defense.ge-ip.com/products/pcie-5565rc/p2239">PCIe-5565RC Manual</a> +/// \brief File contains the initialization routine and various register +/// read/write +///< operations for the Gefanuc PCIe-5565RC reflected memory modules. +///< \n +///< For board info, see +///< <a +///< href="http://defense.ge-ip.com/products/pcie-5565rc/p2239">PCIe-5565RC +///< Manual</a> #include "vmic5565.h" @@ -10,122 +14,136 @@ /// \brief Routine to initialize VMIC RFM modules. \n ///< Support provided is only for use of RFM with RCG IPC components. // ***************************************************************************** -int vmic5565Init(CDS_HARDWARE *pHardware, struct pci_dev *rfmdev) +int +vmic5565Init( CDS_HARDWARE* pHardware, struct pci_dev* rfmdev ) { - static unsigned int pci_io_addr; - int devNum; - static char *csrAddr; - static char *dmaAddr; - static unsigned int csrAddress; - static unsigned int dmaAddress; - int pedStatus; - - devNum = pHardware->rfmCount; - pedStatus = pci_enable_device(rfmdev); - // Register module as Master capable, required for DMA - pci_set_master(rfmdev); + static unsigned int pci_io_addr; + int devNum; + static char* csrAddr; + static char* dmaAddr; + static unsigned int csrAddress; + static unsigned int dmaAddress; + int pedStatus; + + devNum = pHardware->rfmCount; + pedStatus = pci_enable_device( rfmdev ); + // Register module as Master capable, required for DMA + pci_set_master( rfmdev ); // Find the reflected memory base address - pci_read_config_dword(rfmdev, - PCI_BASE_ADDRESS_3, - &pci_io_addr); + pci_read_config_dword( rfmdev, PCI_BASE_ADDRESS_3, &pci_io_addr ); // Map full 128 MByte new cards only - pHardware->pci_rfm[devNum] = (long)ioremap_nocache((unsigned long)pci_io_addr, 128*1024*1024); + pHardware->pci_rfm[ devNum ] = + (long)ioremap_nocache( (unsigned long)pci_io_addr, 128 * 1024 * 1024 ); // Allocate local memory for IPC DMA xfers from RFM module - pHardware->pci_rfm_dma[devNum] = (long) pci_alloc_consistent(rfmdev,IPC_BUFFER_SIZE,&rfm_dma_handle[devNum]); - printk("RFM address is 0x%ux\n",pci_io_addr); + pHardware->pci_rfm_dma[ devNum ] = (long)pci_alloc_consistent( + rfmdev, IPC_BUFFER_SIZE, &rfm_dma_handle[ devNum ] ); + printk( "RFM address is 0x%ux\n", pci_io_addr ); // Find the RFM control/status register - pci_read_config_dword(rfmdev, PCI_BASE_ADDRESS_2, &csrAddress); - printk("CSR address is 0x%x\n", csrAddress); - csrAddr = ioremap_nocache((unsigned long)csrAddress, 0x40); + pci_read_config_dword( rfmdev, PCI_BASE_ADDRESS_2, &csrAddress ); + printk( "CSR address is 0x%x\n", csrAddress ); + csrAddr = ioremap_nocache( (unsigned long)csrAddress, 0x40 ); - p5565Csr[devNum] = (VMIC5565_CSR *)csrAddr; + p5565Csr[ devNum ] = (VMIC5565_CSR*)csrAddr; // pHardware->rfm_reg[devNum] = p5565Csr; - p5565Csr[devNum]->LCSR1 &= ~TURN_OFF_5565_FAIL; - p5565Csr[devNum]->LCSR1 &= !1; // Turn off own data light + p5565Csr[ devNum ]->LCSR1 &= ~TURN_OFF_5565_FAIL; + p5565Csr[ devNum ]->LCSR1 &= !1; // Turn off own data light - printk("Board id = 0x%x\n",p5565Csr[devNum]->BID); - pHardware->rfmConfig[devNum] = p5565Csr[devNum]->NID; + printk( "Board id = 0x%x\n", p5565Csr[ devNum ]->BID ); + pHardware->rfmConfig[ devNum ] = p5565Csr[ devNum ]->NID; // Check switches and such - if(p5565Csr[devNum]->LCSR1 & VMIC_5565_REDUNDANT_MODE) printk("VMIC5565 set to redundant transfers\n"); - else printk("VMIC5565 set to single transfers\n"); - if(p5565Csr[devNum]->LCSR1 & VMIC_5565_ROGUE_MASTER1) printk("VMIC5565 ROGUE MASTER 1 = ON\n"); - else printk("VMIC5565 ROGUE MASTER 1 = OFF\n"); - if(p5565Csr[devNum]->LCSR1 & VMIC_5565_ROGUE_MASTER0) printk("VMIC5565 ROGUE MASTER 0 = ON\n"); - else printk("VMIC5565 ROGUE MASTER 0 = OFF\n"); - if(p5565Csr[devNum]->LCSR1 & VMIC_5565_MEM_SIZE) printk("VMIC5565 Memory size = 128MBytes\n"); - else printk("VMIC5565 Memory size = 64MBytes\n"); + if ( p5565Csr[ devNum ]->LCSR1 & VMIC_5565_REDUNDANT_MODE ) + printk( "VMIC5565 set to redundant transfers\n" ); + else + printk( "VMIC5565 set to single transfers\n" ); + if ( p5565Csr[ devNum ]->LCSR1 & VMIC_5565_ROGUE_MASTER1 ) + printk( "VMIC5565 ROGUE MASTER 1 = ON\n" ); + else + printk( "VMIC5565 ROGUE MASTER 1 = OFF\n" ); + if ( p5565Csr[ devNum ]->LCSR1 & VMIC_5565_ROGUE_MASTER0 ) + printk( "VMIC5565 ROGUE MASTER 0 = ON\n" ); + else + printk( "VMIC5565 ROGUE MASTER 0 = OFF\n" ); + if ( p5565Csr[ devNum ]->LCSR1 & VMIC_5565_MEM_SIZE ) + printk( "VMIC5565 Memory size = 128MBytes\n" ); + else + printk( "VMIC5565 Memory size = 64MBytes\n" ); // - // Find DMA Engine controls in RFM Local Configuration Table - pci_read_config_dword(rfmdev, - PCI_BASE_ADDRESS_0, - &dmaAddress); - printk("DMA address is 0x%ux\n",dmaAddress); - dmaAddr = ioremap_nocache(dmaAddress,0x200); - p5565Dma[devNum] = (VMIC5565DMA *)dmaAddr; + // Find DMA Engine controls in RFM Local Configuration Table + pci_read_config_dword( rfmdev, PCI_BASE_ADDRESS_0, &dmaAddress ); + printk( "DMA address is 0x%ux\n", dmaAddress ); + dmaAddr = ioremap_nocache( dmaAddress, 0x200 ); + p5565Dma[ devNum ] = (VMIC5565DMA*)dmaAddr; // pHardware->rfm_dma[devNum] = p5565Dma[devNum]; - printk("5565DMA at 0x%lx\n",(unsigned long int)p5565Dma[devNum]); - printk("5565 INTCR = 0x%ux\n",p5565Dma[devNum]->INTCSR); - p5565Dma[devNum]->INTCSR = 0; // Disable interrupts from this card - printk("5565 INTCR = 0x%ux\n",p5565Dma[devNum]->INTCSR); - printk("5565 MODE = 0x%ux\n",p5565Dma[devNum]->DMA0_MODE); - printk("5565 DESC = 0x%ux\n",p5565Dma[devNum]->DMA0_DESC); + printk( "5565DMA at 0x%lx\n", (unsigned long int)p5565Dma[ devNum ] ); + printk( "5565 INTCR = 0x%ux\n", p5565Dma[ devNum ]->INTCSR ); + p5565Dma[ devNum ]->INTCSR = 0; // Disable interrupts from this card + printk( "5565 INTCR = 0x%ux\n", p5565Dma[ devNum ]->INTCSR ); + printk( "5565 MODE = 0x%ux\n", p5565Dma[ devNum ]->DMA0_MODE ); + printk( "5565 DESC = 0x%ux\n", p5565Dma[ devNum ]->DMA0_DESC ); // Preload some DMA settings - // Only important items here are BTC and DESC fields, which are used + // Only important items here are BTC and DESC fields, which are used // later by DMA routine. - p5565Dma[devNum]->DMA0_PCI_ADD = pHardware->pci_rfm_dma[0]; - p5565Dma[devNum]->DMA0_LOC_ADD = IPC_BASE_OFFSET; // Start at RFM + 0x100 offset - p5565Dma[devNum]->DMA0_BTC = IPC_RFM_XFER_SIZE; // Set byte xfer to 256 bytes - p5565Dma[devNum]->DMA0_DESC = VMIC_DMA_READ; // Set RFM to local memory - - - pHardware->rfmType[devNum] = 0x5565; - pHardware->rfmCount ++; - return(0); + p5565Dma[ devNum ]->DMA0_PCI_ADD = pHardware->pci_rfm_dma[ 0 ]; + p5565Dma[ devNum ]->DMA0_LOC_ADD = + IPC_BASE_OFFSET; // Start at RFM + 0x100 offset + p5565Dma[ devNum ]->DMA0_BTC = + IPC_RFM_XFER_SIZE; // Set byte xfer to 256 bytes + p5565Dma[ devNum ]->DMA0_DESC = VMIC_DMA_READ; // Set RFM to local memory + + pHardware->rfmType[ devNum ] = 0x5565; + pHardware->rfmCount++; + return ( 0 ); } // ***************************************************************************** /// RFM DMA Read in support of commData // ***************************************************************************** -void vmic5565DMA(CDS_HARDWARE *pHardware, int card, int offset) +void +vmic5565DMA( CDS_HARDWARE* pHardware, int card, int offset ) { -int myAddress; -int rfmAddress; + int myAddress; + int rfmAddress; - rfmAddress = IPC_BASE_OFFSET + (offset * IPC_RFM_BLOCK_SIZE); - myAddress = (pHardware->pci_rfm_dma[card] + (offset * IPC_RFM_BLOCK_SIZE)); + rfmAddress = IPC_BASE_OFFSET + ( offset * IPC_RFM_BLOCK_SIZE ); + myAddress = + ( pHardware->pci_rfm_dma[ card ] + ( offset * IPC_RFM_BLOCK_SIZE ) ); // p5565Dma[card]->DMA_CSR = VMIC_DMA_CLR; // Clear DMA DONE - p5565Dma[card]->DMA0_PCI_ADD = myAddress; // Computer address space - p5565Dma[card]->DMA0_LOC_ADD = rfmAddress; // RFM card offset from base - // These were set during initialization, so don't need them again (save time) - // p5565Dma[card]->DMA0_BTC = 0x400; // Set byte xfer to 1024 bytes - // p5565Dma[card]->DMA0_DESC = 0x8; // Set RFM to local memory - p5565Dma[card]->DMA_CSR = VMIC_DMA_START; // Start DMA + p5565Dma[ card ]->DMA0_PCI_ADD = myAddress; // Computer address space + p5565Dma[ card ]->DMA0_LOC_ADD = rfmAddress; // RFM card offset from base + // These were set during initialization, so don't need them again (save + // time) p5565Dma[card]->DMA0_BTC = 0x400; // Set byte xfer to 1024 + // bytes p5565Dma[card]->DMA0_DESC = 0x8; // Set RFM to local memory + p5565Dma[ card ]->DMA_CSR = VMIC_DMA_START; // Start DMA } // ***************************************************************************** /// Routine to clear RFM DMA done bit // ***************************************************************************** -void vmic5565DMAclr(CDS_HARDWARE *pHardware, int card) +void +vmic5565DMAclr( CDS_HARDWARE* pHardware, int card ) { - p5565Dma[card]->DMA_CSR = VMIC_DMA_CLR; // Clear DMA DONE + p5565Dma[ card ]->DMA_CSR = VMIC_DMA_CLR; // Clear DMA DONE } // ***************************************************************************** /// Routine to check RFM done bit and clear for next DMA // ***************************************************************************** -int vmic5565DMAdone(int card) +int +vmic5565DMAdone( int card ) { -int status; -int ii; + int status; + int ii; ii = 0; - do{ - status = p5565Dma[card]->DMA_CSR; // Check DMA DONE bit (4) - if((status & 0x10) == 0) udelay(1); - ii ++; - }while(((status & 0x10) == 0) && (ii < 10)); - p5565Dma[card]->DMA_CSR = 0x8; // Clear DMA DONE - return (ii); + do + { + status = p5565Dma[ card ]->DMA_CSR; // Check DMA DONE bit (4) + if ( ( status & 0x10 ) == 0 ) + udelay( 1 ); + ii++; + } while ( ( ( status & 0x10 ) == 0 ) && ( ii < 10 ) ); + p5565Dma[ card ]->DMA_CSR = 0x8; // Clear DMA DONE + return ( ii ); } // ***************************************************************************** @@ -133,19 +151,18 @@ int ii; /// @param[in] card ID of card to read /// @return Status of Own Data Bit // ***************************************************************************** -int vmic5565CheckOwnDataRcv(int card) +int +vmic5565CheckOwnDataRcv( int card ) { - return (p5565Csr[card]->LCSR1 & 1); + return ( p5565Csr[ card ]->LCSR1 & 1 ); } // ***************************************************************************** /// \brief Routine to reset RFM Own Data received bit. /// @param[in] card ID of card to read // ***************************************************************************** -void vmic5565ResetOwnDataLight(int card) +void +vmic5565ResetOwnDataLight( int card ) { - p5565Csr[card]->LCSR1 &= ~1; // Turn off own data light - + p5565Csr[ card ]->LCSR1 &= ~1; // Turn off own data light } - - -- GitLab