#include "scope.h" #include #include #include #include #include #define MaxDisplayTraceDataLength 2000 //data point, Scope::Scope(Digitizer2Gen **digi, unsigned int nDigi, ReadDataThread ** readDataThread, QMainWindow *parent) : QMainWindow(parent){ this->digi = digi; this->nDigi = nDigi; if( nDigi > MaxNumberOfDigitizer ) { this->nDigi = MaxNumberOfChannel; qDebug() << "Please increase the MaxNumberOfChannel"; } this->readDataThread = readDataThread; setWindowTitle("Scope"); setGeometry(0, 0, 1000, 800); setWindowFlags( this->windowFlags() & ~Qt::WindowCloseButtonHint ); allowChange = false; originalValueSet = false; plot = new Trace(); 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(40*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->setAnimationDuration(1); // msec plot->setAnimationOptions(QChart::NoAnimation); plot->createDefaultAxes(); /// this must be after addSeries(); /// this must be after createDefaultAxes(); QValueAxis * yaxis = qobject_cast (plot->axes(Qt::Vertical).first()); QValueAxis * xaxis = qobject_cast (plot->axes(Qt::Horizontal).first()); yaxis->setTickCount(6); yaxis->setTickInterval(16384); yaxis->setRange(-16384, 65536); yaxis->setLabelFormat("%.0f"); xaxis->setRange(0, 5000); xaxis->setTickCount(11); xaxis->setLabelFormat("%.0f"); xaxis->setTitleText("Time [ns]"); updateTraceThread = new TimingThread(); updateTraceThread->SetWaitTimeSec(0.2); connect(updateTraceThread, &TimingThread::TimeUp, this, &Scope::UpdateScope); //*================ add Widgets int rowID = -1; QWidget * layoutWidget = new QWidget(this); setCentralWidget(layoutWidget); QGridLayout * layout = new QGridLayout(layoutWidget); layoutWidget->setLayout(layout); //------------ Digitizer + channel selection rowID ++; cbScopeDigi = new RComboBox(this); cbScopeCh = new RComboBox(this); layout->addWidget(cbScopeDigi, rowID, 0); layout->addWidget(cbScopeCh, rowID, 1); allowChange = false; cbScopeDigi->clear(); ///this will also trigger RComboBox::currentIndexChanged cbScopeCh->clear(); for( unsigned int i = 0 ; i < nDigi; i++) { cbScopeDigi->addItem("Digi-" + QString::number(digi[i]->GetSerialNumber()), i); } cbScopeDigi->setCurrentIndex(1); allowChange = true; connect(cbScopeDigi, &RComboBox::currentIndexChanged, this, &Scope::ChangeDigitizer); connect(cbScopeCh, &RComboBox::currentIndexChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); digiMTX[iDigi].lock(); ReadScopeSettings(); digiMTX[iDigi].unlock(); }); bnScopeReset = new QPushButton("ReProgram Channels", this); layout->addWidget(bnScopeReset, rowID, 2); connect(bnScopeReset, &QPushButton::clicked, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); //digi[iDigi]->Reset(); digi[iDigi]->ProgramChannels(); //SendLogMsg("Reset Digi-" + QString::number(digi[iDigi]->GetSerialNumber()) + " and Set Default PHA."); ReadScopeSettings(); UpdateOtherPanels(); SendLogMsg("Re-program all Channels to default PHA settings"); }); bnScopeReadSettings = new QPushButton("Read Ch. Settings", this); layout->addWidget(bnScopeReadSettings, rowID, 3); connect(bnScopeReadSettings, &QPushButton::clicked, this, [=](){ if( !allowChange ) return; ReadScopeSettings(); UpdateOtherPanels(); }); //TODO----- add copy settings and paste settings chkSetAllChannel = new QCheckBox("apply to all channels", this); layout->addWidget(chkSetAllChannel, rowID, 4); //------------ Probe selection rowID ++; //TODO --- add None for probel selection cbAnaProbe[0] = new RComboBox(this); cbAnaProbe[1] = new RComboBox(this); cbDigProbe[0] = new RComboBox(this); cbDigProbe[1] = new RComboBox(this); cbDigProbe[2] = new RComboBox(this); cbDigProbe[3] = new RComboBox(this); connect(cbAnaProbe[0], &RComboBox::currentIndexChanged, this, [=](){ this->ProbeChange(cbAnaProbe, 2);}); connect(cbAnaProbe[1], &RComboBox::currentIndexChanged, this, [=](){ this->ProbeChange(cbAnaProbe, 2);}); connect(cbAnaProbe[0], &RComboBox::currentIndexChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); int ch = cbScopeCh->currentIndex(); if( chkSetAllChannel->isChecked() ) ch = -1; digiMTX[iDigi].lock(); digi[iDigi]->WriteValue(anaProbeList[0], (cbAnaProbe[0]->currentData()).toString().toStdString(), ch); digiMTX[iDigi].unlock(); }); connect(cbAnaProbe[1], &RComboBox::currentIndexChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); int ch = cbScopeCh->currentIndex(); if( chkSetAllChannel->isChecked() ) ch = -1; digiMTX[iDigi].lock(); digi[iDigi]->WriteValue(anaProbeList[1], (cbAnaProbe[1]->currentData()).toString().toStdString(), ch); digiMTX[iDigi].unlock(); }); connect(cbDigProbe[0], &RComboBox::currentIndexChanged, this, [=](){ this->ProbeChange(cbDigProbe, 4);}); connect(cbDigProbe[1], &RComboBox::currentIndexChanged, this, [=](){ this->ProbeChange(cbDigProbe, 4);}); connect(cbDigProbe[2], &RComboBox::currentIndexChanged, this, [=](){ this->ProbeChange(cbDigProbe, 4);}); connect(cbDigProbe[3], &RComboBox::currentIndexChanged, this, [=](){ this->ProbeChange(cbDigProbe, 4);}); connect(cbDigProbe[0], &RComboBox::currentIndexChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); int ch = cbScopeCh->currentIndex(); if( chkSetAllChannel->isChecked() ) ch = -1; digiMTX[iDigi].lock(); digi[iDigi]->WriteValue(digiProbeList[0], (cbDigProbe[0]->currentData()).toString().toStdString(), ch); digiMTX[iDigi].unlock(); }); connect(cbDigProbe[1], &RComboBox::currentIndexChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); int ch = cbScopeCh->currentIndex(); if( chkSetAllChannel->isChecked() ) ch = -1; digiMTX[iDigi].lock(); digi[iDigi]->WriteValue(digiProbeList[1], (cbDigProbe[1]->currentData()).toString().toStdString(), ch); digiMTX[iDigi].unlock(); }); connect(cbDigProbe[2], &RComboBox::currentIndexChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); int ch = cbScopeCh->currentIndex(); if( chkSetAllChannel->isChecked() ) ch = -1; digiMTX[iDigi].lock(); digi[iDigi]->WriteValue(digiProbeList[2], (cbDigProbe[2]->currentData()).toString().toStdString(), ch); digiMTX[iDigi].unlock(); }); connect(cbDigProbe[3], &RComboBox::currentIndexChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); int ch = cbScopeCh->currentIndex(); if( chkSetAllChannel->isChecked() ) ch = -1; digiMTX[iDigi].lock(); digi[iDigi]->WriteValue(digiProbeList[3], (cbDigProbe[3]->currentData()).toString().toStdString(), ch); digiMTX[iDigi].unlock(); }); layout->addWidget(cbAnaProbe[0], rowID, 0); layout->addWidget(cbAnaProbe[1], rowID, 1); layout->addWidget(cbDigProbe[0], rowID, 2); layout->addWidget(cbDigProbe[1], rowID, 3); layout->addWidget(cbDigProbe[2], rowID, 4); layout->addWidget(cbDigProbe[3], rowID, 5); for( int i = 0; i < 6; i++) layout->setColumnStretch(i, 1); rowID ++; {//------------ wave settings settingBox = new QGroupBox("Channel Settings (need ACQ stop)", this); layout->addWidget(settingBox, rowID, 0, 1, 6); bLayout = new QGridLayout(settingBox); bLayout->setSpacing(0); if( digi[0]->GetFPGAType() == DPPType::PHA ) SetupPHA(); if( digi[0]->GetFPGAType() == DPPType::PSD ) SetupPSD(); } //Trigger the ChangeDigitizer() cbScopeDigi->setCurrentIndex(0); cbScopeCh->setCurrentIndex(1); cbScopeCh->setCurrentIndex(0); //------------ plot view rowID ++; TraceView * plotView = new TraceView(plot); plotView->setRenderHints(QPainter::Antialiasing); layout->addWidget(plotView, rowID, 0, 1, 6); //------------- Key binding rowID ++; QLabel * lbhints = new QLabel("Type 'r' to restore view, '+/-' Zoom in/out, arrow key to pan.", this); layout->addWidget(lbhints, rowID, 0, 1, 4); QLabel * lbinfo = new QLabel("Trace update every " + QString::number(updateTraceThread->GetWaitTimeinSec()) + " sec.", this); lbinfo->setAlignment(Qt::AlignRight); layout->addWidget(lbinfo, rowID, 5); rowID ++; QLabel * lbinfo2 = new QLabel("Maximum time range is " + QString::number(MaxDisplayTraceDataLength * PHA::TraceStep) + " ns due to processing speed.", this); layout->addWidget(lbinfo2, rowID, 0, 1, 5); //------------ close button rowID ++; bnScopeStart = new QPushButton("Start", this); layout->addWidget(bnScopeStart, rowID, 0); bnScopeStart->setEnabled(true); connect(bnScopeStart, &QPushButton::clicked, this, [=](){this->StartScope();}); bnScopeStop = new QPushButton("Stop", this); layout->addWidget(bnScopeStop, rowID, 1); bnScopeStop->setEnabled(false); connect(bnScopeStop, &QPushButton::clicked, this, &Scope::StopScope); QLabel * lbTriggerRate = new QLabel("Trigger Rate [Hz] : ", this); lbTriggerRate->setAlignment(Qt::AlignCenter | Qt::AlignRight); layout->addWidget(lbTriggerRate, rowID, 2); leTriggerRate = new QLineEdit(this); leTriggerRate->setAlignment(Qt::AlignRight); leTriggerRate->setReadOnly(true); layout->addWidget(leTriggerRate, rowID, 3); QPushButton * bnClose = new QPushButton("Close", this); layout->addWidget(bnClose, rowID, 5); connect(bnClose, &QPushButton::clicked, this, &Scope::close); show(); //StartScope(); UpdateSettingsFromMemeory(); } Scope::~Scope(){ printf("------- %s \n", __func__); StopScope(); updateTraceThread->Stop(); updateTraceThread->quit(); updateTraceThread->wait(); delete updateTraceThread; for( int i = 0; i < 6; i++) delete dataTrace[i]; delete plot; printf("------- end of %s \n", __func__); } void Scope::ChangeDigitizer(){ int index = cbScopeDigi->currentIndex(); if( index == -1 ) return; allowChange = false; cbScopeCh->clear(); for( int i = 0; i < digi[index]->GetNChannels(); i++){ cbScopeCh->addItem("ch-" + QString::number(i), i); } cbScopeCh->setCurrentIndex(0); anaProbeList.clear(); digiProbeList.clear(); if( digi[index]->GetFPGAType() == DPPType::PHA ) { anaProbeList.push_back(PHA::CH::WaveAnalogProbe0); anaProbeList.push_back(PHA::CH::WaveAnalogProbe1); digiProbeList.push_back(PHA::CH::WaveDigitalProbe0); digiProbeList.push_back(PHA::CH::WaveDigitalProbe1); digiProbeList.push_back(PHA::CH::WaveDigitalProbe2); digiProbeList.push_back(PHA::CH::WaveDigitalProbe3); } if( digi[index]->GetFPGAType() == DPPType::PSD){ anaProbeList.push_back(PSD::CH::WaveAnalogProbe0); anaProbeList.push_back(PSD::CH::WaveAnalogProbe1); digiProbeList.push_back(PSD::CH::WaveDigitalProbe0); digiProbeList.push_back(PSD::CH::WaveDigitalProbe1); digiProbeList.push_back(PSD::CH::WaveDigitalProbe2); digiProbeList.push_back(PSD::CH::WaveDigitalProbe3); } cbAnaProbe[0]->clear(); cbAnaProbe[1]->clear(); for( int i = 0; i < (int) anaProbeList[0].GetAnswers().size(); i++ ) { cbAnaProbe[0]->addItem(QString::fromStdString((anaProbeList[0].GetAnswers())[i].second), QString::fromStdString((anaProbeList[0].GetAnswers())[i].first)); } for( int i = 0; i < cbAnaProbe[0]->count() ; i++) cbAnaProbe[1]->addItem(cbAnaProbe[0]->itemText(i), cbAnaProbe[0]->itemData(i)); cbDigProbe[0]->clear(); cbDigProbe[1]->clear(); cbDigProbe[2]->clear(); cbDigProbe[3]->clear(); for( int i = 0; i < (int) digiProbeList[0].GetAnswers().size(); i++ ) { cbDigProbe[0]->addItem(QString::fromStdString((digiProbeList[0].GetAnswers())[i].second), QString::fromStdString((digiProbeList[0].GetAnswers())[i].first)); } for( int i = 0; i < cbDigProbe[0]->count() ; i++) { cbDigProbe[1]->addItem(cbDigProbe[0]->itemText(i), cbDigProbe[0]->itemData(i)); cbDigProbe[2]->addItem(cbDigProbe[0]->itemText(i), cbDigProbe[0]->itemData(i)); cbDigProbe[3]->addItem(cbDigProbe[0]->itemText(i), cbDigProbe[0]->itemData(i)); } if( digi[index]->GetFPGAType() == DPPType::PHA ) SetupPHA(); if( digi[index]->GetFPGAType() == DPPType::PSD ) SetupPSD(); digiMTX[index].lock(); ReadScopeSettings(); digiMTX[index].unlock(); allowChange = true; } void Scope::CleanUpSettingsGroupBox(){ QList labelChildren1 = settingBox->findChildren(); for( int i = 0; i < labelChildren1.size(); i++) delete labelChildren1[i]; QList labelChildren2 = settingBox->findChildren(); for( int i = 0; i < labelChildren2.size(); i++) delete labelChildren2[i]; QList labelChildren3 = settingBox->findChildren(); for( int i = 0; i < labelChildren3.size(); i++) delete labelChildren3[i]; } void Scope::SetupPHA(){ CleanUpSettingsGroupBox(); ScopeMakeSpinBox(sbRL, "Record Lenght [ns] ", bLayout, 0, 0, PHA::CH::RecordLength); ScopeMakeSpinBox(sbThreshold, "Threshold [LSB] ", bLayout, 0, 2, PHA::CH::TriggerThreshold); ScopeMakeComoBox(cbPolarity, "Polarity ", bLayout, 0, 4, PHA::CH::Polarity); ScopeMakeComoBox(cbWaveRes, "Wave Re. ", bLayout, 0, 6, PHA::CH::WaveResolution); //------------------ next row ScopeMakeSpinBox(sbPT, "Pre Trigger [ns] ", bLayout, 1, 0, PHA::CH::PreTrigger); ScopeMakeSpinBox(sbDCOffset, "DC offset [%] ", bLayout, 1, 2, PHA::CH::DC_Offset); ScopeMakeSpinBox(sbTimeRiseTime, "Trigger Rise Time [ns] ", bLayout, 1, 4, PHA::CH::TimeFilterRiseTime); ScopeMakeSpinBox(sbTimeGuard, "Trigger Guard [ns] ", bLayout, 1, 6, PHA::CH::TimeFilterRetriggerGuard); //----------------- next row ScopeMakeSpinBox(sbTrapRiseTime, "Trap. Rise Time [ns] ", bLayout, 2, 0, PHA::CH::EnergyFilterRiseTime); ScopeMakeSpinBox(sbTrapFlatTop, "Trap. Flat Top [ns] ", bLayout, 2, 2, PHA::CH::EnergyFilterFlatTop); ScopeMakeSpinBox(sbTrapPoleZero, "Trap. Pole Zero [ns] ", bLayout, 2, 4, PHA::CH::EnergyFilterPoleZero); ScopeMakeSpinBox(sbEnergyFineGain, "Energy Fine Gain ", bLayout, 2, 6, PHA::CH::EnergyFilterFineGain); //----------------- next row ScopeMakeSpinBox(sbTrapPeaking, "Trap. Peaking [%] ", bLayout, 3, 0, PHA::CH::EnergyFilterPeakingPosition); ScopeMakeComoBox(cbTrapPeakAvg, "Trap. Peaking ", bLayout, 3, 2, PHA::CH::EnergyFilterPeakingAvg); ScopeMakeSpinBox(sbBaselineGuard, "Baseline Guard [ns] ", bLayout, 3, 4, PHA::CH::EnergyFilterBaselineGuard); ScopeMakeComoBox(cbBaselineAvg, "Baseline Avg ", bLayout, 3, 6, PHA::CH::EnergyFilterBaselineAvg); //----------------- next row ScopeMakeSpinBox(sbPileUpGuard, "Pile-up Guard [ns] ", bLayout, 4, 0, PHA::CH::EnergyFilterPileUpGuard); ScopeMakeComoBox(cbLowFreqFilter, "Low Freq. Filter ", bLayout, 4, 2, PHA::CH::EnergyFilterLowFreqFilter); } void Scope::SetupPSD(){ CleanUpSettingsGroupBox(); ScopeMakeSpinBox(sbRL, "Record Lenght [ns] ", bLayout, 0, 0, PSD::CH::RecordLength); ScopeMakeSpinBox(sbThreshold, "Threshold [LSB] ", bLayout, 0, 2, PSD::CH::TriggerThreshold); ScopeMakeComoBox(cbPolarity, "Polarity ", bLayout, 0, 4, PSD::CH::Polarity); ScopeMakeComoBox(cbWaveRes, "Wave Re. ", bLayout, 0, 6, PSD::CH::WaveResolution); //------------------ next row ScopeMakeSpinBox(sbPT, "Pre Trigger [ns] ", bLayout, 1, 0, PSD::CH::PreTrigger); ScopeMakeSpinBox(sbDCOffset, "DC offset [%] ", bLayout, 1, 2, PSD::CH::DC_Offset); ScopeMakeComoBox(cbbADCInputBaselineAvg, "ADC BL Avg. ", bLayout, 1, 4, PSD::CH::ADCInputBaselineAvg); ScopeMakeSpinBox(spbADCInputBaselineGuard, "ADC BL Guard [ns] ", bLayout, 1, 6, PSD::CH::ADCInputBaselineGuard); //------------------ next row ScopeMakeSpinBox(spbCFDDelay, "CFD Delay [ns] ", bLayout, 2, 0, PSD::CH::CFDDelay); ScopeMakeSpinBox(spbCFDFraction, "CFD Frac. [%] ", bLayout, 2, 2, PSD::CH::CFDFraction); ScopeMakeComoBox(cbbSmoothingFactor, "Smoothing ", bLayout, 2, 4, PSD::CH::SmoothingFactor); ScopeMakeSpinBox(spbAbsBaseline, "Abs. BL ", bLayout, 2, 6, PSD::CH::AbsoluteBaseline); //------------------ next row ScopeMakeComoBox(cbbTriggerFilter, "Trig. Filter ", bLayout, 3, 0, PSD::CH::TriggerFilterSelection); ScopeMakeComoBox(cbbTimeFilterSmoothing, "Trig. Smooth ", bLayout, 3, 2, PSD::CH::TimeFilterSmoothing); ScopeMakeSpinBox(spbTimeFilterReTriggerGuard, "Trig. Guard [ns] ", bLayout, 3, 4, PSD::CH::TimeFilterRetriggerGuard); ScopeMakeSpinBox(spbPileupGap, "PileUp Gap [ns] ", bLayout, 3, 6, PSD::CH::PileupGap); //------------------ next row ScopeMakeSpinBox(spbGateLong, "Long Gate [ns] ", bLayout, 4, 0, PSD::CH::GateLongLength); ScopeMakeSpinBox(spbGateShort, "Shart Gate [ns] ", bLayout, 4, 2, PSD::CH::GateLongLength); ScopeMakeSpinBox(spbGateOffset, "Gate offset [ns] ", bLayout, 4, 4, PSD::CH::GateLongLength); ScopeMakeComoBox(cbbEnergyGain, "Energy Gain ", bLayout, 4, 6, PSD::CH::EnergyGain); } void Scope::ReadScopeSettings(){ if( !isVisible() ) return; int iDigi = cbScopeDigi->currentIndex(); if( !digi[iDigi] || digi[iDigi]->IsDummy() || !digi[iDigi]->IsConnected()) return; UpdateSettingsFromMemeory(); } void Scope::UpdateSettingsFromMemeory(){ if( !isVisible() ) return; printf("Scope::%s\n", __func__); int iDigi = cbScopeDigi->currentIndex(); if( !digi[iDigi] || digi[iDigi]->IsDummy() || !digi[iDigi]->IsConnected()) return; allowChange = false; int ch = cbScopeCh->currentIndex(); for( int i = 0 ; i < 2; i++){ if( digi[iDigi]->GetFPGAType() == DPPType::PHA ) ScopeReadComboBoxValue(iDigi, ch, cbAnaProbe[i], PHA::CH::AnalogProbe[i]); if( digi[iDigi]->GetFPGAType() == DPPType::PSD ) ScopeReadComboBoxValue(iDigi, ch, cbAnaProbe[i], PSD::CH::AnalogProbe[i]); } for( int i = 0 ; i < 4; i++){ if( digi[iDigi]->GetFPGAType() == DPPType::PHA ) ScopeReadComboBoxValue(iDigi, ch, cbDigProbe[i], PHA::CH::DigitalProbe[i]); if( digi[iDigi]->GetFPGAType() == DPPType::PSD ) ScopeReadComboBoxValue(iDigi, ch, cbDigProbe[i], PSD::CH::DigitalProbe[i]); } if( digi[iDigi]->GetFPGAType() == DPPType::PHA ){ ScopeReadComboBoxValue(iDigi, ch, cbPolarity, PHA::CH::Polarity); ScopeReadComboBoxValue(iDigi, ch, cbWaveRes, PHA::CH::WaveResolution); ScopeReadComboBoxValue(iDigi, ch, cbTrapPeakAvg, PHA::CH::EnergyFilterPeakingAvg); ScopeReadComboBoxValue(iDigi, ch, cbBaselineAvg, PHA::CH::EnergyFilterBaselineAvg); ScopeReadComboBoxValue(iDigi, ch, cbLowFreqFilter, PHA::CH::EnergyFilterLowFreqFilter); ScopeReadSpinBoxValue(iDigi, ch, sbRL, PHA::CH::RecordLength); ScopeReadSpinBoxValue(iDigi, ch, sbPT, PHA::CH::PreTrigger); ScopeReadSpinBoxValue(iDigi, ch, sbDCOffset, PHA::CH::DC_Offset); ScopeReadSpinBoxValue(iDigi, ch, sbThreshold, PHA::CH::TriggerThreshold); ScopeReadSpinBoxValue(iDigi, ch, sbTimeRiseTime, PHA::CH::TimeFilterRiseTime); ScopeReadSpinBoxValue(iDigi, ch, sbTimeGuard, PHA::CH::TimeFilterRetriggerGuard); ScopeReadSpinBoxValue(iDigi, ch, sbTrapRiseTime, PHA::CH::EnergyFilterRiseTime); ScopeReadSpinBoxValue(iDigi, ch, sbTrapFlatTop, PHA::CH::EnergyFilterFlatTop); ScopeReadSpinBoxValue(iDigi, ch, sbTrapPoleZero, PHA::CH::EnergyFilterPoleZero); ScopeReadSpinBoxValue(iDigi, ch, sbEnergyFineGain, PHA::CH::EnergyFilterFineGain); ScopeReadSpinBoxValue(iDigi, ch, sbTrapPeaking, PHA::CH::EnergyFilterPeakingPosition); ScopeReadSpinBoxValue(iDigi, ch, sbBaselineGuard, PHA::CH::EnergyFilterBaselineGuard); ScopeReadSpinBoxValue(iDigi, ch, sbPileUpGuard, PHA::CH::EnergyFilterPileUpGuard); sbRL->setStyleSheet(""); sbPT->setStyleSheet(""); sbThreshold->setStyleSheet(""); sbTimeRiseTime->setStyleSheet(""); sbTimeGuard->setStyleSheet(""); sbTrapRiseTime->setStyleSheet(""); sbTrapFlatTop->setStyleSheet(""); sbTrapPoleZero->setStyleSheet(""); sbEnergyFineGain->setStyleSheet(""); sbTrapPeaking->setStyleSheet(""); sbBaselineGuard->setStyleSheet(""); sbPileUpGuard->setStyleSheet(""); } if( digi[iDigi]->GetFPGAType() == DPPType::PSD ){ ScopeReadComboBoxValue(iDigi, ch, cbPolarity, PSD::CH::Polarity); ScopeReadComboBoxValue(iDigi, ch, cbWaveRes, PSD::CH::WaveResolution); ScopeReadComboBoxValue(iDigi, ch, cbbADCInputBaselineAvg, PSD::CH::ADCInputBaselineAvg); ScopeReadComboBoxValue(iDigi, ch, cbbSmoothingFactor, PSD::CH::SmoothingFactor); ScopeReadComboBoxValue(iDigi, ch, cbbTriggerFilter, PSD::CH::TriggerFilterSelection); ScopeReadComboBoxValue(iDigi, ch, cbbTimeFilterSmoothing, PSD::CH::TimeFilterSmoothing); ScopeReadComboBoxValue(iDigi, ch, cbbEnergyGain, PSD::CH::EnergyGain); ScopeReadSpinBoxValue(iDigi, ch, sbRL, PSD::CH::RecordLength); ScopeReadSpinBoxValue(iDigi, ch, sbThreshold, PSD::CH::TriggerThreshold); ScopeReadSpinBoxValue(iDigi, ch, sbPT, PSD::CH::PreTrigger); ScopeReadSpinBoxValue(iDigi, ch, sbDCOffset, PSD::CH::DC_Offset); ScopeReadSpinBoxValue(iDigi, ch, spbADCInputBaselineGuard, PSD::CH::ADCInputBaselineGuard); ScopeReadSpinBoxValue(iDigi, ch, spbCFDDelay, PSD::CH::CFDDelay); ScopeReadSpinBoxValue(iDigi, ch, spbCFDFraction, PSD::CH::CFDFraction); ScopeReadSpinBoxValue(iDigi, ch, spbAbsBaseline, PSD::CH::AbsoluteBaseline); ScopeReadSpinBoxValue(iDigi, ch, spbTimeFilterReTriggerGuard, PSD::CH::TimeFilterRetriggerGuard); ScopeReadSpinBoxValue(iDigi, ch, spbPileupGap, PSD::CH::PileupGap); ScopeReadSpinBoxValue(iDigi, ch, spbGateLong, PSD::CH::GateLongLength); ScopeReadSpinBoxValue(iDigi, ch, spbGateShort, PSD::CH::GateShortLength); ScopeReadSpinBoxValue(iDigi, ch, spbGateOffset, PSD::CH::GateOffset); cbPolarity->setStyleSheet(""); cbWaveRes->setStyleSheet(""); cbbADCInputBaselineAvg->setStyleSheet(""); cbbSmoothingFactor->setStyleSheet(""); cbbTriggerFilter->setStyleSheet(""); cbbTimeFilterSmoothing->setStyleSheet(""); cbbEnergyGain->setStyleSheet(""); sbRL->setStyleSheet(""); sbThreshold->setStyleSheet(""); sbPT->setStyleSheet(""); sbDCOffset->setStyleSheet(""); spbADCInputBaselineGuard->setStyleSheet(""); spbCFDDelay->setStyleSheet(""); spbCFDFraction->setStyleSheet(""); spbAbsBaseline->setStyleSheet(""); spbTimeFilterReTriggerGuard->setStyleSheet(""); spbPileupGap->setStyleSheet(""); spbGateLong->setStyleSheet(""); spbGateShort->setStyleSheet(""); spbGateOffset->setStyleSheet(""); } allowChange = true; } void Scope::StartScope(){ if( !digi ) return; for( int iDigi = 0 ; iDigi < nDigi; iDigi ++ ){ if( digi[iDigi]->IsDummy() ) return; int ch = cbScopeCh->currentIndex(); //*---- set digitizer to take full trace; since in scope mode, no data saving, speed would be fast (How fast?) //* when the input rate is faster than trigger rate, Digitizer will stop data taking. ReadScopeSettings(); /// the settings are the same for PHA and PSD for( int ch2 = 0 ; ch2 < digi[iDigi]->GetNChannels(); ch2 ++){ channelEnable[iDigi][ch2] = digi[iDigi]->ReadValue(PHA::CH::ChannelEnable, ch2); } digi[iDigi]->WriteValue(PHA::CH::ChannelEnable, "False", -1); if( iDigi == cbScopeDigi->currentIndex() ){ digi[iDigi]->WriteValue(PHA::CH::ChannelEnable, "True", ch); waveSaving = digi[iDigi]->ReadValue(PHA::CH::WaveSaving, ch); digi[iDigi]->WriteValue(PHA::CH::WaveSaving, "Always", ch); waveTriggerSource = digi[iDigi]->ReadValue(PHA::CH::WaveTriggerSource, ch); digi[iDigi]->WriteValue(PHA::CH::WaveTriggerSource, "ChSelfTrigger", ch); } originalValueSet = true; digi[iDigi]->SetDataFormat(DataFormat::ALL); digi[iDigi]->StartACQ(); readDataThread[iDigi]->SetSaveData(false); readDataThread[iDigi]->start(); updateTraceThread->start(); ScopeControlOnOff(false); emit TellSettingsPanelControlOnOff(); } emit TellACQOnOff(true); allowChange = true; } void Scope::StopScope(){ printf("%s\n", __func__); updateTraceThread->Stop(); updateTraceThread->quit(); updateTraceThread->wait(); /// the settings are the same for PHA and PSD if(digi){ for(int i = 0; i < nDigi; i++){ if( digi[i]->IsDummy() ) continue; readDataThread[i]->Stop(); readDataThread[i]->quit(); readDataThread[i]->wait(); digiMTX[i].lock(); digi[i]->StopACQ(); if( originalValueSet ){ for( int ch2 = 0 ; ch2 < digi[i]->GetNChannels(); ch2 ++){ digi[i]->WriteValue(PHA::CH::ChannelEnable, channelEnable[i][ch2], ch2); } if( i == cbScopeDigi->currentIndex() ) { digi[i]->WriteValue(PHA::CH::WaveTriggerSource, waveTriggerSource, cbScopeCh->currentIndex()); digi[i]->WriteValue(PHA::CH::WaveSaving, waveSaving, cbScopeCh->currentIndex()); } originalValueSet = false; } digiMTX[i].unlock(); } emit TellACQOnOff(false); } ScopeControlOnOff(true); emit TellSettingsPanelControlOnOff(); allowChange = true; } void Scope::UpdateScope(){ int iDigi = cbScopeDigi->currentIndex(); int ch = cbScopeCh->currentIndex(); int sample2ns = PHA::TraceStep * (1 << cbWaveRes->currentIndex()); emit UpdateScalar(); /// the settings are the same for PHA and PSD if( digi ){ digiMTX[iDigi].lock(); std::string time = digi[iDigi]->ReadValue(PHA::CH::ChannelRealtime, ch); // for refreashing SelfTrgRate and SavedCount std::string haha = digi[iDigi]->ReadValue(PHA::CH::SelfTrgRate, ch); leTriggerRate->setText(QString::fromStdString(haha)); //unsigned int traceLength = qMin((int) digi[iDigi]->evt->traceLenght, MaxDisplayTraceDataLength); unsigned int traceLength = qMin( atoi(digi[iDigi]->GetSettingValue(PHA::CH::RecordLength, ch).c_str())/sample2ns, MaxDisplayTraceDataLength ); if( atoi(haha.c_str()) == 0 ) { digiMTX[iDigi].unlock(); for( int j = 0; j < 6; j++){ QVector points; for( unsigned int i = 0 ; i < traceLength; i++) points.append(QPointF(sample2ns * i , j > 1 ? 0 : (j+1)*1000)); dataTrace[j]->replace(points); } plot->axes(Qt::Horizontal).first()->setRange(0, sample2ns * traceLength); return; } //printf("%s, traceLength : %d , %d\n", __func__, traceLength, digi[iDigi]->evt->analog_probes[0][10]); for( int j = 0; j < 2; j++) { QVector points; for( unsigned int i = 0 ; i < traceLength; i++) points.append(QPointF(sample2ns * i , digi[iDigi]->evt->analog_probes[j][i])); dataTrace[j]->replace(points); } for( int j = 0; j < 4; j++) { QVector points; for( unsigned int i = 0 ; i < traceLength; i++) points.append(QPointF(sample2ns * i , (j+1)*5000 + 4000*digi[iDigi]->evt->digital_probes[j][i])); dataTrace[j+2]->replace(points); } //digi[iDigi]->evt->ClearTrace(); digiMTX[iDigi].unlock(); plot->axes(Qt::Horizontal).first()->setRange(0, sample2ns * traceLength); } } void Scope::ProbeChange(RComboBox * cb[], const int size ){ if( allowChange == false ) return; //printf("%s\n", __func__); QStandardItemModel * model[size] = {NULL}; for( int i = 0; i < size; i++){ model[i] = qobject_cast(cb[i]->model()); } /// Enable all items for( int i = 0; i < cb[0]->count(); i++) { for( int j = 0; j < size; j ++ ) model[j]->item(i)->setEnabled(true); } for( int i = 0; i < size; i++){ int index = cb[i]->currentIndex(); for( int j = 0; j < size; j++){ if( i == j ) continue; model[j]->item(index)->setEnabled(false); } } //int ID = cbScopeDigi->currentIndex(); //digiMTX[ID].lock(); if( size == 2) {// analog probes 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[ID].unlock(); } void Scope::ScopeControlOnOff(bool on){ bnScopeStop->setEnabled(!on); bnScopeStart->setEnabled(on); bnScopeReset->setEnabled(on); bnScopeReadSettings->setEnabled(on); if( digi[cbScopeDigi->currentIndex()]->GetFPGAType() == DPPType::PHA ){ sbRL->setEnabled(on); sbPT->setEnabled(on); sbTimeRiseTime->setEnabled(on); sbTimeGuard->setEnabled(on); sbTrapRiseTime->setEnabled(on); sbTrapFlatTop->setEnabled(on); sbTrapPoleZero->setEnabled(on); sbEnergyFineGain->setEnabled(on); sbTrapPeaking->setEnabled(on); cbPolarity->setEnabled(on); cbWaveRes->setEnabled(on); cbTrapPeakAvg->setEnabled(on); cbBaselineAvg->setEnabled(on); //sbDCOffset->setEnabled(on); //sbThreshold->setEnabled(on); //sbBaselineGuard->setEnabled(on); //sbPileUpGuard->setEnabled(on); //cbLowFreqFilter->setEnabled(on); } if( digi[cbScopeDigi->currentIndex()]->GetFPGAType() == DPPType::PSD ){ cbPolarity->setEnabled(on); cbWaveRes->setEnabled(on); cbbADCInputBaselineAvg->setEnabled(on); cbbSmoothingFactor->setEnabled(on); cbbTriggerFilter->setEnabled(on); cbbTimeFilterSmoothing->setEnabled(on); cbbEnergyGain->setEnabled(on); sbRL->setEnabled(on); sbPT->setEnabled(on); //sbThreshold->setEnabled(on); //sbDCOffset->setEnabled(on); //spbADCInputBaselineGuard->setEnabled(on); //spbCFDDelay->setEnabled(on); //spbCFDFraction->setEnabled(on); //spbAbsBaseline->setEnabled(on); //spbTimeFilterReTriggerGuard->setEnabled(on); //spbPileupGap->setEnabled(on); //spbGateLong->setEnabled(on); //spbGateShort->setEnabled(on); //spbGateOffset->setEnabled(on); } } void Scope::ScopeReadSpinBoxValue(int iDigi, int ch, RSpinBox *sb, const Reg digPara){ std::string ans = digi[iDigi]->GetSettingValue(digPara, ch); sb->setValue(atoi(ans.c_str())); } void Scope::ScopeReadComboBoxValue(int iDigi, int ch, RComboBox *cb, const Reg digPara){ std::string ans = digi[iDigi]->GetSettingValue(digPara, ch); int index = cb->findData(QString::fromStdString(ans)); if( index >= 0 && index < cb->count()) { cb->setCurrentIndex(index); }else{ qDebug() << QString::fromStdString(ans); } } void Scope::ScopeMakeSpinBox(RSpinBox * &sb, QString str, QGridLayout *layout, int row, int col, const Reg digPara){ //printf("%s\n", __func__); QLabel * lb = new QLabel(str, settingBox); lb->setAlignment(Qt::AlignRight | Qt::AlignCenter); layout->addWidget(lb, row, col); sb = new RSpinBox(settingBox); sb->setMinimum(atof(digPara.GetAnswers()[0].first.c_str())); sb->setMaximum(atof(digPara.GetAnswers()[1].first.c_str())); sb->setSingleStep(atof(digPara.GetAnswers()[2].first.c_str())); layout->addWidget(sb, row, col+1); connect(sb, &RSpinBox::valueChanged, this, [=](){ if( !allowChange ) return; sb->setStyleSheet("color:blue"); }); connect(sb, &RSpinBox::returnPressed, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); if( sb->decimals() == 0 && sb->singleStep() != 1) { double step = sb->singleStep(); double value = sb->value(); sb->setValue( (std::round(value/step)*step)); } int ch = cbScopeCh->currentIndex(); if( chkSetAllChannel->isChecked() ) ch = -1; QString msg; msg = QString::fromStdString(digPara.GetPara()) + "|DIG:"+ QString::number(digi[iDigi]->GetSerialNumber()) + ",CH:" + (ch == -1 ? "All" : QString::number(ch)); msg += " = " + QString::number(sb->value()); if( digi[iDigi]->WriteValue(digPara, std::to_string(sb->value()), ch)){ SendLogMsg(msg + "|OK."); sb->setStyleSheet(""); UpdateSettingsFromMemeory(); UpdateOtherPanels(); }else{ SendLogMsg(msg + "|Fail."); sb->setStyleSheet("color:red;"); } }); } void Scope::ScopeMakeComoBox(RComboBox * &cb, QString str, QGridLayout *layout, int row, int col, const Reg digPara){ QLabel * lb = new QLabel(str, settingBox); lb->setAlignment(Qt::AlignRight | Qt::AlignCenter); layout->addWidget(lb, row, col); cb = new RComboBox(settingBox); for( int i = 0 ; i < (int) digPara.GetAnswers().size(); i++){ cb->addItem(QString::fromStdString((digPara.GetAnswers())[i].second), QString::fromStdString((digPara.GetAnswers())[i].first)); } layout->addWidget(cb, row, col+1); connect(cb, &RComboBox::currentIndexChanged, this, [=](){ if( !allowChange ) return; int iDigi = cbScopeDigi->currentIndex(); int ch = cbScopeCh->currentIndex(); if( chkSetAllChannel->isChecked() ) ch = -1; QString msg; msg = QString::fromStdString(digPara.GetPara()) + "|DIG:"+ QString::number(digi[iDigi]->GetSerialNumber()) + ",CH:" + (ch == -1 ? "All" : QString::number(ch)); msg += " = " + cb->currentData().toString(); if( digi[iDigi]->WriteValue(digPara, cb->currentData().toString().toStdString(), ch)){ SendLogMsg(msg + "|OK."); cb->setStyleSheet(""); UpdateSettingsFromMemeory(); UpdateOtherPanels(); }else{ SendLogMsg(msg + "|Fail."); cb->setStyleSheet("color:red;"); } }); }