summaryrefslogtreecommitdiff
path: root/src/gui.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui.cxx')
-rw-r--r--src/gui.cxx755
1 files changed, 755 insertions, 0 deletions
diff --git a/src/gui.cxx b/src/gui.cxx
new file mode 100644
index 0000000..75f1f9c
--- /dev/null
+++ b/src/gui.cxx
@@ -0,0 +1,755 @@
+#include <iostream>
+#include <iomanip>
+#include "gui_class.h"
+#include <gsl/gsl_fit.h>
+#include <iostream>
+using namespace std;
+
+#define STRETCH /* nothing */
+
+extern int verbosity; // should be in a .h file somewhere
+
+/////////////////
+// some kludgey global variables,
+// mostly for inter-thread communication
+int pcmRate(0);
+double cpkp(0); // cycles per krunch period
+double fpkp(0); // frames per krunch period:
+double actOutFreq(0); // actual refout frequency
+double refOutAmp_dB(-15.); // default should not be not too loud
+double VoCal_dB(0.);
+double ViCal_dB(0.);
+double timeShift(0.); // in seconds
+double phaseShift(0.); // in degrees
+double lockerPhase(0.); // in degrees
+int repaintFrame(0);
+//
+// Note: more globals can be found in lockin.cxx
+
+class colorer {
+public:
+ Qt::GlobalColor code;
+ const char* name;
+
+ colorer(const Qt::GlobalColor _code, const char* const _name)
+ : code(_code), name(_name)
+ {}
+};
+
+#define X(foo) colorer(Qt::foo, #foo)
+
+static colorer color_list[] = {X(red), X(blue), X(black)};
+
+#undef X
+
+static int color_list_size = sizeof(color_list) / sizeof(color_list[0]);
+
+#if 0 /* code not needed at present */
+double now(){
+ timespec xx;
+
+#ifdef _POSIX_MONOTONIC_CLOCK
+ clock_gettime(CLOCK_MONOTONIC, &xx);
+#else
+ clock_gettime(CLOCK_MONOTONIC, &xx);
+#endif
+
+ return xx.tv_sec + xx.tv_nsec*1e-9;
+}
+#endif
+
+myWindow::myWindow() {
+// The top myWindow and its layout : horizontal:
+ // topWindow == this
+ topLayout = new QHBoxLayout;
+ setLayout(topLayout);
+
+ ctrlCol = new ctrl_column(this);
+ topLayout->addWidget(ctrlCol->group);
+
+ for (int ii = 0; ii < myWindow::numRsltPanels; ii++){
+ rsltPanel[ii] = new rslt_panel(this);
+ topLayout->addWidget(rsltPanel[ii]->group);
+ }
+
+// setting the indication to its current value won't
+// change the indicator, but will cause it to update
+// the associated plot
+ for (unsigned int ii = 0; ii < ndc8r.size(); ii++){
+ indicator* foo = ndc8r[ii];
+ foo->setIndication(0,0, foo->rpBox->value(), foo->ipBox->value());
+ }
+
+ frameTimer = new timer;
+}
+
+void myWindow::flush() {
+ if (!repaintFrame) return;
+ repaintFrame = 0;
+ for (int ii = 0; ii < numRsltPanels; ii++){
+ rsltPanel[ii]->plot->flush();
+ }
+}
+
+ctrl_column::ctrl_column(myWindow* topwin){
+ group = new QGroupBox;
+ group->setFlat(0);
+ layout = new QVBoxLayout;
+ group->setLayout(layout);
+
+ refOutGroup = new refOut_grouper(topwin);
+ layout->addWidget(refOutGroup->group);
+
+ layout->insertStretch(-1);
+
+ entrailsGroup = new entrails_grouper(topwin);
+ layout->addWidget(entrailsGroup->group);
+}
+
+
+// the refOut group and its layout: vertical:
+refOut_grouper::refOut_grouper(myWindow* _topwin)
+: topwin(_topwin),
+ VLabel(0)
+{
+// the freq box
+ group = new QGroupBox("Ref Out");
+ layout = new QVBoxLayout;
+ group->setLayout(layout);
+//group->setStyleSheet("background-color: lavenderblush;");
+//group->setStyleSheet("background-color: rgba(100, 0, 0, 150);");
+//group->setStyleSheet("background-color: lightcyan;");
+ group->setStyleSheet(".QGroupBox{background-color: #E8ffFF}");
+ freqLabel = new QLabel;
+ freqLabel->setText("Frequency");
+
+ freqBox = new QDoubleSpinBox;
+ freqBox->setRange(0.0, 10000.0);
+ freqBox->setSingleStep(1);
+ freqBox->setValue(440);
+ freqBox->setKeyboardTracking(0);
+ freqBox->setSuffix(" Hz");
+ connect(freqBox, SIGNAL(valueChanged(double)),
+ this, SLOT(freqChanged(double)));
+
+ actFreqLabel = new QLabel;
+ actFreqLabel->setText("Actual");
+
+ actFreqBox = new QDoubleSpinBox;
+ actFreqBox->setRange(0.0, 10000.0);
+ actFreqBox->setValue(440);
+ actFreqBox->setReadOnly(1);
+ actFreqBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ actFreqBox->setSuffix(" Hz");
+
+ dBLabel = new QLabel;
+ dBLabel->setText("Amplitude");
+
+ dBBox = new QDoubleSpinBox;
+ dBBox->setRange(-1000.0, 1000.0);
+ dBBox->setDecimals(3);
+ dBBox->setSingleStep(1);
+//later: dBBox->setValue(refOutAmp_dB);
+ dBBox->setKeyboardTracking(0);
+ dBBox->setSuffix(" dBV");
+ connect(dBBox, SIGNAL(valueChanged(double)),
+ this, SLOT(ampChanged(double)));
+
+// express amplitude in V, not just in dB:
+//?? VLabel = new QLabel;
+//?? VLabel->setText("???");
+
+ VBox = new QDoubleSpinBox;
+ VBox->setRange(-1e300, +1e300);
+ VBox->setReadOnly(1);
+ VBox->setDecimals(6);
+ VBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ VBox->setSuffix(" V");
+
+ dBBox->setValue(refOutAmp_dB); // will throw ampChanged signal
+
+ layout->addWidget(freqLabel STRETCH);
+ layout->addWidget(freqBox STRETCH);
+ layout->addWidget(actFreqLabel STRETCH);
+ layout->addWidget(actFreqBox STRETCH);
+ layout->addWidget(dBLabel STRETCH);
+ layout->addWidget(dBBox STRETCH);
+ if (VLabel) layout->addWidget(VLabel STRETCH);
+ layout->addWidget(VBox STRETCH);
+}
+
+// the entrails group and its layout: vertical:
+entrails_grouper::entrails_grouper(myWindow* _topwin)
+: topwin(_topwin),
+ tweakFreq(tweakSize),
+ tweakPhase(tweakSize),
+ tweakPtr(0),
+ howmany(0)
+{
+ group = new QGroupBox("Entrails");
+ layout = new QVBoxLayout;
+ group->setLayout(layout);
+ group->setStyleSheet("QGroupBox{background-color: #ffffe0}");
+
+ VoCalLabel = new QLabel;
+ VoCalLabel->setText("Vo Calibration");
+
+ VoCalBox = new QDoubleSpinBox;
+ VoCalBox->setRange(-1e300, +1e300);
+ VoCalBox->setSingleStep(1);
+ VoCalBox->setKeyboardTracking(0);
+ VoCalBox->setSuffix(" dBV FS");
+ connect(VoCalBox, SIGNAL(valueChanged(double)),
+ this, SLOT(VoChanged(double)));
+ VoCalBox->setValue(VoCal_dB);
+
+ ViCalLabel = new QLabel;
+ ViCalLabel->setText("Vi Calibration");
+
+ ViCalBox = new QDoubleSpinBox;
+ ViCalBox->setRange(-1e300, +1e300);
+ ViCalBox->setSingleStep(1);
+ ViCalBox->setKeyboardTracking(0);
+ ViCalBox->setSuffix(" dBV FS");
+ connect(ViCalBox, SIGNAL(valueChanged(double)),
+ this, SLOT(ViChanged(double)));
+ ViCalBox->setValue(ViCal_dB);
+
+ rateLabel = new QLabel;
+ rateLabel->setText("Krunch Rate");
+
+ rateBox = new QDoubleSpinBox;
+ rateBox->setRange(0.0, 1e300);
+ rateBox->setSingleStep(1);
+ rateBox->setValue(6.);
+ rateBox->setKeyboardTracking(0);
+ rateBox->setSuffix(" Hz");
+ connect(rateBox, SIGNAL(valueChanged(double)),
+ this, SLOT(rateChanged(double)));
+
+ actRateLabel = new QLabel;
+ actRateLabel->setText("Actual");
+
+ actRateBox = new QDoubleSpinBox;
+ actRateBox->setRange(0.0, 1e300);
+ actRateBox->setValue(6.);
+ actRateBox->setReadOnly(1);
+ actRateBox->setSuffix(" Hz");
+ actRateBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+
+ pcmLabel = new QLabel;
+ pcmLabel->setText("PCM Rate");
+
+ pcmBox = new QDoubleSpinBox;
+ pcmBox->setRange(-1e300, +1e300);
+ pcmBox->setValue(440);
+ pcmBox->setReadOnly(1);
+ pcmBox->setSuffix(" Hz");
+ pcmBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+
+ timeShiftLabel = new QLabel;
+ timeShiftLabel->setText("Time Shift");
+
+ timeShiftBox = new QDoubleSpinBox;
+ timeShiftBox->setRange(-1000.0, 1000.0);
+ timeShiftBox->setDecimals(6);
+ timeShiftBox->setSingleStep(1e-6);
+ timeShiftBox->setValue(timeShift);
+ timeShiftBox->setKeyboardTracking(0);
+ timeShiftBox->setSuffix(" s");
+ connect(timeShiftBox, SIGNAL(valueChanged(double)),
+ this, SLOT(timeShiftChanged(double)));
+
+ phaseShiftLabel = new QLabel;
+ phaseShiftLabel->setText("Phase Shift");
+
+ phaseShiftBox = new QDoubleSpinBox;
+ phaseShiftBox->setRange(-1e300, +1e300);
+ phaseShiftBox->setDecimals(2);
+ phaseShiftBox->setSingleStep(1);
+ phaseShiftBox->setValue(phaseShift);
+ phaseShiftBox->setKeyboardTracking(0);
+ phaseShiftBox->setSuffix(QString::fromUtf8(" °"));
+ connect(phaseShiftBox, SIGNAL(valueChanged(double)),
+ this, SLOT(phaseShiftChanged(double)));
+
+ tweakButton = new QPushButton("&Tweak");
+ connect(tweakButton, SIGNAL(clicked()),
+ this, SLOT(tweakButtonClicked()));
+
+ layout->addWidget(VoCalLabel STRETCH);
+ layout->addWidget(VoCalBox STRETCH);
+
+ layout->addWidget(ViCalLabel STRETCH);
+ layout->addWidget(ViCalBox STRETCH);
+
+ layout->addWidget(rateLabel STRETCH);
+ layout->addWidget(rateBox STRETCH);
+ layout->addWidget(actRateLabel STRETCH);
+ layout->addWidget(actRateBox STRETCH);
+ layout->addWidget(pcmLabel STRETCH);
+ layout->addWidget(pcmBox STRETCH);
+ layout->addWidget(timeShiftLabel STRETCH);
+ layout->addWidget(timeShiftBox STRETCH);
+ layout->addWidget(phaseShiftLabel STRETCH);
+ layout->addWidget(phaseShiftBox STRETCH);
+ layout->addWidget(tweakButton STRETCH);
+}
+
+rslt_panel::rslt_panel(myWindow* _topWin)
+: topWin(_topWin)
+{
+ group = new QGroupBox;
+ group->setFlat(0);
+ layout = new QHBoxLayout;
+ group->setLayout(layout);
+ plot = new myPlot("plotname");
+ block = new blockOfIndicators(topWin, plot);
+// layout->addWidget(plot, 0, Qt::AlignHCenter);
+ layout->addWidget(plot);
+ layout->addWidget(block->group);
+ layout->insertStretch(-1);
+}
+
+double quantize125(double arg){
+ if (arg < sqrt(2.)) return 1.;
+ if (arg < sqrt(10.)) return 2.;
+ if (arg < sqrt(50.)) return 5.;
+ return 10.;
+}
+
+double logstep(double arg){
+ double ctc = pow(10., floor(log10(arg)));
+ double mant = arg / ctc;
+ return quantize125(mant) * ctc;
+}
+
+scaleBoxer::scaleBoxer(indicator* _parent)
+: parent(_parent)
+{}
+
+void scaleBoxer::stepBy(int steps){
+ double newval(1);
+ if (steps == 1) newval = logstep(2.0 * logstep(value()));
+ if (steps == -1) newval = logstep(0.5 * logstep(value()));
+
+ if (steps == 10) newval = logstep(10.0 * value());
+ if (steps == -10) newval = logstep( 0.1 * value());
+ parent->setDecim(newval);
+ setValue(newval);
+}
+
+void indicator::setDecim(const double newval){
+ int decim = -int(floor(log10(newval)));
+ scaleBox->setDecimals(std::max(0, decim));
+ rpBox->setDecimals(std::max(0, 2+decim));
+ ipBox->setDecimals(std::max(0, 2+decim));
+ magBox->setDecimals(std::max(0, 2+decim));
+}
+
+
+// An indicator and its internal layout: grid:
+indicator::indicator(myPlot* _plot, int _locker)
+: plot(_plot),
+ plotcur(0),
+ locker(_locker)
+{
+ if (plot) {
+ plotcur = plot->assign_curve();
+ }
+
+ group = new QGroupBox;
+ group->setFlat(0);
+ QString style = ".QGroupBox{";
+ if (plot) {
+ style += "border-top: 4px solid ";
+ style += color_list[plotcur % color_list_size].name;
+ style += ";";
+ }
+ style += "background-color: #D0ffD0;";
+ style += "}";
+ group->setStyleSheet(style);
+
+ layout = new QGridLayout;
+ group->setLayout(layout);
+
+ scaleLabel = new QLabel;
+ scaleLabel->setText("Scale");
+
+ scaleBox = new scaleBoxer(this);
+ scaleBox->setKeyboardTracking(0);
+ scaleBox->setRange(-1e300, +1e300);
+ double sc(pow(10., ViCal_dB/20.));
+ sc /= 2.5; // half scale, where full scale is 5 divisions
+ sc = logstep(sc);
+ scaleBox->setDecimals(10);
+ scaleBox->setValue(sc);
+ scaleBox->setSuffix(" V/div");
+
+ rpLabel = new QLabel;
+ rpLabel->setText("Rp");
+
+ rpBox = new QDoubleSpinBox;
+ rpBox->setReadOnly(1);
+ rpBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ rpBox->setRange(-1e300, +1e300);
+ rpBox->setValue(0);
+ rpBox->setSuffix(" V");
+
+ ipLabel = new QLabel;
+ ipLabel->setText("Ip");
+
+ ipBox = new QDoubleSpinBox;
+ ipBox->setReadOnly(1);
+ ipBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ ipBox->setRange(-1e300, +1e300);
+ ipBox->setValue(0);
+ ipBox->setSuffix(" V");
+
+ magLabel = new QLabel;
+ magLabel->setText("Mag");
+
+ magBox = new QDoubleSpinBox;
+ magBox->setReadOnly(1);
+ magBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ magBox->setRange(-1e300, +1e300);
+ magBox->setValue(0.1234);
+ magBox->setSuffix(" V");
+
+ phaseLabel = new QLabel;
+ phaseLabel->setText("Phase");
+
+ phaseBox = new QDoubleSpinBox;
+ phaseBox->setReadOnly(1);
+ phaseBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
+ phaseBox->setRange(-1e300, +1e300);
+ phaseBox->setSuffix(QString::fromUtf8(" °"));
+
+ setDecim(sc);
+
+ int row(0);
+ layout->addWidget(scaleLabel, row, 0);
+ row++;
+ layout->addWidget(scaleBox, row, 0);
+ row++;
+ layout->addWidget(rpLabel, row, 0);
+ layout->addWidget(ipLabel, row, 1);
+ row++;
+ layout->addWidget(rpLabel, row, 0);
+ layout->addWidget(ipLabel, row, 1);
+ row++;
+ layout->addWidget(rpBox, row, 0);
+ layout->addWidget(ipBox, row, 1);
+ row++;
+ layout->addWidget(magLabel, row, 0);
+ layout->addWidget(phaseLabel, row, 1);
+ row++;
+ layout->addWidget(magBox, row, 0);
+ layout->addWidget(phaseBox, row, 1);
+}
+
+blockOfIndicators::blockOfIndicators(myWindow* topwin, myPlot* plot)
+{
+ group = new QGroupBox;
+ group->setFlat(0);
+ group->setStyleSheet("border:0;");
+ layout = new QVBoxLayout;
+ indicator* temp;
+ group->setLayout(layout);
+
+ temp = new indicator(plot, 1/* phaselock */);
+ topwin->ndc8r.push_back(temp);
+ layout->addWidget(temp->group);
+
+ temp = new indicator(plot);
+ topwin->ndc8r.push_back(temp);
+ layout->addWidget(temp->group);
+
+ temp = new indicator(plot);
+ topwin->ndc8r.push_back(temp);
+ layout->addWidget(temp->group);
+
+ layout->insertStretch(-1);
+}
+
+void indicator::setIndication(const double rp0, const double ip0,
+ const double rp1, const double ip1){
+ double rp(rp1-rp0);
+ double ip(ip1-ip0);
+ double mag(sqrt(rp*rp + ip*ip));
+ double phase(0);
+ if (mag) phase = atan2(ip, rp);
+ rpBox->setValue(rp);
+ ipBox->setValue(ip);
+ magBox->setValue(mag);
+ double phDeg = phase * 180 / M_PI;
+ phaseBox->setValue(phDeg);
+ if (locker) lockerPhase = phDeg;
+ if (plot) {
+ double denom = scaleBox->value(); // volts per division
+ denom *= plot->divsPerUnit; // volts full scale
+ plot->setReading(plotcur, rp0/denom, ip0/denom, rp1/denom, ip1/denom);
+ }
+}
+
+void myPlot::flush() {
+ if (need_replot) replot();
+}
+
+void myPlot::setReading(const int ndx,
+ const double rp0, const double ip0,
+ const double rp1, const double ip1){
+ int npts(2);
+ double xxx[npts];
+ double yyy[npts];
+ xxx[0] = rp0;
+ yyy[0] = ip0;
+ xxx[1] = rp1;
+ yyy[1] = ip1;
+////////////////// curve[ndx]->setData(xxx, yyy, npts);
+ curve[ndx]->setSamples(xxx, yyy, npts);
+ need_replot = 1;
+}
+
+// There is no such thing as a scale change on the plot.
+// Rescale the data instead.
+#ifdef OLD_SCALE_IDEA
+void myPlot::scaleChange(double newScale){
+ setAxisScale(QwtPlot::xBottom, -newScale, newScale);
+ setAxisScale(QwtPlot::yLeft, -newScale, newScale);
+ replot();
+}
+#endif
+
+// Unless you set keyboardTracking to false,
+// this is useless when typing in digits :
+// signals too early and too often.
+void refOut_grouper::freqChanged(double /* newfreq not used */)
+{
+ topwin->actualFreqs();
+}
+
+void entrails_grouper::VoChanged(double newVo)
+{
+ VoCal_dB = newVo;
+//wrong topwin->ctrlCol->refOutGroup->VBox->
+//wrong setValue(pow(10., (refOutAmp_dB + VoCal_dB)/20.));
+}
+
+void entrails_grouper::ViChanged(double newVi)
+{
+ ViCal_dB = newVi;
+}
+
+void refOut_grouper::ampChanged(double newAmp)
+{
+ refOutAmp_dB = newAmp;
+//wrong: VBox->setValue(pow(10., (refOutAmp_dB + VoCal_dB)/20.));
+ VBox->setValue(pow(10., (refOutAmp_dB)/20.));
+}
+
+void entrails_grouper::rateChanged(double /* newRate not used */)
+{
+ topwin->actualFreqs();
+}
+
+// beware the fmod of a negative number is negative
+double pval(const double angle){
+ double rslt = fmod(angle, 360.);
+ if (rslt > 180.) rslt -= 360.;
+ if (rslt < -180.) rslt += 360.;
+ return rslt;
+}
+
+void entrails_grouper::timeShiftChanged(double newTimeShift)
+{
+//-- std::cout << "timeShiftChange: " << newTimeShift << std::endl;
+
+// Calculate new phase such that changing the timeShift
+// doesn't change the phase; it is only supposed to
+// change d(phase)/d(frequency).
+ double newPhase = phaseShift - (newTimeShift - timeShift) * actOutFreq * 360.;
+ newPhase = pval(newPhase);
+ timeShift = newTimeShift;
+ phaseShiftBox->setValue(newPhase);
+}
+
+void entrails_grouper::phaseShiftChanged(double newPhaseShift)
+{
+//-- std::cout << "phaseShiftChange: " << newPhaseShift << std::endl;
+
+ while (newPhaseShift > 360.) newPhaseShift -= 360.;
+ while (newPhaseShift < -360.) newPhaseShift += 360.;
+
+ phaseShift = newPhaseShift;
+}
+
+class bad_thing: public std::exception{
+ const char* msg;
+ virtual const char* what() const throw() {
+ return msg;
+ }
+public:
+ bad_thing(const char* _msg)
+ : msg(_msg) {}
+};
+
+double max(const std::valarray<double>& foo){
+ unsigned int howmany(foo.size());
+ if (howmany == 0) throw bad_thing("max of empty list");
+ double rslt = foo[0];
+ for (unsigned int ii = 1; ii < howmany; ii++) {
+ rslt = std::max(rslt, foo[ii]);
+ }
+ return rslt;
+}
+
+double min(const std::valarray<double>& foo){
+ unsigned int howmany(foo.size());
+ if (howmany == 0) throw bad_thing("min of empty list");
+ double rslt = foo[0];
+ for (unsigned int ii = 1; ii < howmany; ii++) {
+ rslt = std::min(rslt, foo[ii]);
+ }
+ return rslt;
+}
+
+void entrails_grouper::tweakButtonClicked(){
+ using namespace std;
+ double rawPhase = (lockerPhase + phaseShift)
+ + actOutFreq*timeShift * 360.;
+
+ if (tweakPtr >= 10) tweakPtr = 0;
+ tweakFreq[tweakPtr] = actOutFreq;
+ tweakPhase[tweakPtr] = rawPhase;
+ tweakPtr++;
+ if (howmany < tweakPtr) howmany = tweakPtr;
+ // otherwise howmany stays at its maximum, i.e. tweakSize.
+
+ valarray<double> myFreq(&tweakFreq[0], howmany);
+ valarray<double> myPhase(&tweakPhase[0], howmany);
+
+ double big = max(myFreq);
+ double little = min(myFreq);
+ if (big == little) {
+ double newPhase = myPhase.sum() / howmany - timeShift*myFreq[0]*360.;
+// This will change the value in the box, and raise
+// the valueChanged signal:
+ phaseShiftBox->setValue(pval(newPhase));
+ } else do {
+ valarray<double> cookedPhase(myPhase);
+ valarray<double> cookedFreq(myFreq);
+ for (unsigned int ii = 0; ii < howmany; ii++) {
+ cookedFreq[ii] -= actOutFreq;
+ cookedPhase[ii] -= phaseShift + timeShift*myFreq[ii]*360.;
+ cookedPhase[ii] = pval(cookedPhase[ii]);
+ }
+ if (max(cookedPhase) > 90. || min(cookedPhase) < -90.) {
+ cout << "Phase range too big; can't tweak." << endl;
+ break;
+ }
+ double intercept, slope;
+ double cv00, cv01, cv11;
+ double sumsq;
+ gsl_fit_linear(&cookedFreq[0], 1,
+ &cookedPhase[0], 1, howmany,
+ &intercept, &slope,
+ &cv00, &cv01, &cv11,
+ &sumsq);
+
+ double newTime = timeShift + slope / 360.;
+ double newPhase = phaseShift + intercept
+ - (newTime - timeShift) * actOutFreq * 360.;
+// must do time shift first:
+ timeShiftBox->setValue(newTime);
+ phaseShiftBox->setValue(pval(newPhase));
+
+ } while (0);
+}
+
+void myWindow::actualFreqs() {
+ using namespace std;
+ double d_out_freq = ctrlCol->refOutGroup->freqBox->value();
+ { // calculatte cycles per krunch period
+ double d_krunch_rate = ctrlCol->entrailsGroup->rateBox->value();
+ if (d_krunch_rate == 0.) cpkp = 1;
+ else cpkp = round(d_out_freq/d_krunch_rate);
+ if (cpkp < 1.) cpkp = 1.;
+ }
+// frames per krunch period:
+ fpkp = round(cpkp * pcmRate / d_out_freq);
+ double actUp = pcmRate / fpkp;
+ ctrlCol->entrailsGroup->actRateBox->setValue(actUp);
+ ctrlCol->entrailsGroup->pcmBox->setValue(pcmRate);
+
+ actOutFreq = cpkp * actUp;
+ ctrlCol->refOutGroup->actFreqBox->setValue(actOutFreq);
+ if (verbosity > 0) {
+ cout.precision(4);
+ cout << fixed;
+ cout << " d_out_freq: " << d_out_freq
+ << " cpkp: " << cpkp
+ << " fpkp: " << fpkp
+ << " actUp: " << setw(10) << actUp
+ << " actOutFreq: " << actOutFreq
+ << endl;
+ }
+}
+
+myPlot::myPlot(const QString name) : QwtPlot(QwtText(name)),
+ grid(), divsPerUnit(5), need_replot(0)
+ {
+// FIXME : should calculate these sizes:
+ setMinimumWidth(500); setMaximumWidth(500);
+ setMinimumHeight(500); setMaximumHeight(500);
+
+// Set up axis, permanently -1 to 1 in both directions.
+// We are ASSUMING the library function will give us
+// five minor divisions per unit (ten total).
+ setAxisScale(QwtPlot::xBottom,-1.0, 1.0, 1.);
+ setAxisScale(QwtPlot::yLeft, -1.0, 1.0, 1.);
+ enableAxis(QwtPlot::xBottom, 0);
+ enableAxis(QwtPlot::yLeft, 0);
+ setStyleSheet("border:0;");
+
+ grid.enableXMin(true);
+ grid.enableYMin(true);
+ grid.setMajorPen(QPen(Qt::white, 2));
+ grid.setMinorPen(QPen(Qt::white, 1));
+// was: (QPen(Qt::white, 1, Qt::DotLine));
+ grid.attach(this);
+}
+
+int myPlot::assign_curve(){
+ int ndx = curve.size();
+
+ curve.push_back(new QwtPlotCurve);
+
+ int npts(2);
+ double xxx[npts];
+ double yyy[npts];
+ xxx[0] = 0;
+ yyy[0] = 0;
+ xxx[1] = sin(.1 * ndx);
+ yyy[1] = cos(.2 * ndx);
+
+///////////// curve[ndx]->setData(xxx, yyy, npts);
+ curve[ndx]->setSamples(xxx, yyy, npts);
+ curve[ndx]->setPen(QPen(color_list[ndx % color_list_size].code, 4));
+ curve[ndx]->attach(this);
+
+ return ndx;
+}
+
+////////////////////////////////////
+
+timer::timer(QWidget *parent)
+: QWidget(parent)
+{
+ startTimer(33); // 30.303 repaints per second
+}
+
+void timer::timerEvent(QTimerEvent* /* event not used */){
+ using namespace std;
+ repaintFrame = 1;
+}