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
-      
-     
-    
+