/* * Title: PupeDiagnosticsWin.cpp * Author: M.Thomas BEAM Ltd * Date: 2007-02-13 * * Contents: Status Display * * Mod Rec: * */ #include <PupeDiagnosticsWin.h> #include <qlayout.h> #include <qvbox.h> #include <qlabel.h> #include <qtable.h> #include <BError.h> #include <TmsD.h> #include <qvalidator.h> #include <qmessagebox.h> #include <qgroupbox.h> #include <qvgroupbox.h> #include <BQComboBox.h> #include <math.h> #include <Globals.h> #include <qfiledialog.h> #include <fftw3.h> const int BUTTON_WIDTH = 200; const int LINE_EDIT_MAX_WIDTH = 200; const int GRAPHS_TOTAL_HEIGHT = 620; const int GRAPHS_X_LEDGEND_HEIGHT = 50; using namespace std; using namespace Tms; #define BIT(v,b) ((v >> b) & 1) PupeDiagBitDefinition defSource0[] = { // name startBit nBits isSigned gain { "fref", 63, 1, 0, 1 }, { "PllMsb", 62, 1, 0, -1 }, { "PhaseTableMsb", 61, 1, 0, -1 }, { "lo1", 60, 1, 0, 1 }, { "sigma", 32, 12, 1, 4 }, { "lo2", 56, 1, 0, 1 }, { "gate", 49, 1, 0, 1 }, { "blr", 48, 1, 0, 1 }, { "mean1", 50, 1, 0, 1 }, { "mean2", 51, 1, 0, 1 }, { "rfSelect1", 52, 1, 0, 1 }, { "rfSelect2", 53, 1, 0, 1 }, { "selFilter", 54, 1, 0, 1 }, { "SwitchState", 44, 4, 0, 1 }, { "dds_freq", 0, 26, 1, 64 }, { 0,0,0,0,0 } }; PupeDiagBitDefinition defSource1[] = { { "FREF", 63, 1, 0, 1 }, { "PllMsb", 62, 1, 0, -1 }, { "PhaseTableMsb", 61, 1, 0, -1 }, { "LO_pulse1", 60, 1, 0, 1 }, { "sigma", 57, 3, 1, 2048 }, { "LO_pulse2", 56, 1, 0, 1 }, { "mult_out1", 38, 14, 1, 1 }, { "mult_out2", 24, 14, 1, 1 }, { "f_error", 0, 24, 1, 1 }, { 0,0,0,0,0 } }; // Source = 2 PupeDiagBitDefinition defSource2[] = { { "FREF", 63, 1, 0, 1 }, { "PllMsb", 62, 1, 0, -1 }, { "PhaseTableMsb", 61, 1, 0, -1 }, { "LO1", 60, 1, 0, 1 }, { "sigma", 57, 3, 1, 2048 }, { "LO2", 56, 1, 0, 1 }, { "Gate", 55, 1, 0, 1 }, { "B0", 32, 23, 1, 1 }, { "Result0", 0, 32, 1, 1 }, { 0,0,0,0,0 } }; PupeDiagBitDefinition defSource3[] = { { "fref", 63, 1, 0, 1 }, { "PllMsb", 62, 1, 0, -1 }, { "PhaseTableMsb", 61, 1, 0, -1 }, { "lo1", 60, 1, 0, 1 }, #ifdef ZAP { "hchange_temp", 59, 1, 0, 1 }, { "hchange_switch", 58, 1, 0, 1 }, { "ms_pulse_reg", 57, 1, 0, 1 }, #else { "SigmaDelayed", 57, 3, 1, 2048 }, #endif { "lo2", 56, 1, 0, 1 }, { "BLR", 55, 1, 0, 1 }, { "Gate", 54, 1, 0, 1 }, { "Sigma", 40, 14, 1, 1 }, { "DeltaX", 26, 14, 1, 1 }, { "DeltaY", 12, 14, 1, 1 }, { 0,0,0,0,0 } }; PupeDiagBitDefinition defSigma[] = { { "Sigma", 40, 14, 1, 1 }, { 0,0,0,0,0 } }; PupeDiagBitDefinition defDeltaX[] = { { "DeltaX", 26, 14, 1, 1 }, { 0,0,0,0,0 } }; PupeDiagBitDefinition defDeltaY[] = { { "DeltaY", 12, 14, 1, 1 }, { 0,0,0,0,0 } }; PupeDiagBitDefinition defSource0trigger[] = { { "FREF", 7, 1, 0, 1 }, { "HCHANGE", 6, 1, 0, 1 }, { "INJECTION", 5, 1, 0, 1 }, { "CAL_STOP", 4, 1, 0, 1 }, { "CAL_START", 3, 1, 0, 1 }, { "CYCLE_STOP", 2, 1, 0, 1 }, { "CYCLE_START", 1, 1, 0, 1 }, { "10MHz", 0, 1, 0, 1 }, }; typedef BArray<float> BFArray; static ComboDefinition sourceDef[] = { { 0, "Source 0", 0, 1 }, { 1, "Source 1", 1, 0 }, { 2, "Source 2", 2, 0 }, { 3, "Source 3", 3, 0 }, { 4, "Sigma", 4, 0 }, { 5, "DeltaX", 5, 0 }, { 6, "DeltaY", 6, 0 }, { 0,0,0,0 } }; static ComboDefinition clockDef[] = { { 0, "ADC Clock", ClkAdcDiv_1, 1 }, { 1, "ADC Clock/2", ClkAdcDiv_2, 0 }, { 2, "ADC Clock/5", ClkAdcDiv_5, 0 }, { 3, "ADC Clock/10", ClkAdcDiv_10, 0 }, { 4, "ADC Clock/20", ClkAdcDiv_20, 0 }, { 5, "ADC Clock/50", ClkAdcDiv_50, 0 }, { 6, "ADC Clock/100", ClkAdcDiv_100, 0 }, { 7, "ADC Clock/200", ClkAdcDiv_200, 0 }, { 8, "ADC Clock/500", ClkAdcDiv_500, 0 }, { 9, "ADC Clock/1000", ClkAdcDiv_1000, 0 }, { 10, "ADC Clock/2000", ClkAdcDiv_2000, 0 }, { 11, "ADC Clock/5000", ClkAdcDiv_5000, 0 }, { 12, "ADC Clock/10000", ClkAdcDiv_10000, 0 }, { 13, "ADC Clock/20000", ClkAdcDiv_20000, 0 }, { 14, "ADC Clock/50000", ClkAdcDiv_50000, 0 }, { 15, "ADC Clock/100000", ClkAdcDiv_100000, 0 }, { 16, "Ms", ClkMs, 0 }, { 17, "FREF", ClkFref, 0 }, { 0,0,0,0 } }; Int32 getBitValue(UInt64 value, int startBit, int nBits, int s){ Int64 v; UInt64 bm = (1ULL << nBits) - 1; UInt64 sm = (1ULL << (nBits - 1)); v = (value >> startBit) & bm; if(s){ v = -(v & sm) | v; } return v; } PupeDiagnosticsWin::PupeDiagnosticsWin(QWidget* w,Control& c) : ocontrol(c) { QVBox* mv = new QVBox(this); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); oplots.append(new BGraph(mv)); ographControls = new BGraphControlBasic(mv); QValidator* validator = new QIntValidator(0, (int)pow(2.0,31.0), this ); QRegExpValidator* validatorHex = new QRegExpValidator(this); QRegExp rx; QWidget* t = new QWidget(mv,"dataEntry"); QVGroupBox* masksG = new QVGroupBox(t); QWidget* masks = new QWidget(masksG); QGridLayout* v1 = new QGridLayout(masks); QHBox* h = new QHBox(mv,"controls"); QGridLayout* v = new QGridLayout(t); int row = 0; int col = 0; rx.setPattern("0x[0-9,a-f][0-9,a-f]"); validatorHex->setRegExp(rx); orefreshButton = new QPushButton("Refresh Data",h,"refreshButton"); osaveButton = new QPushButton("Save To File",h,"saveButton"); okst = new QCheckBox(t,""); ochannel = new QSpinBox(1,60,1,t,""); osource = new BQComboBox(sourceDef,t,""); oclock = new BQComboBox(clockDef,t,""); ostartTime = new QLineEdit(t,"");ostartTime->setValidator(validator); opostTriggerDelay = new QLineEdit(t,"");opostTriggerDelay->setValidator(validator); v1->addWidget(oClock = new QCheckBox("Clock",masks,""),1,3); v1->addWidget(oCycleStart = new QCheckBox("Cycle Start",masks,""),1,2); v1->addWidget(oCycleStop = new QCheckBox("Cycle Stop",masks,""),1,1); v1->addWidget(oCalStart = new QCheckBox("Cal Start",masks,""),1,0); v1->addWidget(oCalStop = new QCheckBox("Cal Stop",masks,""),0,3); v1->addWidget(oInjection = new QCheckBox("Injection",masks,""),0,2); v1->addWidget(oHChange = new QCheckBox("H Change",masks,""),0,1); v1->addWidget(oFref = new QCheckBox("Fref",masks,""),0,0); oInjection->setChecked(true); otriggerSourceData = new QCheckBox(t,""); otriggerAnd = new QCheckBox(t,""); otriggerStore = new QCheckBox(t,""); ostartTime->setText("0"); opostTriggerDelay->setText("0"); masksG->setTitle("Trigger Mask"); h->setMargin(4); ochannel->setWrapping(true); orefreshButton->setMaximumWidth(BUTTON_WIDTH); osaveButton->setMaximumWidth(BUTTON_WIDTH); ochannel->setMaximumWidth(LINE_EDIT_MAX_WIDTH); osource->setMaximumWidth(LINE_EDIT_MAX_WIDTH); oclock->setMaximumWidth(LINE_EDIT_MAX_WIDTH); ostartTime->setMaximumWidth(LINE_EDIT_MAX_WIDTH); opostTriggerDelay->setMaximumWidth(LINE_EDIT_MAX_WIDTH); otriggerAnd->setMaximumWidth(LINE_EDIT_MAX_WIDTH); otriggerStore->setMaximumWidth(LINE_EDIT_MAX_WIDTH); otriggerSourceData->setMaximumWidth(LINE_EDIT_MAX_WIDTH); col = 0;row = 0; v->setSpacing(5); v->addMultiCellWidget(masksG ,row,2,col+4,col+4); v->addWidget(new QLabel("Channel",t,""),row,col); v->addWidget(ochannel,row,col+1); row++; v->addWidget(new QLabel("Source",t,""),row,col); v->addWidget(osource,row,col+1); row++; v->addWidget(new QLabel("Clock",t,""),row,col); v->addWidget(oclock,row,col+1); row++; v->addWidget(new QLabel("StartTime",t,""),row,col); v->addWidget(ostartTime,row,col+1); row++; v->addWidget(new QLabel("Post Trigger Delay",t,""),row,col); v->addWidget(opostTriggerDelay,row,col+1); row++; col = 2;row = 0; v->addWidget(new QLabel("Trigger Src Data",t,""),row,col); v->addWidget(otriggerSourceData,row,col+1); row++; v->addWidget(new QLabel("Trigger And",t,""),row,col); v->addWidget(otriggerAnd,row,col+1); row++; v->addWidget(new QLabel("Trigger Store",t,""),row,col); v->addWidget(otriggerStore,row,col+1); row++; v->addWidget(new QLabel("Save Format Kst",t,""),row,col); v->addWidget(okst ,row,col+1); row++; BIter i; for (oplots.start(i);! oplots.isEnd(i);oplots.next(i)) { ographControls->addGraph(oplots[i]); oplots[i]->setGrid(16,0); oplots[i]->installEventFilter(this); } connect(orefreshButton,SIGNAL(clicked()),this,SLOT(refresh())); connect(osaveButton,SIGNAL(clicked()),this,SLOT(saveFile())); } PupeDiagnosticsWin::~PupeDiagnosticsWin() {} void PupeDiagnosticsWin::show() { QWidget::show(); } void PupeDiagnosticsWin::refresh() { BError err; int source; Tms::TestCaptureInfo captureInfo; Tms::PuChannel puPhysChannel; // Build request source = (int)osource->getValue(); if((source == 4) || (source == 5) || (source == 6)) source = 3; captureInfo.source = source;; captureInfo.clock = (int)oclock->getValue(); captureInfo.startTime = ostartTime->text().toUInt(); captureInfo.postTriggerDelay = opostTriggerDelay->text().toUInt(); captureInfo.triggerSourceData = otriggerSourceData->isChecked(); captureInfo.triggerAnd = otriggerAnd->isChecked(); captureInfo.triggerStore = otriggerStore->isChecked(); captureInfo.triggerMask = oClock->isChecked() << 0 | oCycleStart->isChecked() << 1 | oCycleStop->isChecked() << 2 | oCalStart->isChecked() << 3 | oCalStop->isChecked() << 4 | oInjection->isChecked() << 5 | oHChange->isChecked() << 6 | oFref->isChecked() << 7; if (err = ocontrol.getPuChannel (ochannel->value(),puPhysChannel)) { warningDialog("Reading Test Data",err); return; } if (err = ocontrol.getTestData(puPhysChannel,captureInfo,odata)) { warningDialog("Reading Test Data",err); return; } setPlotData(); } void PupeDiagnosticsWin::doFft(){ BArray<float> dataIn; BArray<float> dataOut; int n; fftw_complex* in; fftw_complex* out; fftw_plan p; int i; oplots[0]->getData(dataIn); n = dataIn.size(); in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * n); out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * n); p = fftw_plan_dft_1d(n, in, out, FFTW_FORWARD, FFTW_ESTIMATE); for(i = 0; i < n; i++){ in[i][0] = dataIn[i] / 8192.0; // in[i][0] = 1.0 * sin(100 * 3.14 * i / n) + 0.5 * sin(n / 4 * 2 * 3.14 * i / n); in[i][1] = 0; } fftw_execute(p); dataOut.resize(n); for(i = 0; i < n; i++){ out[i][0] /= (n / 2.0); out[i][1] /= (n / 2.0); dataOut[i] = 10 * log10(out[i][0] * out[i][0] + out[i][1] * out[i][1]); } dataOut[0] = dataOut[1]; setGraphHeights(2); oplots[1]->setData(dataOut); oplots[0]->setXLabel("Sample"); oplots[1]->setYLabel("Power dB"); oplots[1]->setXLabel("Frequency"); fftw_destroy_plan(p); fftw_free(in); fftw_free(out); } void PupeDiagnosticsWin::setPlotData() { BIter i; // Bit Pattern Source 0 int source = (int)osource->getValue(); switch (source) { case 0: if (! otriggerStore->isChecked()) updateGraphs(defSource0); else updateGraphs(defSource0trigger); break; case 1: updateGraphs(defSource1); break; case 2: updateGraphs(defSource2); break; case 3: updateGraphs(defSource3); break; case 4: updateGraphs(defSigma); doFft(); break; case 5: updateGraphs(defDeltaX); doFft(); break; case 6: updateGraphs(defDeltaY); doFft(); break; default: BError err; err.set(1,"Unsupported source type"); warningDialog("Viewing Pupe Diagnostics",err); break; } ographControls->setMax(odata.size()); } void PupeDiagnosticsWin::saveFile() { BError err; BString fname; BString msg; int source = (int)osource->getValue(); int n; fname.printf("pupeSource%d.txt",(int)osource->getValue()); QFileDialog saveDialog( ".", "Pupe Diagnostics Dump File (*.txt)", this, "save file dialog", "Choose a file" ); saveDialog.setMode(QFileDialog::QFileDialog::AnyFile); saveDialog.setSelection(fname.retStr()); switch (n = saveDialog.exec()) { case 0: return; //Cancel Button break; case 1: break; //Save Button default: printf("Unknown Button (%d)\n",n); } if ((fname = saveDialog.selectedFile().ascii()) == "") return; if (ofile.open(fname,"w+")) { warningDialog("PupeDiagnostics",BString("Cannot open save file (") + fname + ")"); return; } switch (source) { case 0: if (! otriggerStore->isChecked()) writeFile(defSource0); else writeFile(defSource0trigger); break; case 1: writeFile(defSource1); break; case 2: writeFile(defSource2); break; case 3: writeFile(defSource3); break; case 4: writeFile(defSigma); break; case 5: writeFile(defDeltaX); break; case 6: writeFile(defDeltaY); break; default: BError err; err.set(1,"Unsupported source type"); warningDialog("Viewing Pupe Diagnostics",err); break; } ofile.close(); msg = BString("File Saved (") + fname + ")"; gstatusbar->message(msg.retStr(),2000); } // Utility routines void PupeDiagnosticsWin::updateGraphs(PupeDiagBitDefinition sourceDefs[]) { PupeDiagBitDefinition def; int i = 0; while (sourceDefs[i].name) { def = sourceDefs[i]; oplots[i]->setData(extractBitLinear(def)); oplots[i]->setYLabel(def.name); i++; } setGraphHeights(i); setXAxisLabel(); } BArray<float> PupeDiagnosticsWin::extractBitLinear(PupeDiagBitDefinition def) { unsigned int n; float f; BArray<float> data; data.resize(odata.size()); for(n = 0; n < odata.size(); n++){ f = getBitValue(odata[n], def.startBit, def.nBits,def.isSigned); data[n] = def.gain * f; } return data; } void PupeDiagnosticsWin::writeFile(PupeDiagBitDefinition defs[]) { unsigned int n; float f; PupeDiagBitDefinition def; if (okst->isChecked()) { int i = 0; while (defs[i].name) ofile.printf("%s ",defs[i++].name); ofile.printf("\n"); } for(n = 0; n < odata.size(); n++){ int i = 0; while (defs[i].name) { def = defs[i]; f = getBitValue(odata[n], def.startBit, def.nBits,def.isSigned); f *= def.gain; ofile.printf("%f ",f); i++; } ofile.printf("\n"); } } void PupeDiagnosticsWin::setGraphHeights(int num) { BIter i; int height = (GRAPHS_TOTAL_HEIGHT - GRAPHS_X_LEDGEND_HEIGHT)/num; int n = 1; for (oplots.start(i);! oplots.isEnd(i);oplots.next(i)) { oplots[i]->show(); if (n < num) { oplots[i]->setMaximumHeight(height); oplots[i]->setMinimumHeight(height); } else if ( n == num) { oplots[i]->setMinimumHeight(height + GRAPHS_X_LEDGEND_HEIGHT); } else { oplots[i]->hide(); oplots[i]->setMinimumHeight(height); } n++; } } void PupeDiagnosticsWin::setXAxisLabel() { BIter i,o; for (oplots.start(i);! oplots.isEnd(i);oplots.next(i)) { oplots[i]->setXLabel(""); } for (oplots.start(i);! oplots.isEnd(i);oplots.next(i)) { if (oplots[i]->isHidden()) break; o = i; } oplots[o]->setXLabel("Sample"); } bool PupeDiagnosticsWin::eventFilter( QObject *o, QEvent *e ) { if ( e->type() == QEvent::Wheel ) { QWheelEvent* we = (QWheelEvent*)e; int delta = (we->delta() > 0) ? -1 : 1; ographControls->scroll(delta); return TRUE; } else { // standard event processing return FALSE; } } void PupeDiagnosticsWin::warningDialog(BString title, BError err){ BString m; QMessageBox b; m = BString("<h5>") + title + "</h5><p>" + err.getString() + "</p>"; b.setMinimumWidth(300); b.setCaption("tmsControlGui - Warning"); b.setIcon(QMessageBox::Warning); b.setText(m.retStr()); b.exec(); }