diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,6 +61,11 @@ qt5_wrap_ui(UI_FILES
src/commandwidget.ui
src/dataformatpanel.ui
src/plotcontrolpanel.ui
+ src/numberformatbox.ui
+ src/endiannessbox.ui
+ src/binarystreamreadersettings.ui
+ src/asciireadersettings.ui
+ src/framedreadersettings.ui
)
if (WIN32)
@@ -93,6 +98,16 @@ add_executable(${PROGRAM_NAME} WIN32
src/sneakylineedit.cpp
src/channelmanager.cpp
src/framebufferseries.cpp
+ src/numberformatbox.cpp
+ src/endiannessbox.cpp
+ src/abstractreader.cpp
+ src/binarystreamreader.cpp
+ src/binarystreamreadersettings.cpp
+ src/asciireader.cpp
+ src/asciireadersettings.cpp
+ src/demoreader.cpp
+ src/framedreader.cpp
+ src/framedreadersettings.cpp
misc/windows_icon.rc
${UI_FILES}
${RES_FILES}
diff --git a/misc/pseudo_device.py b/misc/pseudo_device.py
--- a/misc/pseudo_device.py
+++ b/misc/pseudo_device.py
@@ -71,6 +71,34 @@ def uint32_test(port, little):
time.sleep(0.05)
i = i+1 if i <= maxi else 0
+def frame_test(port, fixed_size=False, hasChecksum=True):
+ """Sends binary data in framed format."""
+ SYNCWORD = [0xAA, 0xBB]
+ NUMSAMPLES = 10
+ SIZE = NUMSAMPLES * 4 # integer
+ if fixed_size:
+ HEADER = bytes(SYNCWORD)
+ else:
+ HEADER = bytes(SYNCWORD + [SIZE])
+ i = 0
+ checksum = 0
+ bytesent = 0
+ while True:
+ if i > 100: i = 0
+ if bytesent == 0: # beginning of a frame?
+ os.write(port, HEADER)
+ os.write(port, struct.pack('.
+*/
+
+#include "abstractreader.h"
+
+AbstractReader::AbstractReader(QIODevice* device, ChannelManager* channelMan, QObject *parent) :
+ QObject(parent)
+{
+ _device = device;
+ _channelMan = channelMan;
+
+ // initialize sps counter
+ sampleCount = 0;
+ samplesPerSecond = 0;
+ QObject::connect(&spsTimer, &QTimer::timeout,
+ this, &AbstractReader::spsTimerTimeout);
+ // TODO: start sps timer when reader is enabled
+ spsTimer.start(SPS_UPDATE_TIMEOUT * 1000);
+}
+
+void AbstractReader::spsTimerTimeout()
+{
+ unsigned currentSps = samplesPerSecond;
+ samplesPerSecond = (sampleCount/numOfChannels())/SPS_UPDATE_TIMEOUT;
+ if (currentSps != samplesPerSecond)
+ {
+ emit samplesPerSecondChanged(samplesPerSecond);
+ }
+ sampleCount = 0;
+}
diff --git a/src/abstractreader.h b/src/abstractreader.h
new file mode 100644
--- /dev/null
+++ b/src/abstractreader.h
@@ -0,0 +1,89 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef ABSTRACTREADER_H
+#define ABSTRACTREADER_H
+
+#include
+#include
+#include
+#include
+
+#include "channelmanager.h"
+
+/**
+ * All reader classes must inherit this class.
+ */
+class AbstractReader : public QObject
+{
+ Q_OBJECT
+public:
+ explicit AbstractReader(QIODevice* device, ChannelManager* channelMan, QObject *parent = 0);
+
+ /**
+ * Returns a widget to be shown in data format panel when reader
+ * is selected.
+ */
+ virtual QWidget* settingsWidget() = 0;
+
+ /**
+ * Number of channels being read.
+ *
+ * This number may be user selected or automatically determined
+ * from incoming stream.
+ */
+ virtual unsigned numOfChannels() = 0;
+
+ /// Reader should only read when enabled. Default state should be
+ /// 'disabled'.
+ virtual void enable(bool enabled = true) = 0;
+
+signals:
+ void numOfChannelsChanged(unsigned);
+ // TODO: this must be signaled by 'channel man' for better abstraction
+ void dataAdded(); ///< emitted when data added to channel man.
+ // TODO: this should be a part of 'channel man'
+ void samplesPerSecondChanged(unsigned);
+
+public slots:
+ /**
+ * Pauses the reading.
+ *
+ * Reader should actually continue reading to keep the
+ * synchronization but shouldn't commit data.
+ */
+ virtual void pause(bool) = 0;
+
+protected:
+ QIODevice* _device;
+ ChannelManager* _channelMan;
+
+ /// Implementing class should simply increase this count as samples are read
+ unsigned sampleCount;
+
+private:
+ const int SPS_UPDATE_TIMEOUT = 1; // second
+ unsigned samplesPerSecond;
+ QTimer spsTimer;
+
+private slots:
+ void spsTimerTimeout();
+};
+
+#endif // ABSTRACTREADER_H
diff --git a/src/asciireader.cpp b/src/asciireader.cpp
new file mode 100644
--- /dev/null
+++ b/src/asciireader.cpp
@@ -0,0 +1,110 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include
+
+#include "asciireader.h"
+
+AsciiReader::AsciiReader(QIODevice* device, ChannelManager* channelMan, QObject *parent) :
+ AbstractReader(device, channelMan, parent)
+{
+ paused = false;
+ sampleCount = 0;
+ // TODO: sps counter
+
+ _numOfChannels = _settingsWidget.numOfChannels();
+ connect(&_settingsWidget, &AsciiReaderSettings::numOfChannelsChanged,
+ this, &AsciiReader::numOfChannelsChanged);
+ connect(&_settingsWidget, &AsciiReaderSettings::numOfChannelsChanged,
+ [this](unsigned value){_numOfChannels = value;});
+}
+
+QWidget* AsciiReader::settingsWidget()
+{
+ return &_settingsWidget;
+}
+
+unsigned AsciiReader::numOfChannels()
+{
+ return _numOfChannels;
+}
+
+// TODO: this could be a part of AbstractReader
+void AsciiReader::enable(bool enabled)
+{
+ if (enabled)
+ {
+ QObject::connect(_device, &QIODevice::readyRead,
+ this, &AsciiReader::onDataReady);
+ }
+ else
+ {
+ QObject::disconnect(_device, 0, this, 0);
+ }
+}
+
+void AsciiReader::pause(bool enabled)
+{
+ paused = enabled;
+}
+
+void AsciiReader::onDataReady()
+{
+ while(_device->canReadLine())
+ {
+ QByteArray line = _device->readLine();
+
+ // discard data if paused
+ if (paused)
+ {
+ return;
+ }
+
+ line = line.trimmed();
+ auto separatedValues = line.split(',');
+
+ int numReadChannels; // effective number of channels to read
+ if (separatedValues.length() >= int(_numOfChannels))
+ {
+ numReadChannels = _numOfChannels;
+ }
+ else // there is missing channel data
+ {
+ numReadChannels = separatedValues.length();
+ qWarning() << "Incoming data is missing data for some channels!";
+ }
+
+ // parse read line
+ for (int ci = 0; ci < numReadChannels; ci++)
+ {
+ bool ok;
+ double channelSample = separatedValues[ci].toDouble(&ok);
+ if (ok)
+ {
+ _channelMan->addChannelData(ci, &channelSample, 1);
+ sampleCount++;
+ }
+ else
+ {
+ qWarning() << "Data parsing error for channel: " << ci;
+ }
+ }
+ emit dataAdded();
+ }
+}
diff --git a/src/asciireader.h b/src/asciireader.h
new file mode 100644
--- /dev/null
+++ b/src/asciireader.h
@@ -0,0 +1,48 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef ASCIIREADER_H
+#define ASCIIREADER_H
+
+#include "abstractreader.h"
+#include "asciireadersettings.h"
+
+class AsciiReader : public AbstractReader
+{
+ Q_OBJECT
+
+public:
+ explicit AsciiReader(QIODevice* device, ChannelManager* channelMan, QObject *parent = 0);
+ QWidget* settingsWidget();
+ unsigned numOfChannels();
+ void enable(bool enabled = true);
+
+public slots:
+ void pause(bool);
+
+private:
+ AsciiReaderSettings _settingsWidget;
+ unsigned _numOfChannels;
+ bool paused;
+
+private slots:
+ void onDataReady();
+};
+
+#endif // ASCIIREADER_H
diff --git a/src/asciireadersettings.cpp b/src/asciireadersettings.cpp
new file mode 100644
--- /dev/null
+++ b/src/asciireadersettings.cpp
@@ -0,0 +1,47 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include "utils.h"
+
+#include "asciireadersettings.h"
+#include "ui_asciireadersettings.h"
+
+AsciiReaderSettings::AsciiReaderSettings(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::AsciiReaderSettings)
+{
+ ui->setupUi(this);
+
+ // Note: if directly connected we get a runtime warning on incompatible signal arguments
+ connect(ui->spNumOfChannels, SELECT::OVERLOAD_OF(&QSpinBox::valueChanged),
+ [this](int value)
+ {
+ emit numOfChannelsChanged(value);
+ });
+}
+
+AsciiReaderSettings::~AsciiReaderSettings()
+{
+ delete ui;
+}
+
+unsigned AsciiReaderSettings::numOfChannels()
+{
+ return ui->spNumOfChannels->value();
+}
diff --git a/src/asciireadersettings.h b/src/asciireadersettings.h
new file mode 100644
--- /dev/null
+++ b/src/asciireadersettings.h
@@ -0,0 +1,46 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef ASCIIREADERSETTINGS_H
+#define ASCIIREADERSETTINGS_H
+
+#include
+
+namespace Ui {
+class AsciiReaderSettings;
+}
+
+class AsciiReaderSettings : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit AsciiReaderSettings(QWidget *parent = 0);
+ ~AsciiReaderSettings();
+
+ unsigned numOfChannels();
+
+signals:
+ void numOfChannelsChanged(unsigned);
+
+private:
+ Ui::AsciiReaderSettings *ui;
+};
+
+#endif // ASCIIREADERSETTINGS_H
diff --git a/src/asciireadersettings.ui b/src/asciireadersettings.ui
new file mode 100644
--- /dev/null
+++ b/src/asciireadersettings.ui
@@ -0,0 +1,92 @@
+
+
+ AsciiReaderSettings
+
+
+
+ 0
+ 0
+ 414
+ 171
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
-
+
+
+ Number Of Channels:
+
+
+
+ -
+
+
+
+ 60
+ 0
+
+
+
+ Select number of channels
+
+
+ false
+
+
+ 1
+
+
+ 32
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 1
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 1
+
+
+
+
+
+
+
+
+
diff --git a/src/binarystreamreader.cpp b/src/binarystreamreader.cpp
new file mode 100644
--- /dev/null
+++ b/src/binarystreamreader.cpp
@@ -0,0 +1,190 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include
+#include
+
+#include "binarystreamreader.h"
+#include "floatswap.h"
+
+BinaryStreamReader::BinaryStreamReader(QIODevice* device, ChannelManager* channelMan, QObject *parent) :
+ AbstractReader(device, channelMan, parent)
+{
+ paused = false;
+ skipByteRequested = false;
+ sampleCount = 0;
+
+ _numOfChannels = _settingsWidget.numOfChannels();
+ connect(&_settingsWidget, &BinaryStreamReaderSettings::numOfChannelsChanged,
+ this, &BinaryStreamReader::numOfChannelsChanged);
+ connect(&_settingsWidget, &BinaryStreamReaderSettings::numOfChannelsChanged,
+ this, &BinaryStreamReader::onNumOfChannelsChanged);
+
+ // initial number format selection
+ onNumberFormatChanged(_settingsWidget.numberFormat());
+ connect(&_settingsWidget, &BinaryStreamReaderSettings::numberFormatChanged,
+ this, &BinaryStreamReader::onNumberFormatChanged);
+
+ // enable skip byte button
+ connect(&_settingsWidget, &BinaryStreamReaderSettings::skipByteRequested,
+ [this]()
+ {
+ skipByteRequested = true;
+ });
+}
+
+QWidget* BinaryStreamReader::settingsWidget()
+{
+ return &_settingsWidget;
+}
+
+unsigned BinaryStreamReader::numOfChannels()
+{
+ return _numOfChannels;
+}
+
+void BinaryStreamReader::enable(bool enabled)
+{
+ if (enabled)
+ {
+ QObject::connect(_device, &QIODevice::readyRead,
+ this, &BinaryStreamReader::onDataReady);
+ }
+ else
+ {
+ QObject::disconnect(_device, 0, this, 0);
+ }
+}
+
+void BinaryStreamReader::pause(bool enabled)
+{
+ paused = enabled;
+}
+
+void BinaryStreamReader::onNumberFormatChanged(NumberFormat numberFormat)
+{
+ switch(numberFormat)
+ {
+ case NumberFormat_uint8:
+ sampleSize = 1;
+ readSample = &BinaryStreamReader::readSampleAs;
+ break;
+ case NumberFormat_int8:
+ sampleSize = 1;
+ readSample = &BinaryStreamReader::readSampleAs;
+ break;
+ case NumberFormat_uint16:
+ sampleSize = 2;
+ readSample = &BinaryStreamReader::readSampleAs;
+ break;
+ case NumberFormat_int16:
+ sampleSize = 2;
+ readSample = &BinaryStreamReader::readSampleAs;
+ break;
+ case NumberFormat_uint32:
+ sampleSize = 4;
+ readSample = &BinaryStreamReader::readSampleAs;
+ break;
+ case NumberFormat_int32:
+ sampleSize = 4;
+ readSample = &BinaryStreamReader::readSampleAs;
+ break;
+ case NumberFormat_float:
+ sampleSize = 4;
+ readSample = &BinaryStreamReader::readSampleAs;
+ break;
+ }
+}
+
+void BinaryStreamReader::onNumOfChannelsChanged(unsigned value)
+{
+ _numOfChannels = value;
+}
+
+void BinaryStreamReader::onDataReady()
+{
+ // a package is a set of channel data like {CHAN0_SAMPLE, CHAN1_SAMPLE...}
+ int packageSize = sampleSize * _numOfChannels;
+ int bytesAvailable = _device->bytesAvailable();
+ int numOfPackagesToRead =
+ (bytesAvailable - (bytesAvailable % packageSize)) / packageSize;
+
+ if (paused)
+ {
+ // read and discard data
+ _device->read(numOfPackagesToRead*packageSize);
+ return;
+ }
+
+ if (bytesAvailable > 0 && skipByteRequested)
+ {
+ _device->read(1);
+ skipByteRequested = false;
+ bytesAvailable--;
+ }
+
+ if (bytesAvailable < packageSize) return;
+
+ double* channelSamples = new double[numOfPackagesToRead*_numOfChannels];
+
+ for (int i = 0; i < numOfPackagesToRead; i++)
+ {
+ for (unsigned int ci = 0; ci < _numOfChannels; ci++)
+ {
+ // channelSamples[ci].replace(i, (this->*readSample)());
+ channelSamples[ci*numOfPackagesToRead+i] = (this->*readSample)();
+ }
+ }
+
+ for (unsigned int ci = 0; ci < _numOfChannels; ci++)
+ {
+ addChannelData(ci,
+ channelSamples + ci*numOfPackagesToRead,
+ numOfPackagesToRead);
+ }
+ emit dataAdded();
+
+ delete channelSamples;
+}
+
+
+template double BinaryStreamReader::readSampleAs()
+{
+ T data;
+
+ _device->read((char*) &data, sizeof(data));
+
+ if (_settingsWidget.endianness() == LittleEndian)
+ {
+ data = qFromLittleEndian(data);
+ }
+ else
+ {
+ data = qFromBigEndian(data);
+ }
+
+ return double(data);
+}
+
+void BinaryStreamReader::addChannelData(unsigned int channel,
+ double* data, unsigned size)
+{
+ _channelMan->addChannelData(channel, data, size);
+ sampleCount += size;
+}
diff --git a/src/binarystreamreader.h b/src/binarystreamreader.h
new file mode 100644
--- /dev/null
+++ b/src/binarystreamreader.h
@@ -0,0 +1,70 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef BINARYSTREAMREADER_H
+#define BINARYSTREAMREADER_H
+
+#include "abstractreader.h"
+#include "binarystreamreadersettings.h"
+
+/**
+ * Reads a simple stream of samples in binary form from the
+ * device. There is no means of synchronization other than a button
+ * that should be manually triggered by user.
+ */
+class BinaryStreamReader : public AbstractReader
+{
+ Q_OBJECT
+public:
+ explicit BinaryStreamReader(QIODevice* device, ChannelManager* channelMan, QObject *parent = 0);
+ QWidget* settingsWidget();
+ unsigned numOfChannels();
+ void enable(bool enabled = true);
+
+public slots:
+ void pause(bool);
+
+private:
+ BinaryStreamReaderSettings _settingsWidget;
+ unsigned _numOfChannels;
+ unsigned sampleSize;
+ bool paused;
+ bool skipByteRequested;
+
+ /// points to the readSampleAs function for currently selected number format
+ double (BinaryStreamReader::*readSample)();
+
+ /**
+ * Reads 1 sample from the device in given format.
+ *
+ * @note Device should already have enough bytes present before
+ * calling this function.
+ */
+ template double readSampleAs();
+
+ // `data` contains i th channels data
+ void addChannelData(unsigned int channel, double* data, unsigned size);
+
+private slots:
+ void onNumberFormatChanged(NumberFormat numberFormat);
+ void onNumOfChannelsChanged(unsigned value);
+ void onDataReady();
+};
+
+#endif // BINARYSTREAMREADER_H
diff --git a/src/binarystreamreadersettings.cpp b/src/binarystreamreadersettings.cpp
new file mode 100644
--- /dev/null
+++ b/src/binarystreamreadersettings.cpp
@@ -0,0 +1,62 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include "binarystreamreadersettings.h"
+#include "ui_binarystreamreadersettings.h"
+
+#include "utils.h"
+
+BinaryStreamReaderSettings::BinaryStreamReaderSettings(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::BinaryStreamReaderSettings)
+{
+ ui->setupUi(this);
+
+ // Note: if directly connected we get a runtime warning on incompatible signal arguments
+ connect(ui->spNumOfChannels, SELECT::OVERLOAD_OF(&QSpinBox::valueChanged),
+ [this](int value)
+ {
+ emit numOfChannelsChanged(value);
+ });
+
+ connect(ui->nfBox, SIGNAL(selectionChanged(NumberFormat)),
+ this, SIGNAL(numberFormatChanged(NumberFormat)));
+
+ connect(ui->pbSkipByte, SIGNAL(clicked()), this, SIGNAL(skipByteRequested()));
+}
+
+BinaryStreamReaderSettings::~BinaryStreamReaderSettings()
+{
+ delete ui;
+}
+
+unsigned BinaryStreamReaderSettings::numOfChannels()
+{
+ return ui->spNumOfChannels->value();
+}
+
+NumberFormat BinaryStreamReaderSettings::numberFormat()
+{
+ return ui->nfBox->currentSelection();
+}
+
+Endianness BinaryStreamReaderSettings::endianness()
+{
+ return ui->endiBox->currentSelection();
+}
diff --git a/src/binarystreamreadersettings.h b/src/binarystreamreadersettings.h
new file mode 100644
--- /dev/null
+++ b/src/binarystreamreadersettings.h
@@ -0,0 +1,52 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef BINARYSTREAMREADERSETTINGS_H
+#define BINARYSTREAMREADERSETTINGS_H
+
+#include
+#include "numberformatbox.h"
+#include "endiannessbox.h"
+
+namespace Ui {
+class BinaryStreamReaderSettings;
+}
+
+class BinaryStreamReaderSettings : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit BinaryStreamReaderSettings(QWidget *parent = 0);
+ ~BinaryStreamReaderSettings();
+
+ unsigned numOfChannels();
+ NumberFormat numberFormat();
+ Endianness endianness();
+
+signals:
+ void numOfChannelsChanged(unsigned);
+ void numberFormatChanged(NumberFormat);
+ void skipByteRequested();
+
+private:
+ Ui::BinaryStreamReaderSettings *ui;
+};
+
+#endif // BINARYSTREAMREADERSETTINGS_H
diff --git a/src/binarystreamreadersettings.ui b/src/binarystreamreadersettings.ui
new file mode 100644
--- /dev/null
+++ b/src/binarystreamreadersettings.ui
@@ -0,0 +1,172 @@
+
+
+ BinaryStreamReaderSettings
+
+
+
+ 0
+ 0
+ 588
+ 212
+
+
+
+ Form
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
-
+
+
+ Number Of Channels:
+
+
+
+ -
+
+
+
+ 60
+ 0
+
+
+
+ Select number of channels
+
+
+ false
+
+
+ 1
+
+
+ 32
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Skip reading 1 byte to correct the alignment
+
+
+ Skip Byte
+
+
+
+
+
+ -
+
+
+ QFormLayout::FieldsStayAtSizeHint
+
+
+ 3
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Number Type:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Endianness:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+ NumberFormatBox
+ QWidget
+
+ 1
+
+
+ EndiannessBox
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/src/dataformatpanel.cpp b/src/dataformatpanel.cpp
--- a/src/dataformatpanel.cpp
+++ b/src/dataformatpanel.cpp
@@ -1,5 +1,5 @@
/*
- Copyright © 2015 Hasan Yavuz Özderya
+ Copyright © 2016 Hasan Yavuz Özderya
This file is part of serialplot.
@@ -20,6 +20,7 @@
#include "dataformatpanel.h"
#include "ui_dataformatpanel.h"
+#include
#include
#include
@@ -30,7 +31,11 @@ DataFormatPanel::DataFormatPanel(QSerial
ChannelManager* channelMan,
QWidget *parent) :
QWidget(parent),
- ui(new Ui::DataFormatPanel)
+ ui(new Ui::DataFormatPanel),
+ bsReader(port, channelMan, this),
+ asciiReader(port, channelMan, this),
+ framedReader(port, channelMan, this),
+ demoReader(port, channelMan, this)
{
ui->setupUi(this);
@@ -38,41 +43,36 @@ DataFormatPanel::DataFormatPanel(QSerial
_channelMan = channelMan;
paused = false;
- // setup number format buttons
- numberFormatButtons.addButton(ui->rbUint8, NumberFormat_uint8);
- numberFormatButtons.addButton(ui->rbUint16, NumberFormat_uint16);
- numberFormatButtons.addButton(ui->rbUint32, NumberFormat_uint32);
- numberFormatButtons.addButton(ui->rbInt8, NumberFormat_int8);
- numberFormatButtons.addButton(ui->rbInt16, NumberFormat_int16);
- numberFormatButtons.addButton(ui->rbInt32, NumberFormat_int32);
- numberFormatButtons.addButton(ui->rbFloat, NumberFormat_float);
- numberFormatButtons.addButton(ui->rbASCII, NumberFormat_ASCII);
-
- QObject::connect(
- &numberFormatButtons, SIGNAL(buttonToggled(int, bool)),
- this, SLOT(onNumberFormatButtonToggled(int, bool)));
-
- // init number format
- selectNumberFormat((NumberFormat) numberFormatButtons.checkedId());
+ // initalize default reader
+ currentReader = &bsReader;
+ bsReader.enable();
+ ui->rbBinary->setChecked(true);
+ ui->horizontalLayout->addWidget(bsReader.settingsWidget(), 1);
+ connect(&bsReader, SIGNAL(dataAdded()), this, SIGNAL(dataAdded()));
+ connect(&bsReader, SIGNAL(numOfChannelsChanged(unsigned)),
+ this, SIGNAL(numOfChannelsChanged(unsigned)));
+ connect(&bsReader, SIGNAL(samplesPerSecondChanged(unsigned)),
+ this, SIGNAL(samplesPerSecondChanged(unsigned)));
- // setup number of channels spinbox
- QObject::connect(ui->spNumOfChannels,
- SELECT::OVERLOAD_OF(&QSpinBox::valueChanged),
- this, &DataFormatPanel::onNumOfChannelsSP);
-
- _numOfChannels = ui->spNumOfChannels->value();
+ // initalize reader selection buttons
+ connect(ui->rbBinary, &QRadioButton::toggled, [this](bool checked)
+ {
+ if (checked) selectReader(&bsReader);
+ });
- // Init sps (sample per second) counter
- sampleCount = 0;
- QObject::connect(&spsTimer, &QTimer::timeout,
- this, &DataFormatPanel::spsTimerTimeout);
- spsTimer.start(SPS_UPDATE_TIMEOUT * 1000);
+ connect(ui->rbAscii, &QRadioButton::toggled, [this](bool checked)
+ {
+ if (checked) selectReader(&asciiReader);
+ });
- // Init demo mode
- demoCount = 0;
- demoTimer.setInterval(100);
- QObject::connect(&demoTimer, &QTimer::timeout,
- this, &DataFormatPanel::demoTimerTimeout);
+ connect(ui->rbFramed, &QRadioButton::toggled, [this](bool checked)
+ {
+ if (checked) selectReader(&framedReader);
+ });
+
+ // re-purpose numofchannels settings from actual reader settings to demo reader
+ connect(this, &DataFormatPanel::numOfChannelsChanged,
+ &demoReader, &DemoReader::setNumOfChannels);
}
DataFormatPanel::~DataFormatPanel()
@@ -80,246 +80,68 @@ DataFormatPanel::~DataFormatPanel()
delete ui;
}
-void DataFormatPanel::onNumberFormatButtonToggled(int numberFormatId,
- bool checked)
-{
- if (checked) selectNumberFormat((NumberFormat) numberFormatId);
-}
-
-void DataFormatPanel::selectNumberFormat(NumberFormat numberFormatId)
-{
- numberFormat = numberFormatId;
-
- switch(numberFormat)
- {
- case NumberFormat_uint8:
- sampleSize = 1;
- readSample = &DataFormatPanel::readSampleAs;
- break;
- case NumberFormat_int8:
- sampleSize = 1;
- readSample = &DataFormatPanel::readSampleAs;
- break;
- case NumberFormat_uint16:
- sampleSize = 2;
- readSample = &DataFormatPanel::readSampleAs;
- break;
- case NumberFormat_int16:
- sampleSize = 2;
- readSample = &DataFormatPanel::readSampleAs;
- break;
- case NumberFormat_uint32:
- sampleSize = 4;
- readSample = &DataFormatPanel::readSampleAs;
- break;
- case NumberFormat_int32:
- sampleSize = 4;
- readSample = &DataFormatPanel::readSampleAs;
- break;
- case NumberFormat_float:
- sampleSize = 4;
- readSample = &DataFormatPanel::readSampleAs;
- break;
- case NumberFormat_ASCII:
- sampleSize = 0; // these two members should not be used
- readSample = NULL; // in this mode
- break;
- }
-
- if (numberFormat == NumberFormat_ASCII)
- {
- QObject::disconnect(serialPort, &QSerialPort::readyRead, 0, 0);
- QObject::connect(this->serialPort, &QSerialPort::readyRead,
- this, &DataFormatPanel::onDataReadyASCII);
- }
- else
- {
- QObject::disconnect(serialPort, &QSerialPort::readyRead, 0, 0);
- QObject::connect(serialPort, &QSerialPort::readyRead,
- this, &DataFormatPanel::onDataReady);
- }
-
- emit skipByteEnabledChanged(skipByteEnabled());
-}
-
-bool DataFormatPanel::skipByteEnabled()
-{
- return numberFormat != NumberFormat_ASCII;
-}
-
unsigned DataFormatPanel::numOfChannels()
{
- return _numOfChannels;
-}
-
-void DataFormatPanel::onNumOfChannelsSP(int value)
-{
- _numOfChannels = value;
- emit numOfChannelsChanged(value);
-}
-
-void DataFormatPanel::requestSkipByte()
-{
- skipByteRequested = true;
+ return currentReader->numOfChannels();
}
void DataFormatPanel::pause(bool enabled)
{
paused = enabled;
+ currentReader->pause(enabled);
+ demoReader.pause(enabled);
}
void DataFormatPanel::enableDemo(bool enabled)
{
if (enabled)
{
- demoTimer.start();
+ demoReader.enable();
+ connect(&demoReader, &DemoReader::dataAdded,
+ this, &DataFormatPanel::dataAdded);
+ connect(&demoReader, &DemoReader::samplesPerSecondChanged,
+ this, &DataFormatPanel::samplesPerSecondChanged);
}
else
{
- demoTimer.stop();
- }
-}
-
-void DataFormatPanel::spsTimerTimeout()
-{
- unsigned currentSps = _samplesPerSecond;
- _samplesPerSecond = (sampleCount/_numOfChannels)/SPS_UPDATE_TIMEOUT;
- if (currentSps != _samplesPerSecond)
- {
- emit samplesPerSecondChanged(_samplesPerSecond);
- }
- sampleCount = 0;
-}
-
-
-void DataFormatPanel::demoTimerTimeout()
-{
- const double period = 100;
- demoCount++;
- if (demoCount >= 100) demoCount = 0;
-
- if (!paused)
- {
- for (unsigned ci = 0; ci < _numOfChannels; ci++)
- {
- // we are calculating the fourier components of square wave
- double value = 4*sin(2*M_PI*double((ci+1)*demoCount)/period)/((2*(ci+1))*M_PI);
- addChannelData(ci, &value, 1);
- }
- emit dataAdded();
- }
-}
-
-void DataFormatPanel::onDataReady()
-{
- // a package is a set of channel data like {CHAN0_SAMPLE, CHAN1_SAMPLE...}
- int packageSize = sampleSize * _numOfChannels;
- int bytesAvailable = serialPort->bytesAvailable();
- int numOfPackagesToRead =
- (bytesAvailable - (bytesAvailable % packageSize)) / packageSize;
-
- if (paused)
- {
- // read and discard data
- serialPort->read(numOfPackagesToRead*packageSize);
- return;
- }
-
- if (bytesAvailable > 0 && skipByteRequested)
- {
- serialPort->read(1);
- skipByteRequested = false;
- bytesAvailable--;
- }
-
- if (bytesAvailable < packageSize) return;
-
- double* channelSamples = new double[numOfPackagesToRead*_numOfChannels];
-
- for (int i = 0; i < numOfPackagesToRead; i++)
- {
- for (unsigned int ci = 0; ci < _numOfChannels; ci++)
- {
- // channelSamples[ci].replace(i, (this->*readSample)());
- channelSamples[ci*numOfPackagesToRead+i] = (this->*readSample)();
- }
+ demoReader.enable(false);
+ disconnect(&demoReader, 0, this, 0);
}
-
- for (unsigned int ci = 0; ci < _numOfChannels; ci++)
- {
- addChannelData(ci,
- channelSamples + ci*numOfPackagesToRead,
- numOfPackagesToRead);
- }
- emit dataAdded();
-
- delete channelSamples;
-}
-
-void DataFormatPanel::onDataReadyASCII()
-{
- while(serialPort->canReadLine())
- {
- QByteArray line = serialPort->readLine();
-
- // discard data if paused
- if (paused)
- {
- return;
- }
-
- line = line.trimmed();
- auto separatedValues = line.split(',');
-
- int numReadChannels; // effective number of channels to read
- if (separatedValues.length() >= int(_numOfChannels))
- {
- numReadChannels = _numOfChannels;
- }
- else // there is missing channel data
- {
- numReadChannels = separatedValues.length();
- qWarning() << "Incoming data is missing data for some channels!";
- }
-
- // parse read line
- for (int ci = 0; ci < numReadChannels; ci++)
- {
- bool ok;
- double channelSample = separatedValues[ci].toDouble(&ok);
- if (ok)
- {
- addChannelData(ci, &channelSample, 1);
- }
- else
- {
- qWarning() << "Data parsing error for channel: " << ci;
- }
- }
- emit dataAdded();
- }
-}
-
-template double DataFormatPanel::readSampleAs()
-{
- T data;
- serialPort->read((char*) &data, sizeof(data));
-
- if (ui->rbLittleE->isChecked())
- {
- data = qFromLittleEndian(data);
- }
- else
- {
- data = qFromBigEndian(data);
- }
-
- return double(data);
}
void DataFormatPanel::addChannelData(unsigned int channel,
double* data, unsigned size)
{
_channelMan->addChannelData(channel, data, size);
- sampleCount += size;
}
+
+void DataFormatPanel::selectReader(AbstractReader* reader)
+{
+ currentReader->enable(false);
+ reader->enable();
+
+ // re-connect signals
+ disconnect(currentReader, 0, this, 0);
+ connect(reader, SIGNAL(dataAdded()), this, SIGNAL(dataAdded()));
+ connect(reader, SIGNAL(numOfChannelsChanged(unsigned)),
+ this, SIGNAL(numOfChannelsChanged(unsigned)));
+ connect(reader, SIGNAL(samplesPerSecondChanged(unsigned)),
+ this, SIGNAL(samplesPerSecondChanged(unsigned)));
+
+ // switch the settings widget
+ ui->horizontalLayout->removeWidget(currentReader->settingsWidget());
+ currentReader->settingsWidget()->hide();
+ ui->horizontalLayout->addWidget(reader->settingsWidget(), 1);
+ reader->settingsWidget()->show();
+
+ // notify if number of channels is different
+ if (currentReader->numOfChannels() != reader->numOfChannels())
+ {
+ emit numOfChannelsChanged(reader->numOfChannels());
+ }
+
+ // pause
+ reader->pause(paused);
+
+ currentReader = reader;
+}
diff --git a/src/dataformatpanel.h b/src/dataformatpanel.h
--- a/src/dataformatpanel.h
+++ b/src/dataformatpanel.h
@@ -1,5 +1,5 @@
/*
- Copyright © 2015 Hasan Yavuz Özderya
+ Copyright © 2016 Hasan Yavuz Özderya
This file is part of serialplot.
@@ -29,6 +29,10 @@
#include "framebuffer.h"
#include "channelmanager.h"
+#include "binarystreamreader.h"
+#include "asciireader.h"
+#include "demoreader.h"
+#include "framedreader.h"
namespace Ui {
class DataFormatPanel;
@@ -45,74 +49,36 @@ public:
~DataFormatPanel();
unsigned numOfChannels();
- unsigned samplesPerSecond();
- bool skipByteEnabled(void); // true for binary formats
public slots:
- // during next read operation reader will skip 1 byte,
- // requests are not accumulated
- void requestSkipByte();
void pause(bool);
void enableDemo(bool); // demo shouldn't be enabled when port is open
signals:
void numOfChannelsChanged(unsigned);
void samplesPerSecondChanged(unsigned);
- void skipByteEnabledChanged(bool);
void dataAdded();
private:
- enum NumberFormat
- {
- NumberFormat_uint8,
- NumberFormat_uint16,
- NumberFormat_uint32,
- NumberFormat_int8,
- NumberFormat_int16,
- NumberFormat_int32,
- NumberFormat_float,
- NumberFormat_ASCII
- };
-
Ui::DataFormatPanel *ui;
- QButtonGroup numberFormatButtons;
QSerialPort* serialPort;
ChannelManager* _channelMan;
- unsigned int _numOfChannels;
- NumberFormat numberFormat;
- unsigned int sampleSize; // number of bytes in the selected number format
- bool skipByteRequested;
+ BinaryStreamReader bsReader;
+ AsciiReader asciiReader;
+ FramedReader framedReader;
+ /// Currently selected reader
+ AbstractReader* currentReader;
+ /// Disable current reader and enable a another one
+ void selectReader(AbstractReader* reader);
+
bool paused;
- const int SPS_UPDATE_TIMEOUT = 1; // second
- unsigned _samplesPerSecond;
- unsigned int sampleCount;
- QTimer spsTimer;
-
- // demo
- QTimer demoTimer;
- int demoCount;
-
- void selectNumberFormat(NumberFormat numberFormatId);
-
- // points to the readSampleAs function for currently selected number format
- double (DataFormatPanel::*readSample)();
-
- // note that serialPort should already have enough bytes present
- template double readSampleAs();
+ DemoReader demoReader;
// `data` contains i th channels data
void addChannelData(unsigned int channel, double* data, unsigned size);
-
-private slots:
- void onDataReady(); // used with binary number formats
- void onDataReadyASCII(); // used with ASCII number format
- void onNumberFormatButtonToggled(int numberFormatId, bool checked);
- void onNumOfChannelsSP(int value);
- void spsTimerTimeout();
- void demoTimerTimeout();
};
#endif // DATAFORMATPANEL_H
diff --git a/src/dataformatpanel.ui b/src/dataformatpanel.ui
--- a/src/dataformatpanel.ui
+++ b/src/dataformatpanel.ui
@@ -15,195 +15,38 @@
-
-
-
-
-
-
- Number Of Channels:
+
+
-
+
+
+ Data is sent as consecutive samples in binary form. Syncing can be a problem.
-
-
- -
-
-
-
- 60
- 0
-
+
+ Simple Binary
-
- false
-
-
- 1
-
-
- 32
+
+ true
-
-
- -
-
-
- Qt::Vertical
-
-
-
- -
-
-
- 0
-
-
-
-
- Number Format:
+
+
+ Data is sent in the form of ASCII text as comma seperated values. Easy to implement.
-
-
-
-
-
- unsigned 4 bytes integer
-
-
- uint32
-
-
-
- -
-
-
- signed 1 byte integer
-
-
- int8
-
-
-
- -
-
-
- unsigned 1 byte integer
-
-
- uint8
-
-
- true
-
-
-
- -
-
-
- Comma Separated Values
-
-
- ASCII(CSV)
-
-
-
- -
-
-
- signed 2 bytes integer
-
-
- int16
-
-
-
- -
-
-
- signed 4 bytes integer
-
-
- int32
-
-
-
- -
-
-
- 4 bytes floating point number
-
-
- float
-
-
-
- -
-
-
- unsigned 2 bytes integer
-
-
- uint16
-
-
-
-
+
+ ASCII
+
-
-
-
- Qt::Vertical
-
-
-
- 20
- 1
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
-
- 0
- 0
-
+
+
+ Define a custom binary frame. Powerful.
-
- Byte Order:
+
+ Custom Frame
-
-
-
-
-
- least significant byte first
-
-
- Little Endian
-
-
- true
-
-
-
- -
-
-
- most significant byte first
-
-
- Big Endian
-
-
-
-
-
@@ -214,7 +57,7 @@
20
- 1
+ 40
@@ -222,20 +65,11 @@
-
-
+
- Qt::Horizontal
-
-
- QSizePolicy::MinimumExpanding
+ Qt::Vertical
-
-
- 37
- 20
-
-
-
+
diff --git a/src/demoreader.cpp b/src/demoreader.cpp
new file mode 100644
--- /dev/null
+++ b/src/demoreader.cpp
@@ -0,0 +1,82 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include "demoreader.h"
+
+DemoReader::DemoReader(QIODevice* device, ChannelManager* channelMan, QObject *parent) :
+ AbstractReader(device, channelMan, parent)
+{
+ paused = false;
+ _numOfChannels = 1;
+ count = 0;
+ timer.setInterval(100);
+ QObject::connect(&timer, &QTimer::timeout,
+ this, &DemoReader::demoTimerTimeout);
+}
+
+QWidget* DemoReader::settingsWidget()
+{
+ return NULL;
+}
+
+void DemoReader::enable(bool enabled)
+{
+ if (enabled)
+ {
+ timer.start();
+ }
+ else
+ {
+ timer.stop();
+ }
+}
+
+unsigned DemoReader::numOfChannels()
+{
+ return _numOfChannels;
+}
+
+void DemoReader::setNumOfChannels(unsigned value)
+{
+ _numOfChannels = value;
+}
+
+void DemoReader::pause(bool enabled)
+{
+ paused = enabled;
+}
+
+void DemoReader::demoTimerTimeout()
+{
+ const double period = 100;
+ count++;
+ if (count >= 100) count = 0;
+
+ if (!paused)
+ {
+ for (unsigned ci = 0; ci < _numOfChannels; ci++)
+ {
+ // we are calculating the fourier components of square wave
+ double value = 4*sin(2*M_PI*double((ci+1)*count)/period)/((2*(ci+1))*M_PI);
+ _channelMan->addChannelData(ci, &value, 1);
+ sampleCount++;
+ }
+ emit dataAdded();
+ }
+}
diff --git a/src/demoreader.h b/src/demoreader.h
new file mode 100644
--- /dev/null
+++ b/src/demoreader.h
@@ -0,0 +1,66 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef DEMOREADER_H
+#define DEMOREADER_H
+
+#include
+
+#include "abstractreader.h"
+
+/**
+ * This is a special case of reader implementation and should be used
+ * with care.
+ *
+ * There is no settings widget. Number of channels should be set from
+ * currently selected actual readers settings widget.
+ *
+ * This reader should not be enabled when port is open!
+ */
+class DemoReader : public AbstractReader
+{
+ Q_OBJECT
+
+public:
+ explicit DemoReader(QIODevice* device, ChannelManager* channelMan, QObject *parent = 0);
+
+ /// Demo reader is an exception so this function returns NULL
+ QWidget* settingsWidget();
+
+ unsigned numOfChannels();
+
+ void enable(bool enabled = true);
+
+public slots:
+ void pause(bool);
+
+ /// Sets the number of channels, this doesn't trigger a `numOfChannelsChanged` signal.
+ void setNumOfChannels(unsigned value);
+
+private:
+ bool paused;
+ unsigned _numOfChannels;
+ QTimer timer;
+ int count;
+
+private slots:
+ void demoTimerTimeout();
+};
+
+#endif // DEMOREADER_H
diff --git a/src/endiannessbox.cpp b/src/endiannessbox.cpp
new file mode 100644
--- /dev/null
+++ b/src/endiannessbox.cpp
@@ -0,0 +1,50 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include "endiannessbox.h"
+#include "ui_endiannessbox.h"
+
+EndiannessBox::EndiannessBox(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::EndiannessBox)
+{
+ ui->setupUi(this);
+
+ connect(ui->rbLittleE, &QRadioButton::toggled, [this](bool checked)
+ {
+ emit selectionChanged(currentSelection());
+ });
+}
+
+EndiannessBox::~EndiannessBox()
+{
+ delete ui;
+}
+
+Endianness EndiannessBox::currentSelection()
+{
+ if (ui->rbLittleE->isChecked())
+ {
+ return LittleEndian;
+ }
+ else
+ {
+ return BigEndian;
+ }
+}
diff --git a/src/endiannessbox.h b/src/endiannessbox.h
new file mode 100644
--- /dev/null
+++ b/src/endiannessbox.h
@@ -0,0 +1,53 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef ENDIANNESSBOX_H
+#define ENDIANNESSBOX_H
+
+#include
+
+namespace Ui {
+class EndiannessBox;
+}
+
+enum Endianness
+{
+ LittleEndian,
+ BigEndian
+};
+
+class EndiannessBox : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit EndiannessBox(QWidget *parent = 0);
+ ~EndiannessBox();
+
+ Endianness currentSelection(); ///< currently selected endianness
+
+signals:
+ /// Signaled when endianness selection is changed
+ void selectionChanged(Endianness endianness);
+
+private:
+ Ui::EndiannessBox *ui;
+};
+
+#endif // ENDIANNESSBOX_H
diff --git a/src/endiannessbox.ui b/src/endiannessbox.ui
new file mode 100644
--- /dev/null
+++ b/src/endiannessbox.ui
@@ -0,0 +1,59 @@
+
+
+ EndiannessBox
+
+
+
+ 0
+ 0
+ 202
+ 22
+
+
+
+ EndiannessBox
+
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ least significant byte first
+
+
+ Little Endian
+
+
+ true
+
+
+
+ -
+
+
+ most significant byte first
+
+
+ Big Endian
+
+
+
+
+
+
+
+
diff --git a/src/framedreader.cpp b/src/framedreader.cpp
new file mode 100644
--- /dev/null
+++ b/src/framedreader.cpp
@@ -0,0 +1,345 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include
+#include
+#include "floatswap.h"
+
+#include "framedreader.h"
+
+FramedReader::FramedReader(QIODevice* device, ChannelManager* channelMan, QObject *parent) :
+ AbstractReader(device, channelMan, parent)
+{
+ paused = false;
+
+ // initial settings
+ settingsInvalid = 0;
+ _numOfChannels = _settingsWidget.numOfChannels();
+ hasSizeByte = _settingsWidget.frameSize() == 0;
+ frameSize = _settingsWidget.frameSize();
+ syncWord = _settingsWidget.syncWord();
+ checksumEnabled = _settingsWidget.isChecksumEnabled();
+ onNumberFormatChanged(_settingsWidget.numberFormat());
+ debugModeEnabled = _settingsWidget.isDebugModeEnabled();
+ checkSettings();
+
+ // init setting connections
+ connect(&_settingsWidget, &FramedReaderSettings::numberFormatChanged,
+ this, &FramedReader::onNumberFormatChanged);
+
+ connect(&_settingsWidget, &FramedReaderSettings::numOfChannelsChanged,
+ this, &FramedReader::onNumOfChannelsChanged);
+
+ connect(&_settingsWidget, &FramedReaderSettings::syncWordChanged,
+ this, &FramedReader::onSyncWordChanged);
+
+ connect(&_settingsWidget, &FramedReaderSettings::frameSizeChanged,
+ this, &FramedReader::onFrameSizeChanged);
+
+ connect(&_settingsWidget, &FramedReaderSettings::checksumChanged,
+ [this](bool enabled){checksumEnabled = enabled; reset();});
+
+ connect(&_settingsWidget, &FramedReaderSettings::debugModeChanged,
+ [this](bool enabled){debugModeEnabled = enabled;});
+
+ // init reader state
+ reset();
+}
+
+void FramedReader::enable(bool enabled)
+{
+ if (enabled)
+ {
+ connect(_device, &QIODevice::readyRead,
+ this, &FramedReader::onDataReady);
+ }
+ else
+ {
+ QObject::disconnect(_device, 0, this, 0);
+ }
+}
+
+QWidget* FramedReader::settingsWidget()
+{
+ return &_settingsWidget;
+}
+
+unsigned FramedReader::numOfChannels()
+{
+ return _numOfChannels;
+}
+
+void FramedReader::pause(bool enabled)
+{
+ paused = enabled;
+}
+
+void FramedReader::onNumberFormatChanged(NumberFormat numberFormat)
+{
+ switch(numberFormat)
+ {
+ case NumberFormat_uint8:
+ sampleSize = 1;
+ readSample = &FramedReader::readSampleAs;
+ break;
+ case NumberFormat_int8:
+ sampleSize = 1;
+ readSample = &FramedReader::readSampleAs;
+ break;
+ case NumberFormat_uint16:
+ sampleSize = 2;
+ readSample = &FramedReader::readSampleAs;
+ break;
+ case NumberFormat_int16:
+ sampleSize = 2;
+ readSample = &FramedReader::readSampleAs;
+ break;
+ case NumberFormat_uint32:
+ sampleSize = 4;
+ readSample = &FramedReader::readSampleAs;
+ break;
+ case NumberFormat_int32:
+ sampleSize = 4;
+ readSample = &FramedReader::readSampleAs;
+ break;
+ case NumberFormat_float:
+ sampleSize = 4;
+ readSample = &FramedReader::readSampleAs;
+ break;
+ }
+
+ checkSettings();
+ reset();
+}
+
+void FramedReader::checkSettings()
+{
+ // sync word is invalid (empty or missing a nibble at the end)
+ if (!syncWord.size())
+ {
+ settingsInvalid |= SYNCWORD_INVALID;
+ }
+ else // sync word is valid
+ {
+ settingsInvalid &= ~SYNCWORD_INVALID;
+ }
+
+ // check if fixed frame size is multiple of a sample set size
+ if (!hasSizeByte && frameSize % (_numOfChannels * sampleSize) != 0)
+ {
+ settingsInvalid |= FRAMESIZE_INVALID;
+ }
+ else
+ {
+ settingsInvalid &= ~FRAMESIZE_INVALID;
+ }
+
+ // show an error message
+ if (settingsInvalid & SYNCWORD_INVALID)
+ {
+ _settingsWidget.showMessage("Sync word is invalid!", true);
+ }
+ else if (settingsInvalid & FRAMESIZE_INVALID)
+ {
+ QString errorMessage =
+ QString("Frame size must be multiple of %1 (#channels * sample size)!")\
+ .arg(_numOfChannels * sampleSize);
+
+ _settingsWidget.showMessage(errorMessage, true);
+ }
+ else
+ {
+ _settingsWidget.showMessage("All is well!");
+ }
+}
+
+void FramedReader::onNumOfChannelsChanged(unsigned value)
+{
+ _numOfChannels = value;
+ checkSettings();
+ reset();
+ emit numOfChannelsChanged(value);
+}
+
+void FramedReader::onSyncWordChanged(QByteArray word)
+{
+ syncWord = word;
+ checkSettings();
+ reset();
+}
+
+void FramedReader::onFrameSizeChanged(unsigned value)
+{
+ if (value == 0)
+ {
+ hasSizeByte = true;
+ }
+ else
+ {
+ hasSizeByte = false;
+ frameSize = value;
+ }
+ checkSettings();
+ reset();
+}
+
+void FramedReader::onDataReady()
+{
+ if (settingsInvalid) return;
+
+ // loop until we run out of bytes or more bytes is required
+ unsigned bytesAvailable;
+ while ((bytesAvailable = _device->bytesAvailable()))
+ {
+ if (!gotSync) // read sync word
+ {
+ char c;
+ _device->getChar(&c);
+ if (c == syncWord[sync_i]) // correct sync byte?
+ {
+ sync_i++;
+ if (sync_i == (unsigned) syncWord.length())
+ {
+ gotSync = true;
+ }
+ }
+ else
+ {
+ if (debugModeEnabled) qCritical() << "Missed " << sync_i+1 << "th sync byte.";
+ }
+ }
+ else if (hasSizeByte && !gotSize) // skipped if fixed frame size
+ {
+ frameSize = 0;
+ _device->getChar((char*) &frameSize);
+
+ if (frameSize == 0) // check size
+ {
+ qCritical() << "Frame size is 0!";
+ reset();
+ }
+ else if (frameSize % (_numOfChannels * sampleSize) != 0)
+ {
+ qCritical() <<
+ QString("Frame size is not multiple of %1 (#channels * sample size)!") \
+ .arg(_numOfChannels * sampleSize);
+ reset();
+ }
+ else
+ {
+ if (debugModeEnabled) qDebug() << "Frame size:" << frameSize;
+ gotSize = true;
+ }
+ }
+ else // read data bytes
+ {
+ // have enough data bytes? (+1 for checksum)
+ if (bytesAvailable < (checksumEnabled ? frameSize+1 : frameSize))
+ {
+ break;
+ }
+ else // read data bytes and checksum
+ {
+ readFrameDataAndCheck();
+ reset();
+ }
+ }
+ }
+}
+
+void FramedReader::reset()
+{
+ sync_i = 0;
+ gotSync = false;
+ gotSize = false;
+ if (hasSizeByte) frameSize = 0;
+ calcChecksum = 0;
+}
+
+// Important: this function assumes device has enough bytes to read a full frames data and checksum
+void FramedReader::readFrameDataAndCheck()
+{
+ // a package is 1 set of samples for all channels
+ unsigned numOfPackagesToRead = frameSize / (_numOfChannels * sampleSize);
+ double* channelSamples = new double[numOfPackagesToRead * _numOfChannels];
+
+ for (unsigned i = 0; i < numOfPackagesToRead; i++)
+ {
+ for (unsigned int ci = 0; ci < _numOfChannels; ci++)
+ {
+ channelSamples[ci*numOfPackagesToRead+i] = (this->*readSample)();
+ }
+ }
+
+ // read checksum
+ unsigned rChecksum = 0;
+ bool checksumPassed = false;
+ if (checksumEnabled)
+ {
+ _device->read((char*) &rChecksum, 1);
+ calcChecksum &= 0xFF;
+ checksumPassed = (calcChecksum == rChecksum);
+ }
+
+ if (!checksumEnabled || checksumPassed)
+ {
+ // commit data
+ for (unsigned int ci = 0; ci < _numOfChannels; ci++)
+ {
+ _channelMan->addChannelData(
+ ci,
+ channelSamples + ci*numOfPackagesToRead,
+ numOfPackagesToRead);
+ sampleCount += numOfPackagesToRead;
+ }
+ emit dataAdded();
+ }
+ else
+ {
+ qCritical() << "Checksum failed! Received:" << rChecksum << "Calculated:" << calcChecksum;
+ }
+
+ delete channelSamples;
+}
+
+template double FramedReader::readSampleAs()
+{
+ T data;
+
+ _device->read((char*) &data, sizeof(data));
+
+ if (checksumEnabled)
+ {
+ for (unsigned i = 0; i < sizeof(data); i++)
+ {
+ calcChecksum += ((unsigned char*) &data)[i];
+ }
+ }
+
+ if (_settingsWidget.endianness() == LittleEndian)
+ {
+ data = qFromLittleEndian(data);
+ }
+ else
+ {
+ data = qFromBigEndian(data);
+ }
+
+ return double(data);
+}
diff --git a/src/framedreader.h b/src/framedreader.h
new file mode 100644
--- /dev/null
+++ b/src/framedreader.h
@@ -0,0 +1,92 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef FRAMEDREADER_H
+#define FRAMEDREADER_H
+
+#include "abstractreader.h"
+#include "framedreadersettings.h"
+
+/**
+ * Reads data in a customizable framed format.
+ */
+class FramedReader : public AbstractReader
+{
+ Q_OBJECT
+
+public:
+ explicit FramedReader(QIODevice* device, ChannelManager* channelMan, QObject *parent = 0);
+ QWidget* settingsWidget();
+ unsigned numOfChannels();
+ void enable(bool enabled = true);
+
+public slots:
+ void pause(bool);
+
+private:
+ /// bit wise fields for `settingsValid` member
+ enum SettingInvalidFlag
+ {
+ SYNCWORD_INVALID = 1,
+ FRAMESIZE_INVALID = 2
+ };
+
+ // settings related members
+ FramedReaderSettings _settingsWidget;
+ unsigned _numOfChannels;
+ unsigned sampleSize;
+ bool paused;
+ unsigned settingsInvalid; /// settings are all valid if this is 0, if not no reading is done
+ QByteArray syncWord;
+ bool checksumEnabled;
+ bool hasSizeByte;
+ unsigned frameSize;
+ bool debugModeEnabled;
+
+ /// Checks the validity of syncWord and frameSize then shows an
+ /// error message. Also updates `settingsInvalid`. If settings are
+ /// valid `settingsInvalid` should be `0`.
+ void checkSettings();
+
+ // read state related members
+ unsigned sync_i; /// sync byte index to be read next
+ bool gotSync; /// indicates if sync word is captured
+ bool gotSize; /// indicates if size is captured, ignored if size byte is disabled (fixed size)
+ unsigned calcChecksum;
+
+ void reset(); /// Resets the reading state. Used in case of error or setting change.
+ /// points to the readSampleAs function for currently selected number format
+ double (FramedReader::*readSample)();
+ template double readSampleAs();
+ /// reads payload portion of the frame, calculates checksum and commits data
+ /// @note should be called only if there are enough bytes on device
+ void readFrameDataAndCheck();
+ // `data` contains i th channels data
+ void addChannelData(unsigned int channel, double* data, unsigned size);
+
+private slots:
+ void onDataReady();
+
+ void onNumberFormatChanged(NumberFormat numberFormat);
+ void onNumOfChannelsChanged(unsigned value);
+ void onSyncWordChanged(QByteArray);
+ void onFrameSizeChanged(unsigned);
+};
+
+#endif // FRAMEDREADER_H
diff --git a/src/framedreadersettings.cpp b/src/framedreadersettings.cpp
new file mode 100644
--- /dev/null
+++ b/src/framedreadersettings.cpp
@@ -0,0 +1,146 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include "utils.h"
+#include "framedreadersettings.h"
+#include "ui_framedreadersettings.h"
+
+FramedReaderSettings::FramedReaderSettings(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::FramedReaderSettings)
+{
+ ui->setupUi(this);
+
+ ui->leSyncWord->setMode(false); // hex mode
+ ui->leSyncWord->setText("AA BB");
+
+ connect(ui->cbChecksum, &QCheckBox::toggled,
+ [this](bool enabled)
+ {
+ emit checksumChanged(enabled);
+ });
+
+ connect(ui->cbDebugMode, &QCheckBox::toggled,
+ this, &FramedReaderSettings::debugModeChanged);
+
+ connect(ui->rbFixedSize, &QRadioButton::toggled,
+ ui->spSize, &QWidget::setEnabled);
+
+ connect(ui->rbFixedSize, &QRadioButton::toggled,
+ [this](bool checked)
+ {
+ emit frameSizeChanged(frameSize());
+ });
+
+ // Note: if directly connected we get a runtime warning on incompatible signal arguments
+ connect(ui->spSize, SELECT::OVERLOAD_OF(&QSpinBox::valueChanged),
+ [this](int value)
+ {
+ emit frameSizeChanged(value);
+ });
+
+ connect(ui->spNumOfChannels, SELECT::OVERLOAD_OF(&QSpinBox::valueChanged),
+ [this](int value)
+ {
+ emit numOfChannelsChanged(value);
+ });
+
+ connect(ui->leSyncWord, &QLineEdit::textChanged,
+ this, &FramedReaderSettings::onSyncWordEdited);
+
+ connect(ui->nfBox, SIGNAL(selectionChanged(NumberFormat)),
+ this, SIGNAL(numberFormatChanged(NumberFormat)));
+}
+
+FramedReaderSettings::~FramedReaderSettings()
+{
+ delete ui;
+}
+
+void FramedReaderSettings::showMessage(QString message, bool error)
+{
+ ui->lMessage->setText(message);
+ if (error)
+ {
+ ui->lMessage->setStyleSheet("color: red;");
+ }
+ else
+ {
+ ui->lMessage->setStyleSheet("");
+ }
+}
+
+unsigned FramedReaderSettings::numOfChannels()
+{
+ return ui->spNumOfChannels->value();
+}
+
+NumberFormat FramedReaderSettings::numberFormat()
+{
+ return ui->nfBox->currentSelection();
+}
+
+Endianness FramedReaderSettings::endianness()
+{
+ return ui->endiBox->currentSelection();
+}
+
+QByteArray FramedReaderSettings::syncWord()
+{
+ QString text = ui->leSyncWord->text().remove(' ');
+
+ // check if nibble is missing
+ if (text.size() % 2 == 1)
+ {
+ // TODO: remove this warning
+ return QByteArray();
+ }
+ else
+ {
+ return QByteArray::fromHex(text.toLatin1());
+ }
+}
+
+void FramedReaderSettings::onSyncWordEdited()
+{
+ // TODO: emit with a delay so that error message doesn't flash!
+ emit syncWordChanged(syncWord());
+}
+
+unsigned FramedReaderSettings::frameSize()
+{
+ if (ui->rbFixedSize->isChecked())
+ {
+ return ui->spSize->value();
+ }
+ else
+ {
+ return 0; // frame byte is enabled
+ }
+}
+
+bool FramedReaderSettings::isChecksumEnabled()
+{
+ return ui->cbChecksum->isChecked();
+}
+
+bool FramedReaderSettings::isDebugModeEnabled()
+{
+ return ui->cbDebugMode->isChecked();
+}
diff --git a/src/framedreadersettings.h b/src/framedreadersettings.h
new file mode 100644
--- /dev/null
+++ b/src/framedreadersettings.h
@@ -0,0 +1,69 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef FRAMEDREADERSETTINGS_H
+#define FRAMEDREADERSETTINGS_H
+
+#include
+#include
+
+#include "numberformatbox.h"
+#include "endiannessbox.h"
+
+namespace Ui {
+class FramedReaderSettings;
+}
+
+class FramedReaderSettings : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit FramedReaderSettings(QWidget *parent = 0);
+ ~FramedReaderSettings();
+
+ void showMessage(QString message, bool error = false);
+
+ unsigned numOfChannels();
+ NumberFormat numberFormat();
+ Endianness endianness();
+ QByteArray syncWord();
+ unsigned frameSize(); /// If frame bye is enabled `0` is returned
+ bool isChecksumEnabled();
+ bool isDebugModeEnabled();
+
+signals:
+ /// If sync word is invalid (empty or 1 nibble missing at the end)
+ /// signaled with an empty array
+ void syncWordChanged(QByteArray);
+ /// `0` indicates frame size byte is enabled
+ void frameSizeChanged(unsigned);
+ void checksumChanged(bool);
+ void numOfChannelsChanged(unsigned);
+ void numberFormatChanged(NumberFormat);
+ void debugModeChanged(bool);
+
+private:
+ Ui::FramedReaderSettings *ui;
+
+private slots:
+ void onSyncWordEdited();
+};
+
+#endif // FRAMEDREADERSETTINGS_H
diff --git a/src/framedreadersettings.ui b/src/framedreadersettings.ui
new file mode 100644
--- /dev/null
+++ b/src/framedreadersettings.ui
@@ -0,0 +1,239 @@
+
+
+ FramedReaderSettings
+
+
+
+ 0
+ 0
+ 852
+ 222
+
+
+
+ Form
+
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ QFormLayout::FieldsStayAtSizeHint
+
+
-
+
+
+ Enter the 'Frame Start' bytes in hexadecimal.
+
+
+
+ -
+
+
+ Number of Channels
+
+
+ # Channels:
+
+
+
+ -
+
+
+ Select number of channels
+
+
+ 1
+
+
+ 32
+
+
+
+ -
+
+
+ Frame Size:
+
+
+
+ -
+
+
-
+
+
+ Frame size is always the same
+
+
+ Fixed Size:
+
+
+
+ -
+
+
+ false
+
+
+ <html><head/><body><p>Enter the frame size. It <span style=" font-weight:600;">must</span> be the multiple of (#channels * sample size).</p></body></html>
+
+
+ 1
+
+
+ 255
+
+
+
+ -
+
+
+ First byte after the 'frame start' bytes should be the size of the frame. Not counting itself and checksum.
+
+
+ First byte of the payload is size
+
+
+ true
+
+
+
+
+
+ -
+
+
+
+
+
+ Number Type:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Byte Order
+
+
+ Endianness:
+
+
+
+ -
+
+
+ -
+
+
+ Checksum:
+
+
+
+ -
+
+
+ Last byte of the frame is checksum.
+
+
+ Enabled
+
+
+
+ -
+
+
+ Frame Start:
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 1
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ All is well.
+
+
+
+ -
+
+
+ Enable printing of extra log messages that can be useful for debugging
+
+
+ Debug Mode
+
+
+
+
+
+
+
+
+
+ NumberFormatBox
+ QWidget
+
+ 1
+
+
+ EndiannessBox
+ QWidget
+
+ 1
+
+
+ CommandEdit
+ QLineEdit
+
+
+
+
+
+
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -105,9 +105,6 @@ MainWindow::MainWindow(QWidget *parent)
QObject::connect(&portControl, &PortControl::portToggled,
this, &MainWindow::onPortToggled);
- QObject::connect(&portControl, &PortControl::skipByteRequested,
- &dataFormatPanel, &DataFormatPanel::requestSkipByte);
-
connect(&plotControlPanel, &PlotControlPanel::numOfSamplesChanged,
this, &MainWindow::onNumOfSamplesChanged);
diff --git a/src/numberformatbox.cpp b/src/numberformatbox.cpp
new file mode 100644
--- /dev/null
+++ b/src/numberformatbox.cpp
@@ -0,0 +1,56 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#include "numberformatbox.h"
+#include "ui_numberformatbox.h"
+
+NumberFormatBox::NumberFormatBox(QWidget *parent) :
+ QWidget(parent),
+ ui(new Ui::NumberFormatBox)
+{
+ ui->setupUi(this);
+
+ // setup buttons
+ buttonGroup.addButton(ui->rbUint8, NumberFormat_uint8);
+ buttonGroup.addButton(ui->rbUint16, NumberFormat_uint16);
+ buttonGroup.addButton(ui->rbUint32, NumberFormat_uint32);
+ buttonGroup.addButton(ui->rbInt8, NumberFormat_int8);
+ buttonGroup.addButton(ui->rbInt16, NumberFormat_int16);
+ buttonGroup.addButton(ui->rbInt32, NumberFormat_int32);
+ buttonGroup.addButton(ui->rbFloat, NumberFormat_float);
+
+ QObject::connect(
+ &buttonGroup, SIGNAL(buttonToggled(int, bool)),
+ this, SLOT(onButtonToggled(int, bool)));
+}
+
+NumberFormatBox::~NumberFormatBox()
+{
+ delete ui;
+}
+
+void NumberFormatBox::onButtonToggled(int numberFormatId, bool checked)
+{
+ if (checked) emit selectionChanged((NumberFormat) numberFormatId);
+}
+
+NumberFormat NumberFormatBox::currentSelection()
+{
+ return (NumberFormat) buttonGroup.checkedId();
+}
diff --git a/src/numberformatbox.h b/src/numberformatbox.h
new file mode 100644
--- /dev/null
+++ b/src/numberformatbox.h
@@ -0,0 +1,63 @@
+/*
+ Copyright © 2016 Hasan Yavuz Özderya
+
+ This file is part of serialplot.
+
+ serialplot is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ serialplot is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with serialplot. If not, see .
+*/
+
+#ifndef NUMBERFORMATBOX_H
+#define NUMBERFORMATBOX_H
+
+#include
+#include
+
+namespace Ui {
+class NumberFormatBox;
+}
+
+enum NumberFormat
+{
+ NumberFormat_uint8,
+ NumberFormat_uint16,
+ NumberFormat_uint32,
+ NumberFormat_int8,
+ NumberFormat_int16,
+ NumberFormat_int32,
+ NumberFormat_float,
+};
+
+class NumberFormatBox : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit NumberFormatBox(QWidget *parent = 0);
+ ~NumberFormatBox();
+
+ NumberFormat currentSelection(); ///< returns the currently selected number format
+
+signals:
+ /// Signaled when number format selection is changed
+ void selectionChanged(NumberFormat numberFormat);
+
+private:
+ Ui::NumberFormatBox *ui;
+ QButtonGroup buttonGroup;
+
+private slots:
+ void onButtonToggled(int numberFormatId, bool checked);
+};
+
+#endif // NUMBERFORMATBOX_H
diff --git a/src/numberformatbox.ui b/src/numberformatbox.ui
new file mode 100644
--- /dev/null
+++ b/src/numberformatbox.ui
@@ -0,0 +1,109 @@
+
+
+ NumberFormatBox
+
+
+
+ 0
+ 0
+ 440
+ 22
+
+
+
+ NumberFormat
+
+
+
+ 3
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ unsigned 1 byte integer
+
+
+ uint8
+
+
+ true
+
+
+
+ -
+
+
+ unsigned 2 bytes integer
+
+
+ uint16
+
+
+
+ -
+
+
+ unsigned 4 bytes integer
+
+
+ uint32
+
+
+
+ -
+
+
+ signed 1 byte integer
+
+
+ int8
+
+
+
+ -
+
+
+ signed 2 bytes integer
+
+
+ int16
+
+
+
+ -
+
+
+ signed 4 bytes integer
+
+
+ int32
+
+
+
+ -
+
+
+ 4 bytes floating point number
+
+
+ float
+
+
+
+
+
+
+
+
diff --git a/src/portcontrol.cpp b/src/portcontrol.cpp
--- a/src/portcontrol.cpp
+++ b/src/portcontrol.cpp
@@ -115,10 +115,6 @@ PortControl::PortControl(QSerialPort* po
SELECT::OVERLOAD_OF(&QButtonGroup::buttonClicked),
this, &PortControl::selectFlowControl);
- // init skip byte button
- QObject::connect(ui->pbSkipByte, &QPushButton::clicked,
- [this](){emit skipByteRequested();});
-
loadPortList();
loadBaudRateList();
ui->cbBaudRate->setCurrentIndex(ui->cbBaudRate->findText("9600"));
@@ -272,11 +268,6 @@ void PortControl::selectPort(QString por
}
}
-void PortControl::enableSkipByte(bool enabled)
-{
- ui->pbSkipByte->setDisabled(enabled);
-}
-
QToolBar* PortControl::toolBar()
{
return &portToolBar;
diff --git a/src/portcontrol.h b/src/portcontrol.h
--- a/src/portcontrol.h
+++ b/src/portcontrol.h
@@ -64,7 +64,6 @@ public slots:
void loadBaudRateList();
void togglePort();
void selectPort(QString portName);
- void enableSkipByte(bool enabled = true);
void selectBaudRate(QString baudRate);
void selectParity(int parity); // parity must be one of QSerialPort::Parity
@@ -79,7 +78,6 @@ private slots:
void onTbPortListActivated(int index);
signals:
- void skipByteRequested();
void portToggled(bool open);
};
diff --git a/src/portcontrol.ui b/src/portcontrol.ui
--- a/src/portcontrol.ui
+++ b/src/portcontrol.ui
@@ -7,7 +7,7 @@
0
0
631
- 213
+ 232
@@ -285,7 +285,7 @@
- 0
+ 85
50
@@ -301,16 +301,6 @@
-
-
-
- Skip reading 1 byte to correct the alignment
-
-
- Skip Byte
-
-
-
- -
Qt::Vertical