Docker-in-Docker (DinD) capabilities of public runners deactivated. More info

Commit b43d57d4 authored by dino's avatar dino
Browse files

Improved readout from GGP and ATCA boards in CrystalProducerATCA.

Non-blocking behavior achieved using a thread and a ring of buffers for each device.  

git-svn-id: svn://gal-serv.lnl.infn.it/agata/trunk/narval_emulator@1304 170316e4-aea8-4b27-aad4-0380ec0519c9
parent 47fe1a17
......@@ -12,9 +12,9 @@ set( CMAKE_BUILD_TYPE "Release" )
set( CMAKE_MODULE_PATH "." )
################################################################
# Set the off-line version of the actors (no NRV_ONLINE for femul)
ADD_DEFINITIONS( -DNRV_TYPE=NRV_OFFLINE )
#ADD_DEFINITIONS( -DNRV_TYPE=NRV_ONLINE )
# Set the on-line/off-line version of the actors
#ADD_DEFINITIONS( -DNRV_TYPE=NRV_OFFLINE )
ADD_DEFINITIONS( -DNRV_TYPE=NRV_ONLINE )
################################################################
# Select the threads library as THR_NONE, THR_BOOST or THR_STD
......@@ -132,6 +132,7 @@ ${ACTORS}/producers/Crystal/CrystalProducer.cpp
${ACTORS}/producers/Crystal/CrystalProducerATCA.cpp
${ACTORS}/producers/Crystal/includeATCA/mezzanine.cpp
${ACTORS}/producers/Crystal/includeATCA/fileATCA.cpp
${ACTORS}/producers/Crystal/includeATCA/hwReader.cpp
${ACTORS}/producers/AncillaryTCP/AncillaryProducerTCP.cpp
${ACTORS}/filters/Preprocessing/PreprocessingFilter.cpp
${ACTORS}/filters/Preprocessing/PreprocessingFilterPSA.cpp
......
......@@ -378,7 +378,7 @@ void showWhat()
}
}
void getparams(int argc, char *argv[])
void getparams(int argc, char **argv)
{
char *cmd = NULL;
int ok;
......
......@@ -60,6 +60,17 @@ inline T AverageVariance(const T * data, int nchan, T meanval = 0)
return vv/nchan;
}
// bit values used in various places
enum retValue {
kEvNormal = 0,
kEvNewBuffer = 1,
kEvNewFile = 2,
kEvFinish = 4,
kEvSkip = 8,
kEvAgain = 16,
kEvReturn = 32
};
//template<class T>
//class median
//{
......
......@@ -29,7 +29,7 @@ void distances(double r_3d[intmax*intmax], /*Distance physique dans le detect
double ri, rj, Ax, Ay, Az, Bx, By, Bz;
double radiusSQ;
double costest, costest1, vectproduct, r_center, r_vacuum, r_vacuumi, ri_orig;
double costest, costest1, vectproduct, r_center, r_vacuum, ri_orig; /* , r_vacuumi; */
double xsource, ysource, zsource;
double cosgo;
......
......@@ -57,7 +57,7 @@ const int nCC = 2;
CrystalProducerATCA::CrystalProducerATCA():
DAQ_NFILE(0), DAQ_NMEZZ(0), ANA_NSEGS(0), DAQ_GGP(false),
FA(NULL), MZ(NULL), CC(NULL), PR(NULL), mezzFound(NULL), mezzToGet(0),
FA(NULL), MZ(NULL), CC(NULL), mezzFound(NULL), mezzToGet(0),
nfiles(0), fnstep(1), bReaFromFile(false),
maxDiff(0), expDiff(0), bStartCalled(false),
bSync(true), bStatistics(false),
......@@ -142,7 +142,7 @@ Int_t CrystalProducerATCA::AlgoInitialise()
}
writeDataMask = fWriteDataMask;
writeDataSplit = (fWriteDataSplit<INT_MAX)?fWriteDataSplit:0;
writeDataSplit = (fWriteDataSplit<INT_MAX) ? fWriteDataSplit : 0;
if(!InitATCA(writeDataMask&1)) {
return 120;
......@@ -152,14 +152,6 @@ Int_t CrystalProducerATCA::AlgoInitialise()
if(fWriteDataMaxAmpl<=fWriteDataMinAmpl)
fWriteDataMaxAmpl = kMaxInt_t; // Int_t(UInt_t(~0)>>1) in ADFConfig.h
if(PR) delete PR;
PR = new pollReader;
for(int nn = 0; nn < DAQ_NFILE; nn++) {
//FA[nn].bTraces = traces; // to be able to disable writing traces (e.g. for test purposes)
PR->AddFile(FA+nn);
FA[nn].thePR = PR;
}
mezzFound = new bool [DAQ_NMEZZ];
for(int nn = 0; nn < DAQ_NMEZZ; ) mezzFound[nn++] = false;
mezzToGet = 0;
......@@ -417,10 +409,10 @@ UInt_t CrystalProducerATCA::ProcessBlock (ADF::FrameBlock &outBlock)
LOCK_COUT;
int rrate = cServer.Prompt(crystal_id, nnev, used_size_of_output_buffer, false);
if (rrate >= 0) {
cout << " evn = " << setw(8) << evnumber
<< " tst = " << fixed << setprecision(1) << setw(4) << timestamp / double(tst1second)
<< " " << setw(4) << irate << "/tss"
<< endl;
//cout << " evn = " << setw(8) << evnumber;
cout << " tst = " << fixed << setprecision(1) << setw(4) << timestamp / double(tst1second)
<< " " << setw(4) << irate << "/tss"
<< endl;
}
#ifdef CRP_MULTIHIST
......@@ -839,7 +831,6 @@ bool CrystalProducerATCA::Decodesetup(std::string setupFile, std::string odirPre
}
FA[filenum].fileID = filenum;
FA[filenum].crystID = fCrystalID;
FA[filenum].domainID = fDomainID;
FA[filenum].numMezz = ncards;
FA[filenum].setFileName(fname);
FA[filenum].bStatistics = bStatistics;
......@@ -847,7 +838,6 @@ bool CrystalProducerATCA::Decodesetup(std::string setupFile, std::string odirPre
else {
FA[0].fileID = 0;
FA[0].crystID = fCrystalID;
FA[0].domainID = fDomainID;
FA[0].numMezz += ncards;
FA[0].setFileName(fIdirPrefix+fInputDataFile);
FA[0].bStatistics = bStatistics;
......@@ -876,7 +866,6 @@ bool CrystalProducerATCA::Decodesetup(std::string setupFile, std::string odirPre
MZ[mezznum].zMask = zmask;
MZ[mezznum].fATCA = FA + filenum;
FA[filenum].Enable(slotnum);
FA[filenum].oneMezz = mezznum;
cout << line << endl;
}
......@@ -986,11 +975,9 @@ bool CrystalProducerATCA::InitATCA(bool writeOriginal)
// cps = 100 ==> reading blocks of 100 events ==> 8000 evs/s
// On-line performance should be checked (in the past we had ~20 kHz)
for(int nn = 0; nn < DAQ_NFILE; nn++) {
//ok = FA[nn].Reset(fTraceLengthRaw, 6, writeOriginal, odir, cps);
ok = FA[nn].Reset(fTraceLengthRaw, MZ[FA[nn].oneMezz].nChan, writeOriginal, odir, DAQ_GGP, cps);
ok = FA[nn].Reset(fTraceLengthRaw, MZ[0].nChan, writeOriginal, odir, DAQ_GGP); // all mezzanine should have the same nChan
if(!ok)
return false;
FA[nn].SetDomain(fDomainID);
}
if(!tStamp) tStamp = new unsigned long long [DAQ_NMEZZ];
......
......@@ -4,7 +4,6 @@
#include "CrystalProducer.h"
#include "Misc.h"
#include "pollReader.h"
#include "fileATCA.h"
#include "mezzanine.h"
#include "detector_t.h"
......@@ -56,7 +55,6 @@ private:
bool bReaFromFile; // If true read raw data from file else, from what says CrystalProducerATCA.conf
pollReader *PR; // manager of PCIx reader using select/poll
fileATCA *FA; // the DAQ_NFILE ATCA datafiles
mezzanine *MZ; // the DAQ_NMEZZ processing mezzanines
core_t *CC; // the detector(36+1)
......
This diff is collapsed.
#ifndef FILEATCA_H_INCLUDED
#define FILEATCA_H_INCLUDED
#include <iostream>
//#include "commonDefs.h"
#include "commonDefs.h"
#include "mezzanine.h"
#include "sAppend.h"
const unsigned int MAXMEZZATCA = 4; // max number of mezzanines per carrier
const unsigned int SIZEDMABUFF = 4*1024*1024; // bytes (defined in the PCI-EXPRESS driver)
const unsigned int numRawBuffs = 4; // multiplier for the length of the read buffer
const unsigned int cacheLength = 64; // several times the number of slots of 2 ATCA carriers
// bit values used in various places
enum kRetValue {
kEvNormal = 0,
kEvNewBuffer = 1,
kEvNewFile = 2,
kEvFinish = 4,
kEvSkip = 8,
kEvAgain = 16,
kEvReturn = 32
};
#if NRV_TYPE == NRV_ONLINE
# ifndef PCI_EXPRESS
# define PCI_EXPRESS
# endif
const unsigned int kMaxMezz = 16; // ID is coded with 4 bits
const unsigned int kMaxMezzATCA = 4; // max number of mezzanines per ATCA carrier
const unsigned int kSizeDMABuff = 2*1024*1024; // bytes (4MiB defined in the PCI-EXPRESS driver); ggp works better with 2MiB
const unsigned int kCacheSize = 2*kMaxMezz; // twice the number of slots of 2 ATCA carriers
// define OS independent IO symbols
#if OS_TYPE == OS_WINDOWS
#define osOPEN _open
#define osCLOSE _close
#define osREAD _read
#define fdOPEN _fdopen
#define O_NONBLOCK 0
#else
#define osOPEN open
#define osCLOSE close
#define osREAD read
#define fdOPEN fdopen
#define O_BINARY 0
#endif
class pollReader;
class mezzanine;
class hwReader;
class fileATCA
{
friend class hwReader;
public:
fileATCA() : fileID(-1), crystID(0), domainID(0), ifd(-1), thePR(NULL), readMezz(NULL),
fromDAQ(false), fromGGP(false), bValid(false), giveUp(false), bTraces(true),
numMezz(0), oneMezz(0), numChan(0), lenTrace(0), lenMezzData(0), lenMezzTotal(0),
nfiles(0), fnstep(1),
fileATCA() : fileID(-1), crystID(-1), ifd(-1), theHWR(NULL), oneMezz(NULL),
fromDAQ(false), fromGGP(false), bValid(false), giveUp(false),
numMezz(0), numChan(0), lenTrace(0), lenMezzData(0), lenMezzTotal(0),
nfiles(0), fnstep(1), bTraces(true),
bIncrLast(false), bWrite(false), iFILE(NULL), rFILE(NULL), oldmezz(0xFFFFFFFF),
rawDataBuffer(NULL), uMezz(0), nMezz(0),
rawDataBuffer(NULL), sizDataBuffer(0), lenDataBuffer(0), uBuff(NULL), uSize(0),
bStatistics(false), firstevent(true), sstat1(NULL), sstat2(NULL), sstat3(NULL),
mezzSlotId_old(0), mezzEvNumb_old(0), mezzTstamp_old(0)
{
totData = fixData = 0;
memset(numData, 0, sizeof(numData));
memset(indData, 0, sizeof(indData));
memset(mezzCache, 0, sizeof(mezzCache));
memset(enabled, false, sizeof(enabled));
memset(dropped, 0, sizeof(dropped));
numCached = numPointed = 0;
memset(numData, 0, sizeof(numData ));
memset(indData, 0, sizeof(indData ));
memset(theCache, 0, sizeof(theCache));
memset(enabled, false, sizeof(enabled ));
memset(dropped, 0, sizeof(dropped ));
numFlushed = 0;
maxCached = 0;
rnb_state = 0;
for(int nn = 0; nn < 16; nn++)
for (int nn = 0; nn < kMaxMezz; nn++)
tFILE[nn] = NULL;
numCapture = 0;
indCapture = 0;
}
virtual ~fileATCA() {
if(sstat1) delete sstat1;
if(sstat2) delete sstat2;
if(sstat3) delete sstat3;
}
bool Reset(int nsamp, int nchan, bool save, std::string odirPrefix, bool is_ggp, int cps=100);
bool Reset(int nsamp, int nchan, bool save, std::string odirPrefix, bool is_ggp);
bool Start(int nf, int stp = 1);
bool Valid() {return true;} // STILL TO BE DONE
int GetMezzanine(unsigned int slot, unsigned short * buff);
int getIndexF() { return fcount; }
void setFileName(std::string fname) { inputdatafile = fname; }
std::string getFileName() { return ifname; }
void Enable(int nslot) { if(nslot >=0 && nslot < 16) enabled[nslot] = true; }
void setFileName(std::string fname) { firstDatafile = fname; }
std::string getFileName() { return datFname; }
void Enable(int nslot) { if (nslot >= 0 && nslot < kMaxMezz) enabled[nslot] = true; }
int Written(int nn) {return nn==0? wWritten[0] : wWritten[1];}
int Dropped(int nn) {return (nn>=0 && nn<16) ? dropped[nn] : 0;}
bool RawBuffFull() {return (nMezz!=uMezz)&&(uMezz>=numRawBuffs)?true:false;}
void SetDomain(unsigned short id) {domainID = id;}
int Dropped(int nn) { return (nn >= 0 && nn<kMaxMezz) ? dropped[nn] : 0; }
int fileID; // which file
unsigned short crystID; // of which crystal
unsigned short domainID; // domain number, coded into the header of the mezzanines
int fileID; // which file
int crystID; // of which crystal
int ifd; // descriptor of input data
pollReader *thePR;
mezzanine *readMezz;
unsigned int numMezz; // number of mezzanines written in this file
unsigned int numChan; // number of channels in this mezzanine (normally 6)
unsigned int lenTrace; //
unsigned int lenMezzData; // expected number of samples
unsigned int lenMezzTotal; // total length of one mezzanine
unsigned int numMezz; // number of mezzanines written in this file
unsigned int oneMezz; // index of one of the all-equal mezzanines associated to this file
unsigned int numChan; // number of channels in the mezzanines of this file (normally 6)
unsigned int lenTrace; //
unsigned int lenMezzData; // expected number of samples
unsigned int lenMezzTotal; // total length of one mezzanine
std::string inputdatafile; // the first file name
hwReader *theHWR; // takes care of reading from HW, possibly in a non blocking way
mezzanine *oneMezz; // fake mezzanine used to read from file
private:
struct mezzCache_t
{
mezzCache_t() : slot(0xFFFFFFFF), addr(NULL), buff(NULL) {}
unsigned int slot; // identifier of cached mezzanine slot==0xFFFFFFFF if empty
unsigned short *addr; // if !NULL the data is still in rawBuff
unsigned short *buff; // if (slot!=0xFFFFFFFF && addr==NULL) data has been moved here
// Decode mezzanine header. Format described in mezzanine.h and mezzanine.cpp
// Not checking for validity of addr ==> use when appropriate.
unsigned short getSlotId() { return ( addr[0] & 0x0F ); }
unsigned int getEvNumb() { return ( (unsigned int) addr[1] |
(unsigned int) addr[2] << 16 ); }
unsigned long long getTstamp() { return ( (unsigned long long)addr[3] |
(unsigned long long)addr[4] << 16 |
(unsigned long long)addr[5] << 32 ); }
unsigned short getTraceLen() { return ( addr[6] ); }
unsigned short getMezzLen() { return ( addr[7] ); }
unsigned short getDomainId() { return ( addr[8] & 0xFF ); }
};
bool fromDAQ; // reading from PCI express or ggp
bool fromGGP; // reading from ggp
bool bValid; // bValid is set by DataFileOpen and reset by DataFileClose or EOF while reading (same as ifd >= 0 ??)
bool giveUp; // giveUp should be set if the file cannot be opened or by AbortRead (e.g. process_stop in Narval)
std::string firstDatafile; // the first file name
private:
unsigned short *rawDataBuffer;
unsigned int lenDataBuffer; // real length of rawDataBuffer is lenDataBuffer*numRawBuffs (ushort)
unsigned int uMezz; // how many mezzanines in the consumer slot
unsigned int nMezz; // index (units of lenMezzTotal) into rawDataBuffer of the next valid mezzanine
int GetMezzFromCache(unsigned int slot, unsigned short * buff);
int GetNextMezzanine(unsigned short **pmezz);
bool CheckSequence(mezzCache_t &cmezz); // readout statistics
bool WriteRawData (unsigned short *buff, int nn);
bool TraceCapture (unsigned short *buff);
void CloseRawData ();
unsigned int sizDataBuffer; // allocated length of rawDataBuffer (ushort)
unsigned int lenDataBuffer; // usable length of rawDataBuffer (ushort)
unsigned short *uBuff; // address of data into rawDataBuffer
int uSize; // available data in rawDataBuffer
int GetMezzFromCache(unsigned int slot, unsigned short * buff);
int GetNextMezzanine(unsigned short* &pmezz); // obtain a pointer to the next mezzanine
int CheckObtained(unsigned short *wBuff, int wSize, int wFrom);
bool CheckSequence(unsigned short *mezz); // readout statistics
bool CheckNextMezz() { // what if compressed ??? (in which case the size is uBuff[16])
return (uSize >= 16) // at least the header
&& ((uBuff[0]&0xFF00) == 0xDA00) // and the tag should be correct
&& (uSize >= uBuff[7]); // and enough length
}
bool IsNormalData() { return (uBuff[0] & 0xFFF0) == magicTagData; }
bool IsLongTrace () { return (uBuff[0] & 0xFFF0) == magicTagWave; }
bool IsSpectrum () { return (uBuff[0] & 0xFFF0) == magicTagSpec; }
void uBuffUpdate () { int mlen = uBuff[7]; uBuff += mlen; uSize -= mlen; }
bool WriteRawData (unsigned short *buff, int nn);
bool TraceCapture (unsigned short *buff);
void CloseRawData ();
unsigned int getEvNumb(unsigned short *buff) {
return (unsigned int)buff[1] |
(unsigned int)buff[2] << 16;
}
unsigned long long getTstamp(unsigned short *buff) {
return (unsigned long long)buff[3] |
(unsigned long long)buff[4] << 16 |
(unsigned long long)buff[5] << 32;
(unsigned long long)buff[4] << 16 |
(unsigned long long)buff[5] << 32;
}
int nfiles; // how many files to open in sequence (0 = as many as possible)
int fnstep; // step to increment file name
int fcount; // local file counter
std::string ifname; // the actual data file name;
std::string rfname; // the file for writing original data;
std::string tfname; // the file for writing captured long traces;
bool enabled[16]; // to cache only valid mezzanines
int nfiles; // how many files to open in sequence (0 = as many as possible)
int fnstep; // step to increment file name
int fcount; // local file counter
std::string datFname; // the actual data file name;
std::string rawFname; // the file for writing original data;
std::string ltcFname; // the file for writing captured long traces;
bool enabled[kMaxMezz]; // will cache only valid mezzanines
public:
bool bWrite; // flag to write the original mezzanines to ofname
FILE *iFILE; // input stream corresponding to ifd
FILE *rFILE; // output of raw data
FILE *tFILE[16]; // trace capture files for all possible mezzanines
unsigned int oldmezz; // the last mezzanine
bool bWrite; // flag to write the original mezzanines to ofname
FILE *iFILE; // input stream corresponding to ifd
FILE *rFILE; // output of raw data
FILE *tFILE[kMaxMezz]; // trace capture files for all possible mezzanines
unsigned int oldmezz; // the last mezzanine
std::string odir;
private:
unsigned int numData[16]; // there are at most 16 mezzanines (address is 4 bits)
unsigned int indData[16][cacheLength]; // index of the stored mezzanines (all catched could be same)
unsigned int totData; // total number of cached mezzanines
unsigned int fixData; // number of entries with pointers to data, instead of data
unsigned int dropped[16]; // count number of dropped mezzanines
unsigned int numFlushed; // to manage printout frequency
mezzCache_t mezzCache[cacheLength]; // local cache of mezzanines
unsigned int maxCached; // useful for debug&statistics
typedef struct {
unsigned int slot; // which slot
unsigned short *addr; // if !NULL the data is still in an external buffer
unsigned short *buff; // moved here (by FixCache) only when the external buffer has to be freed
} mbuff;
unsigned int numData[kMaxMezz]; // there are at most kMaxMezz mezzanines
unsigned int indData[kMaxMezz][kCacheSize]; // index of the stored mezzanines
unsigned int numCached; // number of cached mezzanines
unsigned int numPointed; // number of entries with pointers to data, instead of data
unsigned int dropped[kMaxMezz]; // count number of dropped mezzanines
unsigned int numFlushed; // total number of cache-flush actions
mbuff theCache[kCacheSize]; // local cache of mezzanines
public:
bool bIncrLast; // in multifile mode increment the string after last .
......@@ -170,35 +162,12 @@ public:
sAppend<int> *sstat1, *sstat2, *sstat3;
unsigned int wWritten[2];
// this is ported from nbReader and should be reorganized
bool fromDAQ; // reading from PCI express or ggp
bool fromGGP; // reading from ggp
int ifd; // descriptor of input data
std::string firstfile; // the first file name
// bValid is set by DataFileOpen and reset by DataFileClose or EOF while reading (same as ifd >= 0 ??)
bool bValid; // if true, the file is opened correctly
bool giveUp; // if true, the file could not be opened
bool DataFileOpen ();
void DataFileClose();
int NextDataFile (); // open next data file
// as this is now called by pollReader::ReadAvailableData
// the return values have to be kept at the class level
void FixCache();
int ReadNextBuffer(int which);
unsigned int CheckRawBuffer();
int fileREAD(int ifd, unsigned short *startFrom, int numbytes);
int rnb_state;
// used to simulate generation of trace-capture when reading from file
// usually, numCapture and indCapture are set manually from the debugger
int captREAD(int imz, unsigned short *startFrom, int numbytes);
int numCapture;
int indCapture;
bool DataFileOpen ();
void DataFileClose();
int NextDataFile (); // open next data file
void FixCache(); // copy pointed mezzanines to their real storage
int FromFILE(int wfrom = 0); // read a buffer of data from file
int fileREAD(int ifd, unsigned short *startFrom, int numwords);
};
#endif // FILEATCA_H_INCLUDED
#include "commonDefs.h"
#if NRV_TYPE == NRV_ONLINE
#include <iostream>
#include <iomanip>
#include <memory.h>
#include <errno.h>
#include <fcntl.h>
#include "fileATCA.h"
#include "hwReader.h"
#if OS_TYPE == OS_WINDOWS
#include <io.h>
#endif
using namespace std;
bool hwReader::OpenDeviceATCA() {
char device[64] = { 0 };
int devicenum = pFA->fileID;
sprintf(device, "/dev/xdev%1d", devicenum);
LOCK_COUT;
cout << "Reading from PCI express for ATCA " << device << endl;
pFA->ifd = osOPEN(device, O_RDONLY | O_BINARY); // open the device in readonly
if (pFA->ifd == -1) {
LOCK_COUT;
cout << "Error opening device " << device << endl;
return false;
}
//if (ioctl(ifd, XDEV_IOCTL_DAQ_RESET, NULL) == -1) {
if (ioctl(pFA->ifd, _IO(0xae, 0), NULL) == -1) {
LOCK_COUT;
cout << "IOCTL erorr on XDEV_IOCTL_DAQ_RESET " << device << endl;
return false;
}
unsigned int dmaSize = sizeof(unsigned short)*pFA->lenDataBuffer;
cout << " Setting DMA_SIZE to " << dmaSize << endl;
//if (ioctl(ifd, XDEV_IOCTL_DMA_SIZE, &dmaSize) == -1) {
if (ioctl(pFA->ifd, _IO(0xae, 5), &dmaSize) == -1) {
LOCK_COUT;
cout << "IOCTL erorr on XDEV_IOCTL_DMA_SIZE " << device << endl;
return false;
}
InitBuffers(pFA->lenDataBuffer);
if (!pRingMan)
pRingMan = new rbManager(RINGBUFSIZE, pFA->fileID); // create the ring-buffer manager
pRingMan->Reset();
bRunning = false;
#ifdef HWREADER_LAMBDA
// launch reading-thread using a lambda
pReadThr = new std::thread([&]() { ReadFromPCIE(); });
#else
// launch reading-thread using a functor
pReadThr = new std::thread(ReadPCIE(this));
#endif
return true;
}
bool hwReader::OpenDeviceGGP()
{
char device[64] = { 0 };
int devicenum = pFA->fileID;
sprintf(device, "/dev/ggp-daq%1d", devicenum);
LOCK_COUT;
cout << "Reading from PCI express for GGP " << device << endl;
pFA->ifd = osOPEN(device, O_RDONLY | O_BINARY); // open the device in readonly
if (pFA->ifd == -1) {
LOCK_COUT;
cout << "Error opening device " << device << endl;
return false;
}
if (ioctl(pFA->ifd, _IO(0xaf, 5), NULL) == -1) {
LOCK_COUT;
cout << "IOCTL error on ggp module" << device << endl;
return false;
}
// TO BE DONE ??
//unsigned int dmaSize = sizeof(unsigned short)*pFA->lenDataBuffer;
//cout << " Setting DMA_SIZE to " << dmaSize << endl;
////if (ioctl(ifd, XDEV_IOCTL_DMA_SIZE, &dmaSize) == -1) {
//if (ioctl(pFA->ifd, _IO(0xae, 5), &dmaSize) == -1) {
// LOCK_COUT;
// cout << "IOCTL erorr on XDEV_IOCTL_DMA_SIZE " << device << endl;
// return false;
//}
InitBuffers(pFA->lenDataBuffer);
if (!pRingMan)
pRingMan = new rbManager(RINGBUFSIZE, pFA->fileID); // create the ring-buffer manager
pRingMan->Reset();
bRunning = false;
#ifdef HWREADER_LAMBDA
// launch reading-thread using a lambda
pReadThr = new std::thread( [&]() { ReadFromPCIE(); } );
#else
// launch reading-thread using a functor
pReadThr = new std::thread( ReadPCIE(this) );
#endif
return true;
}
int hwReader::FromPCIE(int wfrom)
{
if (bFinished)
return kEvFinish;