diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,6 +65,7 @@ qt5_wrap_ui(UI_FILES
src/endiannessbox.ui
src/binarystreamreadersettings.ui
src/asciireadersettings.ui
+ src/framedreadersettings.ui
)
if (WIN32)
@@ -105,6 +106,8 @@ add_executable(${PROGRAM_NAME} WIN32
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/serialplot.pro b/serialplot.pro
--- a/serialplot.pro
+++ b/serialplot.pro
@@ -55,7 +55,17 @@ SOURCES += \
src/sneakylineedit.cpp \
src/channelmanager.cpp \
src/framebufferseries.cpp \
- src/plotcontrolpanel.cpp
+ src/plotcontrolpanel.cpp \
+ src/numberformatbox.cpp \
+ src/endiannessbox.cpp \
+ src/framedreadersettings.cpp \
+ src/abstractreader.cpp \
+ src/binarystreamreader.cpp \
+ src/binarystreamreadersettings.cpp \
+ src/asciireadersettings.cpp \
+ src/asciireader.cpp \
+ src/demoreader.cpp \
+ src/framedreader.cpp
HEADERS += \
src/mainwindow.h \
@@ -81,7 +91,17 @@ HEADERS += \
src/sneakylineedit.h \
src/channelmanager.h \
src/framebufferseries.h \
- src/plotcontrolpanel.h
+ src/plotcontrolpanel.h \
+ src/numberformatbox.h \
+ src/endiannessbox.h \
+ src/framedreadersettings.h \
+ src/abstractreader.h \
+ src/binarystreamreader.h \
+ src/binarystreamreadersettings.h \
+ src/asciireadersettings.h \
+ src/asciireader.h \
+ src/demoreader.h \
+ src/framedreader.h
FORMS += \
src/mainwindow.ui \
@@ -91,7 +111,12 @@ FORMS += \
src/commandpanel.ui \
src/commandwidget.ui \
src/dataformatpanel.ui \
- src/plotcontrolpanel.ui
+ src/plotcontrolpanel.ui \
+ src/numberformatbox.ui \
+ src/endiannessbox.ui \
+ src/framedreadersettings.ui \
+ src/binarystreamreadersettings.ui \
+ src/asciireadersettings.ui
INCLUDEPATH += qmake/ src/
diff --git a/src/dataformatpanel.cpp b/src/dataformatpanel.cpp
--- a/src/dataformatpanel.cpp
+++ b/src/dataformatpanel.cpp
@@ -34,6 +34,7 @@ DataFormatPanel::DataFormatPanel(QSerial
ui(new Ui::DataFormatPanel),
bsReader(port, channelMan, this),
asciiReader(port, channelMan, this),
+ framedReader(port, channelMan, this),
demoReader(port, channelMan, this)
{
ui->setupUi(this);
@@ -64,6 +65,11 @@ DataFormatPanel::DataFormatPanel(QSerial
if (checked) selectReader(&asciiReader);
});
+ 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);
diff --git a/src/dataformatpanel.h b/src/dataformatpanel.h
--- a/src/dataformatpanel.h
+++ b/src/dataformatpanel.h
@@ -32,6 +32,7 @@
#include "binarystreamreader.h"
#include "asciireader.h"
#include "demoreader.h"
+#include "framedreader.h"
namespace Ui {
class DataFormatPanel;
@@ -66,6 +67,7 @@ private:
BinaryStreamReader bsReader;
AsciiReader asciiReader;
+ FramedReader framedReader;
/// Currently selected reader
AbstractReader* currentReader;
/// Disable current reader and enable a another one
diff --git a/src/dataformatpanel.ui b/src/dataformatpanel.ui
--- a/src/dataformatpanel.ui
+++ b/src/dataformatpanel.ui
@@ -34,6 +34,13 @@
-
+
+
+ Framed
+
+
+
+ -
Qt::Vertical
diff --git a/src/framedreader.cpp b/src/framedreader.cpp
new file mode 100644
--- /dev/null
+++ b/src/framedreader.cpp
@@ -0,0 +1,208 @@
+/*
+ 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();
+ hasFrameByte = _settingsWidget.frameSize() == 0;
+ frameSize = _settingsWidget.frameSize();
+ syncWord = _settingsWidget.syncWord();
+ checksumEnabled = _settingsWidget.checksumEnabled();
+ onNumberFormatChanged(_settingsWidget.numberFormat());
+ checkSettings();
+
+ 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;});
+}
+
+void FramedReader::enable(bool enabled)
+{
+ if (enabled)
+ {
+ // TODO
+ // QObject::connect(_device, &QIODevice::readyRead,
+ // this, &BinaryStreamReader::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();
+}
+
+template double FramedReader::readSampleAs()
+{
+ T data;
+
+ _device->read((char*) &data, sizeof(data));
+
+ // TODO: checksum
+
+ if (_settingsWidget.endianness() == LittleEndian)
+ {
+ data = qFromLittleEndian(data);
+ }
+ else
+ {
+ data = qFromBigEndian(data);
+ }
+
+ return double(data);
+}
+
+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 (!hasFrameByte && 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();
+}
+
+void FramedReader::onSyncWordChanged(QByteArray word)
+{
+ syncWord = word;
+ checkSettings();
+}
+
+void FramedReader::onFrameSizeChanged(unsigned value)
+{
+ if (value == 0)
+ {
+ hasFrameByte = true;
+ }
+ else
+ {
+ hasFrameByte = false;
+ frameSize = value;
+ }
+ checkSettings();
+}
diff --git a/src/framedreader.h b/src/framedreader.h
new file mode 100644
--- /dev/null
+++ b/src/framedreader.h
@@ -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 .
+*/
+
+#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
+ };
+
+ 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 hasFrameByte;
+ unsigned frameSize;
+
+ // TODO: create a base class that contains common functionality between binary readers
+
+ /// points to the readSampleAs function for currently selected number format
+ double (FramedReader::*readSample)();
+ template double readSampleAs();
+ // `data` contains i th channels data
+ void addChannelData(unsigned int channel, double* data, unsigned size);
+
+ /// 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();
+
+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,137 @@
+/*
+ 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
+
+ connect(ui->cbChecksum, &QCheckBox::toggled,
+ [this](bool enabled)
+ {
+ emit checksumChanged(enabled);
+ });
+
+ 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::checksumEnabled()
+{
+ return ui->cbChecksum->isChecked();
+}
diff --git a/src/framedreadersettings.h b/src/framedreadersettings.h
new file mode 100644
--- /dev/null
+++ b/src/framedreadersettings.h
@@ -0,0 +1,67 @@
+/*
+ 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 checksumEnabled();
+
+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);
+
+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,176 @@
+
+
+ FramedReaderSettings
+
+
+
+ 0
+ 0
+ 542
+ 222
+
+
+
+ Form
+
+
+
+
+ 210
+ 40
+ 141
+ 141
+
+
+
+
+
+
+ 360
+ 40
+ 120
+ 80
+
+
+
+
+
+
+ 210
+ 0
+ 211
+ 29
+
+
+
+
-
+
+
+ Number Of Channels:
+
+
+
+ -
+
+
+ 1
+
+
+ 32
+
+
+
+
+
+
+
+
+ 0
+ 180
+ 471
+ 17
+
+
+
+ All is well.
+
+
+
+
+
+ 1
+ 39
+ 204
+ 93
+
+
+
+ Frame Size:
+
+
+ -
+
+
-
+
+
+ Fixed Size:
+
+
+
+ -
+
+
+ false
+
+
+ 1
+
+
+ 255
+
+
+
+
+
+ -
+
+
+ First byte of frame is size
+
+
+ true
+
+
+
+
+
+
+
+ -
+
+
+ Sync Word:
+
+
+
+ -
+
+
+
+
+
+
+
+ 1
+ 138
+ 123
+ 22
+
+
+
+ Checksum Byte
+
+
+
+
+
+ NumberFormatBox
+ QWidget
+
+ 1
+
+
+ EndiannessBox
+ QWidget
+
+ 1
+
+
+ CommandEdit
+ QLineEdit
+
+
+
+
+
+