/*
* Unofficial Qt Serial Port Library
*
* Copyright (c) 2010 Inbiza Systems Inc. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program 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 Lesser General Public License
* along with this program. If not, see
*
* author labs@inbiza.com
*/
#include
#include
#include
#include
#include
#include
#include
#include "transmitter.h"
TNX::QSerialPort defaultSerPort("", "9600, 8, N, 1");
int Transmitter::DataSetSizes[] = { 4096, 4096*3, 4096*5, 4096*8 };
char Transmitter::PortSettingsToTest[][30] = { "4800,7,O,2", "38400,8,N,1", "9600,8,N,1", "19200,8,N,1", "57600,8,N,1", "115200,8,N,1",
"4800,7,O,2", "38400,8,N,1", "9600,7,O,2", "19200,7,O,2", "57600,7,O,2", "115200,7,O,2",
"4800,7,O,2", "38400,8,N,1", "9600,7,E,1", "19200,7,E,1", "57600,7,E,1", "115200,7,E,1",
"4800,7,O,2", "38400,8,N,1", "9600,7,N,1", "19200,7,N,1", "57600,7,N,1", "115200,7,N,1",
"4800,7,O,2", "38400,8,N,1", "9600,8,E,1", "19200,8,E,1", "57600,8,E,1", "115200,8,E,1"
};
Transmitter::Transmitter(QObject *parent)
: QObject(parent), serialPort_(defaultSerPort), transmitTimer_(0), commTestCounter_(0),
dataSetCounter_(0), signalTestCounter_(0), dataSet_(NULL), test_(DataTransferTest)
{
#if defined(Q_OS_WIN)
serialPort_.setPortName("COM3");
#else
serialPort_.setPortName("/dev/ttyS0");
#endif
socket_ = new QUdpSocket(this);
listenPort_ = 7865;
udpPortNo_ = 7865;
udpIp_ = "193.168.0.52";
}
Transmitter::Transmitter(TNX::QSerialPort &serPort, const QString &udpAddr, int listenPort, QObject *parent)
: QObject(parent), serialPort_(serPort), listenPort_(listenPort), transmitTimer_(0), commTestCounter_(0),
dataSetCounter_(0), signalTestCounter_(0), dataSet_(NULL), test_(DataTransferTest)
{
if ( udpAddr.split(":").count() > 1 ) {
udpIp_ = udpAddr.split(":").at(0);
udpPortNo_ = udpAddr.split(":").at(1).toInt();
}
else {
udpPortNo_ = udpAddr.toInt();
}
socket_ = new QUdpSocket(this);
}
Transmitter::~Transmitter()
{
}
bool Transmitter::start()
{
test_ = DataTransferTest;
if ( !socket_->open(QIODevice::ReadWrite) )
qFatal("Cannot open UDP port: \"%d\". Giving up.", udpPortNo_);
connect(socket_, SIGNAL(readyRead()), SLOT(onControlDataReceived()));
if ( !socket_->bind(listenPort_) )
qFatal("Cannot bind to port: \"%d\". Giving up.", listenPort_);
if ( !serialPort_.open() )
qFatal("Cannot open serial port: \"%s\". Giving up.", qPrintable(serialPort_.errorString()));
else {
serialPort_.flushInBuffer();
serialPort_.flushOutBuffer();
}
qDebug() << "Getting ready for transmitting data via " << serialPort_.portName();
qDebug() << "Control channel @ UDP port " << udpPortNo_;
transmitTimer_ = startTimer(0);
return true;
}
bool Transmitter::stop()
{
disconnect(socket_, SIGNAL(readyRead()), this, SLOT(onControlDataReceived()));
socket_->close();
if ( !serialPort_.isOpen() ) {
return true;
}
else {
qDebug() << "Number of bytes in serial port buffer: " << serialPort_.bytesAvailable();
delete[] dataSet_;
dataSet_ = NULL;
if ( transmitTimer_ != 0 ) {
killTimer(transmitTimer_);
transmitTimer_ = 0;
}
disconnect(&serialPort_, SIGNAL(readyRead()), this, SLOT(onDataReceived()));
serialPort_.close();
}
return true;
}
void Transmitter::timerEvent(QTimerEvent *event)
{
killTimer(event->timerId());
// make sure that we don't leak timer
Q_ASSERT( event->timerId() == transmitTimer_ );
if ( test_ == DataTransferTest ) {
lastDataSize_ = DataSetSizes[dataSetCounter_ % kTotalDataSetCount];
dataSet_ = new char[lastDataSize_];
Q_CHECK_PTR(dataSet_);
for (int i = 0; i < lastDataSize_; i++)
dataSet_[i] = (char)(i % 64);
lastSettings_ = PortSettingsToTest[commTestCounter_++];
serialPort_.setPortSettings(lastSettings_);
socket_->writeDatagram(QString("SEND_START@%1@%2").arg(lastDataSize_).arg(lastSettings_).toLatin1(), QHostAddress(udpIp_), udpPortNo_);
}
else if ( test_ == SignalTest ) {
if ( signalTestCounter_ >= kNumOfSignalsToTest ) {
socket_->writeDatagram("TEST___END", QHostAddress(udpIp_), udpPortNo_);
test_ = DoneTesting;
std::cout << "..........TEST IS COMPLETED.........." << std::endl;
qApp->exit(0);
}
else {
// Signal test
QString msg;
switch ( signalTestCounter_++ ) {
case 0: msg = "SIG_CTS_RQ"; break;
case 1: msg = "SIG_DSR_RQ"; break;
case 2: msg = "SIG_DCD_RQ"; break;
case 3: msg = "SIG_RI__RQ"; break;
}
socket_->writeDatagram(msg.toAscii(), QHostAddress(udpIp_), udpPortNo_);
}
}
}
void Transmitter::onControlDataReceived()
{
using TNX::QSerialPort;
QByteArray recv = socket_->read(1000);
if ( recv.left(10) == "RECV___END" ) {
if ( commTestCounter_ >= kTotalPortSetTestCount ) {
commTestCounter_ = 0;
dataSetCounter_++;
}
delete[] dataSet_;
qDebug() << recv.right(recv.size()-11) << "[" << serialPort_.portSettings().toString() << "]";
if ( dataSetCounter_ >= kTotalDataSetCount ) {
dataSetCounter_ = 0;
test_ = SignalTest;
// tell other party to get ready for signal test
socket_->writeDatagram("SIG_TEST_S", QHostAddress(udpIp_), udpPortNo_);
}
else {
// continue to test data transmission
transmitTimer_ = startTimer(0);
}
}
else if ( recv.left(10) == "RECV_USSET" ) {
// Port settings are not supported by the receiver
qDebug() << "Receiver doesn't support the given settings: " << lastSettings_ << ". Continuing to test with the next settings.";
transmitTimer_ = startTimer(0);
}
else if ( recv.left(10) == "RECV_READY" ) {
serialPort_.write(dataSet_, lastDataSize_);
socket_->writeDatagram("SEND___END", QHostAddress(udpIp_), udpPortNo_);
}
else if ( recv.left(10) == "SIG_CTS___" ) {
QSerialPort::CommSignalValues value = recv.right(recv.size() - 11) == "ON" ? QSerialPort::Signal_On : QSerialPort::Signal_Off;
qDebug() << "Receiver's CTS line: " << sigValToString (value) << "| Expected value: ON";
transmitTimer_ = startTimer(0);
}
else if ( recv.left(10) == "SIG_DSR___" ) {
QSerialPort::CommSignalValues value = recv.right(recv.size() - 11) == "ON" ? QSerialPort::Signal_On : QSerialPort::Signal_Off;
qDebug() << "Receiver's DSR line: " << sigValToString (value) << "| Expected value: ON";
transmitTimer_ = startTimer(0);
}
else if ( recv.left(10) == "SIG_DCD___" ) {
QSerialPort::CommSignalValues value = recv.right(recv.size() - 11) == "ON" ? QSerialPort::Signal_On : QSerialPort::Signal_Off;
qDebug() << "Receiver's DCD line: " << sigValToString (value) << "| Transmitter's DCD line: " << sigValToString(serialPort_.dcd());
transmitTimer_ = startTimer(0);
}
else if ( recv.left(10) == "SIG_RI____" ) {
QSerialPort::CommSignalValues value = recv.right(recv.size() - 11) == "ON" ? QSerialPort::Signal_On : QSerialPort::Signal_Off;
qDebug() << "Receiver's RI line: " << sigValToString (value) << "| Transmitter's RI line: " << sigValToString(serialPort_.ri());
transmitTimer_ = startTimer(0);
}
// ready for signal test
else if ( recv.left(10) == "SIG_TEST_R" ) {
serialPort_.setRts(true);
serialPort_.setDtr(true);
qDebug() << "Setting transmitter's RTS and DTR lines to ON";
transmitTimer_ = startTimer(0);
}
}
void Transmitter::onDataReceived()
{
std::cout << "Received data when expecting nothing. Interesting." << std::endl;
}