diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,6 +61,10 @@ 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
)
if (WIN32)
@@ -93,6 +97,13 @@ 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
misc/windows_icon.rc
${UI_FILES}
${RES_FILES}
diff --git a/src/abstractreader.cpp b/src/abstractreader.cpp
new file mode 100644
--- /dev/null
+++ b/src/abstractreader.cpp
@@ -0,0 +1,27 @@
+/*
+ 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 "abstractreader.h"
+
+AbstractReader::AbstractReader(QIODevice* device, ChannelManager* channelMan, QObject *parent) :
+ QObject(parent)
+{
+ _device = device;
+ _channelMan = channelMan;
+}
diff --git a/src/abstractreader.h b/src/abstractreader.h
new file mode 100644
--- /dev/null
+++ b/src/abstractreader.h
@@ -0,0 +1,77 @@
+/*
+ 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 "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;
+};
+
+#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,49 @@
+/*
+ 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;
+ unsigned sampleCount; ///< used for sps counter
+
+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,57 @@
+
+
+ AsciiReaderSettings
+
+
+
+ 0
+ 0
+ 414
+ 171
+
+
+
+ Form
+
+
+
+
+ 153
+ 10
+ 60
+ 27
+
+
+
+
+ 60
+ 0
+
+
+
+ false
+
+
+ 1
+
+
+ 32
+
+
+
+
+
+ 20
+ 10
+ 127
+ 27
+
+
+
+ Number Of Channels:
+
+
+
+
+
+
diff --git a/src/binarystreamreader.cpp b/src/binarystreamreader.cpp
new file mode 100644
--- /dev/null
+++ b/src/binarystreamreader.cpp
@@ -0,0 +1,192 @@
+/*
+ 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;
+ });
+
+ // TODO sps counter
+}
+
+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,71 @@
+/*
+ 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;
+ unsigned sampleCount; ///< used for sps counter
+
+ /// 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,107 @@
+
+
+ BinaryStreamReaderSettings
+
+
+
+ 0
+ 0
+ 432
+ 203
+
+
+
+ Form
+
+
+
+
+ 17
+ 10
+ 127
+ 27
+
+
+
+ Number Of Channels:
+
+
+
+
+
+ 150
+ 10
+ 60
+ 27
+
+
+
+
+ 60
+ 0
+
+
+
+ false
+
+
+ 1
+
+
+ 32
+
+
+
+
+
+ 20
+ 50
+ 161
+ 141
+
+
+
+
+
+
+ 190
+ 50
+ 120
+ 80
+
+
+
+
+
+
+ 220
+ 10
+ 85
+ 27
+
+
+
+ Skip reading 1 byte to correct the alignment
+
+
+ Skip Byte
+
+
+
+
+
+ NumberFormatBox
+ QWidget
+
+ 1
+
+
+ EndiannessBox
+ QWidget
+
+ 1
+
+
+
+
+
diff --git a/src/dataformatpanel.cpp b/src/dataformatpanel.cpp
--- a/src/dataformatpanel.cpp
+++ b/src/dataformatpanel.cpp
@@ -20,6 +20,7 @@
#include "dataformatpanel.h"
#include "ui_dataformatpanel.h"
+#include
#include
#include
@@ -30,7 +31,9 @@ DataFormatPanel::DataFormatPanel(QSerial
ChannelManager* channelMan,
QWidget *parent) :
QWidget(parent),
- ui(new Ui::DataFormatPanel)
+ ui(new Ui::DataFormatPanel),
+ bsReader(port, channelMan),
+ asciiReader(port, channelMan)
{
ui->setupUi(this);
@@ -38,35 +41,31 @@ 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);
+ // 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)));
- QObject::connect(
- &numberFormatButtons, SIGNAL(buttonToggled(int, bool)),
- this, SLOT(onNumberFormatButtonToggled(int, bool)));
-
- // init number format
- selectNumberFormat((NumberFormat) numberFormatButtons.checkedId());
+ // initalize reader selection buttons
+ connect(ui->rbBinary, &QRadioButton::toggled, [this](bool checked)
+ {
+ if (checked) selectReader(&bsReader);
+ });
- // setup number of channels spinbox
- QObject::connect(ui->spNumOfChannels,
- SELECT::OVERLOAD_OF(&QSpinBox::valueChanged),
- this, &DataFormatPanel::onNumOfChannelsSP);
-
- _numOfChannels = ui->spNumOfChannels->value();
+ connect(ui->rbAscii, &QRadioButton::toggled, [this](bool checked)
+ {
+ if (checked) selectReader(&asciiReader);
+ });
// Init sps (sample per second) counter
- sampleCount = 0;
- QObject::connect(&spsTimer, &QTimer::timeout,
- this, &DataFormatPanel::spsTimerTimeout);
- spsTimer.start(SPS_UPDATE_TIMEOUT * 1000);
+ // sampleCount = 0;
+ // QObject::connect(&spsTimer, &QTimer::timeout,
+ // this, &DataFormatPanel::spsTimerTimeout);
+ // spsTimer.start(SPS_UPDATE_TIMEOUT * 1000);
// Init demo mode
demoCount = 0;
@@ -80,84 +79,18 @@ 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());
-}
-
+// TODO: remove
bool DataFormatPanel::skipByteEnabled()
{
- return numberFormat != NumberFormat_ASCII;
+ return false;
}
unsigned DataFormatPanel::numOfChannels()
{
- return _numOfChannels;
+ return currentReader->numOfChannels();
}
-void DataFormatPanel::onNumOfChannelsSP(int value)
-{
- _numOfChannels = value;
- emit numOfChannelsChanged(value);
-}
-
+// TODO: remove
void DataFormatPanel::requestSkipByte()
{
skipByteRequested = true;
@@ -165,7 +98,7 @@ void DataFormatPanel::requestSkipByte()
void DataFormatPanel::pause(bool enabled)
{
- paused = enabled;
+ currentReader->pause(enabled);
}
void DataFormatPanel::enableDemo(bool enabled)
@@ -182,16 +115,15 @@ void DataFormatPanel::enableDemo(bool en
void DataFormatPanel::spsTimerTimeout()
{
- unsigned currentSps = _samplesPerSecond;
- _samplesPerSecond = (sampleCount/_numOfChannels)/SPS_UPDATE_TIMEOUT;
- if (currentSps != _samplesPerSecond)
- {
- emit samplesPerSecondChanged(_samplesPerSecond);
- }
- sampleCount = 0;
+ // unsigned currentSps = _samplesPerSecond;
+ // _samplesPerSecond = (sampleCount/_numOfChannels)/SPS_UPDATE_TIMEOUT;
+ // if (currentSps != _samplesPerSecond)
+ // {
+ // emit samplesPerSecondChanged(_samplesPerSecond);
+ // }
+ // sampleCount = 0;
}
-
void DataFormatPanel::demoTimerTimeout()
{
const double period = 100;
@@ -200,7 +132,7 @@ void DataFormatPanel::demoTimerTimeout()
if (!paused)
{
- for (unsigned ci = 0; ci < _numOfChannels; ci++)
+ for (unsigned ci = 0; ci < currentReader->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);
@@ -210,116 +142,29 @@ void DataFormatPanel::demoTimerTimeout()
}
}
-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)();
- }
- }
-
- 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)));
+
+ // switch the settings widget
+ ui->horizontalLayout->removeWidget(currentReader->settingsWidget());
+ currentReader->settingsWidget()->hide();
+ ui->horizontalLayout->addWidget(reader->settingsWidget(), 1);
+ reader->settingsWidget()->show();
+
+ currentReader = reader;
+}
diff --git a/src/dataformatpanel.h b/src/dataformatpanel.h
--- a/src/dataformatpanel.h
+++ b/src/dataformatpanel.h
@@ -29,6 +29,8 @@
#include "framebuffer.h"
#include "channelmanager.h"
+#include "binarystreamreader.h"
+#include "asciireader.h"
namespace Ui {
class DataFormatPanel;
@@ -58,33 +60,24 @@ public slots:
signals:
void numOfChannelsChanged(unsigned);
void samplesPerSecondChanged(unsigned);
- void skipByteEnabledChanged(bool);
+ void skipByteEnabledChanged(bool); // remove
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;
- bool paused;
+ BinaryStreamReader bsReader;
+ AsciiReader asciiReader;
+ /// Currently selected reader
+ AbstractReader* currentReader;
+ /// Disable current reader and enable a another one
+ void selectReader(AbstractReader* reader);
+
+ bool skipByteRequested; // remove
+ bool paused; // remove
const int SPS_UPDATE_TIMEOUT = 1; // second
unsigned _samplesPerSecond;
@@ -95,22 +88,10 @@ private:
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();
-
// `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();
};
diff --git a/src/dataformatpanel.ui b/src/dataformatpanel.ui
--- a/src/dataformatpanel.ui
+++ b/src/dataformatpanel.ui
@@ -15,195 +15,22 @@
-
-
-
-
-
+
+
-
+
- Number Of Channels:
+ Simple Binary
-
-
- -
-
-
-
- 60
- 0
-
-
-
- false
-
-
- 1
-
-
- 32
+
+ true
-
-
- -
-
-
- Qt::Vertical
-
-
-
- -
-
-
- 0
-
-
-
-
- Number Format:
+
+
+ ASCII
-
-
-
-
-
- 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
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 1
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
-
- 0
- 0
-
-
-
- Byte Order:
-
-
-
-
-
-
- least significant byte first
-
-
- Little Endian
-
-
- true
-
-
-
- -
-
-
- most significant byte first
-
-
- Big Endian
-
-
-
-
-
@@ -214,7 +41,7 @@
20
- 1
+ 40
@@ -222,20 +49,11 @@
-
-
+
- Qt::Horizontal
-
-
- QSizePolicy::MinimumExpanding
+ Qt::Vertical
-
-
- 37
- 20
-
-
-
+