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();
+}