diff --git a/.gitignore b/.gitignore index c3f5a49a..b2bd967f 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,7 @@ Desktop_Interface/bin/Labrador *.so *.so.* *.qmake.stash -pinout.png +/pinout.png Matlab_Octave_API/___librador/build-librador-Desktop_Qt_5_10_0_GCC_64bit-Release Matlab_Octave_API/___librador/build-librador-Desktop_Qt_5_10_0_GCC_64bit-Debug diff --git a/Desktop_Interface/DisplayControl.cpp b/Desktop_Interface/DisplayControl.cpp new file mode 100644 index 00000000..681c513e --- /dev/null +++ b/Desktop_Interface/DisplayControl.cpp @@ -0,0 +1,108 @@ +#include "DisplayControl.h" + +#include +#include + +void DisplayControl::setVoltageRange (const QPointF &position, const QPoint zoomDelta, const Qt::KeyboardModifiers modifiers, bool isProperlyPaused, double maxWindowSize, QCustomPlot* axes) +{ + const bool isVertical = qAbs(zoomDelta.y()) > qAbs(zoomDelta.x()); + const bool isHorizontal = qAbs(zoomDelta.x()) > qAbs(zoomDelta.y()); + if (!(modifiers == Qt::ControlModifier) && isVertical) { + zoomVertically(zoomDelta.y(), position.y(), axes); + } else if (isHorizontal) { + zoomHorizontally(zoomDelta.x(), position.x(), isProperlyPaused, maxWindowSize, axes); + } +} + +void DisplayControl::zoomVertically(const double delta, const double y, QCustomPlot *axes) +{ + if (qFuzzyIsNull(delta)) { + return; + } + + double c; + if (qFuzzyIsNull(topRange) || qFuzzyIsNull(botRange) || qFuzzyCompare(topRange, botRange)) { + c = 1. / 400.; + } else { + c = (topRange - botRange) / 400.; + } + + QCPRange range = axes->yAxis->range(); + + double pixPct = (double)100 - ((double)100 * (((double)axes->yAxis->pixelToCoord(y)-range.lower) / range.size())); + if (pixPct < 0) pixPct = 0; + if (pixPct > 100) pixPct = 100; + + qDebug() << "WHEEL @ " << pixPct << "%"; + qDebug() << range.upper; + + topRange -= delta / 120.0 * c * pixPct; + botRange += delta / 120.0 * c * (100.0 - pixPct); + + topRange = qMin(topRange, 20.); + botRange = qMin(botRange, 20.); + + // Never allow 0 delta between top and bottom + if (qFuzzyCompare(topRange, botRange)) { + topRange += 0.01; + botRange -= 0.01; + } + + emit topRangeUpdated(topRange); + emit botRangeUpdated(botRange); +} + +void DisplayControl::zoomHorizontally(const double delta, const double x, bool isProperlyPaused, double maxWindowSize, QCustomPlot *axes) +{ + if (qFuzzyIsNull(delta)) { + return; + } + + double c; + if (qFuzzyIsNull(window)) { + c = 1. / 200.; + } else { + c = window / 200.; + } + + QCPRange range = axes->xAxis->range(); + + double pixPct = 100. * (double(axes->xAxis->pixelToCoord(x)) - range.lower); + + if (qFuzzyIsNull(window) || qFuzzyCompare(range.upper, range.lower)) { + pixPct = 1; + } else { + pixPct /= isProperlyPaused ? double(range.upper - range.lower) + : double(window); + } + + pixPct = qBound(0., pixPct, 100.); + + qDebug() << "WHEEL @ " << pixPct << "%"; + qDebug() << delta; + + if (! isProperlyPaused) + { + qDebug() << "TIGGERED"; + qDebug() << "upper = " << range.upper << "lower = " << range.lower; + qDebug() << "window = " << window; + qDebug() << c * ((double)pixPct); + qDebug() << c * ((double)100 - (double)pixPct) * pixPct / 100; + } + + window -= delta / 120.0 * c * pixPct; + + delay += delta / 120.0 * c * (100.0 - pixPct) * pixPct / 100.0; + delay = qBound(0., delay, maxWindowSize - window); + + if (window <= 0.) { + window = 0.01; + } else if (window > maxWindowSize) { + window = maxWindowSize; + } + + qDebug() << window << delay; + + emit delayUpdated(delay); + emit timeWindowUpdated(window); +} diff --git a/Desktop_Interface/DisplayControl.h b/Desktop_Interface/DisplayControl.h new file mode 100644 index 00000000..7c3fce23 --- /dev/null +++ b/Desktop_Interface/DisplayControl.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "desktop_settings.h" + +class QCustomPlot; + +class DisplayControl : public QObject +{ + Q_OBJECT +public: + + double delay = 0; + double window = MAX_WINDOW_SIZE; + double y0 = 0; + double y1 = 0; + double x0 = 0; + double x1 = 0; + double topRange = DEFAULT_TOP_RANGE; + double botRange = DEFAULT_BOTTOM_RANGE; + + void setVoltageRange (const QPointF &position, const QPoint zoomDelta, const Qt::KeyboardModifiers modifiers, bool isProperlyPaused, double maxWindowSize, QCustomPlot* axes); + + void zoomVertically(const double delta, const double y, QCustomPlot *axes); + void zoomHorizontally(const double delta, const double x, bool isProperlyPaused, double maxWindowSize, QCustomPlot* axes); + +signals: + void topRangeUpdated(double); + void botRangeUpdated(double); + void timeWindowUpdated(double); + void delayUpdated(double); +}; diff --git a/Desktop_Interface/Labrador.pro b/Desktop_Interface/Labrador.pro index 20d61baf..ff406d05 100644 --- a/Desktop_Interface/Labrador.pro +++ b/Desktop_Interface/Labrador.pro @@ -11,18 +11,29 @@ QT += core gui -CONFIG += c++14 +CONFIG += c++17 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport TARGET = Labrador TEMPLATE = app -QCP_VER = 1 + +!contains(CONFIG, "USE_SYSTEM_LIBS") { + message("Using bundled version of qcustomplot") + QCP_VER = 1 +} else { + message("Using system version of qcustomplot") + DEFINES += QCUSTOMPLOT_USE_OPENGL + QCP_VER = 2 + LIBS += -lqcustomplot +} + + DEFINES += "QCP_VER=$${QCP_VER}" equals(QCP_VER,"2"){ DEFINES += QCUSTOMPLOT_USE_OPENGL - LIBS += -lOpenGL32 + win32: LIBS += -lOpenGL32 message("Using QCP2 with OpenGL support") } @@ -31,11 +42,13 @@ include(ui_elements.pri) MOC_DIR = $$PWD/moc SOURCES += main.cpp\ + DisplayControl.cpp \ mainwindow.cpp \ functiongencontrol.cpp \ isodriver.cpp \ isobuffer.cpp \ desktop_settings.cpp \ + pinoutDialog.cpp \ scoperangeenterdialog.cpp \ genericusbdriver.cpp \ isobufferbuffer.cpp \ @@ -46,7 +59,9 @@ SOURCES += main.cpp\ i2cdecoder.cpp HEADERS += mainwindow.h \ + DisplayControl.h \ functiongencontrol.h \ + pinoutDialog.h \ xmega.h \ isodriver.h \ isobuffer.h \ @@ -120,54 +135,58 @@ win32{ unix:!android:!macx{ INCLUDEPATH += $$PWD/build_linux + LIBS += -lusb-1.0 ##make sure you have the libusb-1.0-0-dev package! + LIBS += -ldfuprog-0.9 + + QMAKE_CXXFLAGS+=-O2 + contains(QT_ARCH, arm) { message("Building for Raspberry Pi") - #libusb include - unix:!android:!macx:LIBS += -lusb-1.0 ##make sure you have the libusb-1.0-0-dev package! - unix:!android:!macx:INCLUDEPATH += build_linux/libusb - unix:!android:!macx:DEPENDPATH += build_linux/libusb - - #libdfuprog include - unix:!android:!macx:LIBS += -L$$PWD/build_linux/libdfuprog/lib/arm -ldfuprog-0.9 - unix:!android:!macx:INCLUDEPATH += $$PWD/build_linux/libdfuprog/include - unix:!android:!macx:DEPENDPATH += $$PWD/build_linux/libdfuprog/include + + #All ARM-Linux GCC treats char as unsigned by default??? QMAKE_CFLAGS += -fsigned-char QMAKE_CXXFLAGS += -fsigned-char DEFINES += "PLATFORM_RASPBERRY_PI" - #All ARM-Linux GCC treats char as unsigned by default??? - lib_deploy.files = $$PWD/build_linux/libdfuprog/lib/arm/libdfuprog-0.9.so - lib_deploy.path = /usr/lib + + !contains(CONFIG, "USE_SYSTEM_LIBS") { + LIBS += -L$$PWD/build_linux/libdfuprog/lib/arm + lib_deploy.files = $$PWD/build_linux/libdfuprog/lib/arm/libdfuprog-0.9.so + } } else { contains(QT_ARCH, i386) { message("Building for Linux (x86)") - unix:!android:!macx:LIBS += -lusb-1.0 ##make sure you have the libusb-1.0-0-dev package! - unix:!android:!macx:INCLUDEPATH += build_linux/libusb - unix:!android:!macx:DEPENDPATH += build_linux/libusb - - #libdfuprog include - unix:!android:!macx:LIBS += -L$$PWD/build_linux/libdfuprog/lib/x86 -ldfuprog-0.9 - unix:!android:!macx:INCLUDEPATH += $$PWD/build_linux/libdfuprog/include - unix:!android:!macx:DEPENDPATH += $$PWD/build_linux/libdfuprog/include - lib_deploy.files = $$PWD/build_linux/libdfuprog/lib/x86/libdfuprog-0.9.so - lib_deploy.path = /usr/lib + !contains(CONFIG, "USE_SYSTEM_LIBS") { + LIBS += -L$$PWD/build_linux/libdfuprog/lib/x86 + lib_deploy.files = $$PWD/build_linux/libdfuprog/lib/x86/libdfuprog-0.9.so + } } else { message("Building for Linux (x64)") - #libusb include - unix:!android:!macx:LIBS += -Lbuild_linux/libusb -lusb-1.0 ##I suspect the -L here does nothing! - unix:!android:!macx:INCLUDEPATH += build_linux/libusb - unix:!android:!macx:DEPENDPATH += build_linux/libusb - - #libdfuprog include - unix:!android:!macx:LIBS += -L$$PWD/build_linux/libdfuprog/lib/x64 -ldfuprog-0.9 - unix:!android:!macx:INCLUDEPATH += $$PWD/build_linux/libdfuprog/include - unix:!android:!macx:DEPENDPATH += $$PWD/build_linux/libdfuprog/include - lib_deploy.files = $$PWD/build_linux/libdfuprog/lib/x64/libdfuprog-0.9.so - lib_deploy.path = /usr/lib + !contains(CONFIG, "USE_SYSTEM_LIBS") { + LIBS += -Lbuild_linux/libusb ##I suspect the -L here does nothing! + #libdfuprog include + LIBS += -L$$PWD/build_linux/libdfuprog/lib/x64 + lib_deploy.files = $$PWD/build_linux/libdfuprog/lib/x64/libdfuprog-0.9.so + } } } - + + contains(CONFIG, "USE_SYSTEM_LIBS") { + message("Using system version of libusb") + INCLUDEPATH += $$[QT_INSTALL_PREFIX]/include/libusb-1.0 + } else { + INCLUDEPATH += build_linux/libusb + DEPENDPATH += build_linux/libusb + + #libdfuprog include + INCLUDEPATH += $$PWD/build_linux/libdfuprog/include + DEPENDPATH += $$PWD/build_linux/libdfuprog/include + + lib_deploy.path = /usr/lib + INSTALLS += lib_deploy + } + other.files += bin/firmware other.files += bin/waveforms other.path = /usr/bin/EspoTek-Labrador @@ -205,7 +224,6 @@ unix:!android:!macx{ } INSTALLS += target - INSTALLS += lib_deploy INSTALLS += other INSTALLS += udev INSTALLS += icon48 @@ -250,29 +268,6 @@ QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.10 unix:SOURCES += unixusbdriver.cpp unix:HEADERS += unixusbdriver.h -############################################################# -######## SHARED ANDROID/LINUX GCC FLAGS ######### -########################################################### - -unix:!macx: QMAKE_CXXFLAGS_RELEASE -= -O0 -unix:!macx: QMAKE_CXXFLAGS_RELEASE -= -O1 -unix:!macx: QMAKE_CXXFLAGS_RELEASE -= -O2 -unix:!macx: QMAKE_CXXFLAGS_RELEASE -= -O3 - -android: QMAKE_CXXFLAGS_RELEASE -= -O0 -android: QMAKE_CXXFLAGS_RELEASE -= -O1 -android: QMAKE_CXXFLAGS_RELEASE -= -O2 -android: QMAKE_CXXFLAGS_RELEASE -= -O3 -android: QMAKE_CXXFLAGS_RELEASE -= -Os - - -android: QMAKE_CFLAGS_RELEASE -= -O0 -android: QMAKE_CFLAGS_RELEASE -= -O1 -android: QMAKE_CFLAGS_RELEASE -= -O2 -android: QMAKE_CFLAGS_RELEASE -= -O3 -android: QMAKE_CFLAGS_RELEASE -= -Os - - ############################################################# ################# ANDROID BUILD ONLY ################# ########################################################### diff --git a/Desktop_Interface/daqform.cpp b/Desktop_Interface/daqform.cpp index afaa083d..ae847d1c 100644 --- a/Desktop_Interface/daqform.cpp +++ b/Desktop_Interface/daqform.cpp @@ -20,23 +20,23 @@ daqForm::daqForm(QWidget *parent, int initialAverage, qulonglong initialMaxFileS ui->limitFileSizeGroupBox->setChecked(false); } else { ui->limitFileSizeGroupBox->setChecked(true); - ui->fileSizeSpinBox->setValue(initialMaxFileSize/1000000); + ui->fileSizeSpinBox->setValue(initialMaxFileSize/1000000ull); } updateLabels(); //Internal Signal Connect //Changed values - connect(ui->fileSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateValues())); - connect(ui->numberOfPointsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateValues())); - connect(ui->limitFileSizeGroupBox, SIGNAL(toggled(bool)), this, SLOT(updateValues())); - connect(ui->sampleAveragingGroup, SIGNAL(toggled(bool)), this, SLOT(updateValues())); + connect(ui->fileSizeSpinBox, &QSpinBox::textChanged, this, &daqForm::updateValues); + connect(ui->numberOfPointsSpinBox, &QSpinBox::textChanged, this, &daqForm::updateValues); + connect(ui->limitFileSizeGroupBox, &QGroupBox::toggled, this, &daqForm::updateValues); + connect(ui->sampleAveragingGroup, &QGroupBox::toggled, this, &daqForm::updateValues); //Label - connect(ui->numberOfPointsSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateLabels())); - connect(ui->fileSizeSpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateLabels())); + connect(ui->numberOfPointsSpinBox, &QSpinBox::textChanged, this, &daqForm::updateLabels); + connect(ui->fileSizeSpinBox, &QSpinBox::textChanged, this, &daqForm::updateLabels); //Save Button - connect(ui->saveAsDefaultsButton, SIGNAL(clicked(bool)), this, SLOT(trigger_saveButtonPressed())); + connect(ui->saveAsDefaultsButton, &QAbstractButton::clicked, this, &daqForm::trigger_saveButtonPressed); } @@ -46,8 +46,8 @@ daqForm::~daqForm() } void daqForm::updateLabels(){ - double effective_sample_rate_single = 375000/((double)ui->numberOfPointsSpinBox->value()); - double effective_sample_rate_double = 750000/((double)ui->numberOfPointsSpinBox->value()); + double effective_sample_rate_single = 375000/(double(ui->numberOfPointsSpinBox->value())); + double effective_sample_rate_double = 750000/(double(ui->numberOfPointsSpinBox->value())); int num_samples_stored = (ui->fileSizeSpinBox->value() * 1000000) / NUM_BYTES_STORED_PER_DAQ_SAMPLE; //Print in SI units @@ -68,17 +68,17 @@ void daqForm::updateValues(){ //Averaging if(ui->sampleAveragingGroup->isChecked()){ - updatedAveraging(ui->numberOfPointsSpinBox->value()); - } else updatedAveraging(1); + emit updatedAveraging(ui->numberOfPointsSpinBox->value()); + } else emit updatedAveraging(1); //File Size if(ui->limitFileSizeGroupBox->isChecked()){ - updatedMaxFileSize(ui->fileSizeSpinBox->value() * 1000000); - } else updatedMaxFileSize(0); + emit updatedMaxFileSize(ui->fileSizeSpinBox->value() * 1000000); + } else emit updatedMaxFileSize(0); } void daqForm::trigger_saveButtonPressed(){ - saveButtonPressed(); + emit saveButtonPressed(); } diff --git a/Desktop_Interface/daqloadprompt.cpp b/Desktop_Interface/daqloadprompt.cpp index e06d7522..edce0b95 100644 --- a/Desktop_Interface/daqloadprompt.cpp +++ b/Desktop_Interface/daqloadprompt.cpp @@ -18,8 +18,8 @@ daqLoadPrompt::daqLoadPrompt(QWidget *parent, double minTime, double maxTime) : ui->endTimeDoubleSpinBox->setValue(maxTime); //Internal signals - connect(ui->startTimeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(valueChange())); - connect(ui->endTimeDoubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(valueChange())); + connect(ui->startTimeDoubleSpinBox, &QDoubleSpinBox::textChanged, this, &daqLoadPrompt::valueChange); + connect(ui->endTimeDoubleSpinBox, &QDoubleSpinBox::textChanged, this, &daqLoadPrompt::valueChange); valueChange(); } @@ -33,8 +33,8 @@ void daqLoadPrompt::valueChange(){ ui->startTimeDoubleSpinBox->setMaximum(ui->endTimeDoubleSpinBox->value() - min_interval); ui->endTimeDoubleSpinBox->setMinimum(ui->startTimeDoubleSpinBox->value() + min_interval); - startTime(ui->startTimeDoubleSpinBox->value()); - endTime(ui->endTimeDoubleSpinBox->value()); + emit startTime(ui->startTimeDoubleSpinBox->value()); + emit endTime(ui->endTimeDoubleSpinBox->value()); char units[2] = "B"; double contig_ram_required = ((ui->endTimeDoubleSpinBox->value() - ui->startTimeDoubleSpinBox->value()) / min_interval) * 4 + 512; //4 bytes per sample (float), each sample is stored only once. 512 is just a bullshit value to represent the overhead required to store the other variables in the buffer object diff --git a/Desktop_Interface/desktop_settings.cpp b/Desktop_Interface/desktop_settings.cpp index ea9a61aa..1f018a2e 100644 --- a/Desktop_Interface/desktop_settings.cpp +++ b/Desktop_Interface/desktop_settings.cpp @@ -6,7 +6,8 @@ int MAX_PENDING_TRANSFERS = 512; int MAX_PENDING_IO = 16; //Plot settings -int GRAPH_SAMPLES = 1024; +// this should be int GRAPH_SAMPLES = 375000 * 10; to avoid downsampling +int GRAPH_SAMPLES = 8192; int TIMER_PERIOD = 17; int ISO_RECOVERY_TIME = (200); int MAX_WINDOW_SIZE = 10; diff --git a/Desktop_Interface/desktop_settings.h b/Desktop_Interface/desktop_settings.h index 5b8ad610..dfc2bb93 100644 --- a/Desktop_Interface/desktop_settings.h +++ b/Desktop_Interface/desktop_settings.h @@ -17,6 +17,8 @@ extern int TIMER_PERIOD; extern int ISO_RECOVERY_TIME; extern int MAX_WINDOW_SIZE; extern int TICK_SEPARATION; +static constexpr double DEFAULT_TOP_RANGE = 5.1; +static constexpr double DEFAULT_BOTTOM_RANGE = -0.5; //Multimeter settings extern int MULTIMETER_PERIOD; diff --git a/Desktop_Interface/functiongencontrol.cpp b/Desktop_Interface/functiongencontrol.cpp index 465d172d..28d6f72f 100644 --- a/Desktop_Interface/functiongencontrol.cpp +++ b/Desktop_Interface/functiongencontrol.cpp @@ -1,6 +1,10 @@ #include "functiongencontrol.h" + +#include #include "platformspecific.h" +#include + namespace functionGen { ChannelData const& SingleChannelController::getData() const { @@ -14,118 +18,109 @@ void SingleChannelController::waveformName(QString newName) int length; + const QStringList potentialDirs = { #ifdef PLATFORM_ANDROID - QString waveformFilePath("assets:/waveforms/"); - waveformFilePath.append(newName); + "assets:", +#else + QCoreApplication::applicationDirPath(), +#endif + ":", // fall back to builtin + }; + + QString filename; + for (const QString &dir : potentialDirs) { + const QString potential = dir + "/waveforms/" + newName; + if (QFileInfo::exists(potential)) { + filename = potential; + break; + } + } + + QString waveformFilePath(filename); QFile fptr(waveformFilePath); - bool success = fptr.open(QIODevice::ReadOnly); + if (!fptr.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to open" << newName; + return; + } QByteArray line; - char lengthString[16]; - char divisibilityString[16]; - - line = fptr.readLine(); - strcpy(lengthString, line.data()); - sscanf(lengthString, "%d", &length); - qDebug() << "lengthString" << lengthString; - - line = fptr.readLine(); - strcpy(divisibilityString, line.data()); - sscanf(divisibilityString, "%d", &m_data.divisibility); - qDebug() << "divisibilityString" << divisibilityString; - - qDebug() << "Length = " << length; - qDebug() << "Divisibility = " << m_data.divisibility; - - QByteArray remainingData = fptr.readAll(); - char *dataString = remainingData.data(); - - m_data.samples.resize(length); - int dummy; - char *dataStringCurrent = dataString; - for (int i = 0; i < length; i++) - { - sscanf(dataStringCurrent, "%d", &dummy); - dataStringCurrent += strcspn(dataStringCurrent, "\t") + 1; - m_data.samples[i] = static_cast(dummy); + line = fptr.readLine().trimmed(); + bool ok; + length = line.toInt(&ok); + if (!ok) { + qWarning() << "Invalid length line" << line << "in" << filename; + return; + } + if (length == 0) { + qWarning() << "No samples in" << filename; + return; } -#else - - QByteArray filePath = QCoreApplication::applicationDirPath() - .append("/waveforms/").append(newName).toLocal8Bit(); - - qDebug() << "opening" << filePath; - - FILE *fptr = fopen(filePath.constData(), "r"); - if (fptr == NULL) - qFatal("%s could not be opened!", filePath.constData()); - - char lengthString[16]; - fgets(lengthString, 5, fptr); - sscanf(lengthString, "%d", &length); - - char divisibilityString[16]; - //Bit of bullshit to deal with CRLF line endings on Mac. - do - { - fgets(divisibilityString, 5, fptr); - } - while ((divisibilityString[0] == '\r') || (divisibilityString[0] == '\n')); + line = fptr.readLine().trimmed(); + m_data.divisibility = line.toInt(&ok); + if (!ok) { + qWarning() << "Invalid divisibility line" << line << "in" << filename; + return; + } - sscanf(divisibilityString, "%d", &m_data.divisibility); qDebug() << "Length = " << length; qDebug() << "Divisibility = " << m_data.divisibility; - m_data.samples.resize(length); + QString remainingData = QString::fromLatin1(fptr.readAll().simplified()); - char *dataString = (char *) malloc(length*5+1); - fgets(dataString, length*5+1, fptr); + m_data.samples.resize(length); - int dummy; - char *dataStringCurrent = dataString; - for (int i = 0; i < length; i++) - { - sscanf(dataStringCurrent, "%d", &dummy); - dataStringCurrent += strcspn(dataStringCurrent, "\t") + 1; - m_data.samples[i] = static_cast(dummy); + // Should use tabs for separating, but we support any kind of whitespace + const QStringList values = remainingData.split(QRegularExpression("\\s+"), Qt::SkipEmptyParts); + if (values.count() != length) { + qWarning() << "Invalid amount of values" << values.count() << "in" << filename << "expected" << length; + m_data.samples.resize(values.count()); + } + for (int i=0; i 255) { + qWarning() << "Invalid sample value" << values[i]; + } + m_data.samples[i] = uint8_t(sample); } - free(dataString); - fclose(fptr); -#endif - double newMaxFreq = DAC_SPS / (length >> (m_data.divisibility - 1)); + const unsigned divisor = length >> (m_data.divisibility - 1); + if (divisor == 0) { + qWarning() << "Invalid divisor" << divisor; + return; + } + double newMaxFreq = double(DAC_SPS) / divisor; double newMinFreq = double(CLOCK_FREQ) / 1024.0 / 65535.0 / static_cast(length); - setMaxFreq(newMaxFreq); - setMinFreq(newMinFreq); + emit setMaxFreq(newMaxFreq); + emit setMinFreq(newMinFreq); - notifyUpdate(this); + emit notifyUpdate(this); } void SingleChannelController::freqUpdate(double newFreq) { qDebug() << "newFreq = " << newFreq; m_data.freq = newFreq; - notifyUpdate(this); + emit notifyUpdate(this); } void SingleChannelController::amplitudeUpdate(double newAmplitude) { qDebug() << "newAmplitude = " << newAmplitude; m_data.amplitude = newAmplitude; - notifyUpdate(this); + emit notifyUpdate(this); } void SingleChannelController::offsetUpdate(double newOffset) { qDebug() << "newOffset = " << newOffset; m_data.offset = newOffset; - notifyUpdate(this); + emit notifyUpdate(this); } @@ -137,7 +132,7 @@ DualChannelController::DualChannelController(QWidget *parent) : QLabel(parent) SingleChannelController* controller2 = getChannelController(ChannelID::CH2); connect(controller1, &SingleChannelController::notifyUpdate, - this, [=](SingleChannelController* ptr){ this->functionGenToUpdate(ChannelID::CH1, ptr); }); + this, [=](SingleChannelController* ptr){ emit this->functionGenToUpdate(ChannelID::CH1, ptr); }); connect(controller1, &SingleChannelController::setMaxFreq, this, &DualChannelController::setMaxFreq_CH1); @@ -147,7 +142,7 @@ DualChannelController::DualChannelController(QWidget *parent) : QLabel(parent) connect(controller2, &SingleChannelController::notifyUpdate, - this, [=](SingleChannelController* ptr){ this->functionGenToUpdate(ChannelID::CH2, ptr); }); + this, [=](SingleChannelController* ptr){ emit this->functionGenToUpdate(ChannelID::CH2, ptr); }); connect(controller1, &SingleChannelController::setMaxFreq, this, &DualChannelController::setMaxFreq_CH2); @@ -168,7 +163,7 @@ SingleChannelController* DualChannelController::getChannelController(ChannelID c // Hopefuly it can be mostly removed eventually void DualChannelController::waveformName(ChannelID channelID, QString newName) { - getChannelController(channelID)->waveformName(newName); + getChannelController(channelID)->waveformName(std::move(newName)); } void DualChannelController::freqUpdate(ChannelID channelID, double newFreq) @@ -189,7 +184,7 @@ void DualChannelController::offsetUpdate(ChannelID channelID, double newOffset) void DualChannelController::waveformName_CH1(QString newName) { - waveformName(ChannelID::CH1, newName); + waveformName(ChannelID::CH1, std::move(newName)); } void DualChannelController::freqUpdate_CH1(double newFreq) @@ -210,7 +205,7 @@ void DualChannelController::offsetUpdate_CH1(double newOffset) void DualChannelController::waveformName_CH2(QString newName) { - waveformName(ChannelID::CH2, newName); + waveformName(ChannelID::CH2, std::move(newName)); } void DualChannelController::freqUpdate_CH2(double newFreq) @@ -228,5 +223,5 @@ void DualChannelController::offsetUpdate_CH2(double newOffset) offsetUpdate(ChannelID::CH2, newOffset); } -} +} // namespace functionGen diff --git a/Desktop_Interface/functiongencontrol.h b/Desktop_Interface/functiongencontrol.h index 9e22011b..6b813c75 100644 --- a/Desktop_Interface/functiongencontrol.h +++ b/Desktop_Interface/functiongencontrol.h @@ -56,7 +56,7 @@ class DualChannelController : public QLabel { Q_OBJECT public: - explicit DualChannelController(QWidget *parent = 0); + explicit DualChannelController(QWidget *parent = nullptr); public: SingleChannelController* getChannelController(ChannelID channelID); diff --git a/Desktop_Interface/genericusbdriver.cpp b/Desktop_Interface/genericusbdriver.cpp index 98643ccb..a98eabfc 100644 --- a/Desktop_Interface/genericusbdriver.cpp +++ b/Desktop_Interface/genericusbdriver.cpp @@ -23,12 +23,11 @@ class GobindarDialog : public QWidget }; GobindarDialog::GobindarDialog() -: QWidget() { setWindowFlags(Qt::Window); QPalette palette; - palette.setColor(QPalette::Background, Qt::white); + palette.setColor(QPalette::Window, Qt::white); setPalette(palette); QFont largeFont; @@ -59,13 +58,12 @@ GobindarDialog::GobindarDialog() genericUsbDriver::genericUsbDriver(QWidget *parent) : QLabel(parent) { - connectedStatus(false); qDebug() << "Making USB Driver invisible!!"; this->hide(); //Double buffers are used to send the transfers to isoDriver. outBuffers and bufferLengths store the actual data from each transfer as well as length. They are read by isoDriver when it calls isoRead(). - outBuffers[0] = (unsigned char *) calloc(ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX*NUM_ISO_ENDPOINTS + 8, 1); - outBuffers[1] = (unsigned char *) calloc(ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX*NUM_ISO_ENDPOINTS + 8, 1); + outBuffers[0].reset((char *) calloc(ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX*NUM_ISO_ENDPOINTS + 8, 1), free); + outBuffers[1].reset((char *) calloc(ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX*NUM_ISO_ENDPOINTS + 8, 1), free); bufferLengths[0] = 0; bufferLengths[1] = 0; @@ -76,15 +74,20 @@ genericUsbDriver::genericUsbDriver(QWidget *parent) : QLabel(parent) qDebug() << "pipeID" << k << "=" << pipeID[k]; } - connectTimer = new QTimer(); + connectTimer = new QTimer(this); connectTimer->setTimerType(Qt::PreciseTimer); connectTimer->start(USB_RECONNECT_PERIOD); - connect(connectTimer, SIGNAL(timeout()), this, SLOT(checkConnection())); + connect(connectTimer.data(), &QTimer::timeout, this, &genericUsbDriver::checkConnection); qDebug()<< "Generic Usb Driver setup complete"; messageBox = new QMessageBox(); + + // Emitting in a constructor does not work + QMetaObject::invokeMethod(this, [this]() { + emit this->connectedStatus(false); + }); } -genericUsbDriver::~genericUsbDriver(void){ +genericUsbDriver::~genericUsbDriver(){ qDebug() << "genericUsbDriver dectructor entering"; if(connected){ if (psuTimer) @@ -174,9 +177,9 @@ void genericUsbDriver::sendFunctionGenData(functionGen::ChannelID channelID) unsigned char fGenTemp = 0; fGenTemp |= (fGenTriple & 0x01)<<1; fGenTemp |= (fGenTriple & 0x02)>>1; - usbSendControl(0x40, 0xa4, fGenTemp, 0, 0, NULL); + usbSendControl(0x40, 0xa4, fGenTemp, 0, 0, nullptr); #else - usbSendControl(0x40, 0xa4, fGenTriple, 0, 0, NULL); + usbSendControl(0x40, 0xa4, fGenTriple, 0, 0, nullptr); #endif auto applyAmplitudeAndOffset = [&](unsigned char sample) -> unsigned char @@ -213,19 +216,21 @@ void genericUsbDriver::sendFunctionGenData(functionGen::ChannelID channelID) } // Timer Setup - int validClockDivs[7] = {1, 2, 4, 8, 64, 256, 1024}; - auto period = [&](int division) -> int - { - return CLOCK_FREQ / (division * channelData.samples.size() * channelData.freq); - }; - - int* clkSettingIt = std::find_if(std::begin(validClockDivs), std::end(validClockDivs), - [&](int division) -> bool { return period(division) < 65535; }); - - int timerPeriod = period(*clkSettingIt); + static const int validClockDivs[7] = {1, 2, 4, 8, 64, 256, 1024}; + + int timerPeriod = 0; + int clkSetting = 0; + for (size_t i=0; i 0xFFFF && i == 0 /* ensure we always have a valid value */) { + continue; + } - // +1 to change from [0:n) to [1:n] - int clkSetting = std::distance(std::begin(validClockDivs), clkSettingIt) + 1; + // +1 to change from [0:n) to [1:n] + clkSetting = i + 1; + timerPeriod = period; + break; + } if(deviceMode == 5) qDebug("DEVICE IS IN MODE 5"); @@ -235,15 +240,12 @@ void genericUsbDriver::sendFunctionGenData(functionGen::ChannelID channelID) usbSendControl(0x40, 0xa1, timerPeriod, clkSetting, channelData.samples.size(), channelData.samples.data()); else usbSendControl(0x40, 0xa2, timerPeriod, clkSetting, channelData.samples.size(), channelData.samples.data()); - - return; - } void genericUsbDriver::newDig(int digState){ qDebug() << "newDig"; digitalPinState = digState; - usbSendControl(0x40, 0xa6, digState, 0, 0, NULL); + usbSendControl(0x40, 0xa6, digState, 0, 0, nullptr); } /* @@ -255,57 +257,57 @@ void genericUsbDriver::setBufferPtr(bufferControl *newPtr){ void genericUsbDriver::setDeviceMode(int mode){ int oldMode = deviceMode; deviceMode = mode; - usbSendControl(0x40, 0xa5, (mode == 5 ? 0 : mode), gainMask, 0, NULL); + usbSendControl(0x40, 0xa5, (mode == 5 ? 0 : mode), gainMask, 0, nullptr); - if (fGenPtrData[(int)functionGen::ChannelID::CH1] != NULL) + if (fGenPtrData[(int)functionGen::ChannelID::CH1] != nullptr) sendFunctionGenData(functionGen::ChannelID::CH1); - if (fGenPtrData[(int)functionGen::ChannelID::CH2] != NULL) + if (fGenPtrData[(int)functionGen::ChannelID::CH2] != nullptr) sendFunctionGenData(functionGen::ChannelID::CH2); //switch on new deviceMode!! switch(deviceMode){ - case 0: - if(oldMode > 2) sendClearBuffer(1,0,0); - setVisible_CH2(0); - checkXY(0); + case DeviceCH1Analog: + if(oldMode > DeviceCH1AnalogCH2Analog) emit sendClearBuffer(true,false,false); + emit setVisible_CH2(false); + emit checkXY(false); break; - case 1: - if(oldMode > 2) sendClearBuffer(1,0,0); - sendClearBuffer(0,1,0); - setVisible_CH2(1); - checkXY(0); + case DeviceCH1AnalogCH2Digital: + if(oldMode > 2) emit sendClearBuffer(true,false,false); + emit sendClearBuffer(false,true,false); + emit setVisible_CH2(true); + emit checkXY(false); break; - case 2: - if(oldMode > 2) sendClearBuffer(1,0,0); - sendClearBuffer(0,1,0); - setVisible_CH2(1); + case DeviceCH1AnalogCH2Analog: + if(oldMode > 2) emit sendClearBuffer(true,false,false); + emit sendClearBuffer(false,true,false); + emit setVisible_CH2(true); break; - case 3: - if(oldMode != 4) sendClearBuffer(1,0,0); - sendClearBuffer(0,1,0); - setVisible_CH2(0); - checkXY(0); + case DeviceCH1Digital: + if(oldMode != 4) emit sendClearBuffer(true,false,false); + emit sendClearBuffer(false,true,false); + emit setVisible_CH2(true); + emit checkXY(false); break; - case 4: - if(oldMode != 3) sendClearBuffer(1,0,0); - sendClearBuffer(0,1,0); - setVisible_CH2(1); - checkXY(0); + case DeviceCH1DigitalCH2Digital : + if(oldMode != 3) emit sendClearBuffer(true,false,false); + emit sendClearBuffer(false,true,false); + emit setVisible_CH2(true); + emit checkXY(false); break; case 5: - setVisible_CH2(0); - checkXY(0); + emit setVisible_CH2(false); + emit checkXY(false); break; - case 6: - sendClearBuffer(0,0,1); - setVisible_CH2(0); - checkXY(0); + case DeviceCH1Analog750 : + emit sendClearBuffer(false,false,true); + emit setVisible_CH2(false); + emit checkXY(false); break; - case 7: - sendClearBuffer(1,0,0); - enableMMTimer(); - checkXY(0); + case DeviceMultimeter: + emit sendClearBuffer(true,false,false); + emit enableMMTimer(); + emit checkXY(false); break; default: qFatal("Error in genericUsbDriver::setDeviceMode. Invalid device mode."); @@ -331,12 +333,12 @@ void genericUsbDriver::psuTick(){ if ((dutyTemp>106) || (dutyTemp<21)){ qDebug("PSU DUTY CYCLE of dutyTemp = %d OUT OF RANGE (could underflow on SOF)!!! ABORTING!!!", dutyTemp); } - usbSendControl(0x40, 0xa3, dutyTemp, 0, 0, NULL); + usbSendControl(0x40, 0xa3, dutyTemp, 0, 0, nullptr); } void genericUsbDriver::setGain(double newGain){ if (newGain == scopeGain) return; //No update! - gainBuffers(scopeGain/newGain); + emit gainBuffers(scopeGain/newGain); scopeGain = newGain; //See XMEGA_AU Manual, page 359. ADC.CTRL.GAIN. if(newGain==0.5) gainMask = 0x07; @@ -359,11 +361,11 @@ void genericUsbDriver::setGain(double newGain){ */ qDebug("newGain = %f", newGain); qDebug("gainMask = %x", gainMask); - usbSendControl(0x40, 0xa5, deviceMode, gainMask, 0, NULL); + usbSendControl(0x40, 0xa5, deviceMode, gainMask, 0, nullptr); } -void genericUsbDriver::avrDebug(void){ - usbSendControl(0xc0, 0xa0, 0, 0, sizeof(unified_debug), NULL); +void genericUsbDriver::avrDebug(){ + usbSendControl(0xc0, 0xa0, 0, 0, sizeof(unified_debug), nullptr); qDebug() << "unified debug is of size" << sizeof(unified_debug); /* @@ -392,18 +394,18 @@ void genericUsbDriver::avrDebug(void){ */ } -void genericUsbDriver::kickstartIso(void){ +void genericUsbDriver::kickstartIso(){ qDebug() << "Attempting to kickstart iso..."; - usbSendControl(0x40, 0xaa, 0, 0, 0, NULL); + usbSendControl(0x40, 0xaa, 0, 0, 0, nullptr); } -void genericUsbDriver::requestFirmwareVersion(void){ - usbSendControl(0xc0, 0xa8, 0, 0, 2, NULL); +void genericUsbDriver::requestFirmwareVersion(){ + usbSendControl(0xc0, 0xa8, 0, 0, 2, nullptr); firmver = *((unsigned short *) inBuffer); } -void genericUsbDriver::requestFirmwareVariant(void){ - usbSendControl(0xc0, 0xa9, 0, 0, 1, NULL); +void genericUsbDriver::requestFirmwareVariant(){ + usbSendControl(0xc0, 0xa9, 0, 0, 1, nullptr); variant = *((unsigned char *) inBuffer); } @@ -421,7 +423,6 @@ void genericUsbDriver::saveState(int *_out_deviceMode, double *_out_scopeGain, d *(_out_scopeGain) = scopeGain; *(_out_currentPsuVoltage) = currentPsuVoltage; *(_out_digitalPinState) = digitalPinState; - return; } void genericUsbDriver::checkConnection(){ @@ -430,7 +431,7 @@ void genericUsbDriver::checkConnection(){ unsigned char initReturnValue; if(!connected){ - connectedStatus(false); + emit connectedStatus(false); qDebug() << "CHECKING CONNECTION!"; initReturnValue = usbInit(BOARD_VID, BOARD_PID); connected = !(initReturnValue); @@ -459,16 +460,18 @@ void genericUsbDriver::checkConnection(){ connectTimer->stop(); requestFirmwareVersion(); - qDebug("BOARD IS RUNNING FIRMWARE VERSION 0x%04hx", firmver); - qDebug("EXPECTING FIRMWARE VERSION 0x%04hx", EXPECTED_FIRMWARE_VERSION); + qDebug("BOARD IS RUNNING FIRMWARE VERSION 0x%04hhx", firmver); + qDebug("EXPECTING FIRMWARE VERSION 0x%04x", EXPECTED_FIRMWARE_VERSION); requestFirmwareVariant(); - qDebug("FIRMWARE VARIANT = 0x%02hx", variant); - qDebug("EXPECTED VARIANT = 0x%02hx", DEFINED_EXPECTED_VARIANT); + qDebug("FIRMWARE VARIANT = 0x%02hhx", variant); + qDebug("EXPECTED VARIANT = 0x%02x", DEFINED_EXPECTED_VARIANT); if((firmver != EXPECTED_FIRMWARE_VERSION) || (variant != DEFINED_EXPECTED_VARIANT)){ qDebug() << "Unexpected Firmware!!"; int flashRet = flashFirmware(); - qDebug("flashRet: %d", flashRet); + if (flashRet != 0) { + QMessageBox::warning(window(), tr("Flashing firmware failed"), tr("Flashing firmware failed with error code %1").arg(flashRet)); + } connected = false; connectTimer->start(); return; @@ -480,7 +483,7 @@ void genericUsbDriver::checkConnection(){ connectTimer->stop(); delete(connectTimer); - connectedStatus(true); + emit connectedStatus(true); setDeviceMode(deviceMode); @@ -496,22 +499,22 @@ void genericUsbDriver::checkConnection(){ psuTimer = new QTimer(); psuTimer->setTimerType(Qt::PreciseTimer); psuTimer->start(PSU_PERIOD); - connect(psuTimer, SIGNAL(timeout()), this, SLOT(psuTick())); + connect(psuTimer, &QTimer::timeout, this, &genericUsbDriver::psuTick); - if(killOnConnect) usbSendControl(0x40, 0xa7, 0, 0, 0, NULL); + if(killOnConnect) usbSendControl(0x40, 0xa7, 0, 0, 0, nullptr); recoveryTimer = new QTimer(); recoveryTimer->setTimerType(Qt::PreciseTimer); recoveryTimer->start(RECOVERY_PERIOD); - connect(recoveryTimer, SIGNAL(timeout()), this, SLOT(recoveryTick())); - initialConnectComplete(); + connect(recoveryTimer.data(), &QTimer::timeout, this, &genericUsbDriver::recoveryTick); + emit initialConnectComplete(); if(!killOnConnect && calibrateOnConnect){ - calibrateMe(); + emit calibrateMe(); } } void genericUsbDriver::bootloaderJump(){ - usbSendControl(0x40, 0xa7, 1, 0, 0, NULL); + usbSendControl(0x40, 0xa7, 1, 0, 0, nullptr); } diff --git a/Desktop_Interface/genericusbdriver.h b/Desktop_Interface/genericusbdriver.h index 623d8599..7cdcd9ef 100644 --- a/Desktop_Interface/genericusbdriver.h +++ b/Desktop_Interface/genericusbdriver.h @@ -9,6 +9,7 @@ #include #include #include +#include #include "functiongencontrol.h" #include "xmega.h" @@ -28,19 +29,23 @@ #define NUM_ISO_ENDPOINTS (1) #endif -#ifdef PLATFORM_WINDOWS +#ifdef Q_OS_WINDOWS #define ISO_PACKETS_PER_CTX 17 #define NUM_FUTURE_CTX 40 #elif defined PLATFORM_RASPBERRY_PI #define ISO_PACKETS_PER_CTX 66 // 15fps... #define NUM_FUTURE_CTX 4 -#elif defined PLATFORM_LINUX +#elif defined Q_OS_LINUX #define ISO_PACKETS_PER_CTX 17 #define NUM_FUTURE_CTX 20 -#else +#elif defined Q_OS_MACOS // A real Mac may be capable of higher refresh rates and more parallel contexts, but these settings work on a hackintosh too. #define ISO_PACKETS_PER_CTX 33 #define NUM_FUTURE_CTX 4 +#else + #warning "Unknown OS" + #define ISO_PACKETS_PER_CTX 17 + #define NUM_FUTURE_CTX 20 #endif #define ISO_TIMER_PERIOD 1 @@ -66,14 +71,14 @@ class genericUsbDriver : public QLabel int dutyTemp = 21; bool killOnConnect = false; //Generic Vars - unsigned char *outBuffers[2]; + std::shared_ptr outBuffers[2]; unsigned int bufferLengths[2]; bool connected = false; bool calibrateOnConnect = false; //Generic Functions - explicit genericUsbDriver(QWidget *parent = 0); + explicit genericUsbDriver(QWidget *parent); ~genericUsbDriver(); - virtual char *isoRead(unsigned int *newLength) = 0; + virtual std::shared_ptr isoRead(unsigned int *newLength) = 0; //void setBufferPtr(bufferControl *newPtr); void saveState(int *_out_deviceMode, double *_out_scopeGain, double *_out_currentPsuVoltage, int *_out_digitalPinState); virtual void usbSendControl(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length, unsigned char *LDATA) = 0; @@ -83,7 +88,7 @@ class genericUsbDriver : public QLabel //State Vars unsigned char fGenTriple=0; unsigned short gainMask = 2056; - functionGen::SingleChannelController* fGenPtrData[2] = {NULL, NULL}; + functionGen::SingleChannelController* fGenPtrData[2] = {nullptr, nullptr}; int dutyPsu = 0; double currentPsuVoltage; int digitalPinState = 0; @@ -93,9 +98,9 @@ class genericUsbDriver : public QLabel //bufferControl *bufferPtr = NULL; QTimer *psuTimer = nullptr; unsigned char pipeID[3]; - QTimer *isoTimer = nullptr; - QTimer *connectTimer = nullptr; - QTimer *recoveryTimer; + QPointer isoTimer; + QPointer connectTimer; + QPointer recoveryTimer; unsigned char currentWriteBuffer = 0; unsigned long timerCount = 0; unsigned char inBuffer[256]; diff --git a/Desktop_Interface/i2cdecoder.cpp b/Desktop_Interface/i2cdecoder.cpp index abccb609..9b7866d4 100644 --- a/Desktop_Interface/i2cdecoder.cpp +++ b/Desktop_Interface/i2cdecoder.cpp @@ -59,7 +59,7 @@ void i2cDecoder::run() int i2cDecoder::serialDistance(isoBuffer* buffer) { - int back_bit = buffer->m_back * 8; + uint64_t back_bit = buffer->m_back * 8; int bufferEnd_bit = buffer->m_bufferLen * 8; if (back_bit >= serialPtr_bit) return back_bit - serialPtr_bit; @@ -117,7 +117,12 @@ void i2cDecoder::runStateMachine() case transmissionState::data: decodeData(sdaEdge, sclEdge); break; - } + case transmissionState::unknown: + default: + throw std::runtime_error("State machine is in an invalid state!"); + return; + + } } edge i2cDecoder::edgeDetection(uint8_t current, uint8_t prev) diff --git a/Desktop_Interface/isobuffer.cpp b/Desktop_Interface/isobuffer.cpp index 20eb5519..1d240edf 100644 --- a/Desktop_Interface/isobuffer.cpp +++ b/Desktop_Interface/isobuffer.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "isodriver.h" #include "uartstyledecoder.h" @@ -16,14 +17,13 @@ constexpr char const* fileHeaderFormat = constexpr auto kSamplesSeekingCap = 20; #ifdef INVERT_MM -constexpr auto fX0Comp = std::greater {}; -constexpr auto fX1X2Comp = std::less {}; +constexpr auto fX0Comp = std::greater<> {}; +constexpr auto fX1X2Comp = std::less<> {}; #else -constexpr auto fX0Comp = std::less {}; -constexpr auto fX1X2Comp = std::greater {}; +constexpr auto fX0Comp = std::less<> {}; +constexpr auto fX1X2Comp = std::greater<> {}; #endif -constexpr auto kTopMultimeter = 2048; constexpr double kTriggerSensitivityMultiplier = 4; } @@ -62,7 +62,7 @@ void isoBuffer::insertIntoBuffer(short item) short isoBuffer::bufferAt(uint32_t idx) const { if (idx > m_insertedCount) - qFatal("isoBuffer::bufferAt: invalid query, idx = %lu, m_insertedCount = %lu", idx, m_insertedCount); + qFatal("isoBuffer::bufferAt: invalid query, idx = %u, m_insertedCount = %u", idx, m_insertedCount); return m_buffer[(m_back-1) + m_bufferLen - idx]; } @@ -120,15 +120,69 @@ std::unique_ptr isoBuffer::readBuffer(double sampleWindow, int numSampl std::fill (readData.get(), readData.get() + numSamples, short(0)); double itr = delaySamples; - for (int i = 0; i < numSamples && itr < m_insertedCount; i++) + short *data = &m_buffer[(m_back-1) + m_bufferLen]; + for (int pos = 0; pos < numSamples && itr < m_insertedCount; pos++) { + if (int(itr) < 0 || ((m_back-1) + m_bufferLen - itr) >= m_bufferLen * 2) { + qWarning() << "itr out of range" << itr << numSamples << m_insertedCount << pos << timeBetweenSamples; + break; + } assert(int(itr) >= 0); - readData[i] = bufferAt(int(itr)); + + // TODO: to optimize: + // - reverse the loop (I thought the prefetching would be smart enough, but maybe not) + // - Split loop into blocks with constant length, to avoid the pshuflw and whatnot + if (timeBetweenSamples > 1 && m_downsamplingMethod != DownsamplingMethod::Decimate) { + short minimum = std::numeric_limits::max(); + short maximum = std::numeric_limits::min(); + const int end = qMin(m_insertedCount, itr + timeBetweenSamples); + short result = 0; + + // For performance reasons we can't check the method inside each loop, so a bit of repetition of code + switch (m_downsamplingMethod) { + case DownsamplingMethod::AverageDelta: { + double average = 0.; + for (int i=itr; i qAbs(average - minimum) ? maximum : minimum; + break; + } + case DownsamplingMethod::Bottom: + for (int i=itr; i>= gain_log; } } + updateTriggerLevel(); } @@ -213,7 +268,7 @@ void isoBuffer::maybeOutputSampleToFile(double convertedSample) if (m_fileIO_numBytesWritten >= m_fileIO_maxFileSize) { m_fileIOEnabled = false; // Just in case signalling fails. - fileIOinternalDisable(); + emit fileIOinternalDisable(); } } } @@ -249,7 +304,6 @@ void isoBuffer::disableFileIO() m_fileIOEnabled = false; m_currentColumn = 0; m_currentFile->close(); - return; } @@ -258,9 +312,9 @@ double isoBuffer::sampleConvert(short sample, int TOP, bool AC) const double scope_gain = (double)(m_virtualParent->driver->scopeGain); double voltageLevel = (sample * (vcc/2)) / (m_frontendGain*scope_gain*TOP); - if (m_virtualParent->driver->deviceMode != 7) voltageLevel += m_voltage_ref; + if (m_virtualParent->driver->deviceMode != DeviceMultimeter) voltageLevel += m_voltage_ref; #ifdef INVERT_MM - if (m_virtualParent->driver->deviceMode == 7) voltageLevel *= -1; + if (m_virtualParent->driver->deviceMode == DeviceMultimeter) voltageLevel *= -1; #endif if (AC) @@ -284,9 +338,9 @@ short isoBuffer::inverseSampleConvert(double voltageLevel, int TOP, bool AC) con } #ifdef INVERT_MM - if (m_virtualParent->driver->deviceMode == 7) voltageLevel *= -1; + if (m_virtualParent->driver->deviceMode == DeviceMultimeter) voltageLevel *= -1; #endif - if (m_virtualParent->driver->deviceMode != 7) voltageLevel -= m_voltage_ref; + if (m_virtualParent->driver->deviceMode != DeviceMultimeter) voltageLevel -= m_voltage_ref; // voltageLevel = (sample * (vcc/2)) / (frontendGain*scope_gain*TOP); short sample = (voltageLevel * (m_frontendGain*scope_gain*TOP))/(vcc/2); @@ -303,7 +357,7 @@ int isoBuffer::capSample(int offset, int target, double seconds, double value, F if (static_cast(m_back) < (samples + offset)) return -1; - short sample = inverseSampleConvert(value, 2048, 0); + short sample = inverseSampleConvert(value, 2048, false); int found = 0; for (int i = samples + offset; i--;) @@ -338,7 +392,7 @@ int isoBuffer::cap_x2fromLast(double seconds, int x1, double vtop) void isoBuffer::serialManage(double baudRate, UartParity parity, bool hexDisplay) { - if (m_decoder == NULL) + if (m_decoder == nullptr) { m_decoder = new uartStyleDecoder(baudRate, this); } @@ -358,14 +412,28 @@ void isoBuffer::setTriggerType(TriggerType newType) { qDebug() << "Trigger Type: " << (uint8_t)newType; m_triggerType = newType; + m_triggerPositionList.clear(); } void isoBuffer::setTriggerLevel(double voltageLevel, uint16_t top, bool acCoupled) { - m_triggerLevel = inverseSampleConvert(voltageLevel, top, acCoupled); - m_triggerSensitivity = static_cast(1 + abs(voltageLevel * kTriggerSensitivityMultiplier * static_cast(top) / 128.)); + m_triggerPositionList.clear(); + + // Because inverseSampleConvert() depends on e. g. gain, we have to store this and update the level when we change gain + m_triggerVoltage = voltageLevel; + m_triggerTop = top; + m_triggerACCoupled = acCoupled; + + updateTriggerLevel(); +} + +void isoBuffer::updateTriggerLevel() +{ + m_triggerLevel = inverseSampleConvert(m_triggerVoltage, m_triggerTop, m_triggerACCoupled); + m_triggerSensitivity = static_cast(1 + abs(m_triggerVoltage * kTriggerSensitivityMultiplier * static_cast(m_triggerTop) / 128.)); qDebug() << "Trigger Level: " << m_triggerLevel; qDebug() << "Trigger sensitivity:" << m_triggerSensitivity; + } // TODO: Clear trigger @@ -375,14 +443,14 @@ void isoBuffer::checkTriggered() if (m_triggerType == TriggerType::Disabled) return; - if ((bufferAt(0) >= (m_triggerLevel + m_triggerSensitivity)) && (m_triggerSeekState == TriggerSeekState::BelowTriggerLevel)) + if ((m_triggerSeekState == TriggerSeekState::BelowTriggerLevel) && (bufferAt(0) >= (m_triggerLevel + m_triggerSensitivity))) { // Rising Edge m_triggerSeekState = TriggerSeekState::AboveTriggerLevel; if (m_triggerType == TriggerType::Rising) m_triggerPositionList.push_back(m_back - 1); } - else if ((bufferAt(0) < (m_triggerLevel - m_triggerSensitivity)) && (m_triggerSeekState == TriggerSeekState::AboveTriggerLevel)) + else if ((m_triggerSeekState == TriggerSeekState::AboveTriggerLevel) && (bufferAt(0) < (m_triggerLevel - m_triggerSensitivity))) { // Falling Edge m_triggerSeekState = TriggerSeekState::BelowTriggerLevel; @@ -393,51 +461,36 @@ void isoBuffer::checkTriggered() double isoBuffer::getDelayedTriggerPoint(double delay) { - if (m_triggerPositionList.size() == 0) - return 0; + if (m_triggerPositionList.isEmpty()) { + return -1; + } + // Holy fuck the STL APIs suck, + // TODO: port to something sane that is readable + const uint32_t delaySamples = delay * m_samplesPerSecond; - auto isValid = [=](uint32_t index)->bool + QVector::reverse_iterator it = std::find_if(m_triggerPositionList.rbegin(), m_triggerPositionList.rend(), [=](uint32_t index) { - if (m_back > delaySamples) + if (m_back > delaySamples) { return (index < m_back - delaySamples) || (index >= m_back); - else - return (index < m_bufferLen + m_back - delaySamples) && (index >= m_back); - }; + } - auto getDelay = [=](uint32_t index)->double - { - if (m_back > index) - return (m_back - index) / static_cast(m_samplesPerSecond); - else - return (m_bufferLen + (m_back-1) - index) / static_cast(m_samplesPerSecond); - }; - - // Like std::find_if but returns the last element matching the predicate instead of the first one - // TODO: Move this elsewhere (maybe a utils / algorithms file??) - // requires first and last to be Bidirectional iters, and form a valid range - // requires p to be a valid unaryPredicate - // Full signature would be: - // template - // It find_last_if(It begin, It end, Predicate p) - auto find_last_if = [](auto begin, auto end, auto p) - { - using It = decltype(begin); // TODO: remove this line once this is a proper function - std::reverse_iterator rlast(begin), rfirst(end); - auto found = std::find_if(rfirst, rlast, p); - return found == rlast - ? end - : std::prev(found.base()); - }; - - auto it = find_last_if(m_triggerPositionList.begin(), m_triggerPositionList.end(), isValid); - if (it != m_triggerPositionList.end()) + return (index < m_bufferLen + m_back - delaySamples) && (index >= m_back); + }); + + if (it != m_triggerPositionList.rend()) { // NOTE: vector::erase does not remove the element pointed to by the second iterator. - m_triggerPositionList.erase(m_triggerPositionList.begin(), it); - return getDelay(m_triggerPositionList[0]); + m_triggerPositionList.erase(m_triggerPositionList.begin(), std::prev(it.base())); + const uint32_t index = m_triggerPositionList[0]; + + if (m_back > index) { + return (m_back - index) / double(m_samplesPerSecond); + } + + return (m_bufferLen + (m_back-1) - index) / double(m_samplesPerSecond); } - return 0; + return -1; } diff --git a/Desktop_Interface/isobuffer.h b/Desktop_Interface/isobuffer.h index 07c506d2..6a41192b 100644 --- a/Desktop_Interface/isobuffer.h +++ b/Desktop_Interface/isobuffer.h @@ -34,6 +34,14 @@ enum class TriggerSeekState : uint8_t AboveTriggerLevel }; +enum class DownsamplingMethod +{ + Decimate, + Peak, + Bottom, + AverageDelta +}; + // isoBuffer is a generic class that enables O(1) read times (!!!) on all // read/write operations, while maintaining a huge buffer size. // Imagine it as a circular buffer, but with access functions specifically @@ -47,7 +55,7 @@ class isoBuffer : public QWidget { Q_OBJECT public: - isoBuffer(QWidget* parent = 0, int bufferLen = 0, isoDriver* caller = 0, unsigned char channel_value = 0); + isoBuffer(QWidget* parent = nullptr, int bufferLen = 0, isoDriver* caller = nullptr, unsigned char channel_value = 0); ~isoBuffer() = default; // Basic buffer operations @@ -73,11 +81,13 @@ class isoBuffer : public QWidget public: double sampleConvert(short sample, int TOP, bool AC) const; short inverseSampleConvert(double voltageLevel, int TOP, bool AC) const; + void setDownsampleMethod(const DownsamplingMethod method) { m_downsamplingMethod = method; } private: template int capSample(int offset, int target, double seconds, double value, Function comp); void checkTriggered(); + void updateTriggerLevel(); public: int cap_x0fromLast(double seconds, double vbot); int cap_x1fromLast(double seconds, int x0, double vbot); @@ -111,11 +121,15 @@ class isoBuffer : public QWidget int m_sampleRate_bit; TriggerType m_triggerType = TriggerType::Disabled; TriggerSeekState m_triggerSeekState = TriggerSeekState::BelowTriggerLevel; + DownsamplingMethod m_downsamplingMethod = DownsamplingMethod::AverageDelta; + double m_triggerVoltage = 0.; + uint16_t m_triggerTop = 0; + bool m_triggerACCoupled = false; short m_triggerLevel = 0; short m_triggerSensitivity = 0; - std::vector m_triggerPositionList = {}; + QVector m_triggerPositionList = {}; // UARTS decoding - uartStyleDecoder* m_decoder = NULL; + uartStyleDecoder* m_decoder = nullptr; bool m_isDecoding = true; private: // File I/O diff --git a/Desktop_Interface/isobuffer_file.cpp b/Desktop_Interface/isobuffer_file.cpp index 5c73c625..b2aa2749 100644 --- a/Desktop_Interface/isobuffer_file.cpp +++ b/Desktop_Interface/isobuffer_file.cpp @@ -9,7 +9,7 @@ isoBuffer_file::isoBuffer_file(QWidget *parent, int bufferlen, double sampleRate samplesPerSecond = sampleRate_Hz; } -void isoBuffer_file::writeBuffer_float(float* data, int len) +void isoBuffer_file::writeBuffer_float(const float* data, int len) { for (int i=0; isetTimerType(Qt::PreciseTimer); slowTimer->start(MULTIMETER_PERIOD); - connect(slowTimer, SIGNAL(timeout()), this, SLOT(slowTimerTick())); + connect(slowTimer, &QTimer::timeout, this, &isoDriver::slowTimerTick); + + connect(&display, &DisplayControl::delayUpdated, this, &isoDriver::delayUpdated); + connect(&display, &DisplayControl::timeWindowUpdated, this, &isoDriver::timeWindowUpdated); + connect(&display, &DisplayControl::topRangeUpdated, this, &isoDriver::topRangeUpdated); + connect(&display, &DisplayControl::botRangeUpdated, this, &isoDriver::botRangeUpdated); +} + +isoDriver::~isoDriver() +{ + delete v0; + delete v1; + delete dv; + + delete t0; + delete t1; + delete dt; + + delete f; } void isoDriver::setDriver(genericUsbDriver *newDriver){ + if (driver) { + driver->deleteLater(); + } driver = newDriver; qDebug() << "driver = " << driver; } @@ -45,7 +67,7 @@ void isoDriver::setAxes(QCustomPlot *newAxes){ qDebug() << "axes = " << axes; } -void isoDriver::timerTick(void){ +void isoDriver::timerTick(){ //qDebug() << "isoDriver SEZ Tick!"; if(firstFrame){ autoGain(); @@ -71,50 +93,58 @@ void isoDriver::timerTick(void){ // TODO: Do we need to invalidate state when the device is reconnected? bool invalidateTwoWireState = true; switch(driver->deviceMode){ - case 0: - if (deviceMode_prev != 0 && deviceMode_prev != 1 && deviceMode_prev != 2) - clearBuffers(true, false, false); + case DeviceCH1Analog: + if (deviceMode_prev != DeviceCH1Analog && deviceMode_prev != DeviceCH1AnalogCH2Digital && deviceMode_prev != DeviceCH1AnalogCH2Analog) { + clearBuffers(Channel3751); + } - frameActionGeneric(1,0); + frameActionGeneric(ChannelMode::Analog, ChannelMode::Off); break; - case 1: - if (deviceMode_prev != 0 && deviceMode_prev != 1 && deviceMode_prev != 2) - clearBuffers(true, false, false); + case DeviceCH1AnalogCH2Digital: + if (deviceMode_prev != DeviceCH1Analog && deviceMode_prev != 1 && deviceMode_prev != DeviceCH1AnalogCH2Analog) { + clearBuffers(Channel3751); + } - if (deviceMode_prev != 1) - clearBuffers(false, true, false); + if (deviceMode_prev != DeviceCH1AnalogCH2Digital) { + clearBuffers(Channel3752); + } internalBuffer375_CH2->m_channel = 1; - frameActionGeneric(1,2); + frameActionGeneric(ChannelMode::Analog, ChannelMode::Digital); if(serialDecodeEnabled_CH1 && serialType == 0){ internalBuffer375_CH2->serialManage(baudRate_CH1, parity_CH1, hexDisplay_CH1); } break; - case 2: - if (deviceMode_prev != 0 && deviceMode_prev != 1 && deviceMode_prev != 2) - clearBuffers(true, false, false); - if (deviceMode_prev != 2) - clearBuffers(false, true, false); + case DeviceCH1AnalogCH2Analog: + if (deviceMode_prev != DeviceCH1Analog && deviceMode_prev != DeviceCH1AnalogCH2Digital && deviceMode_prev != DeviceCH1AnalogCH2Analog) { + clearBuffers(Channel3751); + } + if (deviceMode_prev != DeviceCH1AnalogCH2Analog) { + clearBuffers(Channel3752); + } - frameActionGeneric(1,1); + frameActionGeneric(ChannelMode::Analog, ChannelMode::Analog); break; - case 3: - if (deviceMode_prev != 3 && deviceMode_prev != 4) - clearBuffers(true, false, false); + case DeviceCH1Digital: + if (deviceMode_prev != DeviceCH1Digital && deviceMode_prev != DeviceCH1DigitalCH2Digital) { + clearBuffers(Channel3751); + } - frameActionGeneric(2,0); + frameActionGeneric(ChannelMode::Digital, ChannelMode::Off); if(serialDecodeEnabled_CH1 && serialType == 0){ internalBuffer375_CH1->serialManage(baudRate_CH1, parity_CH1, hexDisplay_CH1); } break; - case 4: - if (deviceMode_prev != 3 && deviceMode_prev != 4) - clearBuffers(true, false, false); - if (deviceMode_prev != 4) - clearBuffers(false, true, false); + case DeviceCH1DigitalCH2Digital: + if (deviceMode_prev != DeviceCH1Digital && deviceMode_prev != DeviceCH1DigitalCH2Digital) { + clearBuffers(Channel3751); + } + if (deviceMode_prev != DeviceCH1DigitalCH2Digital) { + clearBuffers(Channel3752); + } internalBuffer375_CH2->m_channel = 2; - frameActionGeneric(2,2); + frameActionGeneric(ChannelMode::Digital, ChannelMode::Digital); if(serialDecodeEnabled_CH1 && serialType == 0){ internalBuffer375_CH1->serialManage(baudRate_CH1, parity_CH1, hexDisplay_CH1); } @@ -140,14 +170,16 @@ void isoDriver::timerTick(void){ break; case 5: break; - case 6: - if (deviceMode_prev != 6) - clearBuffers(false, false, true); - frameActionGeneric(-1,0); + case DeviceCH1Analog750: + if (deviceMode_prev != DeviceCH1Analog750) { + clearBuffers(Channel750); + } + frameActionGeneric(ChannelMode::Analog750, ChannelMode::Off); break; - case 7: - if (deviceMode_prev != 7) - clearBuffers(true, false, false); + case DeviceMultimeter: + if (deviceMode_prev != DeviceMultimeter) { + clearBuffers(Channel3751); + } multimeterAction(); break; default: @@ -174,9 +206,9 @@ void isoDriver::analogConvert(short *shortPtr, QVector *doublePtr, int T double *data = doublePtr->data(); for (int i=0;ideviceMode != 7) data[i] += ref; + if (driver->deviceMode != DeviceMultimeter) data[i] += ref; #ifdef INVERT_MM - if(driver->deviceMode == 7) data[i] *= -1; + if(driver->deviceMode == DeviceMultimeter) data[i] *= -1; #endif accumulated += data[i]; @@ -238,117 +270,52 @@ void isoDriver::startTimer(){ //qFatal("ISO TIMER STARTED");*/ } -void isoDriver::clearBuffers(bool ch3751, bool ch3752, bool ch750){ +void isoDriver::clearChannelBuffers(bool ch3751, bool ch3752, bool ch750){ if(ch3751) internalBuffer375_CH1->clearBuffer(); if(ch3752) internalBuffer375_CH2->clearBuffer(); if(ch750) internalBuffer750->clearBuffer(); + total_read = 0; +} + +void isoDriver::clearBuffers(const Channels channels) +{ + if (channels & Channel3751) { + internalBuffer375_CH1->clearBuffer(); + } + if (channels & Channel3752) { + internalBuffer375_CH2->clearBuffer(); + } + if (channels & Channel750) { + internalBuffer750->clearBuffer(); + } + + total_read = 0; } void isoDriver::setVisible_CH2(bool visible){ axes->graph(1)->setVisible(visible); } -void isoDriver::setVoltageRange(QWheelEvent* event) +void isoDriver::onWheelEvent(QWheelEvent* event) { if(doNotTouchGraph && !fileModeEnabled) return; bool isProperlyPaused = properlyPaused(); double maxWindowSize = fileModeEnabled ? daq_maxWindowSize : ((double)MAX_WINDOW_SIZE); - display.setVoltageRange(event, isProperlyPaused, maxWindowSize, axes); + display.setVoltageRange(event->position(), event->angleDelta(), event->modifiers(), isProperlyPaused, maxWindowSize, axes); if (!(event->modifiers() == Qt::ControlModifier)) if (autoGainEnabled && !isProperlyPaused) autoGain(); } -void DisplayControl::setVoltageRange (QWheelEvent* event, bool isProperlyPaused, double maxWindowSize, QCustomPlot* axes) -{ - if (!(event->modifiers() == Qt::ControlModifier) && event->orientation() == Qt::Orientation::Vertical) { - double c = (topRange - botRange) / (double)400; - - QCPRange range = axes->yAxis->range(); - - double pixPct = (double)100 - ((double)100 * (((double)axes->yAxis->pixelToCoord(event->y())-range.lower) / range.size())); - if (pixPct < 0) pixPct = 0; - if (pixPct > 100) pixPct = 100; - - qDebug() << "WHEEL @ " << pixPct << "%"; - qDebug() << range.upper; - - topRange -= event->delta() / 120.0 * c * pixPct; - botRange += event->delta() / 120.0 * c * (100.0 - pixPct); - - if (topRange > (double)20) topRange = (double)20; - if (botRange < -(double)20) botRange = (double)-20; - topRangeUpdated(topRange); - botRangeUpdated(botRange); - } - else - { - double c = (window) / (double)200; - QCPRange range = axes->xAxis->range(); - - double pixPct = (double)100 * ((double)axes->xAxis->pixelToCoord(event->x()) - range.lower); - - pixPct /= isProperlyPaused ? (double)(range.upper - range.lower) - : (double)(window); - - if (pixPct < 0) - pixPct = 0; - - if (pixPct > 100) - pixPct = 100; - - qDebug() << "WHEEL @ " << pixPct << "%"; - qDebug() << event->delta(); - - if (! isProperlyPaused) - { - qDebug() << "TIGGERED"; - qDebug() << "upper = " << range.upper << "lower = " << range.lower; - qDebug() << "window = " << window; - qDebug() << c * ((double)pixPct); - qDebug() << c * ((double)100 - (double)pixPct) * pixPct / 100; - } - - window -= event->delta() / 120.0 * c * pixPct; - delay += event->delta() / 120.0 * c * (100.0 - pixPct) * pixPct / 100.0; - - // NOTE: delayUpdated and timeWindowUpdated are called more than once beyond here, - // maybe they should only be called once at the end? - - delayUpdated(delay); - timeWindowUpdated(window); - - qDebug() << window << delay; - - if (window > maxWindowSize) - { - window = maxWindowSize; - timeWindowUpdated(window); - } - if ((window + delay) > maxWindowSize) - { - delay = maxWindowSize - window; - delayUpdated(delay); - } - if (delay < 0) - { - delay = 0; - delayUpdated(delay); - } - - } - -} - bool isoDriver::properlyPaused(){ if(paused_CH1 & paused_CH2){ qDebug() << "Properly paused"; return true; } - if ((driver->deviceMode == 0) || (driver->deviceMode == 3) || (driver->deviceMode == 6)){ + if ((driver->deviceMode == DeviceCH1Analog) || (driver->deviceMode == DeviceCH1Digital) || (driver->deviceMode == DeviceCH1Analog750)){ if(paused_CH1) qDebug() << "Properly paused"; else qDebug() << "Not properly paused"; return paused_CH1; } @@ -365,11 +332,13 @@ void isoDriver::pauseEnable_CH1(bool enabled){ if(!properlyPaused()) { display.delay = 0; - delayUpdated(display.delay); + emit delayUpdated(display.delay); if (autoGainEnabled) autoGain(); } - if(!enabled) clearBuffers(1,0,1); + if (!enabled) { + clearBuffers(Channel3751 | Channel750); + } qDebug() << "pauseEnable_CH1" << enabled; } @@ -379,11 +348,14 @@ void isoDriver::pauseEnable_CH2(bool enabled){ if(!properlyPaused()){ display.delay = 0; - delayUpdated(display.delay); + emit delayUpdated(display.delay); if (autoGainEnabled) autoGain(); } - if(!enabled) clearBuffers(0,1,0); + if (!enabled) { + clearBuffers(Channel3752); + } + qDebug() << "pauseEnable_CH2" << enabled; } void isoDriver::pauseEnable_multimeter(bool enabled){ @@ -391,10 +363,12 @@ void isoDriver::pauseEnable_multimeter(bool enabled){ if(!properlyPaused()) { display.delay = 0; - delayUpdated(display.delay); + emit delayUpdated(display.delay); } - if(!enabled) clearBuffers(1,0,0); + if (!enabled) { + clearBuffers(Channel3751); + } qDebug() << "pauseEnable_multimeter" << enabled; } @@ -408,7 +382,7 @@ void isoDriver::autoGain(){ for (int i=0;i<8;i++){ if (maxgain>snap[i]){ - setGain(snap[i]); + emit setGain(snap[i]); return; } } @@ -419,14 +393,29 @@ void isoDriver::gainBuffers(double multiplier){ QTimer::singleShot(TIMER_PERIOD*4, this, SLOT(gainTick())); } -void isoDriver::gainTick(void){ +void isoDriver::gainTick(){ #ifdef PLATFORM_ANDROID #warning: "gainTick does nothing on Android!!" #else qDebug() << "Multiplying by " << multi; - if (driver->deviceMode <5) internalBuffer375_CH1->gainBuffer(log2(multi)); - if ((driver->deviceMode == 1) | (driver->deviceMode == 2) | (driver->deviceMode == 4)) internalBuffer375_CH2->gainBuffer(log2(multi)); - if ((driver->deviceMode == 6) | (driver->deviceMode == 7)) internalBuffer750->gainBuffer(log2(multi)); + if (driver->deviceMode <= DeviceCH1DigitalCH2Digital) { + internalBuffer375_CH1->gainBuffer(log2(multi)); + } + + switch(driver->deviceMode) { + case DeviceCH1AnalogCH2Digital: + case DeviceCH1AnalogCH2Analog: + case DeviceCH1DigitalCH2Digital: + internalBuffer375_CH2->gainBuffer(log2(multi)); + break; + case DeviceCH1Analog750: + case DeviceMultimeter: + internalBuffer750->gainBuffer(log2(multi)); + break; + default: + qWarning() << "Invalid device mode" << driver->deviceMode; + break; + } #endif } @@ -490,11 +479,9 @@ void isoDriver::cursorEnableVert(bool enabled){ axes->graph(3)->setVisible(enabled); } -void isoDriver::udateCursors(void){ +void isoDriver::udateCursors(){ if(!(vertCursorEnabled || horiCursorEnabled)){ -#if QCP_VER == 1 - cursorTextPtr->setVisible(0); -#endif + cursorTextPtr->setVisible(false); return; } @@ -528,12 +515,12 @@ void isoDriver::udateCursors(void){ axes->graph(4)->setData(hori0x, hori0y); axes->graph(5)->setData(hori1x, hori1y); } -#if QCP_VER == 1 + cursorTextPtr->setVisible(cursorStatsEnabled); -#endif + if (!cursorStatsEnabled) return; - QString *cursorStatsString = new QString(); + QString cursorStatsString; v0->value = display.y0; v1->value = display.y1; @@ -541,38 +528,29 @@ void isoDriver::udateCursors(void){ t0->value = display.x0; t1->value = display.x1; dt->value = fabs(display.x0 - display.x1); - f->value = 1 / (display.x1 - display.x0); - - char temp_hori[64]; - char temp_vert[64]; - char temp_separator[2]; - sprintf(temp_hori, "V0=%s, V1=%s, ΔV=%s", v0->printVal(), v1->printVal(), dv->printVal()); - sprintf(temp_vert, "t0=%s, t1=%s, Δt=%s, f=%s", t0->printVal(), t1->printVal(), dt->printVal(), f->printVal()); - sprintf(temp_separator, "\n"); - - //sprintf(temp, "hello!"); - if(horiCursorEnabled) cursorStatsString->append(temp_hori); - if(horiCursorEnabled && vertCursorEnabled) cursorStatsString->append(temp_separator); - if(vertCursorEnabled) cursorStatsString->append(temp_vert); - //qDebug() << temp; -#if QCP_VER == 1 - cursorTextPtr->setText(*(cursorStatsString)); -#endif - delete cursorStatsString; + f->value = display.x1 != display.x0 ? 1 / (display.x1 - display.x0) : 0.; + + const QString temp_hori = QString::asprintf("V0=%s, V1=%s, ΔV=%s", v0->printVal(), v1->printVal(), dv->printVal()); + const QString temp_vert = QString::asprintf("t0=%s, t1=%s, Δt=%s, f=%s", t0->printVal(), t1->printVal(), dt->printVal(), f->printVal()); + + if(horiCursorEnabled) cursorStatsString.append(temp_hori); + if(horiCursorEnabled && vertCursorEnabled) cursorStatsString.append("\n"); + if(vertCursorEnabled) cursorStatsString.append(temp_vert); + cursorTextPtr->setText(cursorStatsString); } short isoDriver::reverseFrontEnd(double voltage){ //qFatal("reverseFrontEnd driver mode 7"); #ifdef INVERT_MM - if(driver->deviceMode == 7) voltage *= -1; + if(driver->deviceMode == DeviceMultimeter) voltage *= -1; #endif double vn = vcc * (R2/(R1+R2)); double vx = vn + (voltage - vn) * (R4 / (R3+R4)); - double TOP = (driver->deviceMode == 7) ? 2048 : 128; + double TOP = (driver->deviceMode == DeviceMultimeter) ? 2048 : 128; - if (driver->deviceMode == 7){ + if (driver->deviceMode == DeviceMultimeter){ qDebug() << "SEEEKING"; qDebug() << ((vx - vn)/vref * (double)driver->scopeGain * (double)TOP + (double)0.5); qDebug() << "SEEEKING"; @@ -593,7 +571,7 @@ void isoDriver::setTriggerEnabled(bool enabled) void isoDriver::setTriggerLevel(double level) { - internalBuffer375_CH1->setTriggerLevel(level, (driver->deviceMode == 7 ? 2048 : 128), AC_CH1); + internalBuffer375_CH1->setTriggerLevel(level, (driver->deviceMode == DeviceMultimeter ? 2048 : 128), AC_CH1); internalBuffer375_CH2->setTriggerLevel(level, 128, AC_CH2); internalBuffer750->setTriggerLevel(level, 128, AC_CH1); triggerStateChanged(); @@ -612,65 +590,48 @@ void isoDriver::setTriggerMode(int newMode) } //0 for off, 1 for ana, 2 for dig, -1 for ana750, -2 for file -void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) +void isoDriver::frameActionGeneric(const ChannelMode CH1_mode, const ChannelMode CH2_mode) { //qDebug() << "made it to frameActionGeneric"; - if(!paused_CH1 && CH1_mode == - 1){ + if(!paused_CH1 && CH1_mode == ChannelMode::Analog750) { for (unsigned int i=0;i<(length/ADC_SPF);i++){ internalBuffer750->writeBuffer_char(&isoTemp[ADC_SPF*i], VALID_DATA_PER_750); } } - if(!paused_CH1 && CH1_mode > 0){ + if(!paused_CH1 && (CH1_mode == ChannelMode::Analog || CH1_mode == ChannelMode::Digital)){ for (unsigned int i=0;i<(length/ADC_SPF);i++){ internalBuffer375_CH1->writeBuffer_char(&isoTemp[ADC_SPF*i], VALID_DATA_PER_375); } } - if(!paused_CH2 && CH2_mode > 0){ + if(!paused_CH2 && (CH2_mode == ChannelMode::Analog || CH2_mode == ChannelMode::Digital)){ for (unsigned int i=0;i<(length/ADC_SPF);i++){ internalBuffer375_CH2->writeBuffer_char(&isoTemp[ADC_SPF*i+ADC_SPF/2], VALID_DATA_PER_375); //+375 to get the second half of the packet } } - if(!paused_CH1) - { - int offset = -2; //No trigger! - - int backLength = length/750; - backLength *= (CH1_mode == -1) ? VALID_DATA_PER_750 : VALID_DATA_PER_375; - - if(offset>0){ - int temp_offset = offset % 750; - offset /= 750; - offset *= (CH1_mode == -1) ? VALID_DATA_PER_750 : VALID_DATA_PER_375; - offset += temp_offset; - } - - //qDebug() << "Now offset = " << offset; - } - double triggerDelay = 0; if (triggerEnabled) { - isoBuffer* internalBuffer_CH1 = (CH1_mode == -1) ? internalBuffer750 : internalBuffer375_CH1; + isoBuffer* internalBuffer_CH1 = (CH1_mode == ChannelMode::Analog750) ? internalBuffer750 : internalBuffer375_CH1; triggerDelay = (triggerMode < 2) ? internalBuffer_CH1->getDelayedTriggerPoint(display.window) - display.window : internalBuffer375_CH2->getDelayedTriggerPoint(display.window) - display.window; - - if (triggerDelay < 0) - triggerDelay = 0; } - if(singleShotEnabled && (triggerDelay != 0)) - singleShotTriggered(1); + if(singleShotEnabled && (triggerDelay > 0)) + emit singleShotTriggered(true); - readData375_CH1 = internalBuffer375_CH1->readBuffer(display.window,GRAPH_SAMPLES,CH1_mode==2, display.delay + triggerDelay); - if(CH2_mode) readData375_CH2 = internalBuffer375_CH2->readBuffer(display.window,GRAPH_SAMPLES,CH2_mode==2, display.delay + triggerDelay); - if(CH1_mode == -1) readData750 = internalBuffer750->readBuffer(display.window,GRAPH_SAMPLES,false, display.delay + triggerDelay); - if(CH1_mode == -2) readDataFile = internalBufferFile->readBuffer(display.window,GRAPH_SAMPLES,false, display.delay); + if (triggerDelay < 0) + triggerDelay = 0; + + readData375_CH1 = internalBuffer375_CH1->readBuffer(display.window,GRAPH_SAMPLES,CH1_mode==ChannelMode::Digital, display.delay + triggerDelay); + if(CH2_mode != ChannelMode::Off) readData375_CH2 = internalBuffer375_CH2->readBuffer(display.window,GRAPH_SAMPLES, CH2_mode==ChannelMode::Digital, display.delay + triggerDelay); + if(CH1_mode == ChannelMode::Analog750) readData750 = internalBuffer750->readBuffer(display.window,GRAPH_SAMPLES,false, display.delay + triggerDelay); + if(CH1_mode == ChannelMode::File) readDataFile = internalBufferFile->readBuffer(display.window,GRAPH_SAMPLES,false, display.delay); QVector x(GRAPH_SAMPLES), CH1(GRAPH_SAMPLES), CH2(GRAPH_SAMPLES); - if (CH1_mode == 1){ + if (CH1_mode == ChannelMode::Analog){ analogConvert(readData375_CH1.get(), &CH1, 128, AC_CH1, 1); for (int i=0; i < GRAPH_SAMPLES; i++) { @@ -679,11 +640,11 @@ void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) } xmin = (currentVmin < xmin) ? currentVmin : xmin; xmax = (currentVmax > xmax) ? currentVmax : xmax; - broadcastStats(0); + broadcastStats(false); } - if (CH1_mode == 2) digitalConvert(readData375_CH1.get(), &CH1); + if (CH1_mode == ChannelMode::Digital) digitalConvert(readData375_CH1.get(), &CH1); - if (CH2_mode == 1){ + if (CH2_mode == ChannelMode::Analog){ analogConvert(readData375_CH2.get(), &CH2, 128, AC_CH2, 2); for (int i=0; i < GRAPH_SAMPLES; i++) { @@ -692,23 +653,23 @@ void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) } ymin = (currentVmin < ymin) ? currentVmin : ymin; ymax = (currentVmax > ymax) ? currentVmax : ymax; - broadcastStats(1); + broadcastStats(true); } - if (CH2_mode == 2) digitalConvert(readData375_CH2.get(), &CH2); + if (CH2_mode == ChannelMode::Digital) digitalConvert(readData375_CH2.get(), &CH2); - if(CH1_mode == -1) { + if(CH1_mode == ChannelMode::Analog750) { analogConvert(readData750.get(), &CH1, 128, AC_CH1, 1); xmin = (currentVmin < xmin) ? currentVmin : xmin; xmax = (currentVmax > xmax) ? currentVmax : xmax; - broadcastStats(0); + broadcastStats(false); } - if(CH1_mode == -2) { + if(CH1_mode == ChannelMode::File) { fileStreamConvert(readDataFile, &CH1); } - for (double i=0; i0) { CH1[i] = 0; @@ -725,7 +686,7 @@ void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) axes->yAxis->setRange(ymin, ymax); }else{ axes->graph(0)->setData(x,CH1); - if(CH2_mode) axes->graph(1)->setData(x,CH2); + if(CH2_mode != ChannelMode::Off) axes->graph(1)->setData(x,CH2); axes->xAxis->setRange(-display.window - display.delay, -display.delay); axes->yAxis->setRange(display.topRange, display.botRange); } @@ -762,7 +723,7 @@ void isoDriver::frameActionGeneric(char CH1_mode, char CH2_mode) } void isoDriver::multimeterAction(){ - isoTemp_short = (short *)isoTemp; + isoTemp_short = (short *)isoTemp.get(); if(!paused_multimeter){ for (unsigned int i=0;i<(length/ADC_SPF);i++){ internalBuffer375_CH1->writeBuffer_short(&isoTemp_short[ADC_SPF/2*i], ADC_SPF/2-1); //Offset because the first 8 bytes of the array contain the length (no samples!!)! @@ -778,15 +739,16 @@ void isoDriver::multimeterAction(){ triggerDelay = 0; } - if(singleShotEnabled && (triggerDelay != 0)) - singleShotTriggered(1); + if(singleShotEnabled && (triggerDelay != 0)) { + emit singleShotTriggered(true); + } readData375_CH1 = internalBuffer375_CH1->readBuffer(display.window,GRAPH_SAMPLES, false, display.delay + triggerDelay); QVector x(GRAPH_SAMPLES), CH1(GRAPH_SAMPLES); - analogConvert(readData375_CH1.get(), &CH1, 2048, 0, 1); //No AC coupling! + analogConvert(readData375_CH1.get(), &CH1, 2048, false, 1); //No AC coupling! - for (double i=0; i0) { CH1[i] = 0; @@ -816,13 +778,13 @@ void isoDriver::setMultimeterType(int type){ switch (type){ case R: - multimeterREnabled(multimeterRsource); + emit multimeterREnabled(multimeterRsource); break; case C: - multimeterREnabled(254); + emit multimeterREnabled(254); break; default: - multimeterREnabled(255); + emit multimeterREnabled(255); } qDebug() << "multimeterType = " << multimeterType; @@ -840,7 +802,16 @@ void isoDriver::multimeterStats(){ QTimer::singleShot(MULTIMETER_PERIOD, this, SLOT(enableMM())); multimeterShow = false; - bool mvMax, mvMin, mvMean, mvRMS, maMax, maMin, maMean, maRMS, kOhms, uFarads; //We'll let the compiler work out this one. + bool mvMax = false; + bool mvMin = false; + bool mvMean = false; + bool mvRMS = false; + bool maMax = false; + bool maMin = false; + bool maMean = false; + bool maRMS = false; + bool kOhms = false; + bool uFarads = false; //We'll let the compiler work out this one. if(autoMultimeterV){ mvMax = abs(currentVmax) < 1.; @@ -896,57 +867,57 @@ void isoDriver::multimeterStats(){ if(multimeterType == V){ if(mvMax){ currentVmax *= 1000; - sendMultimeterLabel1("Max (mV)"); - }else sendMultimeterLabel1("Max (V)"); + emit sendMultimeterLabel1("Max (mV)"); + }else emit sendMultimeterLabel1("Max (V)"); if(mvMin){ currentVmin *= 1000; - sendMultimeterLabel2("Min (mV)"); - }else sendMultimeterLabel2("Min (V)"); + emit sendMultimeterLabel2("Min (mV)"); + }else emit sendMultimeterLabel2("Min (V)"); if(mvMean){ currentVmean *= 1000; - sendMultimeterLabel3("Mean (mV)"); - }else sendMultimeterLabel3("Mean (V)"); + emit sendMultimeterLabel3("Mean (mV)"); + }else emit sendMultimeterLabel3("Mean (V)"); if(mvRMS){ currentVRMS *= 1000; - sendMultimeterLabel4("RMS (mV)"); - }else sendMultimeterLabel4("RMS (V)"); + emit sendMultimeterLabel4("RMS (mV)"); + }else emit sendMultimeterLabel4("RMS (V)"); - multimeterMax(currentVmax); - multimeterMin(currentVmin); - multimeterMean(currentVmean); - multimeterRMS(currentVRMS); + emit multimeterMax(currentVmax); + emit multimeterMin(currentVmin); + emit multimeterMean(currentVmean); + emit multimeterRMS(currentVRMS); return; } if(multimeterType == I){ if(maMax){ currentVmax *= 1000; - sendMultimeterLabel1("Max (mA)"); - }else sendMultimeterLabel1("Max (A)"); + emit sendMultimeterLabel1("Max (mA)"); + }else emit sendMultimeterLabel1("Max (A)"); if(maMin){ currentVmin *= 1000; - sendMultimeterLabel2("Min (mA)"); - }else sendMultimeterLabel2("Min (A)"); + emit sendMultimeterLabel2("Min (mA)"); + }else emit sendMultimeterLabel2("Min (A)"); if(maMean){ currentVmean *= 1000; - sendMultimeterLabel3("Mean (mA)"); - }else sendMultimeterLabel3("Mean (A)"); + emit sendMultimeterLabel3("Mean (mA)"); + }else emit sendMultimeterLabel3("Mean (A)"); if(maRMS){ currentVRMS *= 1000; - sendMultimeterLabel4("RMS (mA)"); - }else sendMultimeterLabel4("RMS (A)"); + emit sendMultimeterLabel4("RMS (mA)"); + }else emit sendMultimeterLabel4("RMS (A)"); - multimeterMax(currentVmax / seriesResistance); - multimeterMin(currentVmin / seriesResistance); - multimeterMean(currentVmean / seriesResistance); - multimeterRMS(currentVRMS / seriesResistance); + emit multimeterMax(currentVmax / seriesResistance); + emit multimeterMin(currentVmin / seriesResistance); + emit multimeterMean(currentVmean / seriesResistance); + emit multimeterRMS(currentVRMS / seriesResistance); return; } @@ -968,9 +939,9 @@ void isoDriver::multimeterStats(){ //qDebug() << "Vrat = " << Vrat; //qDebug() << "Rp = " << Rp; //qDebug() << "estimated_resistance = " << estimated_resistance; - multimeterMax(0); - multimeterMin(0); - multimeterMean(0); + emit multimeterMax(0); + emit multimeterMin(0); + emit multimeterMean(0); if(autoMultimeterR){ kOhms = (estimated_resistance) > 1000; @@ -978,9 +949,9 @@ void isoDriver::multimeterStats(){ if(kOhms){ estimated_resistance /= 1000; - sendMultimeterLabel4("Resistance (kΩ)"); - }else sendMultimeterLabel4("Resistance (Ω)"); - multimeterRMS(estimated_resistance); + emit sendMultimeterLabel4("Resistance (kΩ)"); + }else emit sendMultimeterLabel4("Resistance (Ω)"); + emit multimeterRMS(estimated_resistance); } if(multimeterType == C){ double cap_vbot = 0.8; @@ -1015,13 +986,13 @@ void isoDriver::multimeterStats(){ } if(uFarads){ - sendMultimeterLabel4("Capacitance (μF)"); + emit sendMultimeterLabel4("Capacitance (μF)"); Cm = Cm*1000000; } else { - sendMultimeterLabel4("Capacitance (nF)"); + emit sendMultimeterLabel4("Capacitance (nF)"); Cm = Cm*1000000000; } - multimeterRMS(Cm); + emit multimeterRMS(Cm); } } @@ -1122,24 +1093,24 @@ void isoDriver::setXYmode(bool enabled){ } void isoDriver::triggerGroupStateChange(bool enabled){ - if(enabled) sendTriggerValue((currentVmax-currentVmin)*0.85 + currentVmin); + if(enabled) emit sendTriggerValue((currentVmax-currentVmin)*0.85 + currentVmin); } void isoDriver::broadcastStats(bool CH2){ if(CH2){ if(!update_CH2) return; update_CH2 = false; - sendVmax_CH2(currentVmax); - sendVmin_CH2(currentVmin); - sendVmean_CH2(currentVmean); - sendVRMS_CH2(currentVRMS); + emit sendVmax_CH2(currentVmax); + emit sendVmin_CH2(currentVmin); + emit sendVmean_CH2(currentVmean); + emit sendVRMS_CH2(currentVRMS); } else{ if(!update_CH1) return; update_CH1 = false; - sendVmax_CH1(currentVmax); - sendVmin_CH1(currentVmin); - sendVmean_CH1(currentVmean); - sendVRMS_CH1(currentVRMS); + emit sendVmax_CH1(currentVmax); + emit sendVmin_CH1(currentVmin); + emit sendVmean_CH1(currentVmean); + emit sendVRMS_CH1(currentVRMS); } } @@ -1152,24 +1123,24 @@ void isoDriver::setTopRange(double newTop) { // NOTE: Should this be clamped to 20? display.topRange = newTop; - topRangeUpdated(display.topRange); + emit topRangeUpdated(display.topRange); } void isoDriver::setBotRange(double newBot) { // NOTE: Should this be clamped to 20? display.botRange = newBot; - botRangeUpdated(display.botRange); + emit botRangeUpdated(display.botRange); } void isoDriver::setTimeWindow(double newWindow){ display.window = newWindow; - timeWindowUpdated(display.window); + emit timeWindowUpdated(display.window); } void isoDriver::setDelay(double newDelay){ display.delay = newDelay; - delayUpdated(display.delay); + emit delayUpdated(display.delay); } void isoDriver::takeSnapshot(QString *fileName, unsigned char channel){ @@ -1198,13 +1169,16 @@ double isoDriver::meanVoltageLast(double seconds, unsigned char channel, int TOP case 3: currentBuffer = internalBuffer750; break; + default: + qWarning() << "Invalid channel!" << channel; + return 0; } - std::unique_ptr tempBuffer = currentBuffer->readBuffer(seconds, 1024, 0, 0); + std::unique_ptr tempBuffer = currentBuffer->readBuffer(seconds, 1024, false, 0); double sum = 0; double temp; for(int i = 0; i<1024; i++){ - temp = currentBuffer->sampleConvert(tempBuffer[i], TOP, 0); + temp = currentBuffer->sampleConvert(tempBuffer[i], TOP, false); sum += temp; } return sum / 1024; @@ -1216,7 +1190,7 @@ void isoDriver::rSourceChanged(int newSource){ void isoDriver::serialNeedsDisabling(int channel){ qDebug("isoDriver acknowledges disconnect from channel %d", channel); - mainWindowPleaseDisableSerial(channel); + emit mainWindowPleaseDisableSerial(channel); } //Thank you https://stackoverflow.com/questions/27318631/parsing-through-a-csv-file-in-qt @@ -1225,9 +1199,7 @@ void isoDriver::loadFileBuffer(QFile *fileToLoad){ disableFileMode(); - if(internalBufferFile != NULL){ - delete internalBufferFile; - } + delete internalBufferFile; //Load the file if (!fileToLoad->open(QIODevice::ReadOnly)) { @@ -1271,7 +1243,7 @@ void isoDriver::loadFileBuffer(QFile *fileToLoad){ tempList.clear(); } - qDebug("There are %d elements!", numel); + qDebug("There are %llu elements!", numel); //Prompt user for start and end times double defaultSampleRate = 375000; @@ -1283,8 +1255,8 @@ void isoDriver::loadFileBuffer(QFile *fileToLoad){ qDebug() << "maxTime =" << maxTime; daqLoadPrompt dlp(this, minTime, maxTime); - connect(&dlp, SIGNAL(startTime(double)), this, SLOT(daqLoad_startChanged(double))); - connect(&dlp, SIGNAL(endTime(double)), this, SLOT(daqLoad_endChanged(double))); + connect(&dlp, &daqLoadPrompt::startTime, this, &isoDriver::daqLoad_startChanged); + connect(&dlp, &daqLoadPrompt::endTime, this, &isoDriver::daqLoad_endChanged); //Defaults daqLoad_startTime = minTime; @@ -1350,13 +1322,11 @@ void isoDriver::loadFileBuffer(QFile *fileToLoad){ qDebug() << "Initialising timer"; //Initialise the file timer. - if (fileTimer != NULL){ - delete fileTimer; - } + delete fileTimer; fileTimer = new QTimer(); fileTimer->setTimerType(Qt::PreciseTimer); fileTimer->start(TIMER_PERIOD); - connect(fileTimer, SIGNAL(timeout()), this, SLOT(fileTimerTick())); + connect(fileTimer, &QTimer::timeout, this, &isoDriver::fileTimerTick); qDebug() << "File Buffer loaded!"; enableFileMode(); qDebug() << "File Mode Enabled"; @@ -1374,19 +1344,19 @@ void isoDriver::daqLoad_endChanged(double newEnd){ void isoDriver::fileTimerTick(){ //qDebug() << "isoDriver::fileTimerTick()"; - frameActionGeneric(-2,0); + frameActionGeneric(ChannelMode::File, ChannelMode::Off); } void isoDriver::enableFileMode(){ fileModeEnabled = true; daq_maxWindowSize = daqLoad_endTime - daqLoad_startTime; - showRealtimeButton(true); + emit showRealtimeButton(true); } void isoDriver::disableFileMode(){ fileModeEnabled = false; - showRealtimeButton(false); - if(fileTimer != NULL){ + emit showRealtimeButton(false); + if(fileTimer != nullptr){ fileTimer->stop(); } @@ -1395,17 +1365,17 @@ void isoDriver::disableFileMode(){ if (display.window > mws) { display.window = mws; - timeWindowUpdated(display.window); + emit timeWindowUpdated(display.window); } if ((display.window + display.delay) > mws) { display.delay -= display.window + display.delay - mws; - delayUpdated(display.delay); + emit delayUpdated(display.delay); } if (display.delay < 0) { display.delay = 0; - delayUpdated(display.delay); + emit delayUpdated(display.delay); } } @@ -1524,3 +1494,10 @@ void isoDriver::setHexDisplay_CH2(bool enabled) { hexDisplay_CH2 = enabled; } + +void isoDriver::setDownsampleMethod(const DownsamplingMethod method) +{ + internalBuffer375_CH1->setDownsampleMethod(method); + internalBuffer375_CH2->setDownsampleMethod(method); + internalBuffer750->setDownsampleMethod(method); +} diff --git a/Desktop_Interface/isodriver.h b/Desktop_Interface/isodriver.h index cabb288e..60d66211 100644 --- a/Desktop_Interface/isodriver.h +++ b/Desktop_Interface/isodriver.h @@ -5,12 +5,13 @@ #include #include #include -#include "qcustomplot.h" +#include #include "genericusbdriver.h" #include "desktop_settings.h" #include "siprint.h" #include "i2cdecoder.h" #include "uartstyledecoder.h" +#include "DisplayControl.h" class isoBuffer; class isoBuffer_file; @@ -25,44 +26,38 @@ class isoBuffer_file; // That is one of the things I plan on fixing, and in fact // the reason why I began the commenting! -class DisplayControl : public QObject +class isoDriver : public QLabel { Q_OBJECT public: + enum Channel { + Channel3751 = 1 << 0, + Channel3752 = 1 << 1, + Channel750 = 1 << 2, + }; + Q_DECLARE_FLAGS(Channels, Channel); + Q_FLAG(Channel); - double delay = 0; - double window = 0.01; - double y0 = 0; - double y1 = 0; - double x0 = 0; - double x1 = 0; - double topRange = 2.5; - double botRange = -0.5; - - void setVoltageRange (QWheelEvent* event, bool isProperlyPaused, double maxWindowSize, QCustomPlot* axes); + enum class ChannelMode { + Off = 0, + Analog = 1, + Digital = 2, + Analog750 = -1, + File = -2 + }; + Q_ENUM(ChannelMode); -signals: - void topRangeUpdated(double); - void botRangeUpdated(double); - void timeWindowUpdated(double); - void delayUpdated(double); -}; + explicit isoDriver(QWidget *parent = nullptr); + ~isoDriver(); -class isoDriver : public QLabel -{ - Q_OBJECT -public: - explicit isoDriver(QWidget *parent = 0); void autoGain(void); //Generic Vars isoBuffer *internalBuffer375_CH1; isoBuffer *internalBuffer375_CH2; isoBuffer *internalBuffer750; - isoBuffer_file *internalBufferFile = NULL; -#if QCP_VER == 1 + isoBuffer_file *internalBufferFile = nullptr; QCPItemText *cursorTextPtr; -#endif - genericUsbDriver *driver; + QPointer driver; bool doNotTouchGraph = true; double ch1_ref = 1.65; double ch2_ref = 1.65; @@ -88,6 +83,11 @@ class isoDriver : public QLabel //DAQ bool fileModeEnabled = false; double daq_maxWindowSize; + + double vMax() const { return qMax(xmax, ymax); } + double vMin() const { return qMin(xmin, ymin); } + long numSamples() const { return total_read; } + private: //Those bloody bools that just Enable/Disable a single property bool paused_CH1 = false; @@ -132,16 +132,16 @@ class isoDriver : public QLabel short reverseFrontEnd(double voltage); void multimeterAction(); void broadcastStats(bool CH2); - void frameActionGeneric(char CH1_mode, char CH2_mode); + void frameActionGeneric(const ChannelMode CH1_mode, const ChannelMode CH2_mode); void triggerStateChanged(); //Variables that are just pointers to other classes/vars - QCustomPlot *axes; // TODO: move into DisplayControl + QPointer axes; // TODO: move into DisplayControl std::unique_ptr readData375_CH1; std::unique_ptr readData375_CH2; std::unique_ptr readData750; float *readDataFile; - char *isoTemp = NULL; - short *isoTemp_short = NULL; + std::shared_ptr isoTemp; + short *isoTemp_short = nullptr; siprint *v0; siprint *v1; siprint *dv; @@ -174,9 +174,9 @@ class isoDriver : public QLabel i2c::i2cDecoder* twoWire = nullptr; bool twoWireStateInvalid = true; //Generic Vars - QTimer* isoTimer = NULL; - QTimer *slowTimer = NULL; - QTimer *fileTimer = NULL; + QTimer* isoTimer = nullptr; + QTimer *slowTimer = nullptr; + QTimer *fileTimer = nullptr; long total_read = 0; unsigned int length; QFile *snapshotFile_CH1; @@ -199,7 +199,6 @@ class isoDriver : public QLabel void sendMultimeterLabel2(QString); void sendMultimeterLabel3(QString); void sendMultimeterLabel4(QString); - void changeTimeAxis(bool positive); void sendTriggerValue(double); void sendVmax_CH1(double); void sendVmin_CH1(double); @@ -218,13 +217,14 @@ class isoDriver : public QLabel void delayUpdated(double); void enableCursorGroup(bool); public slots: - void setVoltageRange(QWheelEvent *event); + void onWheelEvent(QWheelEvent *event); void timerTick(void); void pauseEnable_CH1(bool enabled); void pauseEnable_CH2(bool enabled); void pauseEnable_multimeter(bool enabled); void startTimer(); - void clearBuffers(bool ch3751, bool ch3752, bool ch750); + void clearChannelBuffers(bool ch3751, bool ch3752, bool ch750); + void clearBuffers(const isoDriver::Channels channels); void setVisible_CH2(bool visible); void gainBuffers(double multiplier); void gainTick(void); @@ -281,6 +281,10 @@ public slots: void attenuationChanged_CH2(int attenuationIndex); void setHexDisplay_CH1(bool enabled); void setHexDisplay_CH2(bool enabled); + + void setDownsampleMethod(const DownsamplingMethod method); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(isoDriver::Channels); + #endif // ISODRIVER_H diff --git a/Desktop_Interface/mainwindow.cpp b/Desktop_Interface/mainwindow.cpp index f00d1b71..a41a6cfb 100644 --- a/Desktop_Interface/mainwindow.cpp +++ b/Desktop_Interface/mainwindow.cpp @@ -1,9 +1,11 @@ #include "mainwindow.h" #include "uartstyledecoder.h" #include "daqform.h" +#include "pinoutDialog.h" #include #include "espospinbox.h" + #include #define DO_QUOTE(X) #X @@ -17,7 +19,6 @@ namespace { constexpr uint32_t MAX_CONSOLE_BLOCK_COUNT = 512; constexpr char kDocumentationUrl[] = "https://github.com/EspoTek/Labrador/wiki"; - constexpr char kPinoutUrl[] = "https://github.com/EspoTek/Labrador/wiki/Pinout"; constexpr char kAboutString[] = "

EspoTek Labrador

" "Continuous Release
"\ "Git hash: " QUOTE(GIT_HASH_SHORT) "
"\ @@ -47,11 +48,9 @@ MainWindow::MainWindow(QWidget *parent) : ui->psuDisplay->display("4.50"); - ui->controller_iso->setDriver(new _PLATFORM_DEPENDENT_USB_OBJECT()); + ui->controller_iso->setDriver(new _PLATFORM_DEPENDENT_USB_OBJECT(this)); ui->controller_iso->setAxes(ui->scopeAxes); - ui->timeBaseSlider->setMaximum(10*log10(MAX_WINDOW_SIZE)); - //ui->controller_iso->driver->setBufferPtr(ui->bufferDisplay); ui->cursorStatsLabel->hide(); initialisePlot(); @@ -71,10 +70,10 @@ MainWindow::MainWindow(QWidget *parent) : ui->controller_iso->internalBuffer375_CH2->m_console2 = ui->console2; initShortcuts(); - ui->debugButton1->setVisible(0); - ui->debugButton2->setVisible(0); - ui->debugButton3->setVisible(0); - ui->debugConsole->setVisible(0); + ui->debugButton1->setVisible(false); + ui->debugButton2->setVisible(false); + ui->debugButton3->setVisible(false); + ui->debugConsole->setVisible(false); // // Set the consoles to be resizeable // for (const auto & console : {ui->console1, ui->console2}) @@ -93,15 +92,14 @@ MainWindow::MainWindow(QWidget *parent) : } #ifndef PLATFORM_ANDROID - ui->kickstartIsoButton->setVisible(0); - ui->console1->setVisible(0); - ui->console2->setVisible(0); + ui->kickstartIsoButton->setVisible(false); + ui->console1->setVisible(false); + ui->console2->setVisible(false); #endif - ui->timeBaseSlider->setVisible(0); //ui->pausedLabel_CH2->setVisible(0); - ui->filterLabel_CH1->setVisible(0); - ui->filterLabel_CH2->setVisible(0); + ui->filterLabel_CH1->setVisible(false); + ui->filterLabel_CH2->setVisible(false); //Reset the device to ensure Labrador_libusbk gets handle!! #ifdef PLATFORM_WINDOWS @@ -157,7 +155,7 @@ MainWindow::MainWindow(QWidget *parent) : //Set the settings again! connect(ui->controller_iso->driver, SIGNAL(gainBuffers(double)), ui->controller_iso, SLOT(gainBuffers(double))); connect(ui->controller_iso->driver, SIGNAL(disableWindow(bool)), this, SLOT(setEnabled(bool))); - connect(ui->controller_iso->driver, SIGNAL(sendClearBuffer(bool,bool,bool)), ui->controller_iso, SLOT(clearBuffers(bool,bool,bool))); + connect(ui->controller_iso->driver, SIGNAL(sendClearBuffer(bool,bool,bool)), ui->controller_iso, SLOT(clearChannelBuffers(bool,bool,bool))); //connect(ui->controller_iso->driver, SIGNAL(startIsoTimer()), ui->controller_iso, SLOT(startTimer())); connect(ui->controller_iso->driver, SIGNAL(setVisible_CH2(bool)), ui->controller_iso, SLOT(setVisible_CH2(bool))); //connect(ui->controller_iso->driver, SIGNAL(enableMMTimer()), ui->controller_iso, SLOT(enableMM())); @@ -178,7 +176,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->menuAndroid_Special->menuAction()->setVisible(false); #endif - connect(ui->controller_iso->driver, SIGNAL(killMe()), this, SLOT(reinitUsb())); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::killMe, this, &MainWindow::reinitUsb); ui->console1->setMaximumBlockCount(MAX_CONSOLE_BLOCK_COUNT); ui->console2->setMaximumBlockCount(MAX_CONSOLE_BLOCK_COUNT); //ui->frequencyValue_CH2->setValue(369); @@ -190,32 +188,32 @@ MainWindow::MainWindow(QWidget *parent) : ui->multimeterRComboBox->setVisible(false); #endif - connect(ui->controller_iso, SIGNAL(multimeterREnabled(int)), this, SLOT(rSourceIndexChanged(int))); - connect(ui->controller_iso, SIGNAL(multimeterRMS(double)), ui->multimeterRmsDisplay, SLOT(display(double))); - connect(ui->controller_iso, SIGNAL(sendMultimeterLabel4(QString)), ui->multimeterRmsLabel, SLOT(setText(QString))); - connect(ui->controller_iso, SIGNAL(sendVRMS_CH1(double)), ui->voltageInfoRmsDisplay_CH1, SLOT(display(double))); - connect(ui->controller_iso, SIGNAL(sendVRMS_CH2(double)), ui->voltageInfoRmsDisplay_CH2, SLOT(display(double))); + connect(ui->controller_iso, &isoDriver::multimeterREnabled, this, &MainWindow::rSourceIndexChanged); + connect(ui->controller_iso, &isoDriver::multimeterRMS, ui->multimeterRmsDisplay, qOverload(&QLCDNumber::display)); + connect(ui->controller_iso, &isoDriver::sendMultimeterLabel4, ui->multimeterRmsLabel, &QLabel::setText); + connect(ui->controller_iso, &isoDriver::sendVRMS_CH1, ui->voltageInfoRmsDisplay_CH1, qOverload(&QLCDNumber::display)); + connect(ui->controller_iso, &isoDriver::sendVRMS_CH2, ui->voltageInfoRmsDisplay_CH2, qOverload(&QLCDNumber::display)); - connect(ui->controller_iso, SIGNAL(mainWindowPleaseDisableSerial(int)), this, SLOT(serialEmergencyDisable(int))); + connect(ui->controller_iso, &isoDriver::mainWindowPleaseDisableSerial, this, &MainWindow::serialEmergencyDisable); - connect(ui->controller_iso->driver, SIGNAL(signalFirmwareFlash(void)), ui->deviceConnected, SLOT(flashingFirmware(void))); - connect(ui->controller_iso->internalBuffer375_CH1, SIGNAL(fileIOinternalDisable()), this, SLOT(fileLimitReached_CH1())); - connect(ui->controller_iso->internalBuffer750, SIGNAL(fileIOinternalDisable()), this, SLOT(fileLimitReached_CH1())); - connect(ui->controller_iso->internalBuffer375_CH2, SIGNAL(fileIOinternalDisable()), this, SLOT(fileLimitReached_CH2())); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::signalFirmwareFlash, ui->deviceConnected, &deviceConnectedDisplay::flashingFirmware); + connect(ui->controller_iso->internalBuffer375_CH1, &isoBuffer::fileIOinternalDisable, this, &MainWindow::fileLimitReached_CH1); + connect(ui->controller_iso->internalBuffer750, &isoBuffer::fileIOinternalDisable, this, &MainWindow::fileLimitReached_CH1); + connect(ui->controller_iso->internalBuffer375_CH2, &isoBuffer::fileIOinternalDisable, this, &MainWindow::fileLimitReached_CH2); - connect(ui->controller_iso, SIGNAL(showRealtimeButton(bool)), ui->realTimeButton, SLOT(setVisible(bool))); - connect(ui->realTimeButton, SIGNAL(pressed()), ui->controller_iso, SLOT(disableFileMode())); + connect(ui->controller_iso, &isoDriver::showRealtimeButton, ui->realTimeButton, &QWidget::setVisible); + connect(ui->realTimeButton, &QAbstractButton::pressed, ui->controller_iso, &isoDriver::disableFileMode); - connect(ui->pausedLabeL_CH1, SIGNAL(toggled(bool)), this, SLOT(paused(bool))); - connect(ui->pausedLabel_CH2, SIGNAL(toggled(bool)), this, SLOT(paused(bool))); - connect(ui->pause_LA, SIGNAL(toggled(bool)), this, SLOT(paused(bool))); - connect(ui->multimeterPauseCheckBox, SIGNAL(toggled(bool)), this, SLOT(paused(bool))); + connect(ui->pausedLabeL_CH1, &QAbstractButton::toggled, this, &MainWindow::paused); + connect(ui->pausedLabel_CH2, &QAbstractButton::toggled, this, &MainWindow::paused); + connect(ui->pause_LA, &QAbstractButton::toggled, this, &MainWindow::paused); + connect(ui->multimeterPauseCheckBox, &QAbstractButton::toggled, this, &MainWindow::paused); #ifndef PLATFORM_ANDROID - connect(ui->hideCH1Box, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(hideCH1(bool))); - connect(ui->hideCH2Box, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(hideCH2(bool))); + connect(ui->hideCH1Box, &QAbstractButton::toggled, ui->controller_iso, &isoDriver::hideCH1); + connect(ui->hideCH2Box, &QAbstractButton::toggled, ui->controller_iso, &isoDriver::hideCH2); connect(ui->actionHexDisplay, &QAction::toggled, ui->controller_iso, &isoDriver::setHexDisplay_CH1); connect(ui->actionHexDisplay_2, &QAction::toggled, ui->controller_iso, &isoDriver::setHexDisplay_CH2); @@ -225,9 +223,9 @@ MainWindow::MainWindow(QWidget *parent) : #endif ui->realTimeButton->setVisible(false); - if ((QApplication::desktop()->availableGeometry().width() < 1520) || (QApplication::desktop()->geometry().height() < 800)) + if ((screen()->availableGeometry().width() < 1520) || (screen()->availableGeometry().height() < 800)) { - qDebug() << "Low resolution detected:" << QApplication::desktop()->availableGeometry().width() << "x" << QApplication::desktop()->availableGeometry().height(); + qDebug() << "Low resolution detected:" << screen()->availableGeometry().width() << "x" << screen()->availableGeometry().height(); this->setMinimumSize(1280, 700); this->resize(1280, 700); } @@ -238,12 +236,19 @@ MainWindow::MainWindow(QWidget *parent) : } #ifndef PLATFORM_ANDROID - connect(ui->offsetSpinBox_CH1, SIGNAL(valueChanged(double)), ui->controller_iso, SLOT(offsetChanged_CH1(double))); - connect(ui->offsetSpinBox_CH2, SIGNAL(valueChanged(double)), ui->controller_iso, SLOT(offsetChanged_CH2(double))); - connect(ui->attenuationComboBox_CH1, SIGNAL(currentIndexChanged(int)), ui->controller_iso, SLOT(attenuationChanged_CH1(int))); - connect(ui->attenuationComboBox_CH2, SIGNAL(currentIndexChanged(int)), ui->controller_iso, SLOT(attenuationChanged_CH2(int))); + // So sue me + for (QWidget *child : findChildren()) { + child->installEventFilter(this); + } + + connect(ui->offsetSpinBox_CH1, qOverload(&QDoubleSpinBox::valueChanged), ui->controller_iso, &isoDriver::offsetChanged_CH1); + connect(ui->offsetSpinBox_CH2, qOverload(&QDoubleSpinBox::valueChanged), ui->controller_iso, &isoDriver::offsetChanged_CH2); + connect(ui->attenuationComboBox_CH1, qOverload(&QComboBox::currentIndexChanged), ui->controller_iso, &isoDriver::attenuationChanged_CH1); + connect(ui->attenuationComboBox_CH2, qOverload(&QComboBox::currentIndexChanged), ui->controller_iso, &isoDriver::attenuationChanged_CH2); #endif connect(ui->controller_iso, &isoDriver::enableCursorGroup, this, &MainWindow::cursorGroupEnabled); + + connect(ui->scopeGroup_CH2, &QGroupBox::toggled, this, &MainWindow::onChannel2Toggled); } MainWindow::~MainWindow() @@ -255,7 +260,11 @@ void MainWindow::initialisePlot() { QCPCurve *xyCurve = new QCPCurve(ui->scopeAxes->xAxis, ui->scopeAxes->yAxis); xyCurve->setPen(QPen(Qt::yellow, 1)); + +#if QCP_VER == 1 ui->scopeAxes->addPlottable(xyCurve); +#endif + ui->scopeAxes->addGraph(); ui->scopeAxes->addGraph(); ui->scopeAxes->addGraph(); @@ -263,9 +272,23 @@ void MainWindow::initialisePlot() ui->scopeAxes->addGraph(); ui->scopeAxes->addGraph(); -#if QCP_VER == 1 + // TODO: port to QWT to get rid of the horrible flickering issues etc. +// ui->scopeAxes->graph(0)->setAntialiased(true); +// ui->scopeAxes->graph(1)->setAntialiased(true); +// ui->scopeAxes->graph(2)->setAntialiased(true); +// ui->scopeAxes->graph(3)->setAntialiased(true); +// ui->scopeAxes->graph(4)->setAntialiased(true); +// ui->scopeAxes->graph(5)->setAntialiased(true); + +// ui->scopeAxes->graph(0)->setAdaptiveSampling(false); +// ui->scopeAxes->graph(1)->setAdaptiveSampling(false); +// ui->scopeAxes->graph(2)->setAdaptiveSampling(false); + textLabel = new QCPItemText(ui->scopeAxes); +#if QCP_VER == 1 ui->scopeAxes->addItem(textLabel); +#endif + textLabel->setPositionAlignment(Qt::AlignTop|Qt::AlignRight); textLabel->position->setType(QCPItemPosition::ptAxisRectRatio); textLabel->position->setCoords(0.99, 0); // place position at center/top of axis rect @@ -275,15 +298,31 @@ void MainWindow::initialisePlot() textLabel->setPen(QPen(Qt::white)); textLabel->setBrush(QBrush(Qt::black)); - textLabel->setVisible(0); + textLabel->setVisible(false); ui->controller_iso->cursorTextPtr = textLabel; + QCPItemText *ch1Label = new QCPItemText(ui->scopeAxes); + ch1Label->setText("Channel 1"); + ch1Label->setPositionAlignment(Qt::AlignLeft|Qt::AlignTop); // holy fuck qcustomplot is a clusterfuck + ch1Label->position->setType(QCPItemPosition::ptAxisRectRatio); + ch1Label->position->setCoords(0.01, 0); + ch1Label->setColor(Qt::yellow); + + ch2Label = new QCPItemText(ui->scopeAxes); + ch2Label->setPositionAlignment(Qt::AlignLeft|Qt::AlignTop); + ch2Label->setText("Channel 2"); + ch2Label->position->setParentAnchorY(ch1Label->bottom); // this API is horribly confusing + ch2Label->position->setParentAnchorX(ch1Label->left); + ch2Label->setColor(Qt::cyan); + ch2Label->setVisible(false); + +#if QCP_VER == 1 ui->scopeAxes->yAxis->setAutoTickCount(9); ui->scopeAxes->xAxis->setAutoTickCount(9); #endif #if QCP_VER == 2 - ui->scopeAxes->setOpenGl(true); +// ui->scopeAxes->setOpenGl(true); QSharedPointer xTicker(new QCPAxisTicker); xTicker->setTickCount(9); ui->scopeAxes->xAxis->setTicker(xTicker); @@ -293,15 +332,15 @@ void MainWindow::initialisePlot() ui->scopeAxes->yAxis->setTicker(yTicker); #endif - QPen *dashPen = new QPen(Qt::white, 2); - dashPen->setStyle(Qt::DashLine); + QPen dashPen(Qt::white, 2); + dashPen.setStyle(Qt::DashLine); - ui->scopeAxes->graph(0)->setPen(QPen(Qt::yellow, 1)); - ui->scopeAxes->graph(1)->setPen(QPen(Qt::cyan, 1)); + ui->scopeAxes->graph(0)->setPen(QPen(QColor(255, 255, 0, 192), 1)); + ui->scopeAxes->graph(1)->setPen(QPen(QColor(0, 255, 255, 192), 1)); ui->scopeAxes->graph(2)->setPen(QPen(Qt::white, 2)); - ui->scopeAxes->graph(3)->setPen(*(dashPen)); + ui->scopeAxes->graph(3)->setPen(dashPen); ui->scopeAxes->graph(4)->setPen(QPen(Qt::white, 2)); - ui->scopeAxes->graph(5)->setPen(*(dashPen)); + ui->scopeAxes->graph(5)->setPen(dashPen); ui->scopeAxes->xAxis->setBasePen(QPen(Qt::white, 1)); @@ -323,12 +362,10 @@ void MainWindow::initialisePlot() } void MainWindow::labelPsu(){ - char tempString[4]; int tempInt = ui->psuSlider->maximum(); int tempCounter = 0; while(tempInt>90){ - sprintf(tempString, "%dV", tempInt/20); - ui->psuSlider->setTickLabel(tempString, tempCounter); + ui->psuSlider->setTickLabel(QString::asprintf("%dV", tempInt/20), tempCounter); tempInt -= 20; tempCounter++; } @@ -336,6 +373,8 @@ void MainWindow::labelPsu(){ } void MainWindow::resizeEvent(QResizeEvent *event){ + Q_UNUSED(event); + //ui->scopeAxes->yAxis->setAutoTickCount((ui->scopeAxes->height() + TICK_SEPARATION / 2) / TICK_SEPARATION); //ui->scopeAxes->xAxis->setAutoTickCount((ui->scopeAxes->width() + TICK_SEPARATION / 2) / TICK_SEPARATION); @@ -376,6 +415,13 @@ void MainWindow::menuSetup(){ gainGroup->addAction(ui->actionGain64); ui->actionGainAuto->setChecked(true); + QActionGroup *downsampleGroup = new QActionGroup(this); + downsampleGroup->addAction(ui->actionDownsampleAverageDelta); + downsampleGroup->addAction(ui->actionDownsamplePeak); + downsampleGroup->addAction(ui->actionDownsampleBottom); + downsampleGroup->addAction(ui->actionDownsampleDecimate); + ui->actionDownsampleAverageDelta->setChecked(true); + rangeGroupV = new QActionGroup(this); rangeGroupV->addAction(ui->actionAutoV); rangeGroupV->addAction(ui->actionMV); @@ -411,18 +457,18 @@ void MainWindow::menuSetup(){ #endif - connect(ui->actionAutoV, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setAutoMultimeterV(bool))); - connect(ui->actionV, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setForceVolts(bool))); - connect(ui->actionMV, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setForceMillivolts(bool))); - connect(ui->actionAutoI, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setAutoMultimeterI(bool))); - connect(ui->actionA, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setForceAmps(bool))); - connect(ui->actionMA, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setForceMilliamps(bool))); - connect(ui->actionAutoR, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setAutoMultimeterR(bool))); - connect(ui->actionOhm, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setForceOhms(bool))); - connect(ui->actionKOhm, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setForceKiloOhms(bool))); - connect(ui->actionAutoC, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setAutoMultimeterC(bool))); - connect(ui->actionNF, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setForceNFarads(bool))); - connect(ui->action_F, SIGNAL(toggled(bool)), ui->controller_iso, SLOT(setForceUFarads(bool))); + connect(ui->actionAutoV, &QAction::toggled, ui->controller_iso, &isoDriver::setAutoMultimeterV); + connect(ui->actionV, &QAction::toggled, ui->controller_iso, &isoDriver::setForceVolts); + connect(ui->actionMV, &QAction::toggled, ui->controller_iso, &isoDriver::setForceMillivolts); + connect(ui->actionAutoI, &QAction::toggled, ui->controller_iso, &isoDriver::setAutoMultimeterI); + connect(ui->actionA, &QAction::toggled, ui->controller_iso, &isoDriver::setForceAmps); + connect(ui->actionMA, &QAction::toggled, ui->controller_iso, &isoDriver::setForceMilliamps); + connect(ui->actionAutoR, &QAction::toggled, ui->controller_iso, &isoDriver::setAutoMultimeterR); + connect(ui->actionOhm, &QAction::toggled, ui->controller_iso, &isoDriver::setForceOhms); + connect(ui->actionKOhm, &QAction::toggled, ui->controller_iso, &isoDriver::setForceKiloOhms); + connect(ui->actionAutoC, &QAction::toggled, ui->controller_iso, &isoDriver::setAutoMultimeterC); + connect(ui->actionNF, &QAction::toggled, ui->controller_iso, &isoDriver::setForceNFarads); + connect(ui->action_F, &QAction::toggled, ui->controller_iso, &isoDriver::setForceUFarads); uartBaudGroup_CH1 = new QActionGroup(this); @@ -491,53 +537,53 @@ void MainWindow::menuSetup(){ void MainWindow::on_actionGain0_5_triggered() { ui->controller_iso->driver->setGain(0.5); - ui->controller_iso->setAutoGain(0); + ui->controller_iso->setAutoGain(false); } void MainWindow::on_actionGain1_triggered() { ui->controller_iso->driver->setGain(1); - ui->controller_iso->setAutoGain(0); + ui->controller_iso->setAutoGain(false); } void MainWindow::on_actionGain2_triggered() { ui->controller_iso->driver->setGain(2); - ui->controller_iso->setAutoGain(0); + ui->controller_iso->setAutoGain(false); } void MainWindow::on_actionGain4_triggered() { ui->controller_iso->driver->setGain(4); - ui->controller_iso->setAutoGain(0); + ui->controller_iso->setAutoGain(false); } void MainWindow::on_actionGain8_triggered() { ui->controller_iso->driver->setGain(8); - ui->controller_iso->setAutoGain(0); + ui->controller_iso->setAutoGain(false); } void MainWindow::on_actionGain16_triggered() { ui->controller_iso->driver->setGain(16); - ui->controller_iso->setAutoGain(0); + ui->controller_iso->setAutoGain(false); } void MainWindow::on_actionGain32_triggered() { ui->controller_iso->driver->setGain(32); - ui->controller_iso->setAutoGain(0); + ui->controller_iso->setAutoGain(false); } void MainWindow::on_actionGain64_triggered() { ui->controller_iso->driver->setGain(64); - ui->controller_iso->setAutoGain(0); + ui->controller_iso->setAutoGain(false); } void MainWindow::on_actionGainAuto_triggered() { - ui->controller_iso->setAutoGain(1); + ui->controller_iso->setAutoGain(true); } void MainWindow::on_actionCursor_Stats_triggered(bool checked) @@ -546,47 +592,47 @@ void MainWindow::on_actionCursor_Stats_triggered(bool checked) } void MainWindow::connectDisplaySignals(){ - connect(ui->actionMax, SIGNAL(toggled(bool)), ui->voltageInfoMaxLabel_CH1, SLOT(setVisible(bool))); - connect(ui->actionMax, SIGNAL(toggled(bool)), ui->voltageInfoMaxDisplay_CH1, SLOT(setVisible(bool))); + connect(ui->actionMax, &QAction::toggled, ui->voltageInfoMaxLabel_CH1, &QWidget::setVisible); + connect(ui->actionMax, &QAction::toggled, ui->voltageInfoMaxDisplay_CH1, &QWidget::setVisible); - connect(ui->actionMin, SIGNAL(toggled(bool)), ui->voltageInfoMinLabel_CH1, SLOT(setVisible(bool))); - connect(ui->actionMin, SIGNAL(toggled(bool)), ui->voltageInfoMinDisplay_CH1, SLOT(setVisible(bool))); + connect(ui->actionMin, &QAction::toggled, ui->voltageInfoMinLabel_CH1, &QWidget::setVisible); + connect(ui->actionMin, &QAction::toggled, ui->voltageInfoMinDisplay_CH1, &QWidget::setVisible); - connect(ui->actionMean, SIGNAL(toggled(bool)), ui->VoltageInfoMeanLabel_CH1, SLOT(setVisible(bool))); - connect(ui->actionMean, SIGNAL(toggled(bool)), ui->voltageInfoMeanDisplay_CH1, SLOT(setVisible(bool))); + connect(ui->actionMean, &QAction::toggled, ui->VoltageInfoMeanLabel_CH1, &QWidget::setVisible); + connect(ui->actionMean, &QAction::toggled, ui->voltageInfoMeanDisplay_CH1, &QWidget::setVisible); - connect(ui->actionRMS, SIGNAL(toggled(bool)), ui->voltageInfoRmsLabel_CH1, SLOT(setVisible(bool))); - connect(ui->actionRMS, SIGNAL(toggled(bool)), ui->voltageInfoRmsDisplay_CH1, SLOT(setVisible(bool))); + connect(ui->actionRMS, &QAction::toggled, ui->voltageInfoRmsLabel_CH1, &QWidget::setVisible); + connect(ui->actionRMS, &QAction::toggled, ui->voltageInfoRmsDisplay_CH1, &QWidget::setVisible); - ui->voltageInfoMaxLabel_CH1->setVisible(0); - ui->voltageInfoMaxDisplay_CH1->setVisible(0); - ui->voltageInfoMinLabel_CH1->setVisible(0); - ui->voltageInfoMinDisplay_CH1->setVisible(0); - ui->VoltageInfoMeanLabel_CH1->setVisible(0); - ui->voltageInfoMeanDisplay_CH1->setVisible(0); - ui->voltageInfoRmsLabel_CH1->setVisible(0); - ui->voltageInfoRmsDisplay_CH1->setVisible(0); + ui->voltageInfoMaxLabel_CH1->setVisible(false); + ui->voltageInfoMaxDisplay_CH1->setVisible(false); + ui->voltageInfoMinLabel_CH1->setVisible(false); + ui->voltageInfoMinDisplay_CH1->setVisible(false); + ui->VoltageInfoMeanLabel_CH1->setVisible(false); + ui->voltageInfoMeanDisplay_CH1->setVisible(false); + ui->voltageInfoRmsLabel_CH1->setVisible(false); + ui->voltageInfoRmsDisplay_CH1->setVisible(false); - connect(ui->actionMax_2, SIGNAL(toggled(bool)), ui->voltageInfoMaxLabel_CH2, SLOT(setVisible(bool))); - connect(ui->actionMax_2, SIGNAL(toggled(bool)), ui->voltageInfoMaxDisplay_CH2, SLOT(setVisible(bool))); + connect(ui->actionMax_2, &QAction::toggled, ui->voltageInfoMaxLabel_CH2, &QWidget::setVisible); + connect(ui->actionMax_2, &QAction::toggled, ui->voltageInfoMaxDisplay_CH2, &QWidget::setVisible); - connect(ui->actionMin_2, SIGNAL(toggled(bool)), ui->voltageInfoMinLabel_CH2, SLOT(setVisible(bool))); - connect(ui->actionMin_2, SIGNAL(toggled(bool)), ui->voltageInfoMinDisplay_CH2, SLOT(setVisible(bool))); + connect(ui->actionMin_2, &QAction::toggled, ui->voltageInfoMinLabel_CH2, &QWidget::setVisible); + connect(ui->actionMin_2, &QAction::toggled, ui->voltageInfoMinDisplay_CH2, &QWidget::setVisible); - connect(ui->actionMean_2, SIGNAL(toggled(bool)), ui->VoltageInfoMeanLabel_CH2, SLOT(setVisible(bool))); - connect(ui->actionMean_2, SIGNAL(toggled(bool)), ui->voltageInfoMeanDisplay_CH2, SLOT(setVisible(bool))); + connect(ui->actionMean_2, &QAction::toggled, ui->VoltageInfoMeanLabel_CH2, &QWidget::setVisible); + connect(ui->actionMean_2, &QAction::toggled, ui->voltageInfoMeanDisplay_CH2, &QWidget::setVisible); - connect(ui->actionRMS_2, SIGNAL(toggled(bool)), ui->voltageInfoRmsLabel_CH2, SLOT(setVisible(bool))); - connect(ui->actionRMS_2, SIGNAL(toggled(bool)), ui->voltageInfoRmsDisplay_CH2, SLOT(setVisible(bool))); + connect(ui->actionRMS_2, &QAction::toggled, ui->voltageInfoRmsLabel_CH2, &QWidget::setVisible); + connect(ui->actionRMS_2, &QAction::toggled, ui->voltageInfoRmsDisplay_CH2, &QWidget::setVisible); - ui->voltageInfoMaxLabel_CH2->setVisible(0); - ui->voltageInfoMaxDisplay_CH2->setVisible(0); - ui->voltageInfoMinLabel_CH2->setVisible(0); - ui->voltageInfoMinDisplay_CH2->setVisible(0); - ui->VoltageInfoMeanLabel_CH2->setVisible(0); - ui->voltageInfoMeanDisplay_CH2->setVisible(0); - ui->voltageInfoRmsLabel_CH2->setVisible(0); - ui->voltageInfoRmsDisplay_CH2->setVisible(0); + ui->voltageInfoMaxLabel_CH2->setVisible(false); + ui->voltageInfoMaxDisplay_CH2->setVisible(false); + ui->voltageInfoMinLabel_CH2->setVisible(false); + ui->voltageInfoMinDisplay_CH2->setVisible(false); + ui->VoltageInfoMeanLabel_CH2->setVisible(false); + ui->voltageInfoMeanDisplay_CH2->setVisible(false); + ui->voltageInfoRmsLabel_CH2->setVisible(false); + ui->voltageInfoRmsDisplay_CH2->setVisible(false); } @@ -976,73 +1022,35 @@ void MainWindow::cycleBaudRateBackwards_CH2(){ } void MainWindow::initShortcuts(){ - shortcut_cycleBaudRate_CH1 = new QShortcut(QKeySequence("Ctrl+B"), ui->menuBar); - shortcut_cycleBaudRateBackwards_CH1 = new QShortcut(QKeySequence("Ctrl+Shift+B"), ui->menuBar); - shortcut_cycleBaudRate_CH2 = new QShortcut(QKeySequence("Ctrl+Alt+B"), ui->menuBar); - shortcut_cycleBaudRateBackwards_CH2 = new QShortcut(QKeySequence("Ctrl+Shift+Alt+B"), ui->menuBar); - shortcut_snapScopeToCursors = new QShortcut(QKeySequence("Z"), ui->menuBar); - shortcut_manualRange = new QShortcut(QKeySequence("M"), ui->menuBar); - shortcut_snapshot_CH1 = new QShortcut(QKeySequence("c"), this); - shortcut_snapshot_CH2 = new QShortcut(QKeySequence("v"), this); - - shortcut_ArrowUp = new QShortcut(QKeySequence("Up"), ui->menuBar); - shortcut_ArrowDown = new QShortcut(QKeySequence("Down"), ui->menuBar); - shortcut_CtrlArrowUp = new QShortcut(QKeySequence("Ctrl+Up"), ui->menuBar); - shortcut_CtrlArrowDown = new QShortcut(QKeySequence("Ctrl+Down"), ui->menuBar); - shortcut_w = new QShortcut(QKeySequence("w"), ui->menuBar); - shortcut_s = new QShortcut(QKeySequence("s"), ui->menuBar); - shortcut_ctrlW = new QShortcut(QKeySequence("Ctrl+w"), ui->menuBar); - shortcut_ctrlS = new QShortcut(QKeySequence("Ctrl+s"), ui->menuBar); - - shortcut_a = new QShortcut(QKeySequence("a"), this); - shortcut_d = new QShortcut(QKeySequence("d"), this); - shortcut_ArrowLeft = new QShortcut(QKeySequence("Left"), this); - shortcut_ArrowRight = new QShortcut(QKeySequence("Right"), this); - shortcut_CtrlArrowLeft = new QShortcut(QKeySequence("Ctrl+Left"), this); - shortcut_CtrlArrowRight = new QShortcut(QKeySequence("Ctrl+Right"), this); - - - - shortcut_Debug = new QShortcut(QKeySequence("Home"), this); - shortcut_Esc = new QShortcut(QKeySequence("Esc"), this); + new QShortcut(QKeySequence("Ctrl+B"), this, SLOT(cycleBaudRate_CH1())); + new QShortcut(QKeySequence("Ctrl+Shift+B"), this, SLOT(cycleBaudRateBackwards_CH1())); + new QShortcut(QKeySequence("Ctrl+Alt+B"), this, SLOT(cycleBaudRate_CH2())); + new QShortcut(QKeySequence("Ctrl+Shift+Alt+B"), this, SLOT(cycleBaudRateBackwards_CH2())); + new QShortcut(QKeySequence("z"), this, SLOT(on_actionSnap_to_Cursors_triggered())); + new QShortcut(QKeySequence("Shift+Z"), this, SLOT(on_actionResetDisplay())); + new QShortcut(QKeySequence("M"), this, SLOT(on_actionEnter_Manually_triggered())); + new QShortcut(QKeySequence("c"), this, SLOT(on_actionSnapshot_CH1_triggered())); + new QShortcut(QKeySequence("v"), this, SLOT(on_actionSnapshot_CH2_triggered())); + new QShortcut(QKeySequence("w"), this, SLOT(arrowUpTriggered())); + new QShortcut(QKeySequence("s"), this, SLOT(arrowDownTriggered())); + new QShortcut(QKeySequence("Ctrl+w"), this, SLOT(ctrlArrowUpTriggered())); + new QShortcut(QKeySequence("Ctrl+s"), this, SLOT(ctrlArrowDownTriggered())); - connect(shortcut_cycleBaudRate_CH1, SIGNAL(activated()), this, SLOT(cycleBaudRate_CH1())); - connect(shortcut_cycleBaudRateBackwards_CH1, SIGNAL(activated()), this, SLOT(cycleBaudRateBackwards_CH1())); - connect(shortcut_cycleBaudRate_CH2, SIGNAL(activated()), this, SLOT(cycleBaudRate_CH2())); - connect(shortcut_cycleBaudRateBackwards_CH2, SIGNAL(activated()), this, SLOT(cycleBaudRateBackwards_CH2())); - connect(shortcut_snapshot_CH1, SIGNAL(activated()), this, SLOT(on_actionSnapshot_CH1_triggered())); - connect(shortcut_snapshot_CH2, SIGNAL(activated()), this, SLOT(on_actionSnapshot_CH2_triggered())); + new QShortcut(QKeySequence("a"), this, SLOT(cycleDelayLeft())); + new QShortcut(QKeySequence("d"), this, SLOT(cycleDelayRight())); + new QShortcut(QKeySequence("Left"), this, SLOT(cycleDelayLeft())); + new QShortcut(QKeySequence("Right"), this, SLOT(cycleDelayRight())); - connect(shortcut_ArrowUp, SIGNAL(activated()), this, SLOT(arrowUpTriggered())); - connect(shortcut_ArrowDown, SIGNAL(activated()), this, SLOT(arrowDownTriggered())); - connect(shortcut_CtrlArrowUp, SIGNAL(activated()), this, SLOT(ctrlArrowUpTriggered())); - connect(shortcut_CtrlArrowDown, SIGNAL(activated()), this, SLOT(ctrlArrowDownTriggered())); - connect(shortcut_w, SIGNAL(activated()), this, SLOT(arrowUpTriggered())); - connect(shortcut_s, SIGNAL(activated()), this, SLOT(arrowDownTriggered())); - connect(shortcut_ctrlW, SIGNAL(activated()), this, SLOT(ctrlArrowUpTriggered())); - connect(shortcut_ctrlS, SIGNAL(activated()), this, SLOT(ctrlArrowDownTriggered())); + new QShortcut(QKeySequence("Ctrl+Left"), this, SLOT(cycleDelayLeft_large())); + new QShortcut(QKeySequence("Ctrl+Right"), this, SLOT(cycleDelayRight_large())); - connect(shortcut_a, SIGNAL(activated()), this, SLOT(cycleDelayLeft())); - connect(shortcut_d, SIGNAL(activated()), this, SLOT(cycleDelayRight())); + new QShortcut(QKeySequence("Home"), this, SLOT(enableLabradorDebugging())); + new QShortcut(QKeySequence("Esc"), this, SLOT(reinitUsb())); - connect(shortcut_ArrowLeft, SIGNAL(activated()), this, SLOT(cycleDelayLeft())); - connect(shortcut_ArrowRight, SIGNAL(activated()), this, SLOT(cycleDelayRight())); - connect(shortcut_CtrlArrowLeft, SIGNAL(activated()), this, SLOT(cycleDelayLeft_large())); - connect(shortcut_CtrlArrowRight, SIGNAL(activated()), this, SLOT(cycleDelayRight_large())); + ui->actionQuit->setShortcut(Qt::CTRL + Qt::Key_Q); // on macOS CTRL is automaticall translated to the command key + ui->actionPinout->setShortcut(Qt::Key_F1); - connect(shortcut_snapScopeToCursors, SIGNAL(activated()), this, SLOT(on_actionSnap_to_Cursors_triggered())); - connect(shortcut_manualRange, SIGNAL(activated()), this, SLOT(on_actionEnter_Manually_triggered())); - - connect(shortcut_Debug, SIGNAL(activated()), this, SLOT(enableLabradorDebugging())); - connect(shortcut_Esc, SIGNAL(activated()), this, SLOT(reinitUsb())); - -} - -void MainWindow::timeBaseNeedsChanging(bool positive){ - int tempVal = ui->timeBaseSlider->value(); - tempVal += positive ? 1 : -1; - ui->timeBaseSlider->setValue(tempVal); } void MainWindow::on_actionForce_Square_triggered(bool checked) @@ -1055,22 +1063,40 @@ void MainWindow::on_actionForce_Square_triggered(bool checked) this->resize(tempWidth, tempHeight); } +// In Qt 6 they have gone insane +static QWheelEvent createWheelEvent(const bool negative, const QPoint &point, const Qt::KeyboardModifier modifier = Qt::NoModifier) +{ + return QWheelEvent(point, // pos + QCursor::pos(), // globalpos + QPoint(0, negative ? -0 : 0), // pixelDelta + QPoint(0, negative ? -120 : 120), // angleDelta + Qt::NoButton, // buttons + modifier, // keyboard modifiers + Qt::NoScrollPhase, // scroll phase + false // inverted + ); +} + void MainWindow::arrowUpTriggered(){ qDebug() << "Boy UP!"; if(!(ui->scopeAxes->underMouse())) return; QPoint point = ui->scopeAxes->mapFromGlobal(QCursor::pos()); - wheelEmu = new QWheelEvent(point, 120, 0, 0, Qt::Vertical); - ui->controller_iso->setVoltageRange(wheelEmu); + + QWheelEvent wheelEmu = createWheelEvent(false, point); + qApp->sendEvent(ui->scopeAxes, &wheelEmu); } void MainWindow::arrowDownTriggered(){ qDebug() << "Boy DOWN!"; - if(!(ui->scopeAxes->underMouse())) return; + if(!(ui->scopeAxes->underMouse())){ + qDebug() << "Not under mouse"; + return; + } QPoint point = ui->scopeAxes->mapFromGlobal(QCursor::pos()); - wheelEmu = new QWheelEvent(point, -120, 0, 0, Qt::Vertical); - ui->controller_iso->setVoltageRange(wheelEmu); + QWheelEvent wheelEmu = createWheelEvent(true, point); + qApp->sendEvent(ui->scopeAxes, &wheelEmu); } void MainWindow::ctrlArrowUpTriggered(){ @@ -1078,8 +1104,8 @@ void MainWindow::ctrlArrowUpTriggered(){ if(!(ui->scopeAxes->underMouse())) return; QPoint point = ui->scopeAxes->mapFromGlobal(QCursor::pos()); - wheelEmu = new QWheelEvent(point, 120, 0, Qt::ControlModifier, Qt::Vertical); - ui->controller_iso->setVoltageRange(wheelEmu); + QWheelEvent wheelEmu = createWheelEvent(false, point, Qt::ControlModifier); + qApp->sendEvent(ui->scopeAxes, &wheelEmu); } void MainWindow::ctrlArrowDownTriggered(){ @@ -1087,15 +1113,15 @@ void MainWindow::ctrlArrowDownTriggered(){ if(!(ui->scopeAxes->underMouse())) return; QPoint point = ui->scopeAxes->mapFromGlobal(QCursor::pos()); - wheelEmu = new QWheelEvent(point, -120, 0, Qt::ControlModifier, Qt::Vertical); - ui->controller_iso->setVoltageRange(wheelEmu); + QWheelEvent wheelEmu = createWheelEvent(true, point, Qt::ControlModifier); + qApp->sendEvent(ui->scopeAxes, &wheelEmu); } void MainWindow::cycleDelayRight(){ qDebug() << "RIGHT"; ui->controller_iso->display.delay -= ui->controller_iso->display.window/10; if(ui->controller_iso->display.delay < 0) ui->controller_iso->display.delay = 0; - ui->controller_iso->delayUpdated(ui->controller_iso->display.delay); + emit ui->controller_iso->delayUpdated(ui->controller_iso->display.delay); } void MainWindow::cycleDelayLeft(){ @@ -1103,14 +1129,14 @@ void MainWindow::cycleDelayLeft(){ double mws = ui->controller_iso->fileModeEnabled ? ui->controller_iso->daq_maxWindowSize : ((double)MAX_WINDOW_SIZE); ui->controller_iso->display.delay += ui->controller_iso->display.window/10; if(ui->controller_iso->display.delay > (mws - ui->controller_iso->display.window)) ui->controller_iso->display.delay = (mws - ui->controller_iso->display.window); - ui->controller_iso->delayUpdated(ui->controller_iso->display.delay); + emit ui->controller_iso->delayUpdated(ui->controller_iso->display.delay); } void MainWindow::cycleDelayRight_large(){ qDebug() << "RIGHT"; ui->controller_iso->display.delay -= ui->controller_iso->display.window/2; if(ui->controller_iso->display.delay < 0) ui->controller_iso->display.delay = 0; - ui->controller_iso->delayUpdated(ui->controller_iso->display.delay); + emit ui->controller_iso->delayUpdated(ui->controller_iso->display.delay); } void MainWindow::cycleDelayLeft_large(){ @@ -1118,19 +1144,19 @@ void MainWindow::cycleDelayLeft_large(){ double mws = ui->controller_iso->fileModeEnabled ? ui->controller_iso->daq_maxWindowSize : ((double)MAX_WINDOW_SIZE); ui->controller_iso->display.delay += ui->controller_iso->display.window/2; if(ui->controller_iso->display.delay > (mws - ui->controller_iso->display.window)) ui->controller_iso->display.delay = (mws - ui->controller_iso->display.window); - ui->controller_iso->delayUpdated(ui->controller_iso->display.delay); + emit ui->controller_iso->delayUpdated(ui->controller_iso->display.delay); } void MainWindow::enableLabradorDebugging(){ qDebug() << "DEBUG MODE ACTIVE"; - ui->debugButton1->setVisible(1); - ui->debugButton2->setVisible(1); - ui->debugButton3->setVisible(1); + ui->debugButton1->setVisible(true); + ui->debugButton2->setVisible(true); + ui->debugButton3->setVisible(true); #ifndef PLATFORM_ANDROID - ui->kickstartIsoButton->setVisible(1); + ui->kickstartIsoButton->setVisible(true); #endif - ui->debugConsole->setVisible(1); + ui->debugConsole->setVisible(true); new Q_DebugStream(std::cout, ui->debugConsole); //Redirect Console output to QTextEdit Q_DebugStream::registerQDebugMessageHandler(); //Redirect qDebug() output to QTextEdit @@ -1220,20 +1246,40 @@ void MainWindow::on_actionEnter_Manually_triggered() ui->controller_iso->display.delay = 0; scopeRangeEnterDialog dialog(this, ui->controller_iso->display.topRange, ui->controller_iso->display.botRange, ui->controller_iso->display.window, ui->controller_iso->display.delay); dialog.setModal(true); - connect(&dialog, SIGNAL(yTopUpdated(double)), ui->controller_iso, SLOT(setTopRange(double))); - connect(&dialog, SIGNAL(yBotUpdated(double)), ui->controller_iso, SLOT(setBotRange(double))); - connect(&dialog, SIGNAL(windowUpdated(double)), ui->controller_iso, SLOT(setTimeWindow(double))); - connect(&dialog, SIGNAL(delayUpdated(double)), ui->controller_iso, SLOT(setDelay(double))); + connect(&dialog, &scopeRangeEnterDialog::yTopUpdated, ui->controller_iso, &isoDriver::setTopRange); + connect(&dialog, &scopeRangeEnterDialog::yBotUpdated, ui->controller_iso, &isoDriver::setBotRange); + connect(&dialog, &scopeRangeEnterDialog::windowUpdated, ui->controller_iso, &isoDriver::setTimeWindow); + connect(&dialog, &scopeRangeEnterDialog::delayUpdated, ui->controller_iso, &isoDriver::setDelay); dialog.exec(); } +void MainWindow::on_actionDownsampleDecimate_triggered() +{ + ui->controller_iso->setDownsampleMethod(DownsamplingMethod::Decimate); +} + +void MainWindow::on_actionDownsamplePeak_triggered() +{ + ui->controller_iso->setDownsampleMethod(DownsamplingMethod::Peak); +} + +void MainWindow::on_actionDownsampleBottom_triggered() +{ + ui->controller_iso->setDownsampleMethod(DownsamplingMethod::Bottom); +} + +void MainWindow::on_actionDownsampleAverageDelta_triggered() +{ + ui->controller_iso->setDownsampleMethod(DownsamplingMethod::AverageDelta); +} + void MainWindow::helloWorld(){ qDebug() << "Hello World!"; } #define QSETTINGS_DEFAULT_RETURN 42069 void MainWindow::readSettingsFile(){ - settings = new QSettings(); + settings = new QSettings(this); int connectionType = settings->value("ConnectionType", QSETTINGS_DEFAULT_RETURN).toInt(); double calibrate_vref_ch1 = settings->value("CalibrateVrefCH1", 1.65).toDouble(); double calibrate_vref_ch2 = settings->value("CalibrateVrefCH2", 1.65).toDouble(); @@ -1291,65 +1337,7 @@ void MainWindow::readSettingsFile(){ } } -void MainWindow::on_actionRecord_triggered(bool checked) -{ - /* - if(!checked){ - ui->controller_iso->internalBuffer375_CH1->disableFileIO(); - ui->controller_iso->internalBuffer375_CH2->disableFileIO(); - ui->controller_iso->internalBuffer750->disableFileIO(); - - delete(output375_CH1); - delete(output375_CH2); - delete(output750); - return; - } - QDateTime now = QDateTime::currentDateTime(); - QString dateString = now.toString("yyyyMMddhhmmsszzz"); - qDebug() << dateString; - - qDebug() << "QStandardPaths::DocumentsLocation" << QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); - outputDir = new QDir(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation)); - outputDir->mkdir("EspoTek"); - outputDir->cd("EspoTek"); - outputDir->mkdir("recordings"); - outputDir->cd("recordings"); - outputDir->mkdir(dateString); - outputDir->cd(dateString); - - qDebug() << outputDir->absolutePath(); - - output375_CH1 = new QFile(outputDir->filePath("375_CH1.csv")); - output375_CH2 = new QFile(outputDir->filePath("375_CH2.csv")); - output750 = new QFile(outputDir->filePath("750.csv")); - - ui->controller_iso->internalBuffer375_CH1->enableFileIO(output375_CH1); - ui->controller_iso->internalBuffer375_CH2->enableFileIO(output375_CH2); - ui->controller_iso->internalBuffer750->enableFileIO(output750); - - delete(outputDir); - return; - */ -} - -void MainWindow::on_actionTake_Snapshot_triggered() -{ - /* - QString fileName; - showFileDialog(&fileName); - qDebug() << fileName; - int len = fileName.length(); - - if(len==0) return; //User cancelled - - qDebug() << len; - fileName.remove(len-4, 4); - qDebug() << fileName; - ui->controller_iso->takeSnapshot(&fileName); - */ -} - -void MainWindow::reinitUsb(void){ +void MainWindow::reinitUsb(){ ui->controller_iso->doNotTouchGraph = true; ui->controller_iso->driver->saveState(&reinitdeviceMode, &reinitScopeGain, &reinitCurrentPsuVoltage, &reinitDigitalPinState); @@ -1366,51 +1354,51 @@ void MainWindow::reinitUsb(void){ qDebug() << "ReinitUsb Stage 1 complete"; } -void MainWindow::reinitUsbStage2(void){ +void MainWindow::reinitUsbStage2(){ qDebug() << "ReinitUsb entering stage 2"; delete(ui->controller_iso->driver); qDebug() << "Reinitialising USB driver!"; - ui->controller_iso->driver = new _PLATFORM_DEPENDENT_USB_OBJECT(); + ui->controller_iso->setDriver(new _PLATFORM_DEPENDENT_USB_OBJECT(this)); //Reconnect the other objects. //ui->controller_iso->driver->setBufferPtr(ui->bufferDisplay); - connect(ui->debugButton1, SIGNAL(clicked()), ui->controller_iso->driver, SLOT(avrDebug())); - connect(ui->debugButton3, SIGNAL(clicked()), ui->controller_iso->driver, SLOT(bootloaderJump())); - connect(ui->psuSlider, SIGNAL(voltageChanged(double)), ui->controller_iso->driver, SLOT(setPsu(double))); - connect(ui->controller_iso, SIGNAL(setGain(double)), ui->controller_iso->driver, SLOT(setGain(double))); + connect(ui->debugButton1, &QAbstractButton::clicked, ui->controller_iso->driver.data(), &genericUsbDriver::avrDebug); + connect(ui->debugButton3, &QAbstractButton::clicked, ui->controller_iso->driver.data(), &genericUsbDriver::bootloaderJump); + connect(ui->psuSlider, &espoSlider::voltageChanged, ui->controller_iso->driver.data(), &genericUsbDriver::setPsu); + connect(ui->controller_iso, &isoDriver::setGain, ui->controller_iso->driver.data(), &genericUsbDriver::setGain); connect(ui->controller_fg, &functionGenControl::functionGenToUpdate, ui->controller_iso->driver, &genericUsbDriver::setFunctionGen); - connect(ui->bufferDisplay, SIGNAL(modeChange(int)), ui->controller_iso->driver, SLOT(setDeviceMode(int))); + connect(ui->bufferDisplay, &bufferControl::modeChange, ui->controller_iso->driver.data(), &genericUsbDriver::setDeviceMode); connect(ui->bufferDisplay, &bufferControl::modeChange, this, [this](){ // Force a trigger refresh ui->controller_iso->setTriggerLevel(ui->triggerLevelValue->value()); }); - connect(ui->bufferDisplay, SIGNAL(updateDig(int)), ui->controller_iso->driver, SLOT(newDig(int))); + connect(ui->bufferDisplay, &bufferControl::updateDig, ui->controller_iso->driver.data(), &genericUsbDriver::newDig); //Set the settings again! - connect(ui->controller_iso->driver, SIGNAL(gainBuffers(double)), ui->controller_iso, SLOT(gainBuffers(double))); - connect(ui->controller_iso->driver, SIGNAL(disableWindow(bool)), this, SLOT(setEnabled(bool))); - connect(ui->controller_iso->driver, SIGNAL(sendClearBuffer(bool,bool,bool)), ui->controller_iso, SLOT(clearBuffers(bool,bool,bool))); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::gainBuffers, ui->controller_iso, &isoDriver::gainBuffers); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::disableWindow, this, &QWidget::setEnabled); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::sendClearBuffer, ui->controller_iso, &isoDriver::clearChannelBuffers); //connect(ui->controller_iso->driver, SIGNAL(startIsoTimer()), ui->controller_iso, SLOT(startTimer())); - connect(ui->controller_iso->driver, SIGNAL(setVisible_CH2(bool)), ui->controller_iso, SLOT(setVisible_CH2(bool))); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::setVisible_CH2, ui->controller_iso, &isoDriver::setVisible_CH2); //connect(ui->controller_iso->driver, SIGNAL(enableMMTimer()), ui->controller_iso, SLOT(enableMM())); - connect(ui->controller_iso->driver, SIGNAL(checkXY(bool)), ui->xyDisplayLabel, SLOT(setChecked(bool))); - connect(ui->controller_iso->driver, SIGNAL(disableWindow(bool)), ui->deviceConnected, SLOT(connectedStatusChanged(bool))); - connect(ui->controller_iso->driver, SIGNAL(upTick()), ui->controller_iso, SLOT(timerTick())); - connect(ui->controller_iso->driver, SIGNAL(killMe()), this, SLOT(reinitUsb())); - connect(ui->controller_iso->driver, SIGNAL(connectedStatus(bool)), ui->deviceConnected, SLOT(connectedStatusChanged(bool))); - connect(ui->controller_iso->driver, SIGNAL(signalFirmwareFlash(void)), ui->deviceConnected, SLOT(flashingFirmware(void))); - connect(ui->controller_iso->driver, SIGNAL(initialConnectComplete()), this, SLOT(resetUsbState())); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::checkXY, ui->xyDisplayLabel, &QAbstractButton::setChecked); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::disableWindow, ui->deviceConnected, &deviceConnectedDisplay::connectedStatusChanged); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::upTick, ui->controller_iso, &isoDriver::timerTick); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::killMe, this, &MainWindow::reinitUsb); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::connectedStatus, ui->deviceConnected, &deviceConnectedDisplay::connectedStatusChanged); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::signalFirmwareFlash, ui->deviceConnected, &deviceConnectedDisplay::flashingFirmware); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::initialConnectComplete, this, &MainWindow::resetUsbState); ui->controller_iso->driver->setGain(reinitScopeGain); ui->controller_iso->driver->psu_offset = psu_voltage_calibration_offset; readSettingsFile(); ui->controller_iso->driver->calibrateOnConnect = (dt_userWantsToCalibrate == 16384); //Yes/No are 16384/65536 for some reason. I think 0/1 are reserved for OK/Cancel. - connect(ui->controller_iso->driver, SIGNAL(calibrateMe()), this, SLOT(on_actionCalibrate_triggered())); + connect(ui->controller_iso->driver.data(), &genericUsbDriver::calibrateMe, this, &MainWindow::on_actionCalibrate_triggered); qDebug() << "ReinitUsbStage2 is returning"; } -void MainWindow::resetUsbState(void){ +void MainWindow::resetUsbState(){ using functionGen::ChannelID; //ui->controller_iso->driver->setDeviceMode(deviceMode); //ui->controller_iso->driver->setPsu(currentPsuVoltage); @@ -1420,7 +1408,7 @@ void MainWindow::resetUsbState(void){ ui->controller_iso->driver->setFunctionGen(ChannelID::CH1, ui->controller_fg->getChannelController(ChannelID::CH1)); ui->controller_iso->driver->setFunctionGen(ChannelID::CH2, ui->controller_fg->getChannelController(ChannelID::CH2)); - ui->controller_iso->clearBuffers(1,1,1); + ui->controller_iso->clearBuffers(isoDriver::Channel3751 | isoDriver::Channel3752 | isoDriver::Channel750); ui->controller_iso->doNotTouchGraph = false; } @@ -1699,7 +1687,7 @@ bool MainWindow::gestureFilter(QGestureEvent *event){ } else{ wheelEmu = new QWheelEvent(point, (embiggen ? 120 : -120), 0, 0, Qt::Vertical); } - ui->controller_iso->setVoltageRange(wheelEmu); + ui->controller_iso->onWheelEvent(wheelEmu); return true; } else { @@ -1740,7 +1728,7 @@ void MainWindow::on_actionCalibrate_triggered() calibrationMessages->exec(); return; } - if(ui->controller_iso->driver->deviceMode!=4){ + if(ui->controller_iso->driver->deviceMode != DeviceCH1DigitalCH2Digital){ calibrationMessages->setStandardButtons(QMessageBox::Ok|QMessageBox::Cancel); calibrationMessages->setText("The calibration sequence requires all devices to be turned off, except for the oscilloscope CH1 and CH2. Is it OK for me to change your workspace?"); int choice = calibrationMessages->exec(); @@ -1788,7 +1776,7 @@ void MainWindow::on_actionCalibrate_triggered() calibrationMessages->setText("Please disconnect all wires from your Labrador board then press OK to continue."); calibrationMessages->exec(); - ui->controller_iso->clearBuffers(1,1,1); + ui->controller_iso->clearBuffers(isoDriver::Channel3751 | isoDriver::Channel3752 | isoDriver::Channel750); QTimer::singleShot(1200, this, SLOT(calibrateStage2())); } @@ -1817,7 +1805,7 @@ void MainWindow::calibrateStage2(){ calibrationMessages->setText("Please connect both oscilloscope channels to the outer shield of the USB connector then press OK to continue."); calibrationMessages->exec(); - ui->controller_iso->clearBuffers(1,1,1); + ui->controller_iso->clearBuffers(isoDriver::Channel3751 | isoDriver::Channel3752 | isoDriver::Channel750); QTimer::singleShot(1200, this, SLOT(calibrateStage3())); } @@ -2039,7 +2027,7 @@ void MainWindow::on_actionRecord_CH1_triggered(bool checked) qDebug() << "on_actionRecord_CH1_triggered(bool checked)"; qDebug() << daq_max_file_size; if(!checked){ - if(ui->controller_iso->driver->deviceMode!=6){ + if(ui->controller_iso->driver->deviceMode != DeviceCH1Analog750) { ui->controller_iso->internalBuffer375_CH1->disableFileIO(); delete(output375_CH1); } else { @@ -2053,15 +2041,14 @@ void MainWindow::on_actionRecord_CH1_triggered(bool checked) QString fileName; showFileDialog(&fileName); qDebug() << fileName; - int len = fileName.length(); #ifndef PLATFORM_ANDROID - if(len==0){ + if(fileName.isEmpty()){ ui->actionRecord_CH1->setChecked(false); return; //User cancelled } #endif - if(ui->controller_iso->driver->deviceMode!=6){ + if(ui->controller_iso->driver->deviceMode != DeviceCH1Analog750) { output375_CH1 = new QFile(fileName); ui->controller_iso->internalBuffer375_CH1->enableFileIO(output375_CH1, daq_num_to_average, daq_max_file_size); } else { @@ -2084,10 +2071,9 @@ void MainWindow::on_actionRecord_CH2_triggered(bool checked) QString fileName; showFileDialog(&fileName); qDebug() << fileName; - int len = fileName.length(); #ifndef PLATFORM_ANDROID - if(len==0){ + if(fileName.isEmpty()){ ui->actionRecord_CH2->setChecked(false); return; //User cancelled } @@ -2095,7 +2081,7 @@ void MainWindow::on_actionRecord_CH2_triggered(bool checked) output375_CH2 = new QFile(fileName); ui->controller_iso->internalBuffer375_CH2->enableFileIO(output375_CH2, daq_num_to_average, daq_max_file_size); - if((checked) && (ui->controller_iso->driver->deviceMode != 4)) + if((checked) && (ui->controller_iso->driver->deviceMode != DeviceCH1DigitalCH2Digital)) QMessageBox::warning(nullptr, "Warning", "CH2 is disabled. The DAQ will NOT RECORD any data from from CH2 until it has been enabled!"); } @@ -2150,30 +2136,37 @@ void MainWindow::on_actionDAQ_Settings_triggered() qDebug() << "on_actionDAQ_Settings_triggered()"; daqForm df(this, daq_num_to_average, daq_max_file_size); df.setModal(true); - connect(&df, SIGNAL(updatedAveraging(int)), this, SLOT(daq_updatedAveraging(int))); - connect(&df, SIGNAL(updatedMaxFileSize(qulonglong)), this, SLOT(daq_updatedMaxFileSize(qulonglong))); - connect(&df, SIGNAL(saveButtonPressed()), this, SLOT(daq_saveButtonPressed())); + connect(&df, &daqForm::updatedAveraging, this, &MainWindow::daq_updatedAveraging); + connect(&df, &daqForm::updatedMaxFileSize, this, &MainWindow::daq_updatedMaxFileSize); + connect(&df, &daqForm::saveButtonPressed, this, &MainWindow::daq_saveButtonPressed); df.exec(); } -void MainWindow::fileLimitReached_CH1(void){ +void MainWindow::on_actionResetDisplay() +{ + ui->controller_iso->setBotRange(DEFAULT_BOTTOM_RANGE); + ui->controller_iso->setTopRange(DEFAULT_TOP_RANGE); + ui->controller_iso->setDelay(0.); + ui->controller_iso->setTimeWindow(MAX_WINDOW_SIZE); + +} + +void MainWindow::fileLimitReached_CH1(){ ui->actionRecord_CH1->setChecked(false); QMessageBox recordingStoppedMessageBox; char recordingStoppedMessage[256]; - sprintf(recordingStoppedMessage, "Maximum file size limit of %uMB reached. Data Acquisition Stopped.", daq_max_file_size/1000000); + sprintf(recordingStoppedMessage, "Maximum file size limit of %lluMB reached. Data Acquisition Stopped.", daq_max_file_size/1000000ull); recordingStoppedMessageBox.setText(recordingStoppedMessage); recordingStoppedMessageBox.exec(); } -void MainWindow::fileLimitReached_CH2(void){ +void MainWindow::fileLimitReached_CH2(){ ui->actionRecord_CH2->setChecked(false); QMessageBox recordingStoppedMessageBox; - char recordingStoppedMessage[256]; - sprintf(recordingStoppedMessage, "Maximum file size limit of %uMB reached. Data Acquisition Stopped.", daq_max_file_size/1000000); - recordingStoppedMessageBox.setText(recordingStoppedMessage); + recordingStoppedMessageBox.setText(QString::asprintf("Maximum file size limit of %lluMB reached. Data Acquisition Stopped.", daq_max_file_size/1000000ull)); recordingStoppedMessageBox.exec(); } @@ -2193,6 +2186,12 @@ void MainWindow::daq_saveButtonPressed(){ settings->setValue("daq_defaultFileSize", daq_max_file_size); } +void MainWindow::onChannel2Toggled() +{ + ch2Label->setVisible(ui->scopeGroup_CH2->isChecked()); + ui->scopeAxes->replot(); // what the fuck qcustomplot +} + void MainWindow::on_actionAbout_triggered() { QMessageBox aboutDialog(this); @@ -2306,7 +2305,7 @@ void MainWindow::on_actionCalibrate_2_triggered() ui->multimeterPauseCheckBox->setChecked(false); ui->controller_iso->setAutoGain(false); - ui->controller_iso->setGain(4); + emit ui->controller_iso->setGain(4); //Remove the offset before setting it again; don't want them to stack! ui->controller_iso->driver->psu_offset = 0; @@ -2317,7 +2316,7 @@ void MainWindow::on_actionCalibrate_2_triggered() calibrationMessages->exec(); ui->controller_iso->driver->setPsu(5); - ui->controller_iso->clearBuffers(1,1,1); + ui->controller_iso->clearBuffers(isoDriver::Channel3751 | isoDriver::Channel3752 | isoDriver::Channel750); QTimer::singleShot(1800, this, SLOT(calibrate_psu_stage2())); } @@ -2328,16 +2327,16 @@ void MainWindow::calibrate_psu_stage2() if((PSU5 > 6) | (PSU5 < 4) ){ ui->controller_iso->driver->setPsu(4.5); ui->psuSlider->setValue(0); - ui->controller_iso->clearBuffers(1,1,1); + ui->controller_iso->clearBuffers(isoDriver::Channel3751 | isoDriver::Channel3752 | isoDriver::Channel750); ui->controller_iso->setAutoGain(true); ui->controller_iso->autoGain(); calibrationMessages->setText("Calibration has been abandoned due to out-of-range values. The oscilloscope should show approximately 5V. Please check all wires on your Labrador board and try again."); calibrationMessages->exec(); return; } - ui->controller_iso->setGain(1); + emit ui->controller_iso->setGain(1); ui->controller_iso->driver->setPsu(10); - ui->controller_iso->clearBuffers(1,1,1); + ui->controller_iso->clearBuffers(isoDriver::Channel3751 | isoDriver::Channel3752 | isoDriver::Channel750); QTimer::singleShot(1800, this, SLOT(calibrate_psu_stage3())); } @@ -2347,7 +2346,7 @@ void MainWindow::calibrate_psu_stage3() qDebug() << "PSU10 =" << PSU10; ui->controller_iso->driver->setPsu(4.5); ui->psuSlider->setValue(0); - ui->controller_iso->clearBuffers(1,1,1); + ui->controller_iso->clearBuffers(isoDriver::Channel3751 | isoDriver::Channel3752 | isoDriver::Channel750); ui->controller_iso->setAutoGain(true); ui->controller_iso->autoGain(); @@ -2371,11 +2370,13 @@ void MainWindow::calibrate_psu_stage3() void MainWindow::on_actionSerial_triggered(bool checked) { + Q_UNUSED(checked); ui->controller_iso->setSerialType(0); } void MainWindow::on_actionI2C_triggered(bool checked) { + Q_UNUSED(checked); ui->controller_iso->setSerialType(1); } @@ -2387,15 +2388,16 @@ void MainWindow::on_actionShow_Range_Dialog_on_Main_Page_triggered(bool checked) scopeRangeSwitch = new scopeRangeEnterDialog(nullptr, false, ui->controller_iso->display.topRange, ui->controller_iso->display.botRange, ui->controller_iso->display.window, ui->controller_iso->display.delay); scopeRangeSwitch->setWindowFlags(Qt::Widget); ui->verticalLayout_5->insertWidget(2, scopeRangeSwitch); - connect(scopeRangeSwitch, SIGNAL(yTopUpdated(double)), ui->controller_iso, SLOT(setTopRange(double))); - connect(scopeRangeSwitch, SIGNAL(yBotUpdated(double)), ui->controller_iso, SLOT(setBotRange(double))); - connect(scopeRangeSwitch, SIGNAL(windowUpdated(double)), ui->controller_iso, SLOT(setTimeWindow(double))); - connect(scopeRangeSwitch, SIGNAL(delayUpdated(double)), ui->controller_iso, SLOT(setDelay(double))); + connect(scopeRangeSwitch, &scopeRangeEnterDialog::yTopUpdated, ui->controller_iso, &isoDriver::setTopRange); + connect(scopeRangeSwitch, &scopeRangeEnterDialog::yBotUpdated, ui->controller_iso, &isoDriver::setBotRange); + connect(scopeRangeSwitch, &scopeRangeEnterDialog::windowUpdated, ui->controller_iso, &isoDriver::setTimeWindow); + connect(scopeRangeSwitch, &scopeRangeEnterDialog::delayUpdated, ui->controller_iso, &isoDriver::setDelay); + connect(scopeRangeSwitch, &scopeRangeEnterDialog::autoClicked, this, &MainWindow::on_setAutoScopeRange); - connect(ui->controller_iso, SIGNAL(topRangeUpdated(double)), scopeRangeSwitch, SLOT(yTopChanged(double))); - connect(ui->controller_iso, SIGNAL(botRangeUpdated(double)), scopeRangeSwitch, SLOT(yBotChanged(double))); - connect(ui->controller_iso, SIGNAL(timeWindowUpdated(double)), scopeRangeSwitch, SLOT(windowChanged(double))); - connect(ui->controller_iso, SIGNAL(delayUpdated(double)), scopeRangeSwitch, SLOT(delayChanged(double))); + connect(ui->controller_iso, &isoDriver::topRangeUpdated, scopeRangeSwitch, &scopeRangeEnterDialog::yTopChanged); + connect(ui->controller_iso, &isoDriver::botRangeUpdated, scopeRangeSwitch, &scopeRangeEnterDialog::yBotChanged); + connect(ui->controller_iso, &isoDriver::timeWindowUpdated, scopeRangeSwitch, &scopeRangeEnterDialog::windowChanged); + connect(ui->controller_iso, &isoDriver::delayUpdated, scopeRangeSwitch, &scopeRangeEnterDialog::delayChanged); } qDebug() << "on_actionShow_Range_Dialog_on_Main_Page_triggered" << checked; settings->setValue("ShowRangeDialog", checked); @@ -2456,7 +2458,11 @@ void MainWindow::on_actionDocumentation_triggered() void MainWindow::on_actionPinout_triggered() { - QDesktopServices::openUrl(QUrl(kPinoutUrl, QUrl::TolerantMode)); + if (m_pinoutDialog) { // only allow one to exist + return; + } + m_pinoutDialog = new pinoutDialog; + m_pinoutDialog->show(); // don't exec, allows } void MainWindow::cursorGroupEnabled(bool enabled) @@ -2511,3 +2517,70 @@ void MainWindow::on_actionHide_Widget_LogicAnalyzer_triggered(bool checked) ui->busSnifferGroup_CH2->setVisible(!checked); ui->digitalOutputGroup->setVisible(!checked); } + +void MainWindow::on_setAutoScopeRange() +{ + if (ui->controller_iso->numSamples() <= 0) { + return; + } + + const double max = ui->controller_iso->vMax(); + const double min = ui->controller_iso->vMin(); + ui->controller_iso->setTopRange(max + max * 0.1); // 10% extra above + ui->controller_iso->setBotRange(min - min * 0.1); // 10% extra below + + +} + +void MainWindow::keyPressEvent(QKeyEvent *event) +{ + if (maybeHandleKeypress(event)) { + event->setAccepted(true); + return; + } + + QMainWindow::keyPressEvent(event); +} + +bool MainWindow::eventFilter(QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::KeyPress) { + if (maybeHandleKeypress(static_cast(event))) { + QWidget *original = qobject_cast(obj); + if (original) { + original->clearFocus(); + } + event->setAccepted(true); + return true; + } + } + + return QObject::eventFilter(obj, event); +} + +bool MainWindow::maybeHandleKeypress(QKeyEvent *event) +{ + if (!(ui->scopeAxes->underMouse())) { + return false; + } + switch(event->key()) { + case Qt::Key_Down: + if (event->modifiers() & Qt::ControlModifier) { + ctrlArrowDownTriggered(); + } else { + arrowDownTriggered(); + } + break; + case Qt::Key_Up: + if (event->modifiers() & Qt::ControlModifier) { + ctrlArrowUpTriggered(); + } else { + arrowUpTriggered(); + } + break; + default: + return false; + } + + return true; +} diff --git a/Desktop_Interface/mainwindow.h b/Desktop_Interface/mainwindow.h index 8edc9a51..65087b82 100644 --- a/Desktop_Interface/mainwindow.h +++ b/Desktop_Interface/mainwindow.h @@ -16,7 +16,7 @@ #include #include -#include "qcustomplot.h" +#include #include "platformspecific.h" #include "qcustomplot.h" @@ -29,7 +29,7 @@ //The Main Window object. This has a lot of control information too (keyboard shortcuts etc.)! - +class pinoutDialog; namespace Ui { class MainWindow; @@ -40,9 +40,9 @@ class MainWindow : public QMainWindow Q_OBJECT public: - explicit MainWindow(QWidget *parent = 0); + explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); - void resizeEvent(QResizeEvent *event); + void resizeEvent(QResizeEvent *event) override; void showFileDialog(QString *fileName); void openFileDialog(QString *fileName); private slots: @@ -67,6 +67,11 @@ private slots: void on_actionSnap_to_Cursors_triggered(); void on_actionEnter_Manually_triggered(); + void on_actionDownsampleDecimate_triggered(); + void on_actionDownsamplePeak_triggered(); + void on_actionDownsampleBottom_triggered(); + void on_actionDownsampleAverageDelta_triggered(); + void connectDisplaySignals(); void calibrateStage2(); void calibrateStage3(); @@ -104,7 +109,6 @@ private slots: void cycleBaudRateBackwards_CH2(); //Deprecated/Unsupported - void timeBaseNeedsChanging(bool positive); void on_actionForce_Square_triggered(bool checked); void helloWorld(); @@ -123,8 +127,6 @@ private slots: void on_actionAuto_Lock_toggled(bool arg1); //File/other - void on_actionRecord_triggered(bool checked); - void on_actionTake_Snapshot_triggered(); void reinitUsb(void); void reinitUsbStage2(void); void resetUsbState(void); @@ -167,6 +169,7 @@ private slots: void on_actionShow_Debug_Console_triggered(); void on_actionDAQ_Settings_triggered(); + void on_actionResetDisplay(); void fileLimitReached_CH1(void); void fileLimitReached_CH2(void); @@ -175,8 +178,10 @@ private slots: void daq_updatedMaxFileSize(qulonglong newVal); void daq_saveButtonPressed(); + void onChannel2Toggled(); +public slots: void on_actionAbout_triggered(); void on_actionOpen_DAQ_File_triggered(); @@ -227,12 +232,19 @@ private slots: void on_actionHide_Widget_LogicAnalyzer_triggered(bool checked); + void on_setAutoScopeRange(); + +protected: + void keyPressEvent(QKeyEvent *event) override; + bool eventFilter(QObject *obj, QEvent *event) override; + bool maybeHandleKeypress(QKeyEvent *event); + private: //Generic Vars Ui::MainWindow *ui; - QWheelEvent *wheelEmu; bool forceSquare = false; QCPItemText *textLabel; + QCPItemText *ch2Label = nullptr; QFile *output375_CH1, *output375_CH2, *output750; unsigned char caibrateStage; QMessageBox *calibrationMessages; @@ -267,30 +279,6 @@ private slots: QActionGroup *fpsGroup; QActionGroup *connectionTypeGroup; QActionGroup *serialProtocolGroup; - QShortcut *shortcut_cycleBaudRate_CH1; - QShortcut *shortcut_cycleBaudRateBackwards_CH1; - QShortcut *shortcut_cycleBaudRate_CH2; - QShortcut *shortcut_cycleBaudRateBackwards_CH2; - QShortcut *shortcut_ArrowUp; - QShortcut *shortcut_ArrowDown; - QShortcut *shortcut_CtrlArrowUp; - QShortcut *shortcut_CtrlArrowDown; - QShortcut *shortcut_w; - QShortcut *shortcut_ctrlW; - QShortcut *shortcut_s; - QShortcut *shortcut_ctrlS; - QShortcut *shortcut_a; - QShortcut *shortcut_d; - QShortcut *shortcut_ArrowLeft; - QShortcut *shortcut_ArrowRight; - QShortcut *shortcut_CtrlArrowLeft; - QShortcut *shortcut_CtrlArrowRight; - QShortcut *shortcut_snapScopeToCursors;\ - QShortcut *shortcut_manualRange; - QShortcut *shortcut_snapshot_CH1; - QShortcut *shortcut_snapshot_CH2; - QShortcut *shortcut_Debug; - QShortcut *shortcut_Esc; //Duct Tape bool dt_AlreadyAskedAboutCalibration = false; @@ -300,6 +288,8 @@ private slots: scopeRangeEnterDialog* scopeRangeSwitch = nullptr; + QPointer m_pinoutDialog; // QPointer automatically resets when object is deleted + #ifdef PLATFORM_ANDROID //Android Special QScreen *screenPtr; diff --git a/Desktop_Interface/pinoutDialog.cpp b/Desktop_Interface/pinoutDialog.cpp new file mode 100644 index 00000000..e3d4a8a6 --- /dev/null +++ b/Desktop_Interface/pinoutDialog.cpp @@ -0,0 +1,74 @@ +#include "pinoutDialog.h" + +#include +#include +#include +#include +#include +#include +#include + +class ImageLabel : public QLabel +{ +public: + ImageLabel(const QString &path) : m_image(path) + { + setPixmap(m_image); + } + + QSize sizeHint() const override { + return m_image.size(); + } +protected: + void resizeEvent(QResizeEvent *event) override + { + setPixmap(m_image.scaled(event->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); + QLabel::resizeEvent(event); + } + +private: + QPixmap m_image; +}; + +static QString loadDescription() +{ + QFile file(":/resources/pinout.html"); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << "Failed to load" << file.fileName(); + return ""; + } + return QString::fromUtf8(file.readAll()); +} + +pinoutDialog::pinoutDialog() +{ + QVBoxLayout *mainLayout = new QVBoxLayout; + setLayout(mainLayout); + + QHBoxLayout *contentLayout = new QHBoxLayout; + mainLayout->addLayout(contentLayout); + + QLabel *imageLabel = new ImageLabel(":/resources/pinout.png"); + imageLabel->setMinimumSize(250, 250); + imageLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + contentLayout->addWidget(imageLabel); + + QLabel *description = new QLabel; + description->setWordWrap(true); + description->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + description->setTextFormat(Qt::RichText); + description->setText(loadDescription()); + description->setAlignment(Qt::AlignTop | Qt::AlignLeft); + contentLayout->addWidget(description); + + QHBoxLayout *buttonLayout = new QHBoxLayout; + mainLayout->addLayout(buttonLayout); + buttonLayout->addStretch(); + + QPushButton *closeButton = new QPushButton(tr("Close")); + closeButton->setDefault(true); + buttonLayout->addWidget(closeButton); + + connect(closeButton, &QPushButton::clicked, this, &QDialog::accept); + +} diff --git a/Desktop_Interface/pinoutDialog.h b/Desktop_Interface/pinoutDialog.h new file mode 100644 index 00000000..20ccb45b --- /dev/null +++ b/Desktop_Interface/pinoutDialog.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +class pinoutDialog : public QDialog +{ +public: + pinoutDialog(); +}; + diff --git a/Desktop_Interface/resources.qrc b/Desktop_Interface/resources.qrc index aca22c87..1f00537f 100644 --- a/Desktop_Interface/resources.qrc +++ b/Desktop_Interface/resources.qrc @@ -5,4 +5,16 @@ buffer_2.bmp diagram.png + + resources/pinout.html + resources/pinout.png + + + bin/waveforms/_list.wfl + bin/waveforms/DC.tlw + bin/waveforms/Sawtooth.tlw + bin/waveforms/Sin.tlw + bin/waveforms/Square.tlw + bin/waveforms/Triangle.tlw + diff --git a/Desktop_Interface/resources/pinout.html b/Desktop_Interface/resources/pinout.html new file mode 100644 index 00000000..df0bb4a6 --- /dev/null +++ b/Desktop_Interface/resources/pinout.html @@ -0,0 +1,26 @@ +

AC-coupled pins

+ +

+ The AC coupled pins remove the DC component from your signals, and are meant + mainly for audio purposes and dual-ended opamps. + For general use, you will almost always want to use the DC-coupled pins, + as they do not alter your signal in any way. +

+ +

Duplicate oscilloscope pins

+

+ The duplicate oscilloscope pins are there for measuring resistance and + capacitance on the multimeter. You do not need them otherwise. +

+ +

Fuse bypass pins

+

+ The fuse bypass pins (to the immediate left of the USB connector on the + diagram) are used for bypassing the fuse, if you need to, by shorting them + together. The top pin, as seen on the image, is a 5V pin directly from the USB + connector, and the bottom pin is the 5V output of the fuse. +

+ +

+ The fuse is a PTC resettable fuse, with a maximum current of around 400 mA. +

diff --git a/Desktop_Interface/resources/pinout.png b/Desktop_Interface/resources/pinout.png new file mode 100644 index 00000000..b96698df Binary files /dev/null and b/Desktop_Interface/resources/pinout.png differ diff --git a/Desktop_Interface/scoperangeenterdialog.cpp b/Desktop_Interface/scoperangeenterdialog.cpp index c6cd00c6..1329a65c 100644 --- a/Desktop_Interface/scoperangeenterdialog.cpp +++ b/Desktop_Interface/scoperangeenterdialog.cpp @@ -1,5 +1,6 @@ #include "scoperangeenterdialog.h" #include "ui_scoperangeenterdialog.h" +#include scopeRangeEnterDialog::scopeRangeEnterDialog(QWidget *parent, bool buttonVisible, double yTop, double yBot, double window, double delay) : QDialog(parent), @@ -10,15 +11,23 @@ scopeRangeEnterDialog::scopeRangeEnterDialog(QWidget *parent, bool buttonVisible ui->vMaxBox->setMinimum(yBot); ui->vMinBox->setMaximum(yTop); + ui->delayBox->setValue(delay); ui->vMaxBox->setValue(yTop); ui->vMinBox->setValue(yBot); ui->timeWindowBox->setValue(window); ui->buttonBox->setVisible(buttonVisible); + if (!buttonVisible) { + QPushButton *autoButton = new QPushButton(tr("&Auto")); + ui->verticalLayout->addWidget(autoButton); + + connect(autoButton, &QPushButton::clicked, this, &scopeRangeEnterDialog::autoClicked); + } + for (espoSpinBox* spinBox : {ui->vMaxBox, ui->vMinBox, ui->timeWindowBox, ui->delayBox}) { spinBox->changeStepping(spinBox->value()); - connect(spinBox, SIGNAL(valueChanged(double)), spinBox, SLOT(changeStepping(double))); + connect(spinBox, qOverload(&QDoubleSpinBox::valueChanged), spinBox, &espoSpinBox::changeStepping); } } @@ -33,7 +42,7 @@ void scopeRangeEnterDialog::toUpdateYTop(double val){ if (yTop != val) { yTop = val; - yTopUpdated(val); + emit yTopUpdated(val); } } @@ -43,7 +52,7 @@ void scopeRangeEnterDialog::toUpdateYBot(double val){ if (yBot != val) { yBot = val; - yBotUpdated(val); + emit yBotUpdated(val); } } @@ -55,7 +64,7 @@ void scopeRangeEnterDialog::toUpdateWindow(double val){ ui->delayBox->setMax(((double)MAX_WINDOW_SIZE) - ui->timeWindowBox->value()); qDebug() << "delayBox updating to" << ui->delayBox->maximum(); timeWindow = val; - windowUpdated(val); + emit windowUpdated(val); } } @@ -67,7 +76,7 @@ void scopeRangeEnterDialog::toUpdateDelay(double val){ ui->timeWindowBox->setMax(((double)MAX_WINDOW_SIZE) - ui->delayBox->value()); qDebug() << "timeWindowBox updating max to" << ui->timeWindowBox->maximum(); delay = val; - delayUpdated(val); + emit delayUpdated(val); } } diff --git a/Desktop_Interface/scoperangeenterdialog.h b/Desktop_Interface/scoperangeenterdialog.h index c6c20cdb..a71c49b8 100644 --- a/Desktop_Interface/scoperangeenterdialog.h +++ b/Desktop_Interface/scoperangeenterdialog.h @@ -17,9 +17,15 @@ class scopeRangeEnterDialog : public QDialog Q_OBJECT public: - explicit scopeRangeEnterDialog(QWidget *parent = 0, bool buttonVisible = true, double yTop = 20, double yBot = -20, double window = -10, double delay = 0); + explicit scopeRangeEnterDialog(QWidget *parent = nullptr, bool buttonVisible = true, double yTop = 20, double yBot = -20, double window = -10, double delay = 0); ~scopeRangeEnterDialog(); +public slots: + void yTopChanged(double val); + void yBotChanged(double val); + void windowChanged(double val); + void delayChanged(double val); + private: Ui::scopeRangeEnterDialog *ui; double delay = 130065506; @@ -32,15 +38,13 @@ class scopeRangeEnterDialog : public QDialog void yBotUpdated(double val); void windowUpdated(double val); void delayUpdated(double val); + void autoClicked(); + private slots: void toUpdateYTop(double val); void toUpdateYBot(double val); void toUpdateWindow(double val); void toUpdateDelay(double val); - void yTopChanged(double val); - void yBotChanged(double val); - void windowChanged(double val); - void delayChanged(double val); }; #endif // SCOPERANGEENTERDIALOG_H diff --git a/Desktop_Interface/uartstyledecoder.cpp b/Desktop_Interface/uartstyledecoder.cpp index cb06e0e4..2f9382f5 100644 --- a/Desktop_Interface/uartstyledecoder.cpp +++ b/Desktop_Interface/uartstyledecoder.cpp @@ -68,7 +68,7 @@ void uartStyleDecoder::serialDecode() else { // Uart starts transmitting after start bit (logic low). - uartTransmitting = uart_bit == false; + uartTransmitting = !uart_bit; jitterCompensationNeeded = true; } @@ -82,7 +82,7 @@ void uartStyleDecoder::serialDecode() if (allZeroes) { qDebug() << "Wire Disconnect detected!"; - wireDisconnected(m_parent->m_channel); + emit wireDisconnected(m_parent->m_channel); m_parent->m_isDecoding = false; m_updateTimer.stop(); } @@ -90,7 +90,7 @@ void uartStyleDecoder::serialDecode() int uartStyleDecoder::serialDistance() const { - int back_bit = m_parent->m_back * 8; + unsigned back_bit = m_parent->m_back * 8; int bufferEnd_bit = (m_parent->m_bufferLen-1) * 8; if (back_bit >= serialPtr_bit) return back_bit - serialPtr_bit; @@ -185,7 +185,7 @@ bool uartStyleDecoder::jitterCompensationProcedure(bool current_bit) if (left_byte != 0xff) { //Step back, one sample at a time, to the 0->1 transition point - bool temp_bit = 1; + bool temp_bit = true; while(temp_bit) { temp_bit = getNextUartBit(); @@ -200,7 +200,7 @@ bool uartStyleDecoder::jitterCompensationProcedure(bool current_bit) } //Basically scaffolding to add character maps for other modes (5 bit, for example). -char uartStyleDecoder::decodeDatabit(int mode, short symbol) const +char uartStyleDecoder::decodeDatabit(int mode, short symbol) { switch(mode) { @@ -211,14 +211,92 @@ char uartStyleDecoder::decodeDatabit(int mode, short symbol) const return symbol; break; default: - qDebug() << "uartStyleDecoder::decodeDatabit is failing..."; + qDebug() << "uartStyleDecoder::decodeDatabit: invalid mode" << mode; return -1; // Garbage } } -char uartStyleDecoder::decodeBaudot(short symbol) const +char uartStyleDecoder::decodeBaudot(short symbol) { - return 'a'; + // Baudot-Murray code, ITA2 variant + + if (m_baudotFigures) { + switch(symbol) { + case 1: return '3'; + case 3: return '-'; + case 5: return '\''; + case 6: return '8'; + case 7: return '7'; + case 9: return 0x5; // Enquiry + case 11: return '\a'; // Bell + case 12: return ','; + case 13: return '!'; + case 14: return ':'; + case 15: return '('; + case 16: return '5'; + case 17: return '+'; + case 18: return ')'; + case 19: return '2'; + case 20: return '$'; // or £ + case 21: return '6'; + case 22: return '0'; + case 23: return '1'; + case 24: return '9'; + case 25: return '?'; + case 26: return '&'; // or @ + case 28: return '.'; + case 29: return '/'; + case 30: return ';'; + + case 27: return ' '; // Switch to figures in letter mode + case 31: m_baudotFigures = false; return -1; // Switch to letters + + default: + // Either a common one, or unknown + break; + } + } + + // Letter mode: + switch(symbol) { + case 0: return '\0'; + case 2: return '\n'; + case 8: return '\r'; + + case 1: return 'E'; + case 3: return 'A'; + case 4: return ' '; + case 5: return 'S'; + case 6: return 'I'; + case 7: return 'U'; + case 9: return 'D'; + case 10: return 'R'; + case 11: return 'J'; + case 12: return 'N'; + case 13: return 'F'; + case 14: return 'C'; + case 15: return 'K'; + case 16: return 'T'; + case 17: return 'Z'; + case 18: return 'L'; + case 19: return 'W'; + case 20: return 'H'; + case 21: return 'Y'; + case 22: return 'P'; + case 23: return 'Q'; + case 24: return 'O'; + case 25: return 'B'; + case 26: return 'G'; + case 28: return 'M'; + case 29: return 'X'; + case 30: return 'V'; + + case 27: m_baudotFigures = true; return ' '; + case 31: return 0x8; // Delete/erase, we return backspace + default: + qWarning() << "Invalid baudot:" << symbol; + return -1; + } } void uartStyleDecoder::setParityMode(UartParity newParity) diff --git a/Desktop_Interface/uartstyledecoder.h b/Desktop_Interface/uartstyledecoder.h index 999f16cd..9a2e8a6f 100644 --- a/Desktop_Interface/uartstyledecoder.h +++ b/Desktop_Interface/uartstyledecoder.h @@ -19,7 +19,7 @@ class uartStyleDecoder : public QObject { Q_OBJECT public: - explicit uartStyleDecoder(double baudRate, QObject *parent = NULL); + explicit uartStyleDecoder(double baudRate, QObject *parent = nullptr); ~uartStyleDecoder() = default; @@ -27,7 +27,7 @@ class uartStyleDecoder : public QObject isoBuffer *m_parent; // Indicates the current bit being decoded. - int serialPtr_bit; + unsigned serialPtr_bit; bool uartTransmitting = false; bool newUartSymbol = false; @@ -61,8 +61,8 @@ public slots: void setHexDisplay(bool enabled); private: - char decodeDatabit(int mode, short symbol) const; - char decodeBaudot(short symbol) const; + char decodeDatabit(int mode, short symbol); + char decodeBaudot(short symbol); std::mutex mutex; UartParity parity = UartParity::None; @@ -71,6 +71,7 @@ public slots: UartParity parityOf(uint32_t bitField) const; bool parityCheckFailed = false; + bool m_baudotFigures = false; }; diff --git a/Desktop_Interface/ui_elements.pri b/Desktop_Interface/ui_elements.pri index c515cb67..2f997737 100644 --- a/Desktop_Interface/ui_elements.pri +++ b/Desktop_Interface/ui_elements.pri @@ -1,8 +1,12 @@ @INCLUDEPATH += $$PWD/ui_elements @DEPENDPATH += $$PWD/ui_elements -INCLUDEPATH += $$PWD/ui_elements/qcp$${QCP_VER} -DEPENDPATH += $$PWD/ui_elements/qcp$${QCP_VER} +!contains(CONFIG, "USE_SYSTEM_LIBS") { + INCLUDEPATH += $$PWD/ui_elements/qcp$${QCP_VER} + DEPENDPATH += $$PWD/ui_elements/qcp$${QCP_VER} + SOURCES += ui_elements/qcp$${QCP_VER}/qcustomplot.cpp + HEADERS += ui_elements/qcp$${QCP_VER}/qcustomplot.h +} SOURCES += ui_elements/buffercontrol.cpp \ @@ -12,7 +16,6 @@ SOURCES += ui_elements/buffercontrol.cpp \ ui_elements/esposlider.cpp \ ui_elements/espospinbox.cpp \ ui_elements/noclosemenu.cpp \ - ui_elements/qcp$${QCP_VER}/qcustomplot.cpp \ ui_elements/siprint.cpp \ ui_elements/timedtickbox.cpp \ ui_elements/voltagespinbox.cpp \ @@ -26,7 +29,6 @@ HEADERS += ui_elements/buffercontrol.h \ ui_elements/esposlider.h \ ui_elements/espospinbox.h \ ui_elements/noclosemenu.h \ - ui_elements/qcp$${QCP_VER}/qcustomplot.h \ ui_elements/siprint.h \ ui_elements/timedtickbox.h \ ui_elements/voltagespinbox.h \ diff --git a/Desktop_Interface/ui_elements/buffercontrol.cpp b/Desktop_Interface/ui_elements/buffercontrol.cpp index 399b0b8f..5bc01004 100644 --- a/Desktop_Interface/ui_elements/buffercontrol.cpp +++ b/Desktop_Interface/ui_elements/buffercontrol.cpp @@ -5,7 +5,7 @@ bufferControl::bufferControl(QWidget *parent) : QLabel(parent) //refreshImage(); } -void bufferControl::refreshImage(void){ +void bufferControl::refreshImage(){ //qDebug() << "Trying to show bitmap " << numBuffers; switch(numBuffers){ @@ -34,16 +34,16 @@ void bufferControl::scopeIn_CH1(bool state){ //What about DSR!? if (scopeState_CH2){ //Implicitly state is false scopeState_CH2 = false; //updateBuffer(0); - Causes issues because the uncheck below called scopeIn_CH2 (but only when toggle)!!! - scopeUncheck(0); + emit scopeUncheck(false); } //Turn off the DSR when CH1 is disabled. if(!state && !scopeDsrDisableOverride){ - scopeDsrUncheck(0); + emit scopeDsrUncheck(false); } - scopeDsrOut(state); - scopeOut_CH2(state); + emit scopeDsrOut(state); + emit scopeOut_CH2(state); updateBuffer(state,1); // Do this last to ensure anything accidentally enabled is immediately switched off qDebug() << "scopeIn_CH1" << state; @@ -66,27 +66,19 @@ void bufferControl::scopeDsrIn(bool state){ updateMode(); } -/*void bufferControl::signalGenIn(bool state){ - signalGenState = state; - - updateBuffer(state,1); - qDebug() << "signalGenIn" << state; - updateMode(); -}*/ - void bufferControl::busSnifferIn_CH1(bool state){ busSnifferState_CH1 = state; if (busSnifferState_CH2){ //Implicitly state is false busSnifferState_CH2 = false; //updateBuffer(0); - Causes issues because the uncheck below called scopeIn_CH2 (but only when toggle)!!! - busSnifferUncheck(0); + emit busSnifferUncheck(false); } //Signal Gen CH2 doesn't work with bus sniffer. - signalGenOut(!state); + emit signalGenOut(!state); - busSnifferOut_CH2(state); + emit busSnifferOut_CH2(state); updateBuffer(state,1); qDebug() << "busSnifferIn_CH1" << state; @@ -123,44 +115,44 @@ void bufferControl::updateBuffer(bool decrement, int amount){ //Write new state switch(numBuffers){ case 0: - if(scopeState_CH1 == false) scopeOut_CH1(0); - if(scopeState_CH2 == false) scopeOut_CH2(0); - if(scopeDsrState == false) scopeDsrOut(0); + if(scopeState_CH1 == false) emit scopeOut_CH1(false); + if(scopeState_CH2 == false) emit scopeOut_CH2(false); + if(scopeDsrState == false) emit scopeDsrOut(false); //if(signalGenState == false) signalGenOut(0); - if(busSnifferState_CH1 == false) busSnifferOut_CH1(0); - if(busSnifferState_CH2 == false) busSnifferOut_CH2(0); - if(multimeterState == false) multimeterOut(0); + if(busSnifferState_CH1 == false) emit busSnifferOut_CH1(false); + if(busSnifferState_CH2 == false) emit busSnifferOut_CH2(false); + if(multimeterState == false) emit multimeterOut(false); break; case 1: - scopeOut_CH1(1); + emit scopeOut_CH1(true); if(scopeState_CH1 == true){ - scopeDsrOut(1); - scopeOut_CH2(1); + emit scopeDsrOut(true); + emit scopeOut_CH2(true); } //signalGenOut(1); - busSnifferOut_CH1(1); + emit busSnifferOut_CH1(true); if(busSnifferState_CH1 == true){ - busSnifferOut_CH2(1); + emit busSnifferOut_CH2(true); } //busSnifferOut_CH2(1); - multimeterOut(0); + emit multimeterOut(false); break; case 2: - scopeOut_CH1(1); + emit scopeOut_CH1(true); //scopeOut_CH2(1); - if(scopeState_CH1 == true) scopeDsrOut(1); + if(scopeState_CH1 == true) emit scopeDsrOut(true); //signalGenOut(1); - busSnifferOut_CH1(1); + emit busSnifferOut_CH1(true); //busSnifferOut_CH2(1); - multimeterOut(1); + emit multimeterOut(true); break; default: qFatal("numBuffers is not equal to 0, 1 or 2"); } if(scopeDsrDisableOverride){ - scopeDsrOut(0); + emit scopeDsrOut(false); } } @@ -172,7 +164,7 @@ void bufferControl::digIn_CH1(bool state){ else{ digState &= (unsigned char) 0xff - mask; } - updateDig(digState); + emit updateDig(digState); } void bufferControl::digIn_CH2(bool state){ @@ -182,7 +174,7 @@ void bufferControl::digIn_CH2(bool state){ } else{ digState &= (unsigned char) 0xff - mask; - } updateDig(digState); + } emit updateDig(digState); } void bufferControl::digIn_CH3(bool state){ @@ -192,7 +184,7 @@ void bufferControl::digIn_CH3(bool state){ } else{ digState &= (unsigned char) 0xff - mask; - } updateDig(digState); + } emit updateDig(digState); } void bufferControl::digIn_CH4(bool state){ @@ -202,56 +194,56 @@ void bufferControl::digIn_CH4(bool state){ } else{ digState &= (unsigned char) 0xff - mask; - } updateDig(digState); + } emit updateDig(digState); } -void bufferControl::updateMode(void){ +void bufferControl::updateMode(){ if(multimeterState){ - modeChange(7); + emit modeChange(7); qDebug() << "Changed to mode 7"; return; } if(scopeDsrState){ - modeChange(6); + emit modeChange(6); qDebug() << "Changed to mode 6"; return; } if (busSnifferState_CH2){ - modeChange(4); + emit modeChange(4); qDebug() << "Changed to mode 4"; return; } if(busSnifferState_CH1 && scopeState_CH1){ - modeChange(1); + emit modeChange(1); qDebug() << "Changed to mode 1"; return; } if (scopeState_CH2){ - modeChange(2); + emit modeChange(2); qDebug() << "Changed to mode 2"; return; } if(busSnifferState_CH1){ - modeChange(3); + emit modeChange(3); qDebug() << "Changed to mode 3"; return; } if(scopeState_CH1){ - modeChange(0); + emit modeChange(0); qDebug() << "Changed to mode 0"; return; } - modeChange(5); + emit modeChange(5); qDebug() << "Changed to mode 5"; return; } -void bufferControl::poke(void){ - updateDig(digState); +void bufferControl::poke(){ + emit updateDig(digState); updateMode(); - updateBuffer(0,0); + updateBuffer(false,0); } diff --git a/Desktop_Interface/ui_elements/buffercontrol.h b/Desktop_Interface/ui_elements/buffercontrol.h index 83bd857e..34b38ffd 100644 --- a/Desktop_Interface/ui_elements/buffercontrol.h +++ b/Desktop_Interface/ui_elements/buffercontrol.h @@ -11,7 +11,7 @@ class bufferControl : public QLabel { Q_OBJECT public: - explicit bufferControl(QWidget *parent = 0); + explicit bufferControl(QWidget *parent = nullptr); void refreshImage(void); bool busSnifferState_CH1 = false; bool scopeDsrDisableOverride = false; @@ -46,7 +46,6 @@ public slots: void scopeIn_CH1(bool state); void scopeIn_CH2(bool state); void scopeDsrIn(bool state); - //void signalGenIn(bool state); void busSnifferIn_CH1(bool state); void busSnifferIn_CH2(bool state); void multimeterIn(bool state); diff --git a/Desktop_Interface/ui_elements/cursorenabler.cpp b/Desktop_Interface/ui_elements/cursorenabler.cpp index 77a5391b..f71ac948 100644 --- a/Desktop_Interface/ui_elements/cursorenabler.cpp +++ b/Desktop_Interface/ui_elements/cursorenabler.cpp @@ -3,7 +3,7 @@ cursorEnabler::cursorEnabler(QWidget *parent) : QLabel(parent) { - this->setVisible(0); + this->setVisible(false); #ifdef PLATFORM_ANDROID this->m_turnedOn = false; #endif @@ -20,12 +20,12 @@ void cursorEnabler::clickDetected(QMouseEvent* event){ if(m_turnedOn){ if (event->button() == Qt::LeftButton) { - tickHori(1); + emit tickHori(true); } else if (event->button() == Qt::RightButton) { - tickVert(1); + emit tickVert(true); } } - passOnSignal(event); + emit passOnSignal(event); } diff --git a/Desktop_Interface/ui_elements/cursorenabler.h b/Desktop_Interface/ui_elements/cursorenabler.h index 6674deb0..c1f84c63 100644 --- a/Desktop_Interface/ui_elements/cursorenabler.h +++ b/Desktop_Interface/ui_elements/cursorenabler.h @@ -11,7 +11,7 @@ class cursorEnabler : public QLabel { Q_OBJECT public: - explicit cursorEnabler(QWidget *parent = 0); + explicit cursorEnabler(QWidget *parent = nullptr); bool turnedOn() {return m_turnedOn;} private: bool m_turnedOn = true; diff --git a/Desktop_Interface/ui_elements/deviceconnecteddisplay.cpp b/Desktop_Interface/ui_elements/deviceconnecteddisplay.cpp index 6980cbbd..46d24abc 100644 --- a/Desktop_Interface/ui_elements/deviceconnecteddisplay.cpp +++ b/Desktop_Interface/ui_elements/deviceconnecteddisplay.cpp @@ -22,7 +22,7 @@ void deviceConnectedDisplay::connectedStatusChanged(bool status){ #endif } -void deviceConnectedDisplay::flashingFirmware(void){ +void deviceConnectedDisplay::flashingFirmware(){ qDebug() << "deviceConnectedDisplay::flashingFirmware"; this->setText("Flashing Device Firmware"); this->setStyleSheet("QLabel { color:green; }"); diff --git a/Desktop_Interface/ui_elements/deviceconnecteddisplay.h b/Desktop_Interface/ui_elements/deviceconnecteddisplay.h index 20dc29b4..c892d3f4 100644 --- a/Desktop_Interface/ui_elements/deviceconnecteddisplay.h +++ b/Desktop_Interface/ui_elements/deviceconnecteddisplay.h @@ -11,7 +11,7 @@ class deviceConnectedDisplay : public QLabel { Q_OBJECT public: - explicit deviceConnectedDisplay(QWidget *parent = 0); + explicit deviceConnectedDisplay(QWidget *parent = nullptr); signals: public slots: void connectedStatusChanged(bool status); diff --git a/Desktop_Interface/ui_elements/espocombobox.cpp b/Desktop_Interface/ui_elements/espocombobox.cpp index 40217ccc..c8a60d71 100644 --- a/Desktop_Interface/ui_elements/espocombobox.cpp +++ b/Desktop_Interface/ui_elements/espocombobox.cpp @@ -6,58 +6,43 @@ espoComboBox::espoComboBox(QWidget *parent) : QComboBox(parent) } -void espoComboBox::readWaveformList(void) +void espoComboBox::readWaveformList() { - //This code gets the name of the current directory, regardless of platform. - //This is so the interface knows where to find the waveform data - //QDir *dir = new QDir(); - //qDebug() << dir->currentPath(); + const QStringList potentialDirs = { #ifdef PLATFORM_ANDROID - QFile qt_list("assets:/waveforms/_list.wfl"); + "assets:", +#else + QCoreApplication::applicationDirPath(), +#endif + ":/", // fall back to builtin + }; + + QString filename; + for (const QString &dir : potentialDirs) { + const QString potential = dir + "/waveforms/_list.wfl"; + if (QFileInfo::exists(potential)) { + filename = potential; + break; + } + } + if (filename.isEmpty()) { + qWarning() << "Failed to find a waveform list!"; + return; + } + + QFile qt_list(filename); bool success = qt_list.open(QIODevice::ReadOnly | QIODevice::Text); if(!success){ - qFatal("Could not load _list.wfl"); + qWarning("Could not load _list.wfl"); + return; } - char nameBuffer[255]; - QStringList *newNames = new QStringList(); + QStringList newNames; while (!qt_list.atEnd()) { - QByteArray line = qt_list.readLine(); - strcpy(nameBuffer, line.data()); - strtok(nameBuffer, "\n\r"); - newNames->append(nameBuffer); - qDebug() << nameBuffer; + this->addItem(qt_list.readLine().trimmed()); } - this->addItems(*(newNames)); - delete newNames; qt_list.close(); -#else - QString dirString = QCoreApplication::applicationDirPath(); - dirString.append("/waveforms/_list.wfl"); - QByteArray array = dirString.toLocal8Bit(); - char* buffer = array.data(); - //qDebug() << buffer; - - qDebug() << "Attempting to open" << dirString; - FILE *listPtr = fopen(buffer, "r"); - QStringList *newNames = new QStringList(); - char nameBuffer[255]; - - if(listPtr == NULL){ - qFatal("Could not load _list.wfl"); - } - - while (fgets(nameBuffer,256,listPtr) !=NULL){ - qDebug() << "nameBuffer = " << nameBuffer; - strtok(nameBuffer, "\n\r"); - newNames->append(nameBuffer); - } - this->addItems(*(newNames)); - delete newNames; - - fclose(listPtr); -#endif qDebug() << "List loaded!!"; } diff --git a/Desktop_Interface/ui_elements/espocombobox.h b/Desktop_Interface/ui_elements/espocombobox.h index ff3cba27..9a4737bc 100644 --- a/Desktop_Interface/ui_elements/espocombobox.h +++ b/Desktop_Interface/ui_elements/espocombobox.h @@ -14,7 +14,7 @@ class espoComboBox : public QComboBox { Q_OBJECT public: - explicit espoComboBox(QWidget *parent = 0); + explicit espoComboBox(QWidget *parent = nullptr); void readWaveformList(void); private: signals: diff --git a/Desktop_Interface/ui_elements/esposlider.cpp b/Desktop_Interface/ui_elements/esposlider.cpp index b29a83be..2eeaa0f9 100644 --- a/Desktop_Interface/ui_elements/esposlider.cpp +++ b/Desktop_Interface/ui_elements/esposlider.cpp @@ -13,7 +13,7 @@ espoSlider::espoSlider(QWidget *parent) : QSlider(parent) labelMargin = 3; } -bool espoSlider::setTickLabel(QString label, int position) +bool espoSlider::setTickLabel(const QString& label, int position) { if (position > maxTick()){ //qDebug() << "Tried to label tick at position " << position << "but ticks range from 0 to " << maxTick(); @@ -29,12 +29,14 @@ bool espoSlider::setTickLabel(QString label, int position) } void espoSlider::resizeEvent(QResizeEvent *event){ + Q_UNUSED(event); this->debug_var++; //qDebug() << "move/resize event" << debug_var; rearrange(); } void espoSlider::moveEvent(QMoveEvent *event){ + Q_UNUSED(event); this->debug_var++; //qDebug() << "move/resize event" << debug_var; rearrange(); @@ -42,10 +44,14 @@ void espoSlider::moveEvent(QMoveEvent *event){ void espoSlider::setTickInterval(int ti){ - addressBook.resize(maxTick(ti) + 1, NULL); //Leaky, but not significantly. Old qlabels never deleted. + // Meh, can't be assed to make sure this is correct, it should only increase anyways +// for (int i=ti+2; ideleteLater(); +// } + addressBook.resize(maxTick(ti) + 1); //Leaky, but not significantly. Old qlabels never deleted. for (int i=0; igeometry().left(); + Q_UNUSED(left); + int right = this->geometry().right(); int top = this->geometry().top(); int bottom = this->geometry().bottom(); @@ -94,13 +102,13 @@ void espoSlider::selfMoved(int newval) QString newstring; newstring.setNum((double) newval/20, 'f', 2); //qDebug() << newstring; - voltageChanged(((double) newval) / 20); - lcdOut(newstring); + emit voltageChanged(((double) newval) / 20); + emit lcdOut(newstring); return; } -void espoSlider::poke(void){ +void espoSlider::poke(){ //qDebug() << "Refreshing to voltage" << ((double) (this->value())) / 20; - voltageChanged(((double) (this->value())) / 20); + emit voltageChanged(((double) (this->value())) / 20); } diff --git a/Desktop_Interface/ui_elements/esposlider.h b/Desktop_Interface/ui_elements/esposlider.h index aeed7aac..dc04b663 100644 --- a/Desktop_Interface/ui_elements/esposlider.h +++ b/Desktop_Interface/ui_elements/esposlider.h @@ -14,8 +14,8 @@ class espoSlider : public QSlider { Q_OBJECT public: - explicit espoSlider(QWidget *parent = 0); - bool setTickLabel(QString label, int position); + explicit espoSlider(QWidget *parent = nullptr); + bool setTickLabel(const QString& label, int position); void resizeEvent(QResizeEvent *event); void moveEvent(QMoveEvent *event); void setTickInterval(int ti); @@ -24,7 +24,7 @@ class espoSlider : public QSlider private: int debug_var = 0; void rearrange(); - std::vector addressBook; + QVector addressBook; QWidget* windowPointer; int labelMargin; signals: diff --git a/Desktop_Interface/ui_elements/espospinbox.cpp b/Desktop_Interface/ui_elements/espospinbox.cpp index 5e5fb949..ecc245cb 100644 --- a/Desktop_Interface/ui_elements/espospinbox.cpp +++ b/Desktop_Interface/ui_elements/espospinbox.cpp @@ -31,12 +31,12 @@ QString espoSpinBox::textFromValue(double value) const{ lastValidValue = value; return windowText; } - if (abs(value) >= 1/1000){ + if (abs(value) >= 1./1000){ QTextStream(&windowText) << value * 1000 << "m"; lastValidValue = value; return windowText; } - if (abs(value) >= 1/1000000){ + if (abs(value) >= 1./1000000){ QTextStream(&windowText) << value * 1000000 << "u"; lastValidValue = value; return windowText; @@ -64,7 +64,9 @@ void espoSpinBox::changeStepping(double value){ QValidator::State espoSpinBox::validate(QString& text, int& pos) const { - return QValidator::State::Acceptable; + Q_UNUSED(text); + Q_UNUSED(pos); + return QValidator::State::Acceptable; } double espoSpinBox::valueFromText(const QString &text) const diff --git a/Desktop_Interface/ui_elements/espospinbox.h b/Desktop_Interface/ui_elements/espospinbox.h index f3c902f3..ca82cf30 100644 --- a/Desktop_Interface/ui_elements/espospinbox.h +++ b/Desktop_Interface/ui_elements/espospinbox.h @@ -14,7 +14,7 @@ class espoSpinBox : public QDoubleSpinBox { Q_OBJECT public: - explicit espoSpinBox(QWidget *parent = 0); + explicit espoSpinBox(QWidget *parent = nullptr); QValidator::State validate(QString& text, int& pos) const override; private: QString textFromValue(double value) const override; diff --git a/Desktop_Interface/ui_elements/noclosemenu.h b/Desktop_Interface/ui_elements/noclosemenu.h index ce966a62..06a65eb3 100644 --- a/Desktop_Interface/ui_elements/noclosemenu.h +++ b/Desktop_Interface/ui_elements/noclosemenu.h @@ -11,7 +11,7 @@ class noCloseMenu : public QMenu { Q_OBJECT public: - explicit noCloseMenu(QWidget *parent = 0); + explicit noCloseMenu(QWidget *parent = nullptr); private: void mouseReleaseEvent(QMouseEvent *e); signals: diff --git a/Desktop_Interface/ui_elements/qcp1/qcustomplot.cpp b/Desktop_Interface/ui_elements/qcp1/qcustomplot.cpp index 30860827..73e64381 100644 --- a/Desktop_Interface/ui_elements/qcp1/qcustomplot.cpp +++ b/Desktop_Interface/ui_elements/qcp1/qcustomplot.cpp @@ -74,8 +74,7 @@ QCPPainter::QCPPainter(QPaintDevice *device) : } QCPPainter::~QCPPainter() -{ -} += default; /*! Sets the pen of the painter and applies certain fixes to it, depending on the mode of this @@ -919,7 +918,7 @@ void QCPLayer::removeChild(QCPLayerable *layerable) plot does. It is not uncommon to set the QObject-parent to something else in the constructors of QCPLayerable subclasses, to guarantee a working destruction hierarchy. */ -QCPLayerable::QCPLayerable(QCustomPlot *plot, QString targetLayer, QCPLayerable *parentLayerable) : +QCPLayerable::QCPLayerable(QCustomPlot *plot, const QString& targetLayer, QCPLayerable *parentLayerable) : QObject(plot), mVisible(true), mParentPlot(plot), @@ -2116,8 +2115,7 @@ int QCPLayoutElement::calculateAutoMargin(QCP::MarginSide side) is an abstract base class, it can't be instantiated directly. */ QCPLayout::QCPLayout() -{ -} += default; /*! First calls the QCPLayoutElement::update base class implementation to update the margins on this @@ -2343,7 +2341,7 @@ void QCPLayout::releaseElement(QCPLayoutElement *el) The return value is a QVector containing the section sizes. */ -QVector QCPLayout::getSectionSizes(QVector maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const +QVector QCPLayout::getSectionSizes(const QVector& maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const { if (maxSizes.size() != minSizes.size() || minSizes.size() != stretchFactors.size()) { @@ -2836,7 +2834,8 @@ QCPLayoutElement *QCPLayoutGrid::elementAt(int index) const /* inherits documentation from base class */ QCPLayoutElement *QCPLayoutGrid::takeAt(int index) { - if (QCPLayoutElement *el = elementAt(index)) + QCPLayoutElement *el = elementAt(index); + if (el && columnCount() > 0) { releaseElement(el); mElements[index / columnCount()][index % columnCount()] = 0; @@ -3077,8 +3076,7 @@ void QCPLayoutGrid::getMaximumRowColSizes(QVector *maxColWidths, QVectorparentAnchorX() == this) child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX } - foreach (QCPItemPosition *child, mChildrenY.toList()) + foreach (QCPItemPosition *child, mChildrenY.values()) { if (child->parentAnchorY() == this) child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY @@ -7622,7 +7619,7 @@ void QCPItemAnchor::removeChildY(QCPItemPosition *pos) you want to make a new item subclass. Use \ref QCPAbstractItem::createPosition instead, as explained in the subclassing section of the QCPAbstractItem documentation. */ -QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name) : +QCPItemPosition::QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString& name) : QCPItemAnchor(parentPlot, parentItem, name), mPositionTypeX(ptAbsolute), mPositionTypeY(ptAbsolute), @@ -7638,12 +7635,12 @@ QCPItemPosition::~QCPItemPosition() // unregister as parent at children: // Note: this is done in ~QCPItemAnchor again, but it's important QCPItemPosition does it itself, because only then // the setParentAnchor(0) call the correct QCPItemPosition::pixelPoint function instead of QCPItemAnchor::pixelPoint - foreach (QCPItemPosition *child, mChildrenX.toList()) + for (QCPItemPosition *child : mChildrenX.values()) { if (child->parentAnchorX() == this) child->setParentAnchorX(0); // this acts back on this anchor and child removes itself from mChildrenX } - foreach (QCPItemPosition *child, mChildrenY.toList()) + for (QCPItemPosition *child : mChildrenY.values()) { if (child->parentAnchorY() == this) child->setParentAnchorY(0); // this acts back on this anchor and child removes itself from mChildrenY @@ -9025,7 +9022,7 @@ QCustomPlot::QCustomPlot(QWidget *parent) : mAutoAddPlottableToLegend(true), mAntialiasedElements(QCP::aeNone), mNotAntialiasedElements(QCP::aeNone), - mInteractions(0), + mInteractions(QCP::iNoInteraction), mSelectionTolerance(8), mNoAntialiasingOnDrag(false), mBackgroundBrush(Qt::white, Qt::SolidPattern), @@ -10858,7 +10855,7 @@ void QCustomPlot::wheelEvent(QWheelEvent *event) emit mouseWheel(event); // call event of affected layout element: - if (QCPLayoutElement *el = layoutElementAt(event->pos())) + if (QCPLayoutElement *el = layoutElementAt(event->position())) el->wheelEvent(event); QWidget::wheelEvent(event); @@ -12583,18 +12580,18 @@ void QCPAxisRect::wheelEvent(QWheelEvent *event) if (mRangeZoom != 0) { double factor; - double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually + QPointF wheelSteps = event->angleDelta() / 120.; // a single step delta is +/-120 usually if (mRangeZoom.testFlag(Qt::Horizontal)) { - factor = qPow(mRangeZoomFactorHorz, wheelSteps); + factor = qPow(mRangeZoomFactorHorz, wheelSteps.x()); if (mRangeZoomHorzAxis.data()) - mRangeZoomHorzAxis.data()->scaleRange(factor, mRangeZoomHorzAxis.data()->pixelToCoord(event->pos().x())); + mRangeZoomHorzAxis.data()->scaleRange(factor, mRangeZoomHorzAxis.data()->pixelToCoord(event->position().x())); } if (mRangeZoom.testFlag(Qt::Vertical)) { - factor = qPow(mRangeZoomFactorVert, wheelSteps); + factor = qPow(mRangeZoomFactorVert, wheelSteps.y()); if (mRangeZoomVertAxis.data()) - mRangeZoomVertAxis.data()->scaleRange(factor, mRangeZoomVertAxis.data()->pixelToCoord(event->pos().y())); + mRangeZoomVertAxis.data()->scaleRange(factor, mRangeZoomVertAxis.data()->pixelToCoord(event->position().y())); } mParentPlot->replot(); } @@ -14015,7 +14012,7 @@ void QCPColorScale::setRangeDrag(bool enabled) if (enabled) mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType)); else - mAxisRect.data()->setRangeDrag(0); + mAxisRect.data()->setRangeDrag(QFlags()); } /*! @@ -14035,7 +14032,7 @@ void QCPColorScale::setRangeZoom(bool enabled) if (enabled) mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType)); else - mAxisRect.data()->setRangeZoom(0); + mAxisRect.data()->setRangeZoom(QFlags()); } /*! @@ -14547,7 +14544,7 @@ void QCPGraph::setData(const QVector &key, const QVector &value) { newData.key = key[i]; newData.value = value[i]; - mData->insertMulti(newData.key, newData); + mData->insert(newData.key, newData); } } @@ -14573,7 +14570,7 @@ void QCPGraph::setDataValueError(const QVector &key, const QVectorinsertMulti(key[i], newData); + mData->insert(key[i], newData); } } @@ -14600,7 +14597,7 @@ void QCPGraph::setDataValueError(const QVector &key, const QVectorinsertMulti(key[i], newData); + mData->insert(key[i], newData); } } @@ -14626,7 +14623,7 @@ void QCPGraph::setDataKeyError(const QVector &key, const QVector newData.value = value[i]; newData.keyErrorMinus = keyError[i]; newData.keyErrorPlus = keyError[i]; - mData->insertMulti(key[i], newData); + mData->insert(key[i], newData); } } @@ -14653,7 +14650,7 @@ void QCPGraph::setDataKeyError(const QVector &key, const QVector newData.value = value[i]; newData.keyErrorMinus = keyErrorMinus[i]; newData.keyErrorPlus = keyErrorPlus[i]; - mData->insertMulti(key[i], newData); + mData->insert(key[i], newData); } } @@ -14682,7 +14679,7 @@ void QCPGraph::setDataBothError(const QVector &key, const QVectorinsertMulti(key[i], newData); + mData->insert(key[i], newData); } } @@ -14713,7 +14710,7 @@ void QCPGraph::setDataBothError(const QVector &key, const QVectorinsertMulti(key[i], newData); + mData->insert(key[i], newData); } } @@ -14874,7 +14871,7 @@ void QCPGraph::addData(const QCPDataMap &dataMap) */ void QCPGraph::addData(const QCPData &data) { - mData->insertMulti(data.key, data); + mData->insert(data.key, data); } /*! \overload @@ -14890,7 +14887,7 @@ void QCPGraph::addData(double key, double value) QCPData newData; newData.key = key; newData.value = value; - mData->insertMulti(newData.key, newData); + mData->insert(newData.key, newData); } /*! \overload @@ -14909,7 +14906,7 @@ void QCPGraph::addData(const QVector &keys, const QVector &value { newData.key = keys[i]; newData.value = values[i]; - mData->insertMulti(newData.key, newData); + mData->insert(newData.key, newData); } } @@ -16873,7 +16870,7 @@ void QCPCurve::setData(const QVector &t, const QVector &key, con newData.t = t[i]; newData.key = key[i]; newData.value = value[i]; - mData->insertMulti(newData.t, newData); + mData->insert(newData.t, newData); } } @@ -16893,7 +16890,7 @@ void QCPCurve::setData(const QVector &key, const QVector &value) newData.t = i; // no t vector given, so we assign t the index of the key/value pair newData.key = key[i]; newData.value = value[i]; - mData->insertMulti(newData.t, newData); + mData->insert(newData.t, newData); } } @@ -16936,7 +16933,7 @@ void QCPCurve::addData(const QCPCurveDataMap &dataMap) */ void QCPCurve::addData(const QCPCurveData &data) { - mData->insertMulti(data.t, data); + mData->insert(data.t, data); } /*! \overload @@ -16949,7 +16946,7 @@ void QCPCurve::addData(double t, double key, double value) newData.t = t; newData.key = key; newData.value = value; - mData->insertMulti(newData.t, newData); + mData->insert(newData.t, newData); } /*! \overload @@ -16969,7 +16966,7 @@ void QCPCurve::addData(double key, double value) newData.t = 0; newData.key = key; newData.value = value; - mData->insertMulti(newData.t, newData); + mData->insert(newData.t, newData); } /*! \overload @@ -16987,7 +16984,7 @@ void QCPCurve::addData(const QVector &ts, const QVector &keys, c newData.t = ts[i]; newData.key = keys[i]; newData.value = values[i]; - mData->insertMulti(newData.t, newData); + mData->insert(newData.t, newData); } } @@ -18578,7 +18575,7 @@ void QCPBars::setData(const QVector &key, const QVector &value) { newData.key = key[i]; newData.value = value[i]; - mData->insertMulti(newData.key, newData); + mData->insert(newData.key, newData); } } @@ -18663,7 +18660,7 @@ void QCPBars::addData(const QCPBarDataMap &dataMap) */ void QCPBars::addData(const QCPBarData &data) { - mData->insertMulti(data.key, data); + mData->insert(data.key, data); } /*! \overload @@ -18675,7 +18672,7 @@ void QCPBars::addData(double key, double value) QCPBarData newData; newData.key = key; newData.value = value; - mData->insertMulti(newData.key, newData); + mData->insert(newData.key, newData); } /*! \overload @@ -18691,7 +18688,7 @@ void QCPBars::addData(const QVector &keys, const QVector &values { newData.key = keys[i]; newData.value = values[i]; - mData->insertMulti(newData.key, newData); + mData->insert(newData.key, newData); } } @@ -20702,7 +20699,7 @@ void QCPFinancial::setData(const QVector &key, const QVector &op n = qMin(n, close.size()); for (int i=0; iinsertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); + mData->insert(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); } } @@ -20818,7 +20815,7 @@ void QCPFinancial::addData(const QCPFinancialDataMap &dataMap) */ void QCPFinancial::addData(const QCPFinancialData &data) { - mData->insertMulti(data.key, data); + mData->insert(data.key, data); } /*! \overload @@ -20833,7 +20830,7 @@ void QCPFinancial::addData(const QCPFinancialData &data) */ void QCPFinancial::addData(double key, double open, double high, double low, double close) { - mData->insertMulti(key, QCPFinancialData(key, open, high, low, close)); + mData->insert(key, QCPFinancialData(key, open, high, low, close)); } /*! \overload @@ -20854,7 +20851,7 @@ void QCPFinancial::addData(const QVector &key, const QVector &op n = qMin(n, close.size()); for (int i=0; iinsertMulti(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); + mData->insert(key[i], QCPFinancialData(key[i], open[i], high[i], low[i], close[i])); } } @@ -21483,8 +21480,7 @@ QCPItemStraightLine::QCPItemStraightLine(QCustomPlot *parentPlot) : } QCPItemStraightLine::~QCPItemStraightLine() -{ -} += default; /*! Sets the pen that will be used to draw the line @@ -21673,8 +21669,7 @@ QCPItemLine::QCPItemLine(QCustomPlot *parentPlot) : } QCPItemLine::~QCPItemLine() -{ -} += default; /*! Sets the pen that will be used to draw the line @@ -21910,8 +21905,7 @@ QCPItemCurve::QCPItemCurve(QCustomPlot *parentPlot) : } QCPItemCurve::~QCPItemCurve() -{ -} += default; /*! Sets the pen that will be used to draw the line @@ -22064,8 +22058,7 @@ QCPItemRect::QCPItemRect(QCustomPlot *parentPlot) : } QCPItemRect::~QCPItemRect() -{ -} += default; /*! Sets the pen that will be used to draw the line of the rectangle @@ -22229,8 +22222,7 @@ QCPItemText::QCPItemText(QCustomPlot *parentPlot) : } QCPItemText::~QCPItemText() -{ -} += default; /*! Sets the color of the text. @@ -22563,8 +22555,7 @@ QCPItemEllipse::QCPItemEllipse(QCustomPlot *parentPlot) : } QCPItemEllipse::~QCPItemEllipse() -{ -} += default; /*! Sets the pen that will be used to draw the line of the ellipse @@ -22750,8 +22741,7 @@ QCPItemPixmap::QCPItemPixmap(QCustomPlot *parentPlot) : } QCPItemPixmap::~QCPItemPixmap() -{ -} += default; /*! Sets the pixmap that will be displayed. @@ -23009,8 +22999,7 @@ QCPItemTracer::QCPItemTracer(QCustomPlot *parentPlot) : } QCPItemTracer::~QCPItemTracer() -{ -} += default; /*! Sets the pen that will be used to draw the line of the tracer @@ -23360,8 +23349,7 @@ QCPItemBracket::QCPItemBracket(QCustomPlot *parentPlot) : } QCPItemBracket::~QCPItemBracket() -{ -} += default; /*! Sets the pen that will be used to draw the bracket. diff --git a/Desktop_Interface/ui_elements/qcp1/qcustomplot.h b/Desktop_Interface/ui_elements/qcp1/qcustomplot.h index bb998f1c..70e61b35 100644 --- a/Desktop_Interface/ui_elements/qcp1/qcustomplot.h +++ b/Desktop_Interface/ui_elements/qcp1/qcustomplot.h @@ -152,7 +152,8 @@ Q_DECLARE_FLAGS(PlottingHints, PlottingHint) \see QCustomPlot::setInteractions */ -enum Interaction { iRangeDrag = 0x001 ///< 0x001 Axis ranges are draggable (see \ref QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeDragAxes) +enum Interaction { iNoInteraction = 0, + iRangeDrag = 0x001 ///< 0x001 Axis ranges are draggable (see \ref QCPAxisRect::setRangeDrag, \ref QCPAxisRect::setRangeDragAxes) ,iRangeZoom = 0x002 ///< 0x002 Axis ranges are zoomable with the mouse wheel (see \ref QCPAxisRect::setRangeZoom, \ref QCPAxisRect::setRangeZoomAxes) ,iMultiSelect = 0x004 ///< 0x004 The user can select multiple objects by holding the modifier set by \ref QCustomPlot::setMultiSelectModifier while clicking ,iSelectPlottables = 0x008 ///< 0x008 Plottables are selectable (e.g. graphs, curves, bars,... see QCPAbstractPlottable) @@ -416,7 +417,7 @@ class QCP_LIB_DECL QCPLayerable : public QObject Q_PROPERTY(bool antialiased READ antialiased WRITE setAntialiased) /// \endcond public: - QCPLayerable(QCustomPlot *plot, QString targetLayer=QString(), QCPLayerable *parentLayerable=0); + QCPLayerable(QCustomPlot *plot, const QString& targetLayer=QString(), QCPLayerable *parentLayerable=0); ~QCPLayerable(); // getters: @@ -746,7 +747,7 @@ class QCP_LIB_DECL QCPLayout : public QCPLayoutElement void sizeConstraintsChanged() const; void adoptElement(QCPLayoutElement *el); void releaseElement(QCPLayoutElement *el); - QVector getSectionSizes(QVector maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const; + QVector getSectionSizes(const QVector& maxSizes, QVector minSizes, QVector stretchFactors, int totalSize) const; private: Q_DISABLE_COPY(QCPLayout) @@ -1503,7 +1504,7 @@ class QCP_LIB_DECL QCPAbstractPlottable : public QCPLayerable class QCP_LIB_DECL QCPItemAnchor { public: - QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name, int anchorId=-1); + QCPItemAnchor(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString& name, int anchorId=-1); virtual ~QCPItemAnchor(); // getters: @@ -1556,7 +1557,7 @@ class QCP_LIB_DECL QCPItemPosition : public QCPItemAnchor ,ptPlotCoords ///< Dynamic positioning at a plot coordinate defined by two axes (see \ref setAxes). }; - QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString name); + QCPItemPosition(QCustomPlot *parentPlot, QCPAbstractItem *parentItem, const QString& name); virtual ~QCPItemPosition(); // getters: @@ -2482,7 +2483,7 @@ Q_DECLARE_TYPEINFO(QCPData, Q_MOVABLE_TYPE); This is the container in which QCPGraph holds its data. \see QCPData, QCPGraph::setData */ -typedef QMap QCPDataMap; +typedef QMultiMap QCPDataMap; typedef QMapIterator QCPDataMapIterator; typedef QMutableMapIterator QCPDataMutableMapIterator; @@ -2579,7 +2580,7 @@ class QCP_LIB_DECL QCPGraph : public QCPAbstractPlottable protected: // property members: - QCPDataMap *mData; + QMultiMap *mData; QPen mErrorPen; LineStyle mLineStyle; QCPScatterStyle mScatterStyle; @@ -2652,7 +2653,7 @@ Q_DECLARE_TYPEINFO(QCPCurveData, Q_MOVABLE_TYPE); \see QCPCurveData, QCPCurve::setData */ -typedef QMap QCPCurveDataMap; +typedef QMultiMap QCPCurveDataMap; typedef QMapIterator QCPCurveDataMapIterator; typedef QMutableMapIterator QCPCurveDataMutableMapIterator; @@ -2815,7 +2816,7 @@ Q_DECLARE_TYPEINFO(QCPBarData, Q_MOVABLE_TYPE); This is the container in which QCPBars holds its data. \see QCPBarData, QCPBars::setData */ -typedef QMap QCPBarDataMap; +typedef QMultiMap QCPBarDataMap; typedef QMapIterator QCPBarDataMapIterator; typedef QMutableMapIterator QCPBarDataMutableMapIterator; @@ -3137,7 +3138,7 @@ Q_DECLARE_TYPEINFO(QCPFinancialData, Q_MOVABLE_TYPE); This is the container in which QCPFinancial holds its data. \see QCPFinancial, QCPFinancial::setData */ -typedef QMap QCPFinancialDataMap; +typedef QMultiMap QCPFinancialDataMap; typedef QMapIterator QCPFinancialDataMapIterator; typedef QMutableMapIterator QCPFinancialDataMutableMapIterator; diff --git a/Desktop_Interface/ui_elements/swipeystack.h b/Desktop_Interface/ui_elements/swipeystack.h index 7090ccc6..ad8a3414 100644 --- a/Desktop_Interface/ui_elements/swipeystack.h +++ b/Desktop_Interface/ui_elements/swipeystack.h @@ -14,7 +14,7 @@ class swipeyStack : public QStackedWidget { Q_OBJECT public: - explicit swipeyStack(QWidget *parent = 0); + explicit swipeyStack(QWidget *parent = nullptr); private: int initial_x; int initial_y; diff --git a/Desktop_Interface/ui_elements/timedtickbox.cpp b/Desktop_Interface/ui_elements/timedtickbox.cpp index 76ad242f..5ec972bf 100644 --- a/Desktop_Interface/ui_elements/timedtickbox.cpp +++ b/Desktop_Interface/ui_elements/timedtickbox.cpp @@ -2,10 +2,10 @@ timedTickBox::timedTickBox(QWidget *parent) : QCheckBox(parent) { - timer = new QTimer(); + timer = new QTimer(this); timer->setTimerType(Qt::PreciseTimer); timer->start(timerLength); - connect(timer, SIGNAL(timeout()), this, SLOT(timerTick())); + connect(timer, &QTimer::timeout, this, &timedTickBox::timerTick); } diff --git a/Desktop_Interface/ui_elements/timedtickbox.h b/Desktop_Interface/ui_elements/timedtickbox.h index 9242e744..a28707c3 100644 --- a/Desktop_Interface/ui_elements/timedtickbox.h +++ b/Desktop_Interface/ui_elements/timedtickbox.h @@ -12,10 +12,10 @@ class timedTickBox : public QCheckBox { Q_OBJECT public: - explicit timedTickBox(QWidget *parent = 0); + explicit timedTickBox(QWidget *parent = nullptr); bool timerEnabled = true; int timerLength = 7500; - QTimer *timer = NULL; + QTimer *timer = nullptr; signals: diff --git a/Desktop_Interface/ui_elements/voltagespinbox.h b/Desktop_Interface/ui_elements/voltagespinbox.h index 36d37887..8917c337 100644 --- a/Desktop_Interface/ui_elements/voltagespinbox.h +++ b/Desktop_Interface/ui_elements/voltagespinbox.h @@ -11,7 +11,7 @@ class voltageSpinBox : public QDoubleSpinBox { Q_OBJECT public: - explicit voltageSpinBox(QWidget *parent = 0); + explicit voltageSpinBox(QWidget *parent = nullptr); bool min = false; signals: diff --git a/Desktop_Interface/ui_files_desktop/mainwindow.ui b/Desktop_Interface/ui_files_desktop/mainwindow.ui index b0837793..27744199 100644 --- a/Desktop_Interface/ui_files_desktop/mainwindow.ui +++ b/Desktop_Interface/ui_files_desktop/mainwindow.ui @@ -81,37 +81,6 @@ - - - - -60 - - - 10 - - - 10 - - - -20 - - - -20 - - - true - - - Qt::Horizontal - - - QSlider::TicksBelow - - - 10 - - - @@ -199,7 +168,7 @@ - Paused + &Paused @@ -1512,7 +1481,7 @@ - File + &File @@ -1537,7 +1506,7 @@ - Oscilloscope + &Oscilloscope @@ -1553,6 +1522,15 @@ + + + &Downsampling method + + + + + + &CH1 Stats @@ -1595,6 +1573,8 @@ + + @@ -1774,7 +1754,7 @@ - Help + &Help @@ -1881,6 +1861,38 @@ QAction::TextHeuristicRole + + + true + + + &Decimate + + + + + true + + + &Peak + + + + + true + + + &Bottom + + + + + true + + + &Maximum delta + + Ca&librate @@ -2664,7 +2676,6 @@ setDSR(bool) scopeIn_CH1(bool) scopeIn_CH2(bool) - signalGenIn(bool) busSnifferIn_CH1(bool) busSnifferIn_CH2(bool) multimeterIn(bool) @@ -2748,12 +2759,11 @@ multimeterREnabled(int) multimeterRMS(double) sendMultimeterLabel4(QString) - setWindow(int) - setVoltageRange(QWheelEvent*) + onWheelEvent(QWheelEvent*) pauseEnable_CH1(bool) pauseEnable_CH2(bool) startTimer() - clearBuffers(bool,bool,bool) + clearChannelBuffers(bool,bool,bool) setVisible_CH2(bool) gainBuffers(double) setAutoGain(bool) @@ -2848,22 +2858,6 @@ - - signalGenGroup_CH2 - toggled(bool) - bufferDisplay - signalGenIn(bool) - - - 1250 - 853 - - - 1356 - 891 - - - bufferDisplay busSnifferOut_CH2(bool) @@ -3328,27 +3322,11 @@ - - timeBaseSlider - valueChanged(int) - controller_iso - setWindow(int) - - - 441 - 559 - - - 1251 - 892 - - - scopeAxes mouseWheel(QWheelEvent*) controller_iso - setVoltageRange(QWheelEvent*) + onWheelEvent(QWheelEvent*) 499 @@ -3776,22 +3754,6 @@ - - controller_iso - changeTimeAxis(bool) - MainWindow - timeBaseNeedsChanging(bool) - - - 1251 - 892 - - - 800 - 696 - - - xyDisplayLabel toggled(bool) @@ -4052,7 +4014,7 @@ lockPsuCheckBox toggled(bool) lockPsuCheckBox - resetTimer(bool) + resetTimer() 1424 @@ -4466,7 +4428,6 @@ - timeBaseNeedsChanging(bool) reinitUsb() rSourceIndexChanged(int) multimeterStateChange(bool) diff --git a/Desktop_Interface/ui_files_mobile/mainwindow.ui b/Desktop_Interface/ui_files_mobile/mainwindow.ui index 3a6dc41d..9e35287d 100644 --- a/Desktop_Interface/ui_files_mobile/mainwindow.ui +++ b/Desktop_Interface/ui_files_mobile/mainwindow.ui @@ -2776,11 +2776,11 @@ multimeterRMS(double) sendMultimeterLabel4(QString) setWindow(int) - setVoltageRange(QWheelEvent*) + onWheelEvent(QWheelEvent*) pauseEnable_CH1(bool) pauseEnable_CH2(bool) startTimer() - clearBuffers(bool,bool,bool) + clearChannelBuffers(bool,bool,bool) setVisible_CH2(bool) gainBuffers(double) setAutoGain(bool) @@ -3381,7 +3381,7 @@ scopeAxes mouseWheel(QWheelEvent*) controller_iso - setVoltageRange(QWheelEvent*) + onWheelEvent(QWheelEvent*) 482 diff --git a/Desktop_Interface/unixusbdriver.cpp b/Desktop_Interface/unixusbdriver.cpp index 50afe2ee..3bd1f607 100644 --- a/Desktop_Interface/unixusbdriver.cpp +++ b/Desktop_Interface/unixusbdriver.cpp @@ -16,19 +16,18 @@ unixUsbDriver::unixUsbDriver(QWidget *parent) : genericUsbDriver(parent) } } -unixUsbDriver::~unixUsbDriver(void){ +unixUsbDriver::~unixUsbDriver(){ qDebug() << "\n\nunixUsbDriver destructor ran!"; //unixDriverDeleteMutex.lock(); + shutdownMode = true; if(connected){ if (workerThread) { - workerThread->deleteLater(); - while(workerThread->isRunning()){ - workerThread->quit(); - qDebug() << "isRunning?" << workerThread->isFinished(); - QThread::msleep(100); - } - } + workerThread->requestInterruption(); + workerThread->quit(); + workerThread->wait(); + workerThread->deleteLater(); + } if (isoHandler) delete(isoHandler); //delete(workerThread); @@ -43,18 +42,22 @@ unixUsbDriver::~unixUsbDriver(void){ qDebug() << "Transfers freed."; } - if(handle != NULL){ + if(handle != nullptr){ libusb_release_interface(handle, 0); qDebug() << "Interface released"; libusb_close(handle); qDebug() << "Device Closed"; } - if(ctx != NULL){ + if(ctx != nullptr){ libusb_exit(ctx); qDebug() << "Libusb exited"; } //unixDriverDeleteMutex.unlock(); qDebug() << "unixUsbDriver destructor completed!\n\n"; + for (unsigned char k=0; k= 0x01000108) + libusb_set_option(ctx, LIBUSB_OPTION_LOG_LEVEL, LIBUSB_LOG_LEVEL_INFO); +#else libusb_set_debug(ctx, 3); +#endif } - if(handle == NULL){ + if(handle == nullptr){ handle = libusb_open_device_with_vid_pid(ctx, VIDin, PIDin); - if(handle==NULL){ + if(handle==nullptr){ qDebug() << "DEVICE NOT FOUND"; return 1; } @@ -89,7 +96,7 @@ unsigned char unixUsbDriver::usbInit(unsigned long VIDin, unsigned long PIDin){ if(error){ qDebug() << "libusb_claim_interface FAILED"; qDebug() << "ERROR" << error << libusb_error_name(error); - handle = NULL; + handle = nullptr; return 1; } else qDebug() << "Interface claimed!"; @@ -105,7 +112,7 @@ void unixUsbDriver::usbSendControl(uint8_t RequestType, uint8_t Request, uint16_ return; } - if (LDATA==NULL){ + if (LDATA==nullptr){ controlBuffer = inBuffer; } else controlBuffer = LDATA; @@ -117,13 +124,12 @@ void unixUsbDriver::usbSendControl(uint8_t RequestType, uint8_t Request, uint16_ } //else qDebug() << "unixUsbDriver::usbSendControl SUCCESS"; if((error == LIBUSB_ERROR_NO_DEVICE) && (Request!=0xa7)){ //Bootloader Jump won't return; this is expected behaviour. qDebug() << "Device not found. Becoming an hero."; - connectedStatus(false); - killMe(); + emit connectedStatus(false); + emit killMe(); } - return; } -int unixUsbDriver::usbIsoInit(void){ +int unixUsbDriver::usbIsoInit(){ int error; for(int n=0;nsetTimerType(Qt::PreciseTimer); isoTimer->start(ISO_TIMER_PERIOD); - connect(isoTimer, SIGNAL(timeout()), this, SLOT(isoTimerTick())); + connect(isoTimer.data(), &QTimer::timeout, this, &unixUsbDriver::isoTimerTick); qDebug() << "Setup successful!"; isoHandler = new worker(); - workerThread = new QThread(); + workerThread = new QThread(this); isoHandler->ctx = ctx; isoHandler->moveToThread(workerThread); - connect(workerThread, SIGNAL(started()), isoHandler, SLOT(handle())); + connect(workerThread, &QThread::started, isoHandler, &worker::handle); workerThread->start(); @@ -182,21 +188,14 @@ int unixUsbDriver::usbIsoInit(void){ return 0; } -void unixUsbDriver::isoTimerTick(void){ +void unixUsbDriver::isoTimerTick(){ timerCount++; - char subString[3] = "th"; - if(timerCount%10 == 1) strcpy(subString, "st"); - if(timerCount%10 == 2) strcpy(subString, "nd"); - if(timerCount%10 == 3) strcpy(subString, "rd"); - if((timerCount<20) && (timerCount > 10)) strcpy(subString, "th"); - - //qDebug("\n\nThis is the %d%s Tick!", timerCount, subString); - int n, error, earliest = MAX_OVERLAP; qint64 minFrame = 9223372036854775807; //max value for 64 bit signed - unsigned int i, packetLength = 0; + int i; + unsigned packetLength = 0; unsigned char* packetPointer; tcBlockMutex.lock(); @@ -247,7 +246,7 @@ void unixUsbDriver::isoTimerTick(void){ }else{ srcPtr = &midBuffer_prev[k][ISO_PACKET_SIZE * (ISO_PACKETS_PER_CTX + current_offset)]; } - memcpy(&(outBuffers[currentWriteBuffer][packetLength]), srcPtr, ISO_PACKET_SIZE); + memcpy(&outBuffers[currentWriteBuffer].get()[packetLength], srcPtr, ISO_PACKET_SIZE); packetLength += ISO_PACKET_SIZE; } } @@ -280,19 +279,18 @@ void unixUsbDriver::isoTimerTick(void){ tcBlockMutex.unlock(); //qDebug() << "Calling upTick()"; - upTick(); - return; + emit upTick(); } -char *unixUsbDriver::isoRead(unsigned int *newLength){ +std::shared_ptr unixUsbDriver::isoRead(unsigned int *newLength){ //*(newLength) = 0; //return (char*) NULL; //qDebug() << "unixUsbDriver::isoRead"; *(newLength) = bufferLengths[!currentWriteBuffer]; - return (char*) outBuffers[(unsigned char) !currentWriteBuffer]; + return outBuffers[uint8_t(!currentWriteBuffer)]; } -void unixUsbDriver::recoveryTick(void){ +void unixUsbDriver::recoveryTick(){ //This should not be called in shutdown mode since it cause double deletion! if(!shutdownMode){ avrDebug(); @@ -311,7 +309,7 @@ bool unixUsbDriver::allEndpointsComplete(int n){ void unixUsbDriver::shutdownProcedure(){ shutdownMode = true; - QTimer::singleShot(100, this, SLOT(backupCleanup())); + QTimer::singleShot(100, this, &unixUsbDriver::backupCleanup); } //On physical disconnect, isoTimerTick will not assert stopTime. Hence this duct-tape function. @@ -320,14 +318,14 @@ void unixUsbDriver::backupCleanup(){ isoHandler->stopTime = true; } -int unixUsbDriver::flashFirmware(void){ +int unixUsbDriver::flashFirmware(){ #ifndef PLATFORM_ANDROID char fname[128]; qDebug() << "\n\n\n\n\n\n\n\nFIRMWARE MISMATCH!!!! FLASHING....\n\n\n\n\n\n\n"; sprintf(fname, "/firmware/labrafirm_%04x_%02x.hex", EXPECTED_FIRMWARE_VERSION, DEFINED_EXPECTED_VARIANT); qDebug() << "FLASHING " << fname; - signalFirmwareFlash(); + emit signalFirmwareFlash(); QApplication::processEvents(); //Go to bootloader mode @@ -387,37 +385,28 @@ int unixUsbDriver::flashFirmware(void){ libusb_exit(ctx); qDebug() << "Libusb exited"; connected = false; - handle = NULL; - ctx = NULL; + handle = nullptr; + ctx = nullptr; return 0; #endif } -void unixUsbDriver::manualFirmwareRecovery(void){ +// TODO: port to QWizard, less annoying than an endless list of popup dialogs +void unixUsbDriver::manualFirmwareRecovery(){ #ifndef PLATFORM_ANDROID //Get location of firmware file - char fname[128]; - sprintf(fname, "/firmware/labrafirm_%04x_%02x.hex", EXPECTED_FIRMWARE_VERSION, DEFINED_EXPECTED_VARIANT); - - QString dirString = QCoreApplication::applicationDirPath(); - dirString.append(fname); - QByteArray array = dirString.toLocal8Bit(); - char* buffer = array.data(); + const QString fname = QString::asprintf("/firmware/labrafirm_%04x_%02x.hex", EXPECTED_FIRMWARE_VERSION, DEFINED_EXPECTED_VARIANT); + const QString dirString = QCoreApplication::applicationDirPath() + fname; //Vars QMessageBox manualFirmwareMessages; - int messageBoxReturn; - - char leaveBootloaderCommand[256]; - sprintf(leaveBootloaderCommand, "dfu-programmer atxmega32a4u launch"); + QByteArray leaveBootloaderCommand = "dfu-programmer atxmega32a4u launch"; int exit_code; - char eraseCommand[256]; - sprintf(eraseCommand, "dfu-programmer atxmega32a4u erase --force"); - char flashCommand[256]; - sprintf(flashCommand, "dfu-programmer atxmega32a4u flash %s", buffer); + QByteArray eraseCommand = "dfu-programmer atxmega32a4u erase --force"; + QByteArray flashCommand = "dfu-programmer atxmega32a4u flash " + dirString.toLocal8Bit(); @@ -432,14 +421,13 @@ void unixUsbDriver::manualFirmwareRecovery(void){ manualFirmwareMessages.exec(); manualFirmwareMessages.setStandardButtons(QMessageBox::Yes|QMessageBox::No); manualFirmwareMessages.setText("Did that fix things?"); - messageBoxReturn = manualFirmwareMessages.exec(); - manualFirmwareMessages.setStandardButtons(QMessageBox::Ok); - if(messageBoxReturn == 16384){ //"Yes" is 16384, no is 65536 - manualFirmwareMessages.setText("Awesome! Have fun!"); - messageBoxReturn = manualFirmwareMessages.exec(); + if(manualFirmwareMessages.exec() == QMessageBox::Yes){ + QMessageBox::information(this, tr("Success"), tr("Awesome! Have fun!")); return; } + manualFirmwareMessages.setStandardButtons(QMessageBox::Ok); + //Real troubleshooting begins here..... //USB Problems. @@ -457,34 +445,36 @@ void unixUsbDriver::manualFirmwareRecovery(void){ manualFirmwareMessages.setText("If that doesn't fix it, please open an issue on github.com/espotek/labrador, or contact me at admin@espotek.com."); manualFirmwareMessages.exec(); return; - } else { - exit_code = dfuprog_virtual_cmd(leaveBootloaderCommand); - manualFirmwareMessages.setText("No Labrador board could be detected.\n\nIt's possible that you're stuck in booloader mode.\n\nI've attempted to launch the firmware manually."); + } + exit_code = dfuprog_virtual_cmd(leaveBootloaderCommand.data()); + manualFirmwareMessages.setText("No Labrador board could be detected.\n\nIt's possible that you're stuck in booloader mode.\n\nI've attempted to launch the firmware manually."); + manualFirmwareMessages.exec(); + if(exit_code){ + manualFirmwareMessages.setText("Command failed. This usually means that no device is detected.\n\nPlease Ensure that the cable you're using can carry data (for example, by using it to transfer data to your phone).\n\nSome cables are for charging only, and not physically contain data lines.\n\nAlso note that the red light on the Labrador board is a power indicator for the PSU output pins.\nIt will turn on even if no data lines are present."); manualFirmwareMessages.exec(); - if(exit_code){ - manualFirmwareMessages.setText("Command failed. This usually means that no device is detected.\n\nPlease Ensure that the cable you're using can carry data (for example, by using it to transfer data to your phone).\n\nSome cables are for charging only, and not physically contain data lines.\n\nAlso note that the red light on the Labrador board is a power indicator for the PSU output pins.\nIt will turn on even if no data lines are present."); - manualFirmwareMessages.exec(); - return; - } - //Firmware launch failed, but bootloader preset - if(!connected){ - exit_code = dfuprog_virtual_cmd(eraseCommand); - exit_code += dfuprog_virtual_cmd(flashCommand); - manualFirmwareMessages.setText("The bootloader is present, but firmware launch failed. I've attempted to reprogram it."); - manualFirmwareMessages.exec(); + return; + } - if(!exit_code){ //Reprogramming was successful, but board is still in bootloader mode. - exit_code = dfuprog_virtual_cmd(leaveBootloaderCommand); - manualFirmwareMessages.setText("Reprogramming was successful! Attempting to launch the board.\n\nIf it does not start working immediately, please wait 10 seconds and then reconnect the board."); - manualFirmwareMessages.exec(); - } else { //Programming failed. - manualFirmwareMessages.setText("Automatic Reprogramming failed.\n\nPlease contact me at admin@espotek.com for further support."); - manualFirmwareMessages.exec(); - } + //Firmware launch failed, but bootloader preset + if(!connected){ + exit_code = dfuprog_virtual_cmd(eraseCommand.data()); + exit_code += dfuprog_virtual_cmd(flashCommand.data()); + manualFirmwareMessages.setText("The bootloader is present, but firmware launch failed. I've attempted to reprogram it."); + manualFirmwareMessages.exec(); - return; + if(!exit_code){ //Reprogramming was successful, but board is still in bootloader mode. + exit_code = dfuprog_virtual_cmd(leaveBootloaderCommand.data()); + Q_UNUSED(exit_code); + manualFirmwareMessages.setText("Reprogramming was successful! Attempting to launch the board.\n\nIf it does not start working immediately, please wait 10 seconds and then reconnect the board."); + manualFirmwareMessages.exec(); + } else { //Programming failed. + manualFirmwareMessages.setText("Automatic Reprogramming failed.\n\nPlease contact me at admin@espotek.com for further support."); + manualFirmwareMessages.exec(); } + + return; } + // ??? #endif } diff --git a/Desktop_Interface/unixusbdriver.h b/Desktop_Interface/unixusbdriver.h index 16306db7..77e6f0ac 100644 --- a/Desktop_Interface/unixusbdriver.h +++ b/Desktop_Interface/unixusbdriver.h @@ -7,7 +7,7 @@ #include #include "genericusbdriver.h" -#include "libusb.h" +#include extern "C" { #include "libdfuprog.h" @@ -29,11 +29,11 @@ class worker : public QObject Q_OBJECT public: - worker(){}; - ~worker(){}; - libusb_context *ctx; + worker() = default; + ~worker() override {} + libusb_context *ctx = nullptr; bool stopTime = false; - unsigned char cleanupRemaining = 4; + unsigned char cleanupRemaining = NUM_FUTURE_CTX ; public slots: void handle(){ qDebug() << "SUB THREAD ID" << QThread::currentThreadId(); @@ -43,7 +43,7 @@ public slots: libusb_handle_events_timeout(ctx, &tv); //qDebug() << "HANDLED"; } - if(stopTime){ + if(stopTime || QThread::currentThread()->isInterruptionRequested()){ if(cleanupRemaining){ cleanupRemaining--; qDebug("Cleaning... #%hhu phases remain.\n", cleanupRemaining); @@ -61,15 +61,15 @@ class unixUsbDriver : public genericUsbDriver { Q_OBJECT public: - explicit unixUsbDriver(QWidget *parent = 0); - ~unixUsbDriver(); - void usbSendControl(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length, unsigned char *LDATA); - char *isoRead(unsigned int *newLength); - void manualFirmwareRecovery(void); + explicit unixUsbDriver(QWidget *parent); + ~unixUsbDriver() override; + void usbSendControl(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length, unsigned char *LDATA) override; + std::shared_ptr isoRead(unsigned int *newLength) override; + void manualFirmwareRecovery(void) override; protected: //USB Vars - libusb_context *ctx = NULL; - libusb_device_handle *handle = NULL; + libusb_context *ctx = nullptr; + libusb_device_handle *handle = nullptr; //USBIso Vars unsigned char *midBuffer_current[NUM_ISO_ENDPOINTS]; unsigned char *midBuffer_prev[NUM_ISO_ENDPOINTS]; @@ -78,25 +78,25 @@ class unixUsbDriver : public genericUsbDriver tcBlock transferCompleted[NUM_ISO_ENDPOINTS][NUM_FUTURE_CTX]; unsigned char dataBuffer[NUM_ISO_ENDPOINTS][NUM_FUTURE_CTX][ISO_PACKET_SIZE*ISO_PACKETS_PER_CTX]; worker *isoHandler = nullptr; - QThread *workerThread = nullptr; + QPointer workerThread; int cumulativeFramePhaseErrors = 0; //Generic Functions - virtual unsigned char usbInit(unsigned long VIDin, unsigned long PIDin); - int usbIsoInit(void); - virtual int flashFirmware(void); + virtual unsigned char usbInit(unsigned long VIDin, unsigned long PIDin) override; + int usbIsoInit(void) override; + virtual int flashFirmware(void) override; bool allEndpointsComplete(int n); bool shutdownMode = false; int numCancelled = 0; signals: public slots: - void isoTimerTick(void); - void recoveryTick(void); - void shutdownProcedure(void); + void isoTimerTick(void) override; + void recoveryTick(void) override; + void shutdownProcedure(void) override; void backupCleanup(void); }; //Callback on iso transfer complete. -static void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){ +inline void LIBUSB_CALL isoCallback(struct libusb_transfer * transfer){ tcBlockMutex.lock(); //int number = ((tcBlock *)transfer->user_data)->number; //bool completed = ((tcBlock *)transfer->user_data)->completed; diff --git a/Desktop_Interface/winusbdriver.cpp b/Desktop_Interface/winusbdriver.cpp index 13368b5e..c8983339 100644 --- a/Desktop_Interface/winusbdriver.cpp +++ b/Desktop_Interface/winusbdriver.cpp @@ -25,8 +25,6 @@ winUsbDriver::~winUsbDriver(void){ UsbK_AbortPipe(handle, pipeID[k]); } OvlK_Free(ovlPool); - free(outBuffers[0]); - free(outBuffers[1]); UsbK_Free(handle); } @@ -199,7 +197,7 @@ int winUsbDriver::usbIsoInit(void){ isoTimer = new QTimer(); isoTimer->setTimerType(Qt::PreciseTimer); isoTimer->start(ISO_TIMER_PERIOD); - connect(isoTimer, SIGNAL(timeout()), this, SLOT(isoTimerTick())); + connect(isoTimer.data(), &QTimer::timeout, this, &winUsbDriver::isoTimerTick); qDebug() << "Setup successful!"; return 0; @@ -247,7 +245,7 @@ void winUsbDriver::isoTimerTick(void){ for(int i=0;iNumberOfPackets;i++){ for(unsigned char k=0; kIsoPackets[i].Offset; - memcpy(&(outBuffers[currentWriteBuffer][packetLength]), &dataBuffer[k][earliest][dataBufferOffset], isoCtx[k][earliest]->IsoPackets[i].Length); + memcpy(&(outBuffers[currentWriteBuffer].get()[packetLength]), &dataBuffer[k][earliest][dataBufferOffset], isoCtx[k][earliest]->IsoPackets[i].Length); packetLength += isoCtx[k][earliest]->IsoPackets[i].Length; } } @@ -300,10 +298,10 @@ void winUsbDriver::isoTimerTick(void){ return; } -char *winUsbDriver::isoRead(unsigned int *newLength){ +std::shared_ptr winUsbDriver::isoRead(unsigned int *newLength){ //This will be called almost immediately after the upTick() signal is sent. Make sure bufferLengths[] abd outBuffers[] are ready! *(newLength) = bufferLengths[!currentWriteBuffer]; - return (char*) outBuffers[(unsigned char) !currentWriteBuffer]; + return outBuffers[(unsigned char) !currentWriteBuffer]; } bool winUsbDriver::allEndpointsComplete(int n){ diff --git a/Desktop_Interface/winusbdriver.h b/Desktop_Interface/winusbdriver.h index 259f2f68..c57a1eac 100644 --- a/Desktop_Interface/winusbdriver.h +++ b/Desktop_Interface/winusbdriver.h @@ -20,7 +20,7 @@ class winUsbDriver : public genericUsbDriver explicit winUsbDriver(QWidget *parent = 0); ~winUsbDriver(); void usbSendControl(uint8_t RequestType, uint8_t Request, uint16_t Value, uint16_t Index, uint16_t Length, unsigned char *LDATA); - char *isoRead(unsigned int *newLength); + std::shared_ptr isoRead(unsigned int *newLength); void manualFirmwareRecovery(void); private: //USB Vars diff --git a/Desktop_Interface/xmega.h b/Desktop_Interface/xmega.h index 3fe8ae51..9990cade 100644 --- a/Desktop_Interface/xmega.h +++ b/Desktop_Interface/xmega.h @@ -17,8 +17,6 @@ #define R2 (double)1000 #define R1 (double)1000 -#define INIT_DEVICE_MODE 0 - #define PSU_STEP 5 #define PSU_PERIOD 100 #define PSU_ADC_TOP 128 @@ -26,4 +24,19 @@ #define INVERT_TRIPLE #define INVERT_MM +enum DeviceMode { + DeviceCH1Analog = 0, + DeviceCH1AnalogCH2Digital = 1, + DeviceCH1AnalogCH2Analog = 2, + + DeviceCH1Digital = 3, + DeviceCH1DigitalCH2Digital = 4, + + DeviceCH1Analog750 = 6, + + DeviceMultimeter = 7 +}; + +#define INIT_DEVICE_MODE DeviceCH1Analog + #endif // XMEGA_H