diff --git a/ClassDigitizer2Gen.cpp b/ClassDigitizer2Gen.cpp index aac21a9..11fe370 100644 --- a/ClassDigitizer2Gen.cpp +++ b/ClassDigitizer2Gen.cpp @@ -1,5 +1,8 @@ #include "ClassDigitizer2Gen.h" + +unsigned short Digitizer2Gen::TraceStep = 8; //? should be variable? + Digitizer2Gen::Digitizer2Gen(){ printf("======== %s \n",__func__); Initialization(); @@ -453,6 +456,8 @@ int Digitizer2Gen::ReadData(){ return CAEN_FELib_UNKNOWN; } + evt->traceZero = false; + if( ret != CAEN_FELib_Success) { //ErrorMsg("ReadData()"); return ret; @@ -584,8 +589,8 @@ void Digitizer2Gen::ProgramPHA(bool testPulse){ //======== Self trigger for each channel - //WriteValue("/ch/0..63/par/EventTriggerSource", "ChSelfTrigger"); - //WriteValue("/ch/0..63/par/WaveTriggerSource" , "ChSelfTrigger"); + WriteValue("/ch/0..63/par/EventTriggerSource", "ChSelfTrigger"); + WriteValue("/ch/0..63/par/WaveTriggerSource" , "ChSelfTrigger"); //======== One (or more) slef-trigger can trigger whole board, ??? depend on Channel Trigger mask //WriteValue("/ch/0..63/par/EventTriggerSource", "Ch64Trigger"); @@ -601,14 +606,14 @@ void Digitizer2Gen::ProgramPHA(bool testPulse){ //WriteValue("/ch/38/par/ChannelsTriggerMask", "0x000F"); // when channel has no input, it still record. //----------- coincident trigger to ch-4n - WriteValue("/ch/0..63/par/EventTriggerSource", "ChSelfTrigger"); - WriteValue("/ch/0..63/par/WaveTriggerSource" , "ChSelfTrigger"); + //WriteValue("/ch/0..63/par/EventTriggerSource", "ChSelfTrigger"); + //WriteValue("/ch/0..63/par/WaveTriggerSource" , "ChSelfTrigger"); - for(int i = 0 ; i < 16; i++){ - WriteValue(("/ch/"+ std::to_string(4*i+1) + ".." + std::to_string(4*i+3) + "/par/ChannelsTriggerMask").c_str(), "0x1"); - WriteValue(("/ch/"+ std::to_string(4*i+1) + ".." + std::to_string(4*i+3) + "/par/CoincidenceMask").c_str(), "Ch64Trigger"); - WriteValue(("/ch/"+ std::to_string(4*i+1) + ".." + std::to_string(4*i+3) + "/par/CoincidenceLengthT").c_str(), "100"); // ns - } + //for(int i = 0 ; i < 16; i++){ + // WriteValue(("/ch/"+ std::to_string(4*i+1) + ".." + std::to_string(4*i+3) + "/par/ChannelsTriggerMask").c_str(), "0x1"); + // WriteValue(("/ch/"+ std::to_string(4*i+1) + ".." + std::to_string(4*i+3) + "/par/CoincidenceMask").c_str(), "Ch64Trigger"); + // WriteValue(("/ch/"+ std::to_string(4*i+1) + ".." + std::to_string(4*i+3) + "/par/CoincidenceLengthT").c_str(), "100"); // ns + //} //======== ACQ trigger? //WriteValue("/ch/0..63/par/EventTriggerSource", "GlobalTriggerSource"); //WriteValue("/ch/0..63/par/WaveTriggerSource" , "GlobalTriggerSource"); @@ -623,8 +628,8 @@ void Digitizer2Gen::ProgramPHA(bool testPulse){ WriteValue("/ch/0..63/par/DCOffset" , "10"); /// 10% WriteValue("/ch/0..63/par/WaveSaving" , "Always"); - WriteValue("/ch/0..63/par/ChRecordLengthS" , "512"); /// 4096 ns - WriteValue("/ch/0..63/par/ChPreTriggerS" , "125"); /// 1000 ns + WriteValue("/ch/0..63/par/ChRecordLengthT" , "4096"); /// 4096 ns, S and T are not Sync + WriteValue("/ch/0..63/par/ChPreTriggerT" , "1000"); /// 1000 ns WriteValue("/ch/0..63/par/WaveResolution" , "RES8"); /// 8 ns WriteValue("/ch/0..63/par/WaveAnalogProbe0" , "ADCInput"); diff --git a/ClassDigitizer2Gen.h b/ClassDigitizer2Gen.h index 6769d56..4f77409 100644 --- a/ClassDigitizer2Gen.h +++ b/ClassDigitizer2Gen.h @@ -70,6 +70,8 @@ class Digitizer2Gen { int OpenDigitizer(const char * url); bool IsConnected() const {return isConnected;} int CloseDigitizer(); + + int GetRet() const {return ret;}; std::string ReadValue(const char * parameter, bool verbose = false); std::string ReadChValue(std::string ch, std::string shortPara, bool verbose = false); @@ -110,6 +112,7 @@ class Digitizer2Gen { void SaveDataToFile(); unsigned int GetFileSize() {return outFileSize;} + static unsigned short TraceStep; }; diff --git a/Event.h b/Event.h index 089bea4..2dacffa 100644 --- a/Event.h +++ b/Event.h @@ -36,6 +36,8 @@ class Event { size_t dataSize; /// number of byte of the data, size/8 = word [64 bits] uint32_t n_events; + bool traceZero; + Event(){ Init(); } @@ -71,6 +73,8 @@ class Event { digital_probes_type[2] = 0xFF; digital_probes_type[3] = 0xFF; data = NULL; + + traceZero = true; // indicate trace are all zero } void ClearMemory(){ @@ -83,6 +87,8 @@ class Event { if( digital_probes[1] != NULL) delete digital_probes[1]; if( digital_probes[2] != NULL) delete digital_probes[2]; if( digital_probes[3] != NULL) delete digital_probes[3]; + + traceZero = true; } void SetDataType(unsigned int type){ @@ -100,8 +106,24 @@ class Event { digital_probes[2] = new uint8_t[MaxTraceLenght]; digital_probes[3] = new uint8_t[MaxTraceLenght]; - } + traceZero = true; + } + } + + void ClearTrace(){ + if( traceZero ) return; // no need to clear again + + for( int i = 0; i < MaxTraceLenght; i++){ + analog_probes[0][i] = 0; + analog_probes[1][i] = 0; + + digital_probes[0][i] = 0; + digital_probes[1][i] = 0; + digital_probes[2][i] = 0; + digital_probes[3][i] = 0; + } + traceZero = true; } void PrintEnergyTimeStamp(){ diff --git a/mainwindow.cpp b/mainwindow.cpp index fe01aaa..1d40834 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -182,12 +182,15 @@ MainWindow::~MainWindow(){ //delete bnNewExp; //delete logInfo; + StopScope(); + updateTraceThread->Stop(); updateTraceThread->quit(); updateTraceThread->wait(); delete updateTraceThread; - delete dataTrace; /// dataTrace must be deleted before plot + for( int i = 0; i < 6; i++) delete dataTrace[i]; + //delete [] dataTrace; /// dataTrace must be deleted before plot delete plot; //---- need manually delete @@ -353,7 +356,12 @@ void MainWindow::OpenScope(){ for( int i = 0 ; i < 2; i++){ ans = digi[iDigi]->ReadChValue(std::to_string(ch), haha[i]); index = cbAnaProbe[i]->findData(QString::fromStdString(ans)); - cbAnaProbe[i]->setCurrentIndex(index); + + if( index >= 0 ) { + cbAnaProbe[i]->setCurrentIndex(index); + }else{ + qDebug() << QString::fromStdString(ans); + } } haha.clear(); @@ -362,7 +370,11 @@ void MainWindow::OpenScope(){ for( int i = 0 ; i < 4; i++){ ans = digi[iDigi]->ReadChValue(std::to_string(ch), haha[i]); index = cbDigProbe[i]->findData(QString::fromStdString(ans)); - cbDigProbe[i]->setCurrentIndex(index); + if( index >= 0 ) { + cbDigProbe[i]->setCurrentIndex(index); + }else{ + qDebug() << QString::fromStdString(ans); + } } ans = digi[iDigi]->ReadChValue(std::to_string(ch), "ChRecordLengthT"); @@ -384,7 +396,6 @@ void MainWindow::OpenScope(){ bnStartACQ->setEnabled(false); bnStopACQ->setEnabled(false); - } scope->show(); @@ -427,10 +438,12 @@ void MainWindow::StopScope(){ if( digi[i]->IsDummy() ) continue; digiMTX.lock(); digi[i]->StopACQ(); + digi[i]->WriteChValue("0..63", "ChEnable", "true"); digiMTX.unlock(); readDataThread[i]->quit(); readDataThread[i]->wait(); + } bnStartACQ->setEnabled(true); bnStopACQ->setEnabled(true); @@ -453,29 +466,20 @@ void MainWindow::UpdateScope(){ if( digi ){ digiMTX.lock(); unsigned int traceLength = digi[iDigi]->evt->traceLenght; - unsigned int dataLength = dataTrace->count(); + unsigned int dataLength = dataTrace[0]->count(); - if( traceLength < dataLength){ - for( unsigned int i = 0; i < traceLength; i++) { - dataTrace->replace(i, i, digi[iDigi]->evt->analog_probes[0][i]); - } - dataTrace->removePoints(traceLength, dataLength-traceLength); - }else{ - - for( unsigned int i = 0 ; i < traceLength; i++){ - if( i < dataLength ) { - dataTrace->replace(i, i, digi[iDigi]->evt->analog_probes[0][i]); - }else{ - dataTrace->append(i, digi[iDigi]->evt->analog_probes[0][i]); - } - - } + //---- remove all points + for( int j = 0; j < 6; j++ ) dataTrace[j]->removePoints(0, dataLength); + for( unsigned int i = 0 ; i < traceLength; i++){ + for( int j = 0; j < 2; j++) dataTrace[j]->append(Digitizer2Gen::TraceStep * i, digi[iDigi]->evt->analog_probes[j][i]); + for( int j = 2; j < 6; j++) dataTrace[j]->append(Digitizer2Gen::TraceStep * i, (j-1)*1000 + 4000 * digi[iDigi]->evt->digital_probes[j-2][i]); } + digiMTX.unlock(); - plot->axes(Qt::Vertical).first()->setRange(-1, 16000); /// this must be after createDefaultAxes(); - plot->axes(Qt::Horizontal).first()->setRange(0, traceLength); + //plot->axes(Qt::Vertical).first()->setRange(-1, 16000); /// this must be after createDefaultAxes(); + //plot->axes(Qt::Horizontal).first()->setRange(-10, traceLength*1.1); } } @@ -499,15 +503,14 @@ void MainWindow::ProbeChange(QComboBox * cb[], const int size ){ model[j]->item(index)->setEnabled(false); } } - + digiMTX.lock(); if( size == 2) {// analog probes - dataTrace->setName(cb[0]->currentText()); + for( int j = 0; j < 2; j++ )dataTrace[j]->setName(cb[j]->currentText()); } if( size == 4){ // digitial probes - + for( int j = 2; j < 6; j++ )dataTrace[j]->setName(cb[j-2]->currentText()); } - digiMTX.unlock(); @@ -522,14 +525,24 @@ void MainWindow::SetUpPlot(){ //@--- this function run at start up allowChange = false; plot = new QChart(); - dataTrace = new QLineSeries(); - dataTrace->setName("Analog Trace 1"); - for(int i = 0; i < 100; i ++) dataTrace->append(i, QRandomGenerator::global()->bounded(10)); + for( int i = 0; i < 6; i++) { + dataTrace[i] = new QLineSeries(); + dataTrace[i]->setName("Trace " + QString::number(i)); + for(int j = 0; j < 100; j ++) dataTrace[i]->append(j, QRandomGenerator::global()->bounded(8000) + 8000); + plot->addSeries(dataTrace[i]); + } + + dataTrace[0]->setPen(QPen(Qt::red, 2)); + dataTrace[1]->setPen(QPen(Qt::blue, 2)); + dataTrace[2]->setPen(QPen(Qt::darkRed, 1)); + dataTrace[3]->setPen(QPen(Qt::darkYellow, 1)); + dataTrace[4]->setPen(QPen(Qt::darkGreen, 1)); + dataTrace[5]->setPen(QPen(Qt::darkBlue, 1)); - plot->addSeries(dataTrace); plot->createDefaultAxes(); /// this must be after addSeries(); - plot->axes(Qt::Vertical).first()->setRange(-1, 11); /// this must be after createDefaultAxes(); - plot->axes(Qt::Horizontal).first()->setRange(-1, 101); + plot->axes(Qt::Vertical).first()->setRange(-2000, 16000); /// this must be after createDefaultAxes(); + plot->axes(Qt::Horizontal).first()->setRange(0, 5000); + plot->axes(Qt::Horizontal).first()->setTitleText("Time [ns]"); updateTraceThread = new UpdateTraceThread(); connect(updateTraceThread, &UpdateTraceThread::updateTrace, this, &MainWindow::UpdateScope); @@ -556,11 +569,21 @@ void MainWindow::SetUpPlot(){ //@--- this function run at start up } }); + connect(cbScopeCh, &QComboBox::currentIndexChanged, this, [=](){ + if( !allowChange ) return; + int iDigi = cbScopeDigi->currentIndex(); + int ch = cbScopeCh->currentIndex(); + digiMTX.lock(); + digi[iDigi]->WriteChValue("0..63", "ChEnable", "false"); + digi[iDigi]->WriteChValue(std::to_string(ch), "ChEnable", "true"); + digiMTX.unlock(); + }); + //------------ Probe selection rowID ++; cbAnaProbe[0] = new QComboBox(scope); cbAnaProbe[0]->addItem("ADC Input", "ADCInput"); - cbAnaProbe[0]->addItem("Time Filter", "TimeFiler"); + cbAnaProbe[0]->addItem("Time Filter", "TimeFilter"); cbAnaProbe[0]->addItem("Trapazoid", "EnergyFilter"); cbAnaProbe[0]->addItem("Trap. Baseline", "EnergyFilterBaseline"); cbAnaProbe[0]->addItem("Trap. - Baseline", "EnergyFilterMinusBaseline"); @@ -582,7 +605,14 @@ void MainWindow::SetUpPlot(){ //@--- this function run at start up digi[iDigi]->WriteChValue(std::to_string(ch), "WaveAnalogProbe0", (cbAnaProbe[0]->currentData()).toString().toStdString()); digiMTX.unlock(); }); - + + connect(cbAnaProbe[1], &QComboBox::currentIndexChanged, this, [=](){ + int iDigi = cbScopeDigi->currentIndex(); + int ch = cbScopeCh->currentIndex(); + digiMTX.lock(); + digi[iDigi]->WriteChValue(std::to_string(ch), "WaveAnalogProbe1", (cbAnaProbe[1]->currentData()).toString().toStdString()); + digiMTX.unlock(); + }); cbDigProbe[0] = new QComboBox(scope); cbDigProbe[0]->addItem("Trigger", "Trigger"); @@ -619,6 +649,36 @@ void MainWindow::SetUpPlot(){ //@--- this function run at start up cbDigProbe[2]->setCurrentIndex(5); cbDigProbe[3]->setCurrentIndex(6); + connect(cbDigProbe[0], &QComboBox::currentIndexChanged, this, [=](){ + int iDigi = cbScopeDigi->currentIndex(); + int ch = cbScopeCh->currentIndex(); + digiMTX.lock(); + digi[iDigi]->WriteChValue(std::to_string(ch), "WaveDigitalProbe0", (cbDigProbe[0]->currentData()).toString().toStdString()); + digiMTX.unlock(); + }); + connect(cbDigProbe[1], &QComboBox::currentIndexChanged, this, [=](){ + int iDigi = cbScopeDigi->currentIndex(); + int ch = cbScopeCh->currentIndex(); + digiMTX.lock(); + digi[iDigi]->WriteChValue(std::to_string(ch), "WaveDigitalProbe1", (cbDigProbe[1]->currentData()).toString().toStdString()); + digiMTX.unlock(); + }); + connect(cbDigProbe[2], &QComboBox::currentIndexChanged, this, [=](){ + int iDigi = cbScopeDigi->currentIndex(); + int ch = cbScopeCh->currentIndex(); + digiMTX.lock(); + digi[iDigi]->WriteChValue(std::to_string(ch), "WaveDigitalProbe2", (cbDigProbe[2]->currentData()).toString().toStdString()); + digiMTX.unlock(); + }); + connect(cbDigProbe[3], &QComboBox::currentIndexChanged, this, [=](){ + int iDigi = cbScopeDigi->currentIndex(); + int ch = cbScopeCh->currentIndex(); + digiMTX.lock(); + digi[iDigi]->WriteChValue(std::to_string(ch), "WaveDigitalProbe3", (cbDigProbe[3]->currentData()).toString().toStdString()); + digiMTX.unlock(); + }); + + layout->addWidget(cbAnaProbe[0], rowID, 0); layout->addWidget(cbAnaProbe[1], rowID, 1); @@ -640,6 +700,7 @@ void MainWindow::SetUpPlot(){ //@--- this function run at start up connect(sbRL, &QSpinBox::valueChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); + sbRL->setValue(8*((sbRL->value() + 7)/8)); digiMTX.lock(); //StopScope(); digi[iDigi]->WriteChValue(std::to_string(cbScopeCh->currentIndex()), @@ -648,7 +709,7 @@ void MainWindow::SetUpPlot(){ //@--- this function run at start up //StartScope(); digiMTX.unlock(); - plot->axes(Qt::Horizontal).first()->setRange(0, sbRL->value()/8); + //plot->axes(Qt::Horizontal).first()->setRange(0, 600); }); diff --git a/mainwindow.h b/mainwindow.h index 5607998..66919fd 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -48,6 +48,7 @@ public: break; }else{ digi->ErrorMsg("ReadDataLoop()"); + digi->evt->ClearTrace(); } if( !isScopeRun ){ @@ -150,7 +151,7 @@ private: QMainWindow * scope; QPushButton * bnOpenScope; QChart * plot; - QLineSeries * dataTrace; + QLineSeries * dataTrace[6]; UpdateTraceThread * updateTraceThread; QComboBox * cbScopeDigi; QComboBox * cbScopeCh;