Changeset - d52402a7de11
[Not reviewed]
Merge add-textview
0 11 3
Hasan Yavuz ÖZDERYA - 10 years ago 2015-07-05 20:27:02
hy@ozderya.net
Merge
14 files changed with 170 insertions and 9 deletions:
0 comments (0 inline, 0 general)
.hgtags
Show inline comments
 
cdddeef73834c62a8ba5f3ac4c000cd4cb059e06 v0.1
 
73524cc41d6c6f4a664b39a74ae202be21b58eaf v0.2
 
1332b87e543fd947b57d45ccf62e9a0886e09cb5 v0.3
CMakeLists.txt
Show inline comments
 
@@ -31,151 +31,180 @@ set(CMAKE_AUTOMOC ON)
 
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
 

	
 
# Find the QtWidgets library
 
find_package(Qt5Widgets)
 

	
 
# Find QWT or use static
 
set(QWT_USE_STATIC false CACHE BOOL "Use a static version of Qwt provided by user.")
 
set(QWT_STATIC_LIBRARY "" CACHE FILEPATH "Path to the static Qwt library, libqwt.a.")
 
set(QWT_STATIC_INCLUDE "" CACHE PATH "Path to the Qwt include directory when building Qwt static.")
 

	
 
if (QWT_USE_STATIC)
 
  set(QWT_LIBRARY ${QWT_STATIC_LIBRARY})
 
  set(QWT_INCLUDE_DIR ${QWT_STATIC_INCLUDE})
 
else (QWT_USE_STATIC)
 
  find_package(Qwt 6.1 REQUIRED)
 
endif (QWT_USE_STATIC)
 

	
 
# includes
 
include_directories(${QWT_INCLUDE_DIR})
 

	
 
# wrap UI files
 
qt5_wrap_ui(UI_FILES mainwindow.ui portcontrol.ui about_dialog.ui)
 

	
 
# Tell CMake to create the helloworld executable
 
add_executable(serialplot main.cpp mainwindow.cpp portcontrol.cpp
 
  customcheckablebutton.cpp ${UI_FILES})
 
add_executable(serialplot WIN32 main.cpp mainwindow.cpp portcontrol.cpp
 
  customcheckablebutton.cpp ${UI_FILES} misc/windows_icon.rc)
 

	
 
# Use the Widgets module from Qt 5.
 
target_link_libraries(serialplot ${QWT_LIBRARY})
 
qt5_use_modules(serialplot Widgets SerialPort Svg)
 

	
 
# set compiler flags
 
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
 

	
 
# Enable C++11 support, fail if not supported
 
include(CheckCXXCompilerFlag)
 
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
 
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
 
if(COMPILER_SUPPORTS_CXX11)
 
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
 
elseif(COMPILER_SUPPORTS_CXX0X)
 
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
 
else()
 
  message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
 
endif()
 

	
 
# version number
 
set(MAJOR_VERSION 0)
 
set(MINOR_VERSION 2)
 
set(MINOR_VERSION 3)
 
set(PATCH_VERSION 0)
 
set(VERSION_STRING "${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}")
 

	
 
# get revision number from mercurial
 
find_program(MERCURIAL hg)
 

	
 
if (MERCURIAL)
 
  execute_process(COMMAND ${MERCURIAL} id -i
 
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
 
    RESULT_VARIABLE MERCURIAL_RESULT
 
    OUTPUT_VARIABLE VERSION_REVISION
 
    OUTPUT_STRIP_TRAILING_WHITESPACE)
 
  if(NOT MERCURIAL_RESULT EQUAL 0)
 
    set(VERSION_SCM_REVISION false)
 
  endif(NOT MERCURIAL_RESULT EQUAL 0)
 
endif (MERCURIAL)
 

	
 
if (NOT VERSION_REVISION)
 
  set(VERSION_REVISION "0")
 
endif (NOT VERSION_REVISION)
 

	
 
message("SCM revision: ${VERSION_REVISION}")
 

	
 
# configure version file
 
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/version.h.in" "${CMAKE_CURRENT_BINARY_DIR}/version.h")
 

	
 
# add make run target
 
add_custom_target(run
 
    COMMAND serialplot
 
    DEPENDS serialplot
 
    WORKING_DIRECTORY ${CMAKE_PROJECT_DIR}
 
)
 

	
 
# installing
 
install(TARGETS serialplot DESTINATION bin)
 

	
 
# for windows put libraries to install directory
 
if (WIN32)
 
  file(GLOB WINDOWS_INSTALL_LIBRARIES
 
    "${CMAKE_BINARY_DIR}/windows_install_libraries/*.*")
 
  install(FILES ${WINDOWS_INSTALL_LIBRARIES} DESTINATION bin)
 
endif (WIN32)
 

	
 
# install menu item and icon
 
find_program(XDG-DESKTOP-MENU xdg-desktop-menu)
 
find_program(XDG-ICON-RESOURCE xdg-icon-resource)
 

	
 
if (UNIX)
 
# first copy files to share/serialplot/
 
install(FILES
 
  ${CMAKE_SOURCE_DIR}/misc/serialplot.desktop
 
  ${CMAKE_SOURCE_DIR}/misc/serialplot.png
 
  DESTINATION share/serialplot)
 

	
 
# install copyright file (in debian format)
 
install(FILES
 
  ${CMAKE_SOURCE_DIR}/debian/copyright
 
  DESTINATION share/doc/serialplot/)
 

	
 
install(CODE "
 
  execute_process(COMMAND ${XDG-DESKTOP-MENU} install --novendor ${CMAKE_INSTALL_PREFIX}/share/serialplot/serialplot.desktop)
 
  execute_process(COMMAND ${XDG-ICON-RESOURCE} install --novendor --size 256 ${CMAKE_INSTALL_PREFIX}/share/serialplot/serialplot.png)
 
")
 
endif (UNIX)
 

	
 
# uninstalling
 
configure_file(
 
  "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
 
  "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
 
  IMMEDIATE @ONLY)
 

	
 
if (UNIX)
 
add_custom_target(uninstall
 
  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
 
  COMMAND ${XDG-DESKTOP-MENU} uninstall --novendor serialplot.desktop
 
  COMMAND ${XDG-ICON-RESOURCE} uninstall --novendor --size 256 serialplot)
 
endif (UNIX)
 

	
 
# packaging
 
if (UNIX)
 
set(CPACK_GENERATOR "DEB")
 
elseif (WIN32)
 
  set(CPACK_GENERATOR "NSIS")
 
endif (UNIX)
 

	
 
include(InstallRequiredSystemLibraries)
 

	
 
set(CPACK_PACKAGE_NAME "serialplot")
 
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Small and simple software for plotting data from serial port")
 
set(CPACK_PACKAGE_CONTACT "Hasan Yavuz Özderya <hy@ozderya.net>")
 
set(CPACK_PACKAGE_VERSION_MAJOR ${MAJOR_VERSION})
 
set(CPACK_PACKAGE_VERSION_MINOR ${MINOR_VERSION})
 
set(CPACK_PACKAGE_VERSION_PATCH ${PATCH_VERSION})
 
set(CPACK_STRIP_FILES TRUE)
 
set(CPACK_PACKAGE_EXECUTABLES "serialplot")
 
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5widgets5 (>= 5.2.1), libqt5serialport5 (>= 5.2.1), libc6 (>= 2.19)")
 
if (NOT QWT_USE_STATIC)
 
  set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}, libqwt6-qt5 (>= 6.1.1)")
 
endif (NOT QWT_USE_STATIC)
 
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_SOURCE_DIR}/debian/postinst" "${CMAKE_SOURCE_DIR}/debian/postrm")
 

	
 
if (UNIX)
 
  set(CPACK_PACKAGE_EXECUTABLES "serialplot")
 
elseif (WIN32)
 
  set(CPACK_PACKAGE_EXECUTABLES "serialplot;SerialPlot")
 
  set(CPACK_CREATE_DESKTOP_LINKS "serialplot")
 
  set(CPACK_NSIS_MODIFY_PATH "ON")
 
  set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/misc/serialplot.bmp")
 
  string(REPLACE "/" "\\\\" CPACK_PACKAGE_ICON ${CPACK_PACKAGE_ICON})
 
  set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/COPYING")
 
  set(CPACK_NSIS_MENU_LINKS
 
    "https://bitbucket.org/hyOzd/serialplot" "SerialPlot source code on bitbucket.org")
 
endif (UNIX)
 

	
 
if (UNIX)
 
# set debian package name
 
string(TOLOWER "${CPACK_PACKAGE_NAME}" CPACK_PACKAGE_NAME_LOWERCASE)
 
find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems")
 
if(DPKG_PROGRAM)
 
  execute_process(
 
    COMMAND ${DPKG_PROGRAM} --print-architecture
 
    OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
 
    OUTPUT_STRIP_TRAILING_WHITESPACE)
 
  set(CPACK_PACKAGE_FILE_NAME
 
	"${CPACK_PACKAGE_NAME_LOWERCASE}_${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
 
else(DPKG_PROGRAM)
 
  set(CPACK_PACKAGE_FILE_NAME
 
	"${CPACK_PACKAGE_NAME_LOWERCASE}_${PROJECT_VERSION}-${PROJECT_VERSION_REVISION}_${CMAKE_SYSTEM_NAME}")
 
endif(DPKG_PROGRAM)
 
endif (UNIX)
 

	
 
include(CPack)
README.md
Show inline comments
 
# SerialPlot
 

	
 
Small and simple software for plotting data from serial port.
 

	
 
![SerialPlot v0.2 Screenshot](http://i.imgur.com/l7mNWfB.png)
 

	
 
## Features
 
* Reading data from serial port
 
* Binary data formats (u)int8, (u)int16, (u)int32, float
 
* ASCII input (Comma Separated Values)
 
* Synchronized multi channel plotting
 

	
 
## Installation
 

	
 
You can obtain installation packages from
 
[downloads](https://bitbucket.org/hyOzd/serialplot/downloads). As of
 
moment there is only Debian and Windows 64 bits packages.
 

	
 
## Dependencies
 
- Qt 5, including SerialPort module
 
- Qwt 6.1
 

	
 
## Building
 

	
 
### Obtain Dependencies
 

	
 
- Qt5 development packages
 
- Qt5 SerialPort module
 
- CMake
 
- Mercurial
 

	
 
Under Ubuntu/Debian:
 
```sudo apt-get install qtbase5-dev libqt5serialport5-dev cmake mercurial```
 

	
 
### Download and Install Qwt
 

	
 
[Qwt](http://qwt.sourceforge.net) is the library that provides
 
plotting widgets for SerialPlot. As of this moment there is no
 
appropriate version of Qwt in debian repositories. You will need to
 
download and build Qwt with Qt5 yourself.
 

	
 
Download Qwt 6 from here: http://sourceforge.net/projects/qwt/files/
 
@@ -38,25 +44,25 @@ Download Qwt 6 from here: http://sourcef
 
Follow these instructions to build and install:
 
http://qwt.sourceforge.net/qwtinstall.html#qwtinstall-unix
 

	
 
Make sure that you have built the Qwt with Qt 5 not Qt 4.
 

	
 
### Download and Build SerialPlot
 

	
 
You can use Mercurial to download SerialPlot source code. Or you can
 
download it from here:
 
https://bitbucket.org/hyOzd/serialplot/downloads
 

	
 
    hg clone https://hyOzd@bitbucket.org/hyOzd/serialplot
 
    cd serialplot
 
    mkdir build && cd build
 
    cmake ..
 
    make
 

	
 
You can also build with QtCreator IDE using `serialplot.pro` file.
 

	
 
## Known Issues
 
- Port error 13 happens when closing. This is a Qt issue. It's known
 
  to not happen with Qt 5.4.1 . Not fatal.
 

	
 
## License
 
This software is licensed under GPLv3. See file COPYING for details.
 
\ No newline at end of file
 
This software is licensed under GPLv3. See file COPYING for details.
about_dialog.ui
Show inline comments
 
<?xml version="1.0" encoding="UTF-8"?>
 
<ui version="4.0">
 
 <class>AboutDialog</class>
 
 <widget class="QDialog" name="AboutDialog">
 
  <property name="geometry">
 
   <rect>
 
    <x>0</x>
 
    <y>0</y>
 
    <width>487</width>
 
    <height>325</height>
 
   </rect>
 
  </property>
 
  <property name="windowTitle">
 
   <string>About</string>
 
  </property>
 
  <layout class="QVBoxLayout" name="verticalLayout">
 
   <item>
 
    <widget class="QLabel" name="lbAbout">
 
     <property name="text">
 
      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:14pt;&quot;&gt;SerialPlot&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;$VERSION_STRING$&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Developed by Hasan Yavuz Özderya&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Using Qt and Qwt (&lt;a href=&quot;http://qwt.sf.net&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://qwt.sf.net&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;This software is GPL licensed. You can obtain source code from &lt;a href=&quot;https://bitbucket.org/hyOzd/serialplot&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://bitbucket.org/hyOzd/serialplot&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;RevID: $VERSION_REVISION$&lt;br/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
 
      <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:14pt;&quot;&gt;SerialPlot&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;$VERSION_STRING$&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Developed by Hasan Yavuz Özderya&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;Using Qt (&lt;a href=&quot;https://www.qt.io/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://www.qt.io/&lt;/span&gt;&lt;/a&gt;) and Qwt (&lt;a href=&quot;http://qwt.sf.net&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;http://qwt.sf.net&lt;/span&gt;&lt;/a&gt;)&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;This software is GPL licensed. You can obtain source code from &lt;a href=&quot;https://bitbucket.org/hyOzd/serialplot&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;https://bitbucket.org/hyOzd/serialplot&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;/p&gt;&lt;p align=&quot;right&quot;&gt;&lt;span style=&quot; font-size:8pt;&quot;&gt;RevID: $VERSION_REVISION$&lt;br/&gt;&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
 
     </property>
 
     <property name="wordWrap">
 
      <bool>true</bool>
 
     </property>
 
     <property name="openExternalLinks">
 
      <bool>true</bool>
 
     </property>
 
    </widget>
 
   </item>
 
   <item>
 
    <layout class="QHBoxLayout" name="horizontalLayout">
 
     <item>
 
      <widget class="QPushButton" name="pbAboutQt">
 
       <property name="text">
 
        <string>About Qt</string>
 
       </property>
 
      </widget>
 
     </item>
 
     <item>
 
      <widget class="QDialogButtonBox" name="buttonBox">
 
       <property name="orientation">
 
        <enum>Qt::Horizontal</enum>
 
       </property>
 
       <property name="standardButtons">
cmake/modules/FindQwt.cmake
Show inline comments
 
#
 
# Copyright © 2015 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 <http://www.gnu.org/licenses/>.
 
#
 

	
 
#
 
# Note: This module will only find local Qwt installations in
 
# /usr/local/qwt-VERSION directories.
 
#
 

	
 
file(GLOB qwt_glob_dir "/usr/local/qwt*/")
 
file(GLOB qwt_glob_dir "/usr/local/qwt*/" "c:/Qwt*")
 

	
 
if(qwt_glob_dir)
 
  foreach(qwt_path ${qwt_glob_dir})
 
	# find the qwt_global.h file
 
	unset(qwt_root CACHE)
 
	find_path(qwt_root
 
	  "include/qwt_global.h"
 
	  HINTS "${qwt_path}")
 
	if(qwt_root)
 
	  list(APPEND qwt_roots ${qwt_root})
 
	endif(qwt_root)
 
  endforeach(qwt_path)
 
endif(qwt_glob_dir)
 

	
 
# select qwt root according to version
 
if(qwt_roots)
 
  foreach(qwt_root ${qwt_roots})
 
	# extract the version information
 
	unset(qwt_version_string)
 
	file(STRINGS "${qwt_root}/include/qwt_global.h" qwt_version_string
 
	  REGEX "#define[ \t]+QWT_VERSION_STR")
 
	if(qwt_version_string)
 
	  string(REGEX REPLACE "[^\"]*\"([0-9.]+)\".*" "\\1"
 
		qwt_version_string ${qwt_version_string})
floatswap.h
Show inline comments
 
#include <byteswap.h>
 
#include <QtGlobal>
 

	
 
template <> inline float qbswap<float>(float source)
 
{
 
    float result;
 
    char* s = (char*) &source;
 
    char* t = (char*) &result;
 
    t[0] = s[3];
 
    t[1] = s[2];
 
    t[2] = s[1];
 
    t[3] = s[0];
 
    return result;
 
}
mainwindow.cpp
Show inline comments
 
@@ -15,68 +15,76 @@
 

	
 
  You should have received a copy of the GNU General Public License
 
  along with serialplot.  If not, see <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#include "mainwindow.h"
 
#include "ui_mainwindow.h"
 
#include <QByteArray>
 
#include <QApplication>
 
#include <QFileDialog>
 
#include <QFile>
 
#include <QTextStream>
 
#include <QtDebug>
 
#include <QtEndian>
 
#include <QTextCursor>
 
#include <qwt_plot.h>
 
#include <limits.h>
 
#include <cmath>
 
#include <iostream>
 

	
 
#include "utils.h"
 
#include "version.h"
 
#include "floatswap.h"
 

	
 
#if defined(Q_OS_WIN) && defined(QT_STATIC)
 
#include <QtPlugin>
 
Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)
 
#endif
 

	
 
MainWindow::MainWindow(QWidget *parent) :
 
    QMainWindow(parent),
 
    ui(new Ui::MainWindow),
 
    portControl(&serialPort)
 
{
 
    ui->setupUi(this);
 
    ui->tabWidget->insertTab(0, &portControl, "Port");
 
    ui->tabWidget->setCurrentIndex(0);
 

	
 
    setupAboutDialog();
 

	
 
    // init UI signals
 

	
 
    // menu signals
 
    QObject::connect(ui->actionHelpAbout, &QAction::triggered,
 
              &aboutDialog, &QWidget::show);
 

	
 
    QObject::connect(ui->actionExportCsv, &QAction::triggered,
 
                     this, &MainWindow::onExportCsv);
 

	
 
    QObject::connect(ui->actionQuit, &QAction::triggered,
 
                     this, &MainWindow::close);
 

	
 
    QObject::connect(&portControl, &PortControl::portToggled,
 
                     this, &MainWindow::onPortToggled);
 

	
 
    QObject::connect(&portControl, &PortControl::skipByteRequested,
 
                     this, &MainWindow::skipByte);
 

	
 
    QObject::connect(ui->spNumOfSamples, SELECT<int>::OVERLOAD_OF(&QSpinBox::valueChanged),
 
                     this, &MainWindow::onNumOfSamplesChanged);
 

	
 
    QObject::connect(ui->cbAutoScale, &QCheckBox::toggled,
 
                     this, &MainWindow::onAutoScaleChecked);
 

	
 
    QObject::connect(ui->spYmin, SIGNAL(valueChanged(double)),
 
                     this, SLOT(onYScaleChanged()));
 

	
 
    QObject::connect(ui->spYmax, SIGNAL(valueChanged(double)),
 
                     this, SLOT(onYScaleChanged()));
 

	
 
    QObject::connect(ui->actionClear, SIGNAL(triggered(bool)),
 
                     this, SLOT(clearPlot()));
 

	
 
    // setup number of channels spinbox
 
    QObject::connect(ui->spNumOfChannels,
 
                     SELECT<int>::OVERLOAD_OF(&QSpinBox::valueChanged),
 
@@ -116,64 +124,87 @@ MainWindow::MainWindow(QWidget *parent) 
 
    {
 
        dataX[i] = i;
 
    }
 

	
 
    // init channel data and curve list
 
    for (unsigned int i = 0; i < numOfChannels; i++)
 
    {
 
        channelsData.append(DataArray(numOfSamples, 0.0));
 
        curves.append(new QwtPlotCurve());
 
        curves[i]->setSamples(dataX, channelsData[i]);
 
        curves[i]->setPen(makeColor(i));
 
        curves[i]->attach(ui->plot);
 
    }
 

	
 
    // init number format
 
    if (numberFormatButtons.checkedId() >= 0)
 
    {
 
        selectNumberFormat((NumberFormat) numberFormatButtons.checkedId());
 
    }
 
    else
 
    {
 
        selectNumberFormat(NumberFormat_uint8);
 
    }
 

	
 

	
 
    // init text view
 
    ui->ptTextView->setEnabled(ui->cbEnableTextView->isChecked());
 
    // TODO: does this work in binary mode? (no new lines)
 
    ui->ptTextView->setMaximumBlockCount(10000);
 
    QObject::connect(ui->cbEnableTextView, &QCheckBox::toggled,
 
                     ui->ptTextView, &QWidget::setEnabled);
 
    QObject::connect(ui->pbClearTextView, &QPushButton::clicked,
 
                     ui->ptTextView, &QPlainTextEdit::clear);
 

	
 

	
 
    // Init sps (sample per second) counter
 
    sampleCount = 0;
 
    spsLabel.setText("0sps");
 
    spsLabel.setToolTip("samples per second (total of all channels)");
 
    ui->statusBar->addPermanentWidget(&spsLabel);
 
    spsTimer.start(SPS_UPDATE_TIMEOUT * 1000);
 
    QObject::connect(&spsTimer, &QTimer::timeout,
 
                     this, &MainWindow::spsTimerTimeout);
 

	
 
    // Init demo mode
 
    demoCount = 0;
 
    demoTimer.setInterval(100);
 
    QObject::connect(&demoTimer, &QTimer::timeout,
 
                     this, &MainWindow::demoTimerTimeout);
 
    QObject::connect(ui->actionDemoMode, &QAction::toggled,
 
                     this, &MainWindow::enableDemo);
 

	
 
    {   // init demo indicator
 
        QwtText demoText(" DEMO RUNNING ");  // looks better with spaces
 
        demoText.setColor(QColor("white"));
 
        demoText.setBackgroundBrush(Qt::darkRed);
 
        demoText.setBorderRadius(4);
 
        demoText.setRenderFlags(Qt::AlignLeft | Qt::AlignTop);
 
        demoIndicator.setText(demoText);
 
        demoIndicator.hide();
 
        demoIndicator.attach(ui->plot);
 
    }
 

	
 
}
 

	
 
MainWindow::~MainWindow()
 
{
 
    for (auto curve : curves)
 
    {
 
        delete curve;
 
    }
 

	
 
    if (serialPort.isOpen())
 
    {
 
        serialPort.close();
 
    }
 
    delete ui;
 
}
 

	
 
void MainWindow::setupAboutDialog()
 
{
 
    Ui_AboutDialog uiAboutDialog;
 
    uiAboutDialog.setupUi(&aboutDialog);
 

	
 
    QObject::connect(uiAboutDialog.pbAboutQt, &QPushButton::clicked,
 
                     [](){ QApplication::aboutQt();});
 

	
 
@@ -225,48 +256,55 @@ void MainWindow::onDataReady()
 
                for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
                {
 
                    channelSamples[ci].replace(i, (this->*readSample)());
 
                }
 
                i++;
 
            }
 

	
 
            for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
            {
 
                addChannelData(ci, channelSamples[ci]);
 
            }
 
        }
 
    }
 
    else
 
    {
 
        serialPort.clear(QSerialPort::Input);
 
    }
 
}
 

	
 
void MainWindow::onDataReadyASCII()
 
{
 
    while(serialPort.canReadLine())
 
    {
 
        QByteArray line = serialPort.readLine();
 

	
 
        // discard data if paused
 
        if (ui->actionPause->isChecked())
 
        {
 
            return;
 
        }
 

	
 
        line = line.trimmed();
 

	
 
        if (ui->cbEnableTextView->isChecked())
 
        {
 
            ui->ptTextView->appendPlainText(line);
 
        }
 

	
 
        auto separatedValues = line.split(',');
 

	
 
        if (separatedValues.length() >= int(numOfChannels))
 
        {
 
            for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
            {
 
                double channelSample = separatedValues[ci].toDouble();
 
                addChannelData(ci, DataArray({channelSample}));
 
            }
 
        }
 
        else // there is missing channel data
 
        {
 
            qWarning() << "Incoming data is missing data for some channels!";
 
            for (int ci = 0; ci < separatedValues.length(); ci++)
 
            {
 
                double channelSample = separatedValues[ci].toDouble();
 
                addChannelData(ci, DataArray({channelSample}));
 
@@ -351,48 +389,50 @@ void MainWindow::addChannelData(unsigned
 
        }
 
    }
 
    else if (offset == 0)
 
    {
 
        (*channelDataArray) = data;
 
    }
 
    else
 
    {
 
        // shift old samples
 
        int shift = data.size();
 
        for (int i = 0; i < offset; i++)
 
        {
 
            (*channelDataArray)[i] = (*channelDataArray)[i + shift];
 
        }
 
        // place new samples
 
        for (int i = 0; i < data.size(); i++)
 
        {
 
            (*channelDataArray)[offset + i] = data[i];
 
        }
 
    }
 

	
 
    // update plot
 
    curves[channel]->setSamples(dataX, (*channelDataArray));
 
    ui->plot->replot(); // TODO: replot after all channel data updated
 

	
 
    sampleCount += data.size();
 
}
 

	
 
void MainWindow::clearPlot()
 
{
 
    for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
    {
 
        channelsData[ci].fill(0.0);
 
        curves[ci]->setSamples(dataX, channelsData[ci]);
 
    }
 

	
 
    // update plot
 
    ui->plot->replot();
 
}
 

	
 
void MainWindow::onNumOfSamplesChanged(int value)
 
{
 
    unsigned int oldNum = this->numOfSamples;
 
    numOfSamples = value;
 

	
 
    // resize data arrays
 
    if (numOfSamples < oldNum)
 
    {
 
        dataX.resize(numOfSamples);
 
        for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
@@ -543,82 +583,92 @@ template<typename T> double MainWindow::
 
    {
 
        QTextCursor cursor(ui->ptTextView->document());
 
        cursor.movePosition(QTextCursor::End);
 
        QByteArray ba((char*) &data, sizeof(data));
 
        cursor.insertText(ba.toHex() + " ");
 
    }
 

	
 
    if (ui->rbLittleE->isChecked())
 
    {
 
        data = qFromLittleEndian(data);
 
    }
 
    else
 
    {
 
        data = qFromBigEndian(data);
 
    }
 

	
 
    return double(data);
 
}
 

	
 
bool MainWindow::isDemoRunning()
 
{
 
    return ui->actionDemoMode->isChecked();
 
}
 

	
 
void MainWindow::spsTimerTimeout()
 
{
 
    spsLabel.setText(QString::number(sampleCount/SPS_UPDATE_TIMEOUT) + "sps");
 
    sampleCount = 0;
 
}
 

	
 
void MainWindow::demoTimerTimeout()
 
{
 
    demoCount++;
 
    if (demoCount > 100) demoCount = 0;
 

	
 
    if (!ui->actionPause->isChecked())
 
    {
 
        for (unsigned int ci = 0; ci < numOfChannels; ci++)
 
        {
 
            DataArray data(1);
 
            data.replace(0, (ci + 1)*demoCount);
 
            addChannelData(ci, data);
 
        }
 
    }
 
}
 

	
 
void MainWindow::enableDemo(bool enabled)
 
{
 
    if (enabled)
 
    {
 
        if (!serialPort.isOpen())
 
        {
 
            demoTimer.start();
 
            ui->actionDemoMode->setChecked(true);
 
            demoIndicator.show();
 
            ui->plot->replot();
 
        }
 
        else
 
        {
 
            ui->actionDemoMode->setChecked(false);
 
        }
 
    }
 
    else
 
    {
 
        demoTimer.stop();
 
        ui->actionDemoMode->setChecked(false);
 
        demoIndicator.hide();
 
        ui->plot->replot();
 
    }
 
}
 

	
 
/*
 
  Below crude drawing demostrates how color selection occurs for
 
  given channel index
 

	
 
  0°                     <--Hue Value-->                           360°
 
  |* . o . + . o . * . o . + . o . * . o . + . o . * . o . + . o . |
 

	
 
  * -> 0-3
 
  + -> 4-7
 
  o -> 8-15
 
  . -> 16-31
 

	
 
 */
 

	
 
QColor MainWindow::makeColor(unsigned int channelIndex)
 
{
 
    auto i = channelIndex;
 

	
 
    if (i < 4)
 
    {
 
        return QColor::fromHsv(360*i/4, 255, 230);
mainwindow.h
Show inline comments
 
/*
 
  Copyright © 2015 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 <http://www.gnu.org/licenses/>.
 
*/
 

	
 
#ifndef MAINWINDOW_H
 
#define MAINWINDOW_H
 

	
 
#include <QMainWindow>
 
#include <QButtonGroup>
 
#include <QLabel>
 
#include <QString>
 
#include <QVector>
 
#include <QList>
 
#include <QSerialPort>
 
#include <QSignalMapper>
 
#include <QTimer>
 
#include <QColor>
 
#include <QtGlobal>
 
#include <qwt_plot_curve.h>
 
#include <qwt_plot_textlabel.h>
 

	
 
#include "portcontrol.h"
 
#include "ui_about_dialog.h"
 

	
 
namespace Ui {
 
class MainWindow;
 
}
 

	
 
class MainWindow : public QMainWindow
 
{
 
    Q_OBJECT
 

	
 
public:
 
    explicit MainWindow(QWidget *parent = 0);
 
    ~MainWindow();
 

	
 
    void messageHandler(QtMsgType type, const QMessageLogContext &context,
 
                        const QString &msg);
 

	
 
private:
 
    enum NumberFormat
 
    {
 
        NumberFormat_uint8,
 
        NumberFormat_uint16,
 
@@ -59,68 +61,76 @@ private:
 
        NumberFormat_int8,
 
        NumberFormat_int16,
 
        NumberFormat_int32,
 
        NumberFormat_float,
 
        NumberFormat_ASCII
 
    };
 

	
 
    Ui::MainWindow *ui;
 
    QButtonGroup numberFormatButtons;
 

	
 
    QDialog aboutDialog;
 
    void setupAboutDialog();
 

	
 
    QSerialPort serialPort;
 
    PortControl portControl;
 

	
 
    unsigned int numOfSamples;
 
    unsigned int numOfChannels;
 

	
 
    QList<QwtPlotCurve*> curves;
 
    typedef QVector<double> DataArray;
 
    DataArray dataX;   // array that simply contains numbers 0..numberOfSamples
 
    QList<DataArray> channelsData;
 

	
 
    // `data` contains channel specific data
 
    // `data` contains i th channels data
 
    void addChannelData(unsigned int channel, DataArray data);
 

	
 
    NumberFormat numberFormat;
 
    unsigned int sampleSize; // number of bytes in the selected number format
 
    double (MainWindow::*readSample)();
 

	
 
    // note that serialPort should already have enough bytes present
 
    template<typename T> double readSampleAs();
 

	
 
    bool skipByteRequested;
 

	
 
    const int SPS_UPDATE_TIMEOUT = 1;  // second
 
    QLabel spsLabel;
 
    unsigned int sampleCount;
 
    QTimer spsTimer;
 

	
 
    // demo
 
    QTimer demoTimer;
 
    int demoCount;
 
    bool isDemoRunning();
 
    QwtPlotTextLabel demoIndicator;
 

	
 
    QColor makeColor(unsigned int channelIndex);
 

	
 
private slots:
 
    void onPortToggled(bool open);
 
    void onDataReady();      // used with binary number formats
 
    void onDataReadyASCII(); // used with ASCII number format
 
    void onPortError(QSerialPort::SerialPortError error);
 

	
 
    void skipByte();
 

	
 
    void onNumOfSamplesChanged(int value);
 
    void onAutoScaleChecked(bool checked);
 
    void onYScaleChanged();
 

	
 
    void onNumOfChannelsChanged(int value);
 
    void onNumberFormatButtonToggled(int numberFormatId, bool checked);
 
    void selectNumberFormat(NumberFormat numberFormatId);
 

	
 
    void clearPlot();
 

	
 
    void spsTimerTimeout();
 

	
 
    void demoTimerTimeout();
 
    void enableDemo(bool enabled);
 

	
 
    void onExportCsv();
 
};
 

	
 
#endif // MAINWINDOW_H
mainwindow.ui
Show inline comments
 
@@ -85,155 +85,182 @@
 
           </widget>
 
          </item>
 
         </layout>
 
        </item>
 
        <item>
 
         <widget class="Line" name="line_2">
 
          <property name="orientation">
 
           <enum>Qt::Vertical</enum>
 
          </property>
 
         </widget>
 
        </item>
 
        <item>
 
         <layout class="QVBoxLayout" name="verticalLayout_5">
 
          <property name="leftMargin">
 
           <number>0</number>
 
          </property>
 
          <item>
 
           <widget class="QGroupBox" name="groupBox">
 
            <property name="title">
 
             <string>Number Format:</string>
 
            </property>
 
            <layout class="QGridLayout" name="gridLayout_2">
 
             <item row="2" column="0">
 
              <widget class="QRadioButton" name="rbUint32">
 
               <property name="toolTip">
 
                <string>unsigned 4 bytes integer</string>
 
               </property>
 
               <property name="text">
 
                <string>uint32</string>
 
               </property>
 
              </widget>
 
             </item>
 
             <item row="0" column="1">
 
              <widget class="QRadioButton" name="rbInt8">
 
               <property name="toolTip">
 
                <string>signed 1 byte integer</string>
 
               </property>
 
               <property name="text">
 
                <string>int8</string>
 
               </property>
 
              </widget>
 
             </item>
 
             <item row="0" column="0">
 
              <widget class="QRadioButton" name="rbUint8">
 
               <property name="toolTip">
 
                <string>unsigned 1 byte integer</string>
 
               </property>
 
               <property name="text">
 
                <string>uint8</string>
 
               </property>
 
               <property name="checked">
 
                <bool>true</bool>
 
               </property>
 
              </widget>
 
             </item>
 
             <item row="3" column="1">
 
              <widget class="QRadioButton" name="rbASCII">
 
               <property name="toolTip">
 
                <string>Comma Separated Values</string>
 
               </property>
 
               <property name="text">
 
                <string>ASCII(CSV)</string>
 
               </property>
 
              </widget>
 
             </item>
 
             <item row="1" column="1">
 
              <widget class="QRadioButton" name="rbInt16">
 
               <property name="toolTip">
 
                <string>signed 2 bytes integer</string>
 
               </property>
 
               <property name="text">
 
                <string>int16</string>
 
               </property>
 
              </widget>
 
             </item>
 
             <item row="2" column="1">
 
              <widget class="QRadioButton" name="rbInt32">
 
               <property name="toolTip">
 
                <string>signed 4 bytes integer</string>
 
               </property>
 
               <property name="text">
 
                <string>int32</string>
 
               </property>
 
              </widget>
 
             </item>
 
             <item row="3" column="0">
 
              <widget class="QRadioButton" name="rbFloat">
 
               <property name="toolTip">
 
                <string>4 bytes floating point number</string>
 
               </property>
 
               <property name="text">
 
                <string>float</string>
 
               </property>
 
              </widget>
 
             </item>
 
             <item row="1" column="0">
 
              <widget class="QRadioButton" name="rbUint16">
 
               <property name="toolTip">
 
                <string>unsigned 2 bytes integer</string>
 
               </property>
 
               <property name="text">
 
                <string>uint16</string>
 
               </property>
 
              </widget>
 
             </item>
 
            </layout>
 
           </widget>
 
          </item>
 
          <item>
 
           <spacer name="verticalSpacer_2">
 
            <property name="orientation">
 
             <enum>Qt::Vertical</enum>
 
            </property>
 
            <property name="sizeHint" stdset="0">
 
             <size>
 
              <width>20</width>
 
              <height>1</height>
 
             </size>
 
            </property>
 
           </spacer>
 
          </item>
 
         </layout>
 
        </item>
 
        <item>
 
         <layout class="QVBoxLayout" name="verticalLayout_4">
 
          <property name="leftMargin">
 
           <number>0</number>
 
          </property>
 
          <item>
 
           <widget class="QGroupBox" name="groupBox_2">
 
            <property name="sizePolicy">
 
             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
 
              <horstretch>0</horstretch>
 
              <verstretch>0</verstretch>
 
             </sizepolicy>
 
            </property>
 
            <property name="title">
 
             <string>Byte Order:</string>
 
            </property>
 
            <layout class="QVBoxLayout" name="verticalLayout">
 
             <item>
 
              <widget class="QRadioButton" name="rbLittleE">
 
               <property name="toolTip">
 
                <string>least significant byte first</string>
 
               </property>
 
               <property name="text">
 
                <string>Little Endian</string>
 
               </property>
 
               <property name="checked">
 
                <bool>true</bool>
 
               </property>
 
              </widget>
 
             </item>
 
             <item>
 
              <widget class="QRadioButton" name="rbBigE">
 
               <property name="toolTip">
 
                <string>most significant byte first</string>
 
               </property>
 
               <property name="text">
 
                <string>Big Endian</string>
 
               </property>
 
              </widget>
 
             </item>
 
            </layout>
 
           </widget>
 
          </item>
 
          <item>
 
           <spacer name="verticalSpacer">
 
            <property name="orientation">
 
             <enum>Qt::Vertical</enum>
 
            </property>
 
            <property name="sizeHint" stdset="0">
 
             <size>
 
              <width>20</width>
 
              <height>1</height>
 
             </size>
 
            </property>
 
           </spacer>
 
          </item>
 
         </layout>
 
        </item>
 
        <item>
 
@@ -274,55 +301,61 @@
 
        </item>
 
        <item>
 
         <widget class="Line" name="line">
 
          <property name="orientation">
 
           <enum>Qt::Vertical</enum>
 
          </property>
 
         </widget>
 
        </item>
 
        <item>
 
         <layout class="QFormLayout" name="formLayout_2">
 
          <property name="fieldGrowthPolicy">
 
           <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
 
          </property>
 
          <item row="3" column="1">
 
           <widget class="QDoubleSpinBox" name="spYmin">
 
            <property name="enabled">
 
             <bool>false</bool>
 
            </property>
 
            <property name="maximumSize">
 
             <size>
 
              <width>75</width>
 
              <height>16777215</height>
 
             </size>
 
            </property>
 
            <property name="toolTip">
 
             <string>lower limit of Y axis</string>
 
            </property>
 
            <property name="value">
 
             <double>0.000000000000000</double>
 
            </property>
 
           </widget>
 
          </item>
 
          <item row="0" column="1">
 
           <widget class="QSpinBox" name="spNumOfSamples">
 
            <property name="toolTip">
 
             <string>length of X axis</string>
 
            </property>
 
            <property name="keyboardTracking">
 
             <bool>false</bool>
 
            </property>
 
            <property name="minimum">
 
             <number>2</number>
 
            </property>
 
            <property name="maximum">
 
             <number>10000</number>
 
            </property>
 
            <property name="value">
 
             <number>1000</number>
 
            </property>
 
           </widget>
 
          </item>
 
          <item row="0" column="0">
 
           <widget class="QLabel" name="label_3">
 
            <property name="text">
 
             <string>Number Of Samples:</string>
 
            </property>
 
           </widget>
 
          </item>
 
          <item row="1" column="0">
 
           <widget class="QCheckBox" name="cbAutoScale">
 
            <property name="text">
 
@@ -343,48 +376,51 @@
 
            </property>
 
           </widget>
 
          </item>
 
          <item row="2" column="0">
 
           <widget class="QLabel" name="lYmax">
 
            <property name="enabled">
 
             <bool>false</bool>
 
            </property>
 
            <property name="text">
 
             <string>Ymax</string>
 
            </property>
 
           </widget>
 
          </item>
 
          <item row="2" column="1">
 
           <widget class="QDoubleSpinBox" name="spYmax">
 
            <property name="enabled">
 
             <bool>false</bool>
 
            </property>
 
            <property name="maximumSize">
 
             <size>
 
              <width>75</width>
 
              <height>16777215</height>
 
             </size>
 
            </property>
 
            <property name="toolTip">
 
             <string>upper limit of Y axis</string>
 
            </property>
 
            <property name="maximum">
 
             <double>1000.000000000000000</double>
 
            </property>
 
            <property name="value">
 
             <double>1000.000000000000000</double>
 
            </property>
 
           </widget>
 
          </item>
 
         </layout>
 
        </item>
 
       </layout>
 
      </widget>
 
      <widget class="QWidget" name="tabTextView">
 
       <attribute name="title">
 
        <string>Text View</string>
 
       </attribute>
 
       <layout class="QHBoxLayout" name="horizontalLayout_2">
 
        <property name="leftMargin">
 
         <number>4</number>
 
        </property>
 
        <property name="topMargin">
 
         <number>4</number>
 
        </property>
 
        <property name="rightMargin">
 
@@ -471,48 +507,50 @@
 
    </item>
 
   </layout>
 
  </widget>
 
  <widget class="QMenuBar" name="menuBar">
 
   <property name="geometry">
 
    <rect>
 
     <x>0</x>
 
     <y>0</y>
 
     <width>653</width>
 
     <height>23</height>
 
    </rect>
 
   </property>
 
   <widget class="QMenu" name="menuHelp">
 
    <property name="title">
 
     <string>Help</string>
 
    </property>
 
    <addaction name="actionDemoMode"/>
 
    <addaction name="actionHelpAbout"/>
 
   </widget>
 
   <widget class="QMenu" name="menuFile">
 
    <property name="title">
 
     <string>File</string>
 
    </property>
 
    <addaction name="actionExportCsv"/>
 
    <addaction name="separator"/>
 
    <addaction name="actionQuit"/>
 
   </widget>
 
   <addaction name="menuFile"/>
 
   <addaction name="menuHelp"/>
 
  </widget>
 
  <widget class="QToolBar" name="mainToolBar">
 
   <attribute name="toolBarArea">
 
    <enum>TopToolBarArea</enum>
 
   </attribute>
 
   <attribute name="toolBarBreak">
 
    <bool>false</bool>
 
   </attribute>
 
   <addaction name="actionPause"/>
 
   <addaction name="actionClear"/>
 
  </widget>
 
  <widget class="QStatusBar" name="statusBar"/>
 
  <action name="actionPause">
 
   <property name="checkable">
 
    <bool>true</bool>
 
   </property>
 
   <property name="checked">
 
    <bool>false</bool>
 
   </property>
 
   <property name="text">
 
    <string>Pause</string>
 
@@ -529,37 +567,45 @@
 
  <action name="actionHelpAbout">
 
   <property name="text">
 
    <string>About</string>
 
   </property>
 
  </action>
 
  <action name="actionDemoMode">
 
   <property name="checkable">
 
    <bool>true</bool>
 
   </property>
 
   <property name="text">
 
    <string>Demo Mode</string>
 
   </property>
 
   <property name="toolTip">
 
    <string>Toggle Demo Mode</string>
 
   </property>
 
  </action>
 
  <action name="actionExportCsv">
 
   <property name="text">
 
    <string>Export CSV</string>
 
   </property>
 
   <property name="toolTip">
 
    <string>Export plot data to CSV</string>
 
   </property>
 
  </action>
 
  <action name="actionQuit">
 
   <property name="text">
 
    <string>Quit</string>
 
   </property>
 
   <property name="shortcut">
 
    <string>Ctrl+Q</string>
 
   </property>
 
  </action>
 
 </widget>
 
 <layoutdefault spacing="6" margin="11"/>
 
 <customwidgets>
 
  <customwidget>
 
   <class>QwtPlot</class>
 
   <extends>QFrame</extends>
 
   <header>qwt_plot.h</header>
 
   <container>1</container>
 
  </customwidget>
 
 </customwidgets>
 
 <resources/>
 
 <connections/>
 
</ui>
misc/pseudo_device.py
Show inline comments
 
@@ -40,41 +40,51 @@ def ascii_test(port):
 
        time.sleep(0.1)
 

	
 
def float_test(port):
 
    """Put 32-bit float test data through pseudo terminal"""
 
    for i in range(0, 1000):
 
        f = float(i)/3.0
 
        data = struct.pack('f', f)
 
        os.write(port, data)
 
        import binascii
 
        time.sleep(0.1)
 

	
 
def float_sine(port):
 
    """Puts 2 channel sine and cosine wafeform through pseudo terminal
 
    continuously."""
 
    i = 0
 
    period = 200
 
    while True:
 
        sin = math.sin(2 * math.pi * i / period)
 
        # cos = math.sin(2 * math.pi * (i / period + 1 / 4))
 
        data = struct.pack('ff', sin, -sin)
 
        os.write(port, data)
 
        i = (i + 1) % period
 
        time.sleep(0.1)
 

	
 
def uint32_test(port, little):
 
    """Puts 32 bit unsigned integer data through pseudo terminal"""
 
    i = 0
 
    maxi = 200
 
    while True:
 
        data = struct.pack('>I', i)
 
        os.write(port, data)
 
        time.sleep(0.05)
 
        i = i+1 if i <= maxi else 0
 

	
 
def run():
 
    # create the pseudo terminal
 
    master, slave = pty.openpty()
 

	
 
    master_name = os.ttyname(master)
 
    slave_name = os.ttyname(slave)
 
    print("Master terminal: {}\nSlave terminal: {}".format(master_name, slave_name))
 

	
 
    try:
 
        float_sine(master)
 
    finally:
 
        # close the pseudo terminal files
 
        os.close(master)
 
        os.close(slave)
 

	
 
if __name__=="__main__":
 
    run()
misc/serialplot.bmp
Show inline comments
 
new file 100644
 
binary diff not shown
Show images
misc/serialplot.ico
Show inline comments
 
new file 100644
 
binary diff not shown
misc/windows_icon.rc
Show inline comments
 
new file 100644
 
IDI_ICON1               ICON    DISCARDABLE     "serialplot.ico"
 
\ No newline at end of file
portcontrol.ui
Show inline comments
 
@@ -48,48 +48,51 @@
 
         </property>
 
        </widget>
 
       </item>
 
       <item row="1" column="0">
 
        <widget class="QLabel" name="label_2">
 
         <property name="text">
 
          <string>Baud Rate:</string>
 
         </property>
 
        </widget>
 
       </item>
 
       <item row="0" column="2">
 
        <widget class="QPushButton" name="pbReloadPorts">
 
         <property name="sizePolicy">
 
          <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
 
           <horstretch>0</horstretch>
 
           <verstretch>0</verstretch>
 
          </sizepolicy>
 
         </property>
 
         <property name="maximumSize">
 
          <size>
 
           <width>30</width>
 
           <height>16777215</height>
 
          </size>
 
         </property>
 
         <property name="toolTip">
 
          <string>Reload port list</string>
 
         </property>
 
         <property name="text">
 
          <string>↺</string>
 
         </property>
 
        </widget>
 
       </item>
 
      </layout>
 
     </item>
 
     <item>
 
      <layout class="QHBoxLayout" name="horizontalLayout_2">
 
       <item>
 
        <widget class="QFrame" name="frame">
 
         <property name="frameShape">
 
          <enum>QFrame::NoFrame</enum>
 
         </property>
 
         <layout class="QVBoxLayout" name="verticalLayout_5">
 
          <item>
 
           <widget class="QRadioButton" name="rbNoParity">
 
            <property name="text">
 
             <string>No Parity</string>
 
            </property>
 
            <property name="checked">
 
             <bool>true</bool>
 
            </property>
 
           </widget>
 
@@ -259,58 +262,64 @@
 
   </item>
 
   <item>
 
    <spacer name="horizontalSpacer">
 
     <property name="orientation">
 
      <enum>Qt::Horizontal</enum>
 
     </property>
 
     <property name="sizeHint" stdset="0">
 
      <size>
 
       <width>10000</width>
 
       <height>20</height>
 
      </size>
 
     </property>
 
    </spacer>
 
   </item>
 
   <item>
 
    <layout class="QVBoxLayout" name="verticalLayout_4">
 
     <item>
 
      <widget class="CustomCheckableButton" name="pbOpenPort">
 
       <property name="minimumSize">
 
        <size>
 
         <width>0</width>
 
         <height>50</height>
 
        </size>
 
       </property>
 
       <property name="toolTip">
 
        <string>Toggle port status</string>
 
       </property>
 
       <property name="text">
 
        <string>Open</string>
 
       </property>
 
       <property name="checkable">
 
        <bool>true</bool>
 
       </property>
 
      </widget>
 
     </item>
 
     <item>
 
      <widget class="QPushButton" name="pbSkipByte">
 
       <property name="toolTip">
 
        <string>Skip reading 1 byte to correct the alignment</string>
 
       </property>
 
       <property name="text">
 
        <string>Skip Byte</string>
 
       </property>
 
      </widget>
 
     </item>
 
     <item>
 
      <spacer name="verticalSpacer">
 
       <property name="orientation">
 
        <enum>Qt::Vertical</enum>
 
       </property>
 
       <property name="sizeHint" stdset="0">
 
        <size>
 
         <width>20</width>
 
         <height>40</height>
 
        </size>
 
       </property>
 
      </spacer>
 
     </item>
 
    </layout>
 
   </item>
 
  </layout>
 
 </widget>
 
 <customwidgets>
 
  <customwidget>
0 comments (0 inline, 0 general)