Skip to content
SerialLink.cc 21.6 KiB
Newer Older
pixhawk's avatar
pixhawk committed
/*=====================================================================
======================================================================*/
/**
 * @file
 *   @brief Cross-platform support for serial ports
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <QTimer>
#include <QDebug>
#include <QSettings>
pixhawk's avatar
pixhawk committed
#include <QMutexLocker>
#include "SerialLink.h"
#include "LinkManager.h"
#include "QGC.h"
pixhawk's avatar
pixhawk committed
#include <MG.h>
#include <iostream>
pixhawk's avatar
pixhawk committed
#ifdef _WIN32
#include "windows.h"
#endif


SerialLink::SerialLink(QString portname, BaudRateType baudrate, FlowType flow, ParityType parity, DataBitsType dataBits, StopBitsType stopBits) :
        port(NULL)
pixhawk's avatar
pixhawk committed
{
    // Setup settings
    this->porthandle = portname.trimmed();
#ifdef _WIN32
    // Port names above 20 need the network path format - if the port name is not already in this format
    // catch this special case
    if (this->porthandle.size() > 0 && !this->porthandle.startsWith("\\"))
    {
        // Append \\.\ before the port handle. Additional backslashes are used for escaping.
        this->porthandle = "\\\\.\\" + this->porthandle;
    }
#endif
    // Set unique ID and add link to the list of links
    this->id = getNextLinkId();
lm's avatar
lm committed
    // *nix (Linux, MacOS tested) serial port support
//    port = new QextSerialPort(porthandle, QextSerialPort::Polling);
lm's avatar
lm committed
    //port = new QextSerialPort(porthandle, QextSerialPort::EventDriven);

    this->baudrate = baudrate;
    this->flow = flow;
    this->parity = parity;
    this->dataBits = dataBits;
    this->stopBits = stopBits;
    this->timeout = 1; ///< The timeout controls how long the program flow should wait for new serial bytes. As we're polling, we don't want to wait at all.
//    port->setTimeout(timeout); // Timeout of 0 ms, we don't want to wait for data, we just poll again next time
//    port->setBaudRate(baudrate);
//    port->setFlowControl(flow);
//    port->setParity(parity);
//    port->setDataBits(dataBits);
//    port->setStopBits(stopBits);
pixhawk's avatar
pixhawk committed

    // Set the port name
    if (porthandle == "")
    {
        //        name = tr("serial link ") + QString::number(getId()) + tr(" (unconfigured)");
        name = tr("Serial Link ") + QString::number(getId());
pixhawk's avatar
pixhawk committed
    }
    else
    {
        name = portname.trimmed();
    }

#ifdef _WIN3232
    // Windows 32bit & 64bit serial connection
    winPort = CreateFile(porthandle,
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         0,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         0);
    if(winPort==INVALID_HANDLE_VALUE){
        if(GetLastError()==ERROR_FILE_NOT_FOUND){
            //serial port does not exist. Inform user.
        }
        //some other error occurred. Inform user.
    }
#else
lm's avatar
lm committed

pixhawk's avatar
pixhawk committed
#endif

lm's avatar
lm committed
    loadSettings();

pixhawk's avatar
pixhawk committed
    // Link is setup, register it with link manager
    LinkManager::instance()->add(this);
}

SerialLink::~SerialLink()
{
    disconnect();
    if(port) delete port;
pixhawk's avatar
pixhawk committed
    port = NULL;
}

void SerialLink::loadSettings()
{
    // Load defaults from settings
    QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
    settings.sync();
    if (settings.contains("SERIALLINK_COMM_PORT"))
    {
        setPortName(settings.value("SERIALLINK_COMM_PORT").toString());
        setBaudRateType(settings.value("SERIALLINK_COMM_BAUD").toInt());
        setParityType(settings.value("SERIALLINK_COMM_PARITY").toInt());
        setStopBits(settings.value("SERIALLINK_COMM_STOPBITS").toInt());
        setDataBits(settings.value("SERIALLINK_COMM_DATABITS").toInt());
        setFlowType(settings.value("SERIALLINK_COMM_FLOW_CONTROL").toInt());
    }
}

void SerialLink::writeSettings()
{
    // Store settings
    QSettings settings(QGC::COMPANYNAME, QGC::APPNAME);
    settings.setValue("SERIALLINK_COMM_PORT", this->porthandle);
    settings.setValue("SERIALLINK_COMM_BAUD", getBaudRateType());
    settings.setValue("SERIALLINK_COMM_PARITY", getParityType());
    settings.setValue("SERIALLINK_COMM_STOPBITS", getStopBits());
    settings.setValue("SERIALLINK_COMM_DATABITS", getDataBits());
    settings.setValue("SERIALLINK_COMM_FLOW_CONTROL", getFlowType());
pixhawk's avatar
pixhawk committed

/**
 * @brief Runs the thread
 *
 **/
pixhawk's avatar
pixhawk committed
    // Initialize the connection
    hardwareConnect();

    // Qt way to make clear what a while(1) loop does
pixhawk's avatar
pixhawk committed
        // Check if new bytes have arrived, if yes, emit the notification signal
        checkForBytes();
        /* Serial data isn't arriving that fast normally, this saves the thread
                 * from consuming too much processing time
                 */
        MG::SLEEP::msleep(SerialLink::poll_interval);
    }
}


pixhawk's avatar
pixhawk committed
    /* Check if bytes are available */
pixhawk's avatar
pixhawk committed
        dataMutex.lock();
        qint64 available = port->bytesAvailable();
        dataMutex.unlock();

pixhawk's avatar
pixhawk committed
        }
pixhawk's avatar
pixhawk committed
        emit disconnected();
    }

}


void SerialLink::writeBytes(const char* data, qint64 size)
{
pixhawk's avatar
pixhawk committed
    {
pixhawk's avatar
pixhawk committed
        int b = port->write(data, size);
        qDebug() << "Serial link " << this->getName() << "transmitted" << b << "bytes:";
pixhawk's avatar
pixhawk committed

pixhawk's avatar
pixhawk committed
        // Increase write counter
pixhawk's avatar
pixhawk committed
        bitsSentTotal += size * 8;

        //        int i;
        //        for (i=0; i<size; i++)
        //        {
        //            unsigned char v=data[i];
pixhawk's avatar
pixhawk committed

        //            //fprintf(stderr,"%02x ", v);
        //        }
pixhawk's avatar
pixhawk committed
    }
}

/**
 * @brief Read a number of bytes from the interface.
 *
 * @param data Pointer to the data byte array to write the bytes to
 * @param maxLength The maximum number of bytes to write
Loading
Loading full blame...