Skip to content

Commit

Permalink
feat(simu): cross-platform connection of host serial ports to simu radio
Browse files Browse the repository at this point in the history
  • Loading branch information
nrw505 committed Oct 3, 2024
1 parent e9430ec commit 8553373
Show file tree
Hide file tree
Showing 22 changed files with 765 additions and 863 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
166 changes: 166 additions & 0 deletions companion/src/simulation/hostserialconnector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* 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"

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

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

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 SimulatorInterface::SerialEncoding encoding)
{
if (index >= MAX_HOST_SERIAL)
return;

QMutexLocker locker(&hostAuxPortsMutex);

hostAuxPortsEncoding[index] = encoding;

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

switch(encoding) {
case SimulatorInterface::SerialEncoding::SERIAL_ENCODING_8N1:
port->setDataBits(QSerialPort::Data8);
port->setParity(QSerialPort::NoParity);
port->setStopBits(QSerialPort::OneStop);
break;
case SimulatorInterface::SerialEncoding::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() << "Failed to open host serial " << index;
}

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();
}
55 changes: 55 additions & 0 deletions companion/src/simulation/hostserialconnector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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();

public slots:
void connectSerialPort(int index, QString portName);
void sendSerialData(const quint8 index, const QByteArray & data);
void setSerialEncoding(const quint8 index, const SimulatorInterface::SerialEncoding 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];
SimulatorInterface::SerialEncoding hostAuxPortsEncoding[MAX_HOST_SERIAL];
quint32 hostAuxPortsBaudRate[MAX_HOST_SERIAL];
bool hostAuxPortsOpen[MAX_HOST_SERIAL];
};
83 changes: 83 additions & 0 deletions companion/src/simulation/serialportsdialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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"

#include "eeprominterface.h"
#include "boards.h"
#include "constants.h"

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

aux1 = QString("");
aux2 = QString("");

populateSerialPortCombo(ui->aux1Combo);
populateSerialPortCombo(ui->aux2Combo);
}

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

void SerialPortsDialog::populateSerialPortCombo(QComboBox * cb)
{
cb->clear();
cb->addItem(tr("Not Assigned"), "");

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

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

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

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

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();
}
56 changes: 56 additions & 0 deletions companion/src/simulation/serialportsdialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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 <QSerialPort>
#include <QSerialPortInfo>
#include <QtWidgets>
#include "appdata.h"
#include "joystick.h"

class QComboBox;

namespace Ui {
class SerialPortsDialog;
}

class SerialPortsDialog : public QDialog
{
Q_OBJECT

public:
explicit SerialPortsDialog(QWidget *parent = 0);
~SerialPortsDialog();
QString aux1;
QString aux2;

private:
Ui::SerialPortsDialog *ui;

private slots:
void populateSerialPortCombo(QComboBox * cb);
void on_cancelButton_clicked();
void on_okButton_clicked();
void on_refreshButton_clicked();
void on_aux1Combo_currentIndexChanged(int index);
void on_aux2Combo_currentIndexChanged(int index);
};
Loading

0 comments on commit 8553373

Please sign in to comment.