SerialConfigurationWindow.cc 8.97 KB
Newer Older
pixhawk's avatar
pixhawk committed
1 2
/*=====================================================================

3
QGroundControl Open Source Ground Control Station
pixhawk's avatar
pixhawk committed
4

5
(c) 2009, 2010 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
pixhawk's avatar
pixhawk committed
6

7
This file is part of the QGROUNDCONTROL project
pixhawk's avatar
pixhawk committed
8

9
    QGROUNDCONTROL is free software: you can redistribute it and/or modify
pixhawk's avatar
pixhawk committed
10 11 12 13
    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.

14
    QGROUNDCONTROL is distributed in the hope that it will be useful,
pixhawk's avatar
pixhawk committed
15 16 17 18 19
    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
20
    along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
pixhawk's avatar
pixhawk committed
21 22 23 24 25

======================================================================*/

/**
 * @file
lm's avatar
lm committed
26
 *   @brief Implementation of SerialConfigurationWindow
pixhawk's avatar
pixhawk committed
27 28 29 30 31
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
 *
 */

#include <QDir>
32
#include <QSettings>
pixhawk's avatar
pixhawk committed
33
#include <QFileInfoList>
34
#include <QDebug>
dogmaphobic's avatar
dogmaphobic committed
35 36 37 38

#ifdef __android__
#include "qserialportinfo.h"
#else
39
#include <QSerialPortInfo>
dogmaphobic's avatar
dogmaphobic committed
40
#endif
pixhawk's avatar
pixhawk committed
41

42 43
#include <SerialConfigurationWindow.h>
#include <SerialLink.h>
Bryant's avatar
Bryant committed
44

45 46 47
#ifndef USE_ANCIENT_RATES
#define USE_ANCIENT_RATES 0
#endif
pixhawk's avatar
pixhawk committed
48

49 50 51 52 53 54
SerialConfigurationWindow::SerialConfigurationWindow(SerialConfiguration *config, QWidget *parent, Qt::WindowFlags flags)
    : QWidget(parent, flags)
{
    _ui.setupUi(this);
    Q_ASSERT(config != NULL);
    _config = config;
pixhawk's avatar
pixhawk committed
55

56 57 58 59
    // Scan for serial ports. Let the user know if none were found for debugging purposes
    if (!setupPortList()) {
        qDebug() << "No serial ports found.";
    }
60

61 62
    // Set up baud rates
    _ui.baudRate->clear();
63

64 65 66
    // Keep track of all desired baud rates by OS. These are iterated through
    // later and added to _ui.baudRate.
    QList<int> supportedBaudRates;
67

68 69
#if USE_ANCIENT_RATES
    // Baud rates supported only by POSIX systems
70
#if defined(Q_OS_UNIX) || defined(Q_OS_LINUX) || defined(Q_OS_DARWIN)
71 72 73 74 75 76
    supportedBaudRates << 50;
    supportedBaudRates << 75;
    supportedBaudRates << 134;
    supportedBaudRates << 150;
    supportedBaudRates << 200;
    supportedBaudRates << 1800;
77
#endif
78
#endif //USE_ANCIENT_RATES
79

80
    // Baud rates supported only by Windows
81
#if defined(Q_OS_WIN)
82 83 84 85
    supportedBaudRates << 14400;
    supportedBaudRates << 56000;
    supportedBaudRates << 128000;
    supportedBaudRates << 256000;
86
#endif
87

88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
    // Baud rates supported by everyone
#if USE_ANCIENT_RATES
    supportedBaudRates << 110;
    supportedBaudRates << 300;
    supportedBaudRates << 600;
    supportedBaudRates << 1200;
#endif //USE_ANCIENT_RATES
    supportedBaudRates << 2400;
    supportedBaudRates << 4800;
    supportedBaudRates << 9600;
    supportedBaudRates << 19200;
    supportedBaudRates << 38400;
    supportedBaudRates << 57600;
    supportedBaudRates << 115200;
    supportedBaudRates << 230400;
    supportedBaudRates << 460800;
104 105

#if defined(Q_OS_LINUX)
106 107 108
    // Baud rates supported only by Linux
    supportedBaudRates << 500000;
    supportedBaudRates << 576000;
109 110
#endif

111
    supportedBaudRates << 921600;
pixhawk's avatar
pixhawk committed
112

113 114 115 116 117
    // Now actually add all of our supported baud rates to the ui.
    qSort(supportedBaudRates.begin(), supportedBaudRates.end());
    for (int i = 0; i < supportedBaudRates.size(); ++i) {
        _ui.baudRate->addItem(QString::number(supportedBaudRates.at(i)), supportedBaudRates.at(i));
    }
pixhawk's avatar
pixhawk committed
118

119
    // Connect the individual user interface inputs
120 121 122 123 124 125 126 127 128
    connect(_ui.portName,           SIGNAL(currentIndexChanged(int)), this,  SLOT(setPortName(int)));
    connect(_ui.baudRate,           SIGNAL(activated(int)), this,            SLOT(setBaudRate(int)));
    connect(_ui.flowControlCheckBox,SIGNAL(toggled(bool)), this,             SLOT(enableFlowControl(bool)));
    connect(_ui.parNone,            SIGNAL(toggled(bool)), this,             SLOT(setParityNone(bool)));
    connect(_ui.parOdd,             SIGNAL(toggled(bool)), this,             SLOT(setParityOdd(bool)));
    connect(_ui.parEven,            SIGNAL(toggled(bool)), this,             SLOT(setParityEven(bool)));
    connect(_ui.dataBitsSpinBox,    SIGNAL(valueChanged(int)), this,         SLOT(setDataBits(int)));
    connect(_ui.stopBitsSpinBox,    SIGNAL(valueChanged(int)), this,         SLOT(setStopBits(int)));
    connect(_ui.advCheckBox,        SIGNAL(clicked(bool)), _ui.advGroupBox,  SLOT(setVisible(bool)));
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149

    _ui.advCheckBox->setCheckable(true);
    _ui.advCheckBox->setChecked(false);
    _ui.advGroupBox->setVisible(false);

    switch(_config->parity()) {
    case QSerialPort::NoParity:
        _ui.parNone->setChecked(true);
        break;
    case QSerialPort::OddParity:
        _ui.parOdd->setChecked(true);
        break;
    case QSerialPort::EvenParity:
        _ui.parEven->setChecked(true);
        break;
    default:
        // Enforce default: no parity in link
        setParityNone(true);
        _ui.parNone->setChecked(true);
        break;
    }
pixhawk's avatar
pixhawk committed
150

151 152 153 154 155 156 157 158 159 160 161
    int idx = 0;
    _ui.flowControlCheckBox->setChecked(_config->flowControl() == QSerialPort::HardwareControl);
    idx = _ui.baudRate->findText(QString("%1").arg(_config->baud()));
    if(idx < 0) idx = _ui.baudRate->findText("57600");
    if(idx < 0) idx = 0;
    _ui.baudRate->setCurrentIndex(idx);
    _ui.dataBitsSpinBox->setValue(_config->dataBits());
    _ui.stopBitsSpinBox->setValue(_config->stopBits());
    _portCheckTimer = new QTimer(this);
    _portCheckTimer->setInterval(1000);
    connect(_portCheckTimer, SIGNAL(timeout()), this, SLOT(setupPortList()));
pixhawk's avatar
pixhawk committed
162

163 164
    // Display the widget
    setWindowTitle(tr("Serial Communication Settings"));
pixhawk's avatar
pixhawk committed
165 166
}

167 168
SerialConfigurationWindow::~SerialConfigurationWindow()
{
pixhawk's avatar
pixhawk committed
169 170 171 172 173

}

void SerialConfigurationWindow::showEvent(QShowEvent* event)
{
174
    Q_UNUSED(event);
175
    _portCheckTimer->start();
pixhawk's avatar
pixhawk committed
176 177 178 179
}

void SerialConfigurationWindow::hideEvent(QHideEvent* event)
{
180
    Q_UNUSED(event);
181
    _portCheckTimer->stop();
pixhawk's avatar
pixhawk committed
182 183
}

184
bool SerialConfigurationWindow::setupPortList()
pixhawk's avatar
pixhawk committed
185
{
186 187 188 189
    bool changed = false;
    // Iterate found ports
    QList<QSerialPortInfo> portList = QSerialPortInfo::availablePorts();
    foreach (const QSerialPortInfo &info, portList)
190
    {
191 192 193
        QString name = info.portName();
        // Append newly found port to the list
        if (_ui.portName->findText(name) < 0)
194
        {
195 196 197
            // We show the user the "short name" but store the full port name
            _ui.portName->addItem(name, QVariant(info.systemLocation()));
            changed = true;
pixhawk's avatar
pixhawk committed
198 199
        }
    }
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
    // See if configured port (if any) is present
    if(changed) {
        int idx = _ui.portName->count() - 1;
        if(!_config->portName().isEmpty()) {
            idx = _ui.portName->findData(QVariant(_config->portName()));
            if(idx < 0) {
                idx = 0;
            }
        }
        _ui.portName->setCurrentIndex(idx);
        if(_ui.portName->count() > 0) {
            _ui.portName->setEditText(_ui.portName->itemText(idx));
        }
        if(_config->portName().isEmpty()) {
            setPortName(idx);
        }
    }
    return (_ui.portName->count() > 0);
pixhawk's avatar
pixhawk committed
218 219 220 221
}

void SerialConfigurationWindow::enableFlowControl(bool flow)
{
222
    _config->setFlowControl(flow ? QSerialPort::HardwareControl : QSerialPort::NoFlowControl);
dogmaphobic's avatar
dogmaphobic committed
223 224
    //-- If this was dynamic, it's now edited and persistent
    _config->setDynamic(false);
pixhawk's avatar
pixhawk committed
225 226
}

lm's avatar
lm committed
227
void SerialConfigurationWindow::setParityNone(bool accept)
pixhawk's avatar
pixhawk committed
228
{
dogmaphobic's avatar
dogmaphobic committed
229 230 231 232 233
    if (accept) {
        _config->setParity(QSerialPort::NoParity);
        //-- If this was dynamic, it's now edited and persistent
        _config->setDynamic(false);
    }
pixhawk's avatar
pixhawk committed
234 235
}

lm's avatar
lm committed
236
void SerialConfigurationWindow::setParityOdd(bool accept)
pixhawk's avatar
pixhawk committed
237
{
dogmaphobic's avatar
dogmaphobic committed
238 239 240 241 242
    if (accept) {
        _config->setParity(QSerialPort::OddParity);
        //-- If this was dynamic, it's now edited and persistent
        _config->setDynamic(false);
    }
pixhawk's avatar
pixhawk committed
243 244
}

lm's avatar
lm committed
245
void SerialConfigurationWindow::setParityEven(bool accept)
pixhawk's avatar
pixhawk committed
246
{
dogmaphobic's avatar
dogmaphobic committed
247 248 249 250 251
    if (accept) {
        _config->setParity(QSerialPort::EvenParity);
        //-- If this was dynamic, it's now edited and persistent
        _config->setDynamic(false);
    }
pixhawk's avatar
pixhawk committed
252 253
}

254
void SerialConfigurationWindow::setPortName(int index)
pixhawk's avatar
pixhawk committed
255
{
256 257 258 259
    // Get the full port name and store it in the config
    QString pname = _ui.portName->itemData(index).toString();
    if (_config->portName() != pname) {
        _config->setPortName(pname);
dogmaphobic's avatar
dogmaphobic committed
260 261
        //-- If this was dynamic, it's now edited and persistent
        _config->setDynamic(false);
pixhawk's avatar
pixhawk committed
262 263 264
    }
}

265
void SerialConfigurationWindow::setBaudRate(int index)
Bryant's avatar
Bryant committed
266
{
267 268
    int baud = _ui.baudRate->itemData(index).toInt();
    _config->setBaud(baud);
dogmaphobic's avatar
dogmaphobic committed
269 270
    //-- If this was dynamic, it's now edited and persistent
    _config->setDynamic(false);
Bryant's avatar
Bryant committed
271 272
}

273
void SerialConfigurationWindow::setDataBits(int bits)
Bryant's avatar
Bryant committed
274
{
275
    _config->setDataBits(bits);
dogmaphobic's avatar
dogmaphobic committed
276 277
    //-- If this was dynamic, it's now edited and persistent
    _config->setDynamic(false);
Bryant's avatar
Bryant committed
278 279
}

280
void SerialConfigurationWindow::setStopBits(int bits)
Bryant's avatar
Bryant committed
281
{
282
    _config->setStopBits(bits);
dogmaphobic's avatar
dogmaphobic committed
283 284
    //-- If this was dynamic, it's now edited and persistent
    _config->setDynamic(false);
Bryant's avatar
Bryant committed
285
}