diff --git a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -136,6 +136,7 @@ add_executable(${PROGRAM_NAME} WIN32
   src/samplecounter.cpp
   src/ledwidget.cpp
   src/datatextview.cpp
+  src/bpslabel.cpp
   misc/windows_icon.rc
   ${UI_FILES}
   ${RES_FILES}
diff --git a/serialplot.pro b/serialplot.pro
--- a/serialplot.pro
+++ b/serialplot.pro
@@ -72,7 +72,8 @@ SOURCES += \
     src/updatechecker.cpp \
     src/updatecheckdialog.cpp \
     src/demoreadersettings.cpp \
-    src/datatextview.cpp
+    src/datatextview.cpp \
+    src/bpslabel.cpp
 
 HEADERS += \
     src/mainwindow.h \
@@ -116,7 +117,8 @@ HEADERS += \
     src/updatechecker.h \
     src/updatecheckdialog.h \
     src/demoreadersettings.h \
-    src/datatextview.h
+    src/datatextview.h \
+    src/bpslabel.h
 
 FORMS += \
     src/mainwindow.ui \
diff --git a/src/bpslabel.cpp b/src/bpslabel.cpp
new file mode 100644
--- /dev/null
+++ b/src/bpslabel.cpp
@@ -0,0 +1,75 @@
+/*
+  Copyright © 2019 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 "bpslabel.h"
+
+const char* BPS_TOOLTIP = "bits per second";
+const char* BPS_TOOLTIP_ERR = "Maximum baud rate may be reached!";
+
+BPSLabel::BPSLabel(PortControl* portControl,
+                   DataFormatPanel* dataFormatPanel,
+                   QWidget *parent) :
+    QLabel(parent)
+{
+    _portControl = portControl;
+    _dataFormatPanel = dataFormatPanel;
+
+    setText("0bps");
+    setToolTip(tr(BPS_TOOLTIP));
+
+    connect(&bpsTimer, &QTimer::timeout,
+            this, &BPSLabel::onBpsTimeout);
+
+    connect(portControl, &PortControl::portToggled,
+            this, &BPSLabel::onPortToggled);
+}
+
+void BPSLabel::onBpsTimeout()
+{
+    unsigned bits = _dataFormatPanel->getBytesRead() * 8;
+    unsigned maxBps = _portControl->maxBitRate();
+    QString str;
+    if (bits >= maxBps)
+    {
+        // TODO: an icon for bps warning
+        str = QString(tr("!%1/%2bps")).arg(bits).arg(maxBps);
+        setToolTip(tr(BPS_TOOLTIP_ERR));
+    }
+    else
+    {
+        str = QString(tr("%1bps")).arg(bits);
+        setToolTip(tr(BPS_TOOLTIP));
+    }
+    setText(str);
+}
+
+void BPSLabel::onPortToggled(bool open)
+{
+    if (open)
+    {
+        bpsTimer.start(1000);
+    }
+    else
+    {
+        bpsTimer.stop();
+        // if not cleared last displayed value is stuck
+        setText("0bps");
+        setToolTip(tr(BPS_TOOLTIP));
+    }
+}
diff --git a/src/bpslabel.h b/src/bpslabel.h
new file mode 100644
--- /dev/null
+++ b/src/bpslabel.h
@@ -0,0 +1,53 @@
+/*
+  Copyright © 2019 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 BPSLABEL_H
+#define BPSLABEL_H
+
+#include 
+#include 
+
+#include "portcontrol.h"
+#include "dataformatpanel.h"
+
+/**
+ * Displays bits per second read from device.
+ *
+ * Displays a warning if maximum bit rate is reached.
+ */
+class BPSLabel : public QLabel
+{
+    Q_OBJECT
+
+public:
+    explicit BPSLabel(PortControl* portControl,
+                      DataFormatPanel* dataFormatPanel,
+                      QWidget *parent = 0);
+
+private:
+    PortControl* _portControl;
+    DataFormatPanel* _dataFormatPanel;
+    QTimer bpsTimer;
+
+private slots:
+    void onBpsTimeout();
+    void onPortToggled(bool open);
+};
+
+#endif // BPSLABEL_H
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -59,9 +59,6 @@ const QMap panelSettingMap
         {6, "Log"}
     });
 
-const char* BPS_TOOLTIP = "bits per second";
-const char* BPS_TOOLTIP_ERR = "Maximum baud rate may be reached!";
-
 MainWindow::MainWindow(QWidget *parent) :
     QMainWindow(parent),
     ui(new Ui::MainWindow),
@@ -73,7 +70,8 @@ MainWindow::MainWindow(QWidget *parent) 
     dataFormatPanel(&serialPort),
     recordPanel(&stream),
     textView(&stream),
-    updateCheckDialog(this)
+    updateCheckDialog(this),
+    bpsLabel(&portControl, &dataFormatPanel, this)
 {
     ui->setupUi(this);
 
@@ -235,11 +233,7 @@ MainWindow::MainWindow(QWidget *parent) 
     plotMan->setPlotWidth(plotControlPanel.plotWidth());
 
     // init bps (bits per second) counter
-    bpsLabel.setText("0bps");
-    bpsLabel.setToolTip(tr(BPS_TOOLTIP));
     ui->statusBar->addPermanentWidget(&bpsLabel);
-    connect(&bpsTimer, &QTimer::timeout,
-            this, &MainWindow::onBpsTimeout);
 
     // Init sps (sample per second) counter
     spsLabel.setText("0sps");
@@ -366,16 +360,8 @@ void MainWindow::onPortToggled(bool open
     if (open && isDemoRunning()) enableDemo(false);
     ui->actionDemoMode->setEnabled(!open);
 
-    if (open)
+    if (!open)
     {
-        bpsTimer.start(1000);
-    }
-    else
-    {
-        bpsTimer.stop();
-        // if not cleared last displayed value is stuck
-        bpsLabel.setText("0bps");
-        bpsLabel.setToolTip(tr(BPS_TOOLTIP));
         spsLabel.setText("0sps");
     }
 }
@@ -405,25 +391,6 @@ void MainWindow::onSpsChanged(float sps)
     spsLabel.setText(QString::number(sps, 'f', precision) + "sps");
 }
 
-void MainWindow::onBpsTimeout()
-{
-    unsigned bits = dataFormatPanel.getBytesRead() * 8;
-    unsigned maxBps = portControl.maxBitRate();
-    QString str;
-    if (bits >= maxBps)
-    {
-        // TODO: an icon for bps warning
-        str = QString(tr("!%1/%2bps")).arg(bits).arg(maxBps);
-        bpsLabel.setToolTip(tr(BPS_TOOLTIP_ERR));
-    }
-    else
-    {
-        str = QString(tr("%1bps")).arg(bits);
-        bpsLabel.setToolTip(tr(BPS_TOOLTIP));
-    }
-    bpsLabel.setText(str);
-}
-
 bool MainWindow::isDemoRunning()
 {
     return ui->actionDemoMode->isChecked();
diff --git a/src/mainwindow.h b/src/mainwindow.h
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -47,6 +47,7 @@
 #include "updatecheckdialog.h"
 #include "samplecounter.h"
 #include "datatextview.h"
+#include "bpslabel.h"
 
 namespace Ui {
 class MainWindow;
@@ -83,11 +84,8 @@ private:
     QWidget* secondaryPlot;
     SnapshotManager snapshotMan;
     SampleCounter sampleCounter;
-    /// bit counter timer
-    QTimer bpsTimer;
 
     QLabel spsLabel;
-    QLabel bpsLabel;
     CommandPanel commandPanel;
     DataFormatPanel dataFormatPanel;
     RecordPanel recordPanel;
@@ -95,6 +93,7 @@ private:
     PlotMenu plotMenu;
     DataTextView textView;
     UpdateCheckDialog updateCheckDialog;
+    BPSLabel bpsLabel;
 
     /// Returns true if demo is running
     bool isDemoRunning();
@@ -122,7 +121,6 @@ private slots:
 
     void clearPlot();
     void onSpsChanged(float sps);
-    void onBpsTimeout();
     void enableDemo(bool enabled);
     void showBarPlot(bool show);