Skip to content

Commit

Permalink
feat(simu): cross-platform connection of host serial ports to simu ra…
Browse files Browse the repository at this point in the history
…dio (#5584)
  • Loading branch information
nrw505 authored Dec 16, 2024
1 parent 8885016 commit 9109d4f
Show file tree
Hide file tree
Showing 22 changed files with 789 additions and 808 deletions.
1 change: 1 addition & 0 deletions cmake/QtDefs.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ find_package(Qt5LinguistTools)
find_package(Qt5PrintSupport)
find_package(Qt5Multimedia)
find_package(Qt5Svg)
find_package(Qt5SerialPort)

if(Qt5Core_FOUND)
message(STATUS "Qt Version: ${Qt5Core_VERSION}")
Expand Down
1 change: 1 addition & 0 deletions companion/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ target_link_libraries(common
Qt5::Core
Qt5::Xml
Qt5::Widgets
Qt5::SerialPort
${PTHREAD_LIBRARY}
${SDL2_LIBRARIES}
${WIN_LINK_LIBRARIES}
Expand Down
2 changes: 2 additions & 0 deletions companion/src/simulation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ set(${PROJECT_NAME}_NAMES
widgets/lcdwidget
widgets/radiowidget
widgets/virtualjoystickwidget
serialportsdialog
hostserialconnector
)

if(SDL2_FOUND)
Expand Down
187 changes: 187 additions & 0 deletions companion/src/simulation/hostserialconnector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/

#include "hostserialconnector.h"
#include <QMessageBox>

HostSerialConnector::HostSerialConnector(QObject *parent, SimulatorInterface *simulator)
: simulator(simulator)
{
for (int i = 0; i < MAX_HOST_SERIAL; i++) {
hostAuxPorts[i] = nullptr;
hostAuxPortsEncoding[i] = SERIAL_ENCODING_8N1;
hostAuxPortsBaudRate[i] = 9600;
hostAuxPortsOpen[i] = false;
}
}

HostSerialConnector::~HostSerialConnector()
{
for (int i = 0; i < MAX_HOST_SERIAL; i++) {
if (hostAuxPorts[i] != nullptr) {
hostAuxPorts[i]->close();
hostAuxPorts[i]->deleteLater();
}
}
}

QString HostSerialConnector::getConnectedSerialPortName(int index)
{
if (index >= MAX_HOST_SERIAL)
return QString("");

QMutexLocker locker(&hostAuxPortsMutex);

QSerialPort * port = hostAuxPorts[index];
if (port == nullptr)
return QString("");

return port->portName();
}

void HostSerialConnector::connectSerialPort(int index, QString portName)
{
if (index >= MAX_HOST_SERIAL)
return;

QMutexLocker locker(&hostAuxPortsMutex);

QSerialPort * port = hostAuxPorts[index];
if (port != nullptr) {
port->close();
port->deleteLater();
}

if (portName.isEmpty()) {
hostAuxPorts[index] = nullptr;
return;
}

port = new QSerialPort(portName, this);
hostAuxPorts[index] = port;

setSerialEncoding(index, hostAuxPortsEncoding[index]);
setSerialBaudRate(index, hostAuxPortsBaudRate[index]);

connect(port, &QSerialPort::readyRead, [this, index, port]() {
QByteArray data = port->readAll();
simulator->receiveAuxSerialData(index, data);
});

if (hostAuxPortsOpen[index])
serialStart(index);
}

void HostSerialConnector::sendSerialData(const quint8 index, const QByteArray & data)
{
if (index >= MAX_HOST_SERIAL)
return;

QMutexLocker locker(&hostAuxPortsMutex);

QSerialPort * port = hostAuxPorts[index];
if (port == nullptr)
return;

port->write(data);
}

void HostSerialConnector::setSerialEncoding(const quint8 index, const quint8 encoding)
{
if (index >= MAX_HOST_SERIAL)
return;

QMutexLocker locker(&hostAuxPortsMutex);

hostAuxPortsEncoding[index] = encoding;

QSerialPort * port = hostAuxPorts[index];
if (port == nullptr)
return;

switch(encoding) {
case SERIAL_ENCODING_8N1:
port->setDataBits(QSerialPort::Data8);
port->setParity(QSerialPort::NoParity);
port->setStopBits(QSerialPort::OneStop);
break;
case SERIAL_ENCODING_8E2:
port->setDataBits(QSerialPort::Data8);
port->setParity(QSerialPort::EvenParity);
port->setStopBits(QSerialPort::TwoStop);
break;
default:
// Do nothing, QSerialPort can't do SERIAL_ENCODING_PXX1_PWM
break;
}
}

void HostSerialConnector::setSerialBaudRate(const quint8 index, const quint32 baudrate)
{
if (index >= MAX_HOST_SERIAL)
return;

QMutexLocker locker(&hostAuxPortsMutex);

hostAuxPortsBaudRate[index] = baudrate;

QSerialPort * port = hostAuxPorts[index];
if (port == nullptr)
return;

if (!port->setBaudRate(baudrate))
qDebug() << "Failed to set baudrate";
}

void HostSerialConnector::serialStart(const quint8 index)
{
if (index >= MAX_HOST_SERIAL)
return;

QMutexLocker locker(&hostAuxPortsMutex);

hostAuxPortsOpen[index] = true;

QSerialPort * port = hostAuxPorts[index];
if (port == nullptr)
return;

if (port->open(QIODevice::ReadWrite))
qDebug() << "Opened host serial " << index;
else
QMessageBox::warning(nullptr, tr("Host Serial Error"), port->errorString(), QMessageBox::Cancel, QMessageBox::Cancel);
}

void HostSerialConnector::serialStop(const quint8 index)
{
if (index >= MAX_HOST_SERIAL)
return;

QMutexLocker locker(&hostAuxPortsMutex);

hostAuxPortsOpen[index] = false;

QSerialPort * port = hostAuxPorts[index];
if (port == nullptr)
return;

port->close();
}
57 changes: 57 additions & 0 deletions companion/src/simulation/hostserialconnector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/

#pragma once

#include "simulatorinterface.h"

#include <QSerialPort>
#include <QMutex>

#define MAX_HOST_SERIAL 2

class HostSerialConnector : public QObject
{
Q_OBJECT

public:
explicit HostSerialConnector(QObject * parent, SimulatorInterface * simulator);
~HostSerialConnector();

QString getConnectedSerialPortName(int index);

public slots:
void connectSerialPort(int index, QString portName);
void sendSerialData(const quint8 index, const QByteArray & data);
void setSerialEncoding(const quint8 index, const quint8 encoding);
void setSerialBaudRate(const quint8 index, const quint32 baudrate);
void serialStart(const quint8 index);
void serialStop(const quint8 index);

private:
SimulatorInterface * simulator;

QRecursiveMutex hostAuxPortsMutex;
QSerialPort * hostAuxPorts[MAX_HOST_SERIAL];
quint8 hostAuxPortsEncoding[MAX_HOST_SERIAL];
quint32 hostAuxPortsBaudRate[MAX_HOST_SERIAL];
bool hostAuxPortsOpen[MAX_HOST_SERIAL];
};
89 changes: 89 additions & 0 deletions companion/src/simulation/serialportsdialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (C) EdgeTX
*
* Based on code named
* opentx - https://github.com/opentx/opentx
* th9x - http://code.google.com/p/th9x
* er9x - http://code.google.com/p/er9x
* gruvin9x - http://code.google.com/p/gruvin9x
*
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 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.
*/

#include "serialportsdialog.h"
#include "ui_serialportsdialog.h"

SerialPortsDialog::SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator, HostSerialConnector *connector) :
QDialog(parent),
simulator(simulator),
connector(connector),
ui(new Ui::SerialPortsDialog)
{
ui->setupUi(this);

aux1 = connector->getConnectedSerialPortName(0);
aux2 = connector->getConnectedSerialPortName(1);

populateSerialPortCombo(ui->aux1Combo, aux1);
populateSerialPortCombo(ui->aux2Combo, aux2);

ui->aux1Combo->setEnabled(simulator->getCapability(SimulatorInterface::Capability::CAP_SERIAL_AUX1));
ui->aux2Combo->setEnabled(simulator->getCapability(SimulatorInterface::Capability::CAP_SERIAL_AUX2));
}

SerialPortsDialog::~SerialPortsDialog()
{
delete ui;
}

void SerialPortsDialog::populateSerialPortCombo(QComboBox * cb, QString currentPortName)
{
cb->clear();
cb->addItem(tr("Not Assigned"), "");
if (currentPortName == "") {
cb->setCurrentIndex(0);
}

const auto serialPortInfos = QSerialPortInfo::availablePorts();
for (int i = 0; i < serialPortInfos.size(); i++) {
const auto portInfo = serialPortInfos[i];
cb->addItem(portInfo.portName(), portInfo.portName());
if (portInfo.portName() == currentPortName)
cb->setCurrentIndex(i + 1);
}
}

void SerialPortsDialog::on_cancelButton_clicked()
{
this->reject();
}

void SerialPortsDialog::on_okButton_clicked()
{
this->accept();
}

void SerialPortsDialog::on_refreshButton_clicked()
{
populateSerialPortCombo(ui->aux1Combo, aux1);
populateSerialPortCombo(ui->aux2Combo, aux2);
}

void SerialPortsDialog::on_aux1Combo_currentIndexChanged(int index)
{
aux1 = ui->aux1Combo->itemData(index).toString();
}

void SerialPortsDialog::on_aux2Combo_currentIndexChanged(int index)
{
aux2 = ui->aux2Combo->itemData(index).toString();
}
Loading

0 comments on commit 9109d4f

Please sign in to comment.