From 1b6a4057e5400f0e99abc1989ba80ebf6ea69b8c Mon Sep 17 00:00:00 2001 From: Nigel Williams Date: Tue, 1 Oct 2024 17:54:13 +1000 Subject: [PATCH 1/4] feat(simu): cross-platform connection of host serial ports to simu radio --- cmake/QtDefs.cmake | 1 + companion/src/CMakeLists.txt | 1 + companion/src/simulation/CMakeLists.txt | 2 + .../src/simulation/hostserialconnector.cpp | 166 +++++++++ .../src/simulation/hostserialconnector.h | 55 +++ .../src/simulation/serialportsdialog.cpp | 83 +++++ companion/src/simulation/serialportsdialog.h | 56 +++ companion/src/simulation/serialportsdialog.ui | 117 +++++++ companion/src/simulation/simulatorinterface.h | 16 + .../src/simulation/simulatormainwindow.cpp | 20 ++ .../src/simulation/simulatormainwindow.h | 3 + .../src/simulation/simulatormainwindow.ui | 6 + companion/src/simulation/simulatorwidget.h | 1 + radio/src/targets/simu/CMakeLists.txt | 14 +- radio/src/targets/simu/opentxsimulator.cpp | 193 +++++++++++ radio/src/targets/simu/opentxsimulator.h | 9 + radio/src/targets/simu/rs232-linux.c | 261 -------------- radio/src/targets/simu/rs232-win.c | 322 ------------------ radio/src/targets/simu/rs232.h | 152 --------- radio/src/targets/simu/simpgmspace.cpp | 81 ++--- tools/setup_buildenv_ubuntu20.04.sh | 2 +- tools/setup_buildenv_ubuntu22.04.sh | 2 +- 22 files changed, 755 insertions(+), 808 deletions(-) create mode 100644 companion/src/simulation/hostserialconnector.cpp create mode 100644 companion/src/simulation/hostserialconnector.h create mode 100644 companion/src/simulation/serialportsdialog.cpp create mode 100644 companion/src/simulation/serialportsdialog.h create mode 100644 companion/src/simulation/serialportsdialog.ui delete mode 100644 radio/src/targets/simu/rs232-linux.c delete mode 100644 radio/src/targets/simu/rs232-win.c delete mode 100644 radio/src/targets/simu/rs232.h diff --git a/cmake/QtDefs.cmake b/cmake/QtDefs.cmake index 7445290c43f..be859da68b7 100644 --- a/cmake/QtDefs.cmake +++ b/cmake/QtDefs.cmake @@ -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}") diff --git a/companion/src/CMakeLists.txt b/companion/src/CMakeLists.txt index 6fd2f8d115f..654cec0c406 100644 --- a/companion/src/CMakeLists.txt +++ b/companion/src/CMakeLists.txt @@ -191,6 +191,7 @@ target_link_libraries(common Qt5::Core Qt5::Xml Qt5::Widgets + Qt5::SerialPort ${PTHREAD_LIBRARY} ${SDL2_LIBRARIES} ${WIN_LINK_LIBRARIES} diff --git a/companion/src/simulation/CMakeLists.txt b/companion/src/simulation/CMakeLists.txt index 661f4228ef7..d221745f5af 100644 --- a/companion/src/simulation/CMakeLists.txt +++ b/companion/src/simulation/CMakeLists.txt @@ -19,6 +19,8 @@ set(${PROJECT_NAME}_NAMES widgets/lcdwidget widgets/radiowidget widgets/virtualjoystickwidget + serialportsdialog + hostserialconnector ) if(SDL2_FOUND) diff --git a/companion/src/simulation/hostserialconnector.cpp b/companion/src/simulation/hostserialconnector.cpp new file mode 100644 index 00000000000..27d531580f0 --- /dev/null +++ b/companion/src/simulation/hostserialconnector.cpp @@ -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(); +} diff --git a/companion/src/simulation/hostserialconnector.h b/companion/src/simulation/hostserialconnector.h new file mode 100644 index 00000000000..5284799c8aa --- /dev/null +++ b/companion/src/simulation/hostserialconnector.h @@ -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 +#include + +#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]; +}; diff --git a/companion/src/simulation/serialportsdialog.cpp b/companion/src/simulation/serialportsdialog.cpp new file mode 100644 index 00000000000..73e79f2bdb7 --- /dev/null +++ b/companion/src/simulation/serialportsdialog.cpp @@ -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(); +} diff --git a/companion/src/simulation/serialportsdialog.h b/companion/src/simulation/serialportsdialog.h new file mode 100644 index 00000000000..f24bc81957b --- /dev/null +++ b/companion/src/simulation/serialportsdialog.h @@ -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 +#include +#include +#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); +}; diff --git a/companion/src/simulation/serialportsdialog.ui b/companion/src/simulation/serialportsdialog.ui new file mode 100644 index 00000000000..03edffe20ee --- /dev/null +++ b/companion/src/simulation/serialportsdialog.ui @@ -0,0 +1,117 @@ + + + SerialPortsDialog + + + + 0 + 0 + 558 + 108 + + + + + 0 + 0 + + + + Configure Serial Ports + + + + + 10 + 10 + 534 + 89 + + + + + + + AUX1 Port + + + + + + + Qt::Horizontal + + + + 360 + 20 + + + + + + + + + 0 + 0 + + + + Cancel + + + + + + + AUX2 Port + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + Ok + + + + + + + Search for Serial Ports + + + + + + + + + diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h index 57a3fa4efeb..e860dcb979b 100644 --- a/companion/src/simulation/simulatorinterface.h +++ b/companion/src/simulation/simulatorinterface.h @@ -33,6 +33,7 @@ #include #include #include +#include #define SIMULATOR_INTERFACE_HEARTBEAT_PERIOD 1000 // ms @@ -84,9 +85,18 @@ class SimulatorInterface : public QObject CAP_ROTARY_ENC, // ROTARY_ENCODERS CAP_ROTARY_ENC_NAV, // ROTARY_ENCODER_NAVIGATION CAP_TELEM_FRSKY_SPORT, // TELEMETRY_FRSKY_SPORT + CAP_SERIAL_AUX1, // Does AUX1 exist on this radio? + CAP_SERIAL_AUX2, // Does AUX2 exist on this radio? CAP_ENUM_COUNT }; + enum SerialEncoding { + SERIAL_ENCODING_8N1, + SERIAL_ENCODING_8E2, + SERIAL_ENCODING_PXX1_PWM, + SERIAL_ENCODING_COUNT + }; + // This allows automatic en/decoding of flight mode + gvarIdx value to/from any int32 struct gVarMode_t { int16_t value; @@ -160,6 +170,7 @@ class SimulatorInterface : public QObject virtual void setLuaStateReloadPermanentScripts() = 0; virtual void addTracebackDevice(QIODevice * device) = 0; virtual void removeTracebackDevice(QIODevice * device) = 0; + virtual void receiveAuxSerialData(const quint8 port_num, const QByteArray & data) = 0; signals: @@ -176,6 +187,11 @@ class SimulatorInterface : public QObject void trimRangeChange(quint8 index, qint32 min, qint16 max); void gVarValueChange(quint8 index, qint32 value); void outputValueChange(int type, quint8 index, qint32 value); + void auxSerialSendData(const quint8 port_num, const QByteArray & data); + void auxSerialSetEncoding(const quint8 port_num, const SerialEncoding encoding); + void auxSerialSetBaudrate(const quint8 port_num, const quint32 baudrate); + void auxSerialStart(const quint8 port_num); + void auxSerialStop(const quint8 port_num); }; class SimulatorFactory { diff --git a/companion/src/simulation/simulatormainwindow.cpp b/companion/src/simulation/simulatormainwindow.cpp index d91b78b46a6..fec93b8c993 100644 --- a/companion/src/simulation/simulatormainwindow.cpp +++ b/companion/src/simulation/simulatormainwindow.cpp @@ -32,6 +32,7 @@ #ifdef JOYSTICKS #include "joystickdialog.h" #endif +#include "serialportsdialog.h" #include #include @@ -82,6 +83,8 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, const QString & simula m_simulator->moveToThread(&simuThread); simuThread.start(); + hostSerialConnector = new HostSerialConnector(this, m_simulator); + ui->setupUi(this); setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea); @@ -131,6 +134,7 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, const QString & simula connect(ui->actionShowKeymap, &QAction::triggered, this, &SimulatorMainWindow::showHelp); connect(ui->actionJoystickSettings, &QAction::triggered, this, &SimulatorMainWindow::openJoystickDialog); + connect(ui->actionSerialPorts, &QAction::triggered, this, &SimulatorMainWindow::openSerialPortsDialog); connect(ui->actionToggleMenuBar, &QAction::toggled, this, &SimulatorMainWindow::showMenuBar); connect(ui->actionFixedRadioWidth, &QAction::toggled, this, &SimulatorMainWindow::showRadioFixedWidth); connect(ui->actionFixedRadioHeight, &QAction::toggled, this, &SimulatorMainWindow::showRadioFixedHeight); @@ -150,6 +154,12 @@ SimulatorMainWindow::SimulatorMainWindow(QWidget *parent, const QString & simula connect(ui->actionScreenshot, &QAction::triggered, m_simulatorWidget, &SimulatorWidget::captureScreenshot); connect(m_simulatorWidget, &SimulatorWidget::windowTitleChanged, this, &SimulatorMainWindow::setWindowTitle); } + + connect(m_simulator, &SimulatorInterface::auxSerialSendData, hostSerialConnector, &HostSerialConnector::sendSerialData); + connect(m_simulator, &SimulatorInterface::auxSerialSetEncoding, hostSerialConnector, &HostSerialConnector::setSerialEncoding); + connect(m_simulator, &SimulatorInterface::auxSerialSetBaudrate, hostSerialConnector, &HostSerialConnector::setSerialBaudRate); + connect(m_simulator, &SimulatorInterface::auxSerialStart, hostSerialConnector, &HostSerialConnector::serialStart); + connect(m_simulator, &SimulatorInterface::auxSerialStop, hostSerialConnector, &HostSerialConnector::serialStop); } SimulatorMainWindow::~SimulatorMainWindow() @@ -470,6 +480,16 @@ void SimulatorMainWindow::openJoystickDialog(bool) #endif } +void SimulatorMainWindow::openSerialPortsDialog(bool) +{ + SerialPortsDialog * dialog = new SerialPortsDialog(this); + if (dialog->exec() == QDialog::Accepted && m_simulator) { + hostSerialConnector->connectSerialPort(0, dialog->aux1); + hostSerialConnector->connectSerialPort(1, dialog->aux2); + } + dialog->deleteLater(); +} + void SimulatorMainWindow::showHelp(bool show) { QString helpText = "" diff --git a/companion/src/simulation/simulatormainwindow.h b/companion/src/simulation/simulatormainwindow.h index 6607161be4d..bec7507ce4d 100644 --- a/companion/src/simulation/simulatormainwindow.h +++ b/companion/src/simulation/simulatormainwindow.h @@ -22,6 +22,7 @@ #pragma once #include "simulator.h" +#include "hostserialconnector.h" #include #include @@ -80,6 +81,7 @@ class SimulatorMainWindow : public QMainWindow void setRadioSizePolicy(int fixType); void toggleRadioDocked(bool dock); void openJoystickDialog(bool); + void openSerialPortsDialog(bool); void showHelp(bool show); protected: @@ -87,6 +89,7 @@ class SimulatorMainWindow : public QMainWindow void addTool(QDockWidget * widget, Qt::DockWidgetArea area, QIcon icon = QIcon(), QKeySequence shortcut = QKeySequence()); SimulatorInterface * m_simulator; + HostSerialConnector * hostSerialConnector; Ui::SimulatorMainWindow * ui; SimulatorWidget * m_simulatorWidget; diff --git a/companion/src/simulation/simulatormainwindow.ui b/companion/src/simulation/simulatormainwindow.ui index fa80926100b..aa6cc3ed629 100644 --- a/companion/src/simulation/simulatormainwindow.ui +++ b/companion/src/simulation/simulatormainwindow.ui @@ -72,6 +72,7 @@ + @@ -216,6 +217,11 @@ Set radio widget height to be a fixed size. + + + Serial Ports + + diff --git a/companion/src/simulation/simulatorwidget.h b/companion/src/simulation/simulatorwidget.h index ea0ccac1f93..0f1e9cafd5f 100644 --- a/companion/src/simulation/simulatorwidget.h +++ b/companion/src/simulation/simulatorwidget.h @@ -74,6 +74,7 @@ class SimulatorWidget : public QWidget void setUiAreaStyle(const QString & style); void captureScreenshot(bool); void setupJoysticks(); + void setupSerialPorts(QSerialPort *aux1, QSerialPort *aux2); QString getSdPath() const { return sdCardPath; } QString getDataPath() const { return radioDataPath; } diff --git a/radio/src/targets/simu/CMakeLists.txt b/radio/src/targets/simu/CMakeLists.txt index 31f74595c30..664aa930305 100644 --- a/radio/src/targets/simu/CMakeLists.txt +++ b/radio/src/targets/simu/CMakeLists.txt @@ -20,20 +20,8 @@ set(SIMU_DRIVERS bt_driver.cpp timers_driver.cpp abnormal_reboot.cpp - rs232-linux.c ) - option(SIMU_AUX "Allow the simulator to use the host's RS-232 port" OFF) - set(SIMU_COM_PORT "2" CACHE STRING "Set COM port number to use") - -if (SIMU_AUX) - if(WIN32) - set(SIMU_DRIVERS ${SIMU_DRIVERS} rs232-win.c) - else() - set(SIMU_DRIVERS ${SIMU_DRIVERS} rs232-linux.c) - endif() -endif() - set(HW_DESC_JSON ${FLAVOUR}.json) AddHardwareDefTarget(${HW_DESC_JSON}) AddHWGenTarget(${HW_DESC_JSON} simu_keys simu_keys.inc) @@ -112,7 +100,7 @@ if(Qt5Widgets_FOUND) target_compile_options(${SIMULATOR_TARGET} PRIVATE ${SIMU_SRC_OPTIONS}) target_compile_definitions(${SIMULATOR_TARGET} PUBLIC ${APP_COMMON_DEFINES}) - target_link_libraries(${SIMULATOR_TARGET} ${SDL2_LIBRARIES} Qt5::Core) + target_link_libraries(${SIMULATOR_TARGET} ${SDL2_LIBRARIES} Qt5::Core Qt5::SerialPort) # Remove debug symbols on release builds if(NOT CLANG) diff --git a/radio/src/targets/simu/opentxsimulator.cpp b/radio/src/targets/simu/opentxsimulator.cpp index 2614402bc52..53a51e11388 100644 --- a/radio/src/targets/simu/opentxsimulator.cpp +++ b/radio/src/targets/simu/opentxsimulator.cpp @@ -23,6 +23,7 @@ #include "edgetx.h" #include "simulcd.h" #include "switches.h" +#include "serial.h" #include "hal/adc_driver.h" #include "hal/rotary_encoder.h" @@ -41,6 +42,16 @@ int16_t g_anas[MAX_ANALOG_INPUTS]; QVector OpenTxSimulator::tracebackDevices; +typedef struct { + uint8_t index; + QMutex mutex; + QQueue receiveBuffer; + OpenTxSimulator * simulator; +} simulated_serial_port_t; + +simulated_serial_port_t simulatedSerialPorts[MAX_AUX_SERIAL]; +extern etx_serial_port_t * serialPorts[MAX_AUX_SERIAL]; + #if defined(HARDWARE_TOUCH) tmr10ms_t downTime = 0; tmr10ms_t tapTime = 0; @@ -74,6 +85,94 @@ void firmwareTraceCb(const char * text) } } +// Serial port handling needs to know about OpenTxSimulator, so we we +// need to update what's in simpgmspace.cpp when we have a simulator +// to point at. + +static void* simulator_host_drv_init(void* hw_def, const etx_serial_init* dev) +{ + if (hw_def == nullptr) + return nullptr; + + simulated_serial_port_t *port = (simulated_serial_port_t *)hw_def; + + port->simulator->drv_auxSerialInit(port->index, dev); + + // Return the port definition as the context + return (void *)port; +} + +static void simulator_host_drv_deinit(void* ctx) +{ + if (ctx == nullptr) + return; + + simulated_serial_port_t *port = (simulated_serial_port_t *)ctx; + port->simulator->drv_auxSerialDeinit(port->index); +} + +static void simulator_host_drv_send_byte(void* ctx, uint8_t b) +{ + if (ctx == nullptr) + return; + + simulated_serial_port_t *port = (simulated_serial_port_t *)ctx; + + port->simulator->drv_auxSerialSendByte(port->index, b); +} + +static void simulator_host_drv_send_buffer(void* ctx, const uint8_t* b, uint32_t l) +{ + if (ctx == nullptr) + return; + + simulated_serial_port_t *port = (simulated_serial_port_t *)ctx; + + port->simulator->drv_auxSerialSendBuffer(port->index, b, l); +} + +static int simulator_host_drv_get_byte(void* ctx, uint8_t* b) +{ + if (ctx == nullptr) + return 0; + + simulated_serial_port_t *port = (simulated_serial_port_t *)ctx; + + return port->simulator->drv_auxSerialGetByte(port->index, b); +} + +static void simulator_host_drv_set_baudrate(void* ctx, uint32_t baudrate) +{ + if (ctx == nullptr) + return; + + simulated_serial_port_t *port = (simulated_serial_port_t *)ctx; + port->simulator->drv_auxSerialSetBaudrate(port->index, baudrate); +} + +static const etx_serial_driver_t simulator_host_drv = { + .init = simulator_host_drv_init, + .deinit = simulator_host_drv_deinit, + .sendByte = simulator_host_drv_send_byte, + .sendBuffer = simulator_host_drv_send_buffer, + .txCompleted = nullptr, + .waitForTxCompleted = nullptr, + .enableRx = nullptr, + .getByte = simulator_host_drv_get_byte, + .getLastByte = nullptr, + .getBufferedBytes = nullptr, + .copyRxBuffer = nullptr, + .clearRxBuffer = nullptr, + .getBaudrate = nullptr, + .setBaudrate = simulator_host_drv_set_baudrate, + .setPolarity = nullptr, + .setHWOption = nullptr, + .setReceiveCb = nullptr, + .setIdleCb = nullptr, + .setBaudrateCb = nullptr, +}; + + OpenTxSimulator::OpenTxSimulator() : SimulatorInterface(), m_timer10ms(nullptr), @@ -82,6 +181,17 @@ OpenTxSimulator::OpenTxSimulator() : { tracebackDevices.clear(); traceCallback = firmwareTraceCb; + + // When we create the simulator, we change the UART driver + for (int i = 0; i < MAX_AUX_SERIAL; i++) { + etx_serial_port_t * port = serialPorts[i]; + if (port != nullptr) { + port->uart = &simulator_host_drv; + port->hw_def = &(simulatedSerialPorts[i]); + simulatedSerialPorts[i].index = i; + simulatedSerialPorts[i].simulator = this; + } + } } OpenTxSimulator::~OpenTxSimulator() @@ -89,6 +199,13 @@ OpenTxSimulator::~OpenTxSimulator() traceCallback = nullptr; tracebackDevices.clear(); + for (int i = 0; i < MAX_AUX_SERIAL; i++) { + etx_serial_port_t * port = serialPorts[i]; + if (port != nullptr) { + port->hw_def = nullptr; + } + } + if (m_timer10ms) delete m_timer10ms; @@ -507,6 +624,14 @@ const int OpenTxSimulator::getCapability(Capability cap) case CAP_TELEM_FRSKY_SPORT : ret = 1; break; + + case CAP_SERIAL_AUX1: + ret = (auxSerialGetPort(SP_AUX1) != nullptr); + break; + + case CAP_SERIAL_AUX2: + ret = (auxSerialGetPort(SP_AUX2) != nullptr); + break; } return ret; } @@ -539,6 +664,74 @@ void OpenTxSimulator::removeTracebackDevice(QIODevice * device) } } +void OpenTxSimulator::receiveAuxSerialData(quint8 port_nr, const QByteArray & data) +{ + if (port_nr >= MAX_AUX_SERIAL) + return; + + QMutexLocker locker(&(simulatedSerialPorts[port_nr].mutex)); + + for (uint8_t byte : data) + simulatedSerialPorts[port_nr].receiveBuffer.enqueue(byte); +} + +void OpenTxSimulator::drv_auxSerialSetBaudrate(quint8 port_nr, quint32 baudrate) +{ + emit auxSerialSetBaudrate(port_nr, baudrate); +} + +void OpenTxSimulator::drv_auxSerialInit(quint8 port_nr, const etx_serial_init* dev) +{ + switch(dev->encoding) { + case ETX_Encoding_8N1: + emit auxSerialSetEncoding(port_nr, SERIAL_ENCODING_8N1); + break; + case ETX_Encoding_8E2: + emit auxSerialSetEncoding(port_nr, SERIAL_ENCODING_8E2); + break; + default: + // Do nothing, host hardware can't do SERIAL_ENCODING_PXX1_PWM + break; + } + + if (dev->baudrate != 0) + emit auxSerialSetBaudrate(port_nr, dev->baudrate); + + emit auxSerialStart(port_nr); +} + +void OpenTxSimulator::drv_auxSerialDeinit(quint8 port_nr) +{ + emit auxSerialStop(port_nr); +} + +void OpenTxSimulator::drv_auxSerialSendByte(quint8 port_nr, uint8_t b) +{ + QByteArray data = QByteArray::fromRawData((const char *)&b, 1); + + emit auxSerialSendData(port_nr, data); +} + +void OpenTxSimulator::drv_auxSerialSendBuffer(quint8 port_nr, const uint8_t* b, uint32_t l) +{ + QByteArray data = QByteArray::fromRawData((const char *)b, l); + + emit auxSerialSendData(port_nr, data); +} + +int OpenTxSimulator::drv_auxSerialGetByte(quint8 port_nr, uint8_t *b) +{ + // Obtain the port's mutex before messing with the buffer + QMutexLocker locker(&(simulatedSerialPorts[port_nr].mutex)); + + if (simulatedSerialPorts[port_nr].receiveBuffer.isEmpty()) + return 0; + + uint8_t byte = simulatedSerialPorts[port_nr].receiveBuffer.dequeue(); + + *b = byte; + return 1; +} /*** Protected functions ***/ diff --git a/radio/src/targets/simu/opentxsimulator.h b/radio/src/targets/simu/opentxsimulator.h index 350355cfe1f..2b61786c8d4 100644 --- a/radio/src/targets/simu/opentxsimulator.h +++ b/radio/src/targets/simu/opentxsimulator.h @@ -22,6 +22,7 @@ #pragma once #include "simulatorinterface.h" +#include "dataconstants.h" #include #include @@ -58,6 +59,13 @@ class DLLEXPORT OpenTxSimulator : public SimulatorInterface static QVector tracebackDevices; + void drv_auxSerialInit(quint8 port_num, const etx_serial_init* dev); + void drv_auxSerialDeinit(quint8 port_num); + void drv_auxSerialSetBaudrate(quint8 port_num, uint32_t baudrate); + void drv_auxSerialSendByte(quint8 port_num, uint8_t byte); + void drv_auxSerialSendBuffer(quint8 port_num, const uint8_t* data, uint32_t size); + int drv_auxSerialGetByte(quint8 port_num, uint8_t* data); + public slots: virtual void init(); @@ -83,6 +91,7 @@ class DLLEXPORT OpenTxSimulator : public SimulatorInterface virtual void setLuaStateReloadPermanentScripts(); virtual void addTracebackDevice(QIODevice * device); virtual void removeTracebackDevice(QIODevice * device); + virtual void receiveAuxSerialData(const quint8 port_num, const QByteArray & data); protected slots: void run(); diff --git a/radio/src/targets/simu/rs232-linux.c b/radio/src/targets/simu/rs232-linux.c deleted file mode 100644 index c8e629a135a..00000000000 --- a/radio/src/targets/simu/rs232-linux.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - Cross-platform serial / RS232 library - Version 0.21, 11/10/2015 - -> LINUX and MacOS implementation - -> rs232-linux.c - - The MIT License (MIT) - - Copyright (c) 2013-2015 Frédéric Meslin, Florent Touchard - Email: fredericmeslin@hotmail.com - Website: www.fredslab.net - Twitter: @marzacdev - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - -*/ - -#if defined(__unix__) || defined(__unix) || \ - defined(__APPLE__) && defined(__MACH__) - -#define _DARWIN_C_SOURCE - -#include "rs232.h" - -#include -#define __USE_MISC // For CRTSCTS -#include -#include -#include - -#define __USE_SVID // For strdup -#include -#include -#include - -/*****************************************************************************/ -/** Base name for COM devices */ -#if defined(__APPLE__) && defined(__MACH__) - static const char * devBases[] = { - "tty." - }; - static int noBases = 1; -#else - static const char * devBases[] = { - "ttyACM", "ttyUSB", "rfcomm", "ttyS" - }; - static int noBases = 4; -#endif - -/*****************************************************************************/ -typedef struct { - char * port; - int handle; -} COMDevice; - -#define COM_MAXDEVICES 64 -static COMDevice comDevices[COM_MAXDEVICES]; -static int noDevices = 0; - -/*****************************************************************************/ -/** Private functions */ -void _AppendDevices(const char * base); -int _BaudFlag(int BaudRate); - -/*****************************************************************************/ -int comEnumerate() -{ - for (int i = 0; i < noDevices; i++) { - if (comDevices[i].port) free(comDevices[i].port); - comDevices[i].port = NULL; - } - noDevices = 0; - for (int i = 0; i < noBases; i++) - _AppendDevices(devBases[i]); - return noDevices; -} - -void comTerminate() -{ - comCloseAll(); - for (int i = 0; i < noDevices; i++) { - if (comDevices[i].port) free(comDevices[i].port); - comDevices[i].port = NULL; - } -} - -int comGetNoPorts() -{ - return noDevices; -} - -/*****************************************************************************/ -int comFindPort(const char * name) -{ - int p; - for (p = 0; p < noDevices; p++) - if (strcmp(name, comDevices[p].port) == 0) - return p; - return -1; -} - -const char * comGetInternalName(int index) -{ - #define COM_MAXNAME 128 - static char name[COM_MAXNAME]; - if (index >= noDevices || index < 0) - return NULL; - sprintf(name, "/dev/%s", comDevices[index].port); - return name; -} - -const char * comGetPortName(int index) { - if (index >= noDevices || index < 0) - return NULL; - return comDevices[index].port; -} - -/*****************************************************************************/ -int comOpen(int index, int baudrate) -{ - if (index >= noDevices || index < 0) - return 0; -// Close if already open - COMDevice * com = &comDevices[index]; - if (com->handle >= 0) comClose(index); -// Open port - printf("Try %s \n", comGetInternalName(index)); - int handle = open(comGetInternalName(index), O_RDWR | O_NOCTTY | O_NDELAY); - if (handle < 0) - return 0; - printf("Open %s \n", comGetInternalName(index)); -// General configuration - struct termios config; - memset(&config, 0, sizeof(config)); - tcgetattr(handle, &config); - config.c_iflag &= ~(INLCR | ICRNL); - config.c_iflag |= IGNPAR | IGNBRK; - config.c_oflag &= ~(OPOST | ONLCR | OCRNL); - config.c_cflag &= ~(PARENB | PARODD | CSTOPB | CSIZE | CRTSCTS); - config.c_cflag |= CLOCAL | CREAD | CS8; - config.c_lflag &= ~(ICANON | ISIG | ECHO); - int flag = _BaudFlag(baudrate); - cfsetospeed(&config, flag); - cfsetispeed(&config, flag); -// Timeouts configuration - config.c_cc[VTIME] = 1; - config.c_cc[VMIN] = 0; - //fcntl(handle, F_SETFL, FNDELAY); -// Validate configuration - if (tcsetattr(handle, TCSANOW, &config) < 0) { - close(handle); - return 0; - } - com->handle = handle; - return 1; -} - -void comClose(int index) -{ - if (index >= noDevices || index < 0) - return; - COMDevice * com = &comDevices[index]; - if (com->handle < 0) - return; - tcdrain(com->handle); - close(com->handle); - com->handle = -1; -} - -void comCloseAll() -{ - for (int i = 0; i < noDevices; i++) - comClose(i); -} - -/*****************************************************************************/ -int comWrite(int index, const char * buffer, size_t len) -{ - if (index >= noDevices || index < 0) - return 0; - if (comDevices[index].handle <= 0) - return 0; - int res = write(comDevices[index].handle, buffer, len); - if (res < 0) - res = 0; - return res; -} - -int comRead(int index, char * buffer, size_t len) -{ - if (index >= noDevices || index < 0) - return 0; - if (comDevices[index].handle <= 0) - return 0; - int res = read(comDevices[index].handle, buffer, len); - if (res < 0) - res = 0; - return res; -} - -/*****************************************************************************/ -int _BaudFlag(int BaudRate) -{ - switch(BaudRate) - { - case 50: return B50; break; - case 110: return B110; break; - case 134: return B134; break; - case 150: return B150; break; - case 200: return B200; break; - case 300: return B300; break; - case 600: return B600; break; - case 1200: return B1200; break; - case 1800: return B1800; break; - case 2400: return B2400; break; - case 4800: return B4800; break; - case 9600: return B9600; break; - case 19200: return B19200; break; - case 38400: return B38400; break; - case 57600: return B57600; break; - case 115200: return B115200; break; - case 230400: return B230400; break; - default : return B0; break; - } -} - -void _AppendDevices(const char * base) -{ - int baseLen = strlen(base); - struct dirent * dp; -// Enumerate devices - DIR * dirp = opendir("/dev"); - while ((dp = readdir(dirp)) && noDevices < COM_MAXDEVICES) { - if (strlen(dp->d_name) >= baseLen) { - if (memcmp(base, dp->d_name, baseLen) == 0) { - COMDevice * com = &comDevices[noDevices ++]; - com->port = (char *) strdup(dp->d_name); - com->handle = -1; - } - } - } - closedir(dirp); -} - -#endif // unix diff --git a/radio/src/targets/simu/rs232-win.c b/radio/src/targets/simu/rs232-win.c deleted file mode 100644 index bfc50c9c95c..00000000000 --- a/radio/src/targets/simu/rs232-win.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - Cross-platform serial / RS232 library - Version 0.21, 11/10/2015 - -> WIN32 implementation - -> rs232-win.c - - The MIT License (MIT) - - Copyright (c) 2013-2015 Frédéric Meslin, Florent Touchard - Email: fredericmeslin@hotmail.com - Website: www.fredslab.net - Twitter: @marzacdev - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#ifdef _WIN32 - -#include "rs232.h" - -#include -#include - -/*****************************************************************************/ -typedef int bool; -#define true -1 -#define false 0 - -typedef struct { - int port; - void * handle; -} COMDevice; - -/*****************************************************************************/ -#define COM_MAXDEVICES 64 -static COMDevice comDevices[COM_MAXDEVICES]; -static int noDevices = 0; - -#define COM_MINDEVNAME 16384 -const char * comPtn = "COM???"; - -/*****************************************************************************/ -const char * findPattern(const char * string, const char * pattern, int * value); -const char * portInternalName(int index); - -/*****************************************************************************/ -typedef struct _COMMTIMEOUTS { - uint32_t ReadIntervalTimeout; - uint32_t ReadTotalTimeoutMultiplier; - uint32_t ReadTotalTimeoutConstant; - uint32_t WriteTotalTimeoutMultiplier; - uint32_t WriteTotalTimeoutConstant; -} COMMTIMEOUTS; - -typedef struct _DCB { - uint32_t DCBlength; - uint32_t BaudRate; - uint32_t fBinary :1; - uint32_t fParity :1; - uint32_t fOutxCtsFlow :1; - uint32_t fOutxDsrFlow :1; - uint32_t fDtrControl :2; - uint32_t fDsrSensitivity :1; - uint32_t fTXContinueOnXoff :1; - uint32_t fOutX :1; - uint32_t fInX :1; - uint32_t fErrorChar :1; - uint32_t fNull :1; - uint32_t fRtsControl :2; - uint32_t fAbortOnError :1; - uint32_t fDummy2 :17; - uint16_t wReserved; - uint16_t XonLim; - uint16_t XoffLim; - uint8_t ByteSize; - uint8_t Parity; - uint8_t StopBits; - int8_t XonChar; - int8_t XoffChar; - int8_t ErrorChar; - int8_t EofChar; - int8_t EvtChar; - uint16_t wReserved1; -} DCB; - -/*****************************************************************************/ -/** Windows system constants */ -#define ERROR_INSUFFICIENT_BUFFER 122 -#define INVALID_HANDLE_VALUE ((void *) -1) -#define GENERIC_READ 0x80000000 -#define GENERIC_WRITE 0x40000000 -#define OPEN_EXISTING 3 -#define MAX_DWORD 0xFFFFFFFF - -/*****************************************************************************/ -/** Windows system functions */ -void * __stdcall CreateFileA(const char * lpFileName, uint32_t dwDesiredAccess, uint32_t dwShareMode, void * lpSecurityAttributes, uint32_t dwCreationDisposition, uint32_t dwFlagsAndAttributes, void * hTemplateFile); -bool __stdcall WriteFile(void * hFile, const void * lpBuffer, uint32_t nNumberOfBytesToWrite, uint32_t * lpNumberOfBytesWritten, void * lpOverlapped); -bool __stdcall ReadFile(void * hFile, void * lpBuffer, uint32_t nNumberOfBytesToRead, uint32_t * lpNumberOfBytesRead, void * lpOverlapped); -bool __stdcall CloseHandle(void * hFile); - -uint32_t __stdcall GetLastError(void); -void __stdcall SetLastError(uint32_t dwErrCode); - -uint32_t __stdcall QueryDosDeviceA(const char * lpDeviceName, char * lpTargetPath, uint32_t ucchMax); - -bool __stdcall GetCommState(void * hFile, DCB * lpDCB); -bool __stdcall GetCommTimeouts(void * hFile, COMMTIMEOUTS * lpCommTimeouts); -bool __stdcall SetCommState(void * hFile, DCB * lpDCB); -bool __stdcall SetCommTimeouts(void * hFile, COMMTIMEOUTS * lpCommTimeouts); -bool __stdcall SetupComm(void * hFile, uint32_t dwInQueue, uint32_t dwOutQueue); - -/*****************************************************************************/ -int comEnumerate() -{ -// Get devices information text - size_t size = COM_MINDEVNAME; - char * list = (char *) malloc(size); - SetLastError(0); - QueryDosDeviceA(NULL, list, size); - while (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - size *= 2; - char * nlist = realloc(list, size); - if (!nlist) { - free(list); - return 0; - } - list = nlist; - SetLastError(0); - QueryDosDeviceA(NULL, list, size); - } -// Gather all COM ports - int port; - const char * nlist = findPattern(list, comPtn, &port); - noDevices = 0; - while(port > 0 && noDevices < COM_MAXDEVICES) { - COMDevice * com = &comDevices[noDevices ++]; - com->port = port; - com->handle = 0; - nlist = findPattern(nlist, comPtn, &port); - } - free(list); - return noDevices; -} - -void comTerminate() -{ - comCloseAll(); -} - -int comGetNoPorts() -{ - return noDevices; -} - -/*****************************************************************************/ -const char * comGetPortName(int index) -{ - #define COM_MAXNAME 32 - static char name[COM_MAXNAME]; - if (index < 0 || index >= noDevices) - return 0; - sprintf(name, "COM%i", comDevices[index].port); - return name; -} - -int comFindPort(const char * name) -{ - for (int i = 0; i < noDevices; i++) - if (strcmp(name, comGetPortName(i)) == 0) - return i; - return -1; -} - -const char * comGetInternalName(int index) -{ - #define COM_MAXNAME 32 - static char name[COM_MAXNAME]; - if (index < 0 || index >= noDevices) - return 0; - sprintf(name, "//./COM%i", comDevices[index].port); - return name; -} - -/*****************************************************************************/ -int comOpen(int index, int baudrate) -{ - DCB config; - COMMTIMEOUTS timeouts; - if (index < 0 || index >= noDevices) - return 0; -// Close if already open - COMDevice * com = &comDevices[index]; - if (com->handle) comClose(index); -// Open COM port - void * handle = CreateFileA(comGetInternalName(index), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (handle == INVALID_HANDLE_VALUE) - return 0; - com->handle = handle; -// Prepare read / write timeouts - SetupComm(handle, 64, 64); - timeouts.ReadIntervalTimeout = MAX_DWORD; - timeouts.ReadTotalTimeoutConstant = 0; - timeouts.WriteTotalTimeoutConstant = 0; - timeouts.ReadTotalTimeoutMultiplier = 0; - timeouts.WriteTotalTimeoutMultiplier = 0; - SetCommTimeouts(handle, &timeouts); -// Prepare serial communication format - GetCommState(handle, &config); - config.BaudRate = baudrate; - config.fBinary = true; - config.fParity = 0; - config.fErrorChar = 0; - config.fNull = 0; - config.fAbortOnError = 0; - config.ByteSize = 8; - config.Parity = 0; - config.StopBits = 0; - config.EvtChar = '\n'; -// Set the port state - if (SetCommState(handle, &config) == 0) { - CloseHandle(handle); - return 0; - } - return 1; -} - -void comClose(int index) -{ - if (index < 0 || index >= noDevices) - return; - COMDevice * com = &comDevices[index]; - if (!com->handle) - return; - CloseHandle(com->handle); - com->handle = 0; -} - -void comCloseAll() -{ - for (int i = 0; i < noDevices; i++) - comClose(i); -} - -/*****************************************************************************/ -int comWrite(int index, const char * buffer, size_t len) -{ - if (index < 0 || index >= noDevices) - return 0; - COMDevice * com = &comDevices[index]; - uint32_t bytes = 0; - WriteFile(com->handle, buffer, len, &bytes, NULL); - return bytes; -} - -int comRead(int index, char * buffer, size_t len) -{ - if (index < 0 || index >= noDevices) - return 0; - COMDevice * com = &comDevices[index]; - uint32_t bytes = 0; - ReadFile(com->handle, buffer, len, &bytes, NULL); - return bytes; -} - -/*****************************************************************************/ -const char * findPattern(const char * string, const char * pattern, int * value) -{ - char c, n = 0; - const char * sp = string; - const char * pp = pattern; -// Check for the string pattern - while (1) { - c = *sp ++; - if (c == '\0') { - if (*pp == '?') break; - if (*sp == '\0') break; - n = 0; - pp = pattern; - }else{ - if (*pp == '?') { - // Expect a digit - if (c >= '0' && c <= '9') { - n = n * 10 + (c - '0'); - if (*pp ++ == '\0') break; - }else{ - n = 0; - pp = comPtn; - } - }else{ - // Expect a character - if (c == *pp) { - if (*pp ++ == '\0') break; - }else{ - n = 0; - pp = comPtn; - } - } - } - } -// Return the value - * value = n; - return sp; -} - -#endif // _WIN32 diff --git a/radio/src/targets/simu/rs232.h b/radio/src/targets/simu/rs232.h deleted file mode 100644 index 73fc13c72e6..00000000000 --- a/radio/src/targets/simu/rs232.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - Cross-platform serial / RS232 library - Version 0.21, 11/10/2015 - -> All platforms header - -> rs232.h - - The MIT License (MIT) - - Copyright (c) 2013-2015 Frédéric Meslin, Florent Touchard - Email: fredericmeslin@hotmail.com - Website: www.fredslab.net - Twitter: @marzacdev - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. -*/ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - - #include - #include - -/*****************************************************************************/ - /* Doxywizard specific */ - /** - * \mainpage RS232 - * \section intro_sec C / C++ RS232 cross-platform serial library - * Version 0.21 - 11/10/2015 - * - * Supported platforms: - * - Windows (XP / Win7, possibly 8 and 10) - * - Linux - * - MacOS X - * - * Copyright (c) 2013-2015 Frédéric Meslin, Florent Touchard
- * Email: fredericmeslin@hotmail.com
- * Website: www.fredslab.net
- * Twitter: \@marzacdev
- */ - -/*****************************************************************************/ - /** - * \fn int comEnumerate() - * \brief Enumerate available serial ports (Serial, USB serial, Bluetooth serial) - * \return number of enumerated ports - */ - int comEnumerate(); - - /** - * \fn int comGetNoPorts() - * \brief Return the number of enumerated ports - * \return number of enumerated ports - */ - int comGetNoPorts(); - - /** - * \fn int comTerminate() - * \brief Release ports and memory resources used by the library - */ - void comTerminate(); - - /** - * \fn const char * comGetPortName(int index) - * \brief Get port user-friendly name - * \param[in] index port index - * \return null terminated port name - */ - const char * comGetPortName(int index); - - /** - * \fn const char * comGetInternalName(int index) - * \brief Get port operating-system name - * \param[in] index port index - * \return null terminated port name - */ - const char * comGetInternalName(int index); - - /** - * \fn int comFindPort(const char * name) - * \brief Try to find a port given its user-friendly name - * \param[in] name port name (case sensitive) - * \return index of found port or -1 if not enumerated - */ - int comFindPort(const char * name); - -/*****************************************************************************/ - /** - * \fn int comOpen(int index, int baudrate) - * \brief Try to open a port at a specific baudrate - * \brief (No parity, single stop bit, no hardware flow control) - * \param[in] index port index - * \param[in] baudrate port baudrate - * \return 1 if opened, 0 if not available - */ - int comOpen(int index, int baudrate); - - /** - * \fn void comClose(int index) - * \brief Close an opened port - * \param[in] index port index - */ - void comClose(int index); - - /** - * \fn void comCloseAll() - * \brief Close all opened ports - */ - void comCloseAll(); - -/*****************************************************************************/ - /** - * \fn int comWrite(int index, const char * buffer, size_t len) - * \brief Write data to the port (non-blocking) - * \param[in] index port index - * \param[in] buffer pointer to transmit buffer - * \param[in] len length of transmit buffer in bytes - * \return number of bytes transferred - */ - int comWrite(int index, const char * buffer, size_t len); - - /** - * \fn int comRead(int index, const char * buffer, size_t len) - * \brief Read data from the port (non-blocking) - * \param[in] index port index - * \param[in] buffer pointer to receive buffer - * \param[in] len length of receive buffer in bytes - * \return number of bytes transferred - */ - int comRead(int index, char * buffer, size_t len); - -#ifdef __cplusplus -} -#endif diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index b44c422f6fc..4ea957029e0 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -36,9 +36,6 @@ #include #include #include -#ifdef SIMU_COM_PORT - #include "rs232.h" -#endif #if !defined (_MSC_VER) || defined (__GNUC__) #include @@ -606,60 +603,28 @@ const etx_serial_port_t UsbSerialPort = { "USB-VCP", nullptr, nullptr }; #endif #if defined(AUX_SERIAL) || defined(AUX2_SERIAL) -static void* _fake_drv_init(void* n, const etx_serial_init* dev) { -#ifdef SIMU_COM_PORT - static bool init = false; - if (!init) { - comEnumerate(); - init=true; - } - comOpen(SIMU_COM_PORT, dev->baudrate); -#endif - return (void*)1; - } -static void _fake_drv_fct1(void*) { -#ifdef SIMU_COM_PORT - comClose(SIMU_COM_PORT); -#endif -} -static void _fake_drv_send_byte(void*, uint8_t b) { -#ifdef SIMU_COM_PORT - comWrite(SIMU_COM_PORT, (char*)&b, 1); -#endif -} -static void _fake_drv_send_buffer(void*, const uint8_t* b, uint32_t l) { -#ifdef SIMU_COM_PORT - comWrite(SIMU_COM_PORT, (char*)b, l); -#endif -} -static int _fake_drv_get_byte(void*, uint8_t* b) { -#ifdef SIMU_COM_PORT - return comRead(SIMU_COM_PORT, (char*)b, 1); -#else - return 0; -#endif - } -static void _fake_drv_set_baudrate(void*, uint32_t baudrate) { -#ifdef SIMU_COM_PORT - comClose(SIMU_COM_PORT); - comOpen(SIMU_COM_PORT, baudrate); -#endif -} -static const etx_serial_driver_t _fake_drv = { - .init = _fake_drv_init, - .deinit = _fake_drv_fct1, - .sendByte = _fake_drv_send_byte, - .sendBuffer = _fake_drv_send_buffer, +static void* null_drv_init(void* hw_def, const etx_serial_init* dev) { return nullptr; } +static void null_drv_deinit(void* ctx) { } +static void null_drv_send_byte(void* ctx, uint8_t b) { } +static void null_drv_send_buffer(void* ctx, const uint8_t* b, uint32_t l) { } +static int null_drv_get_byte(void* ctx, uint8_t* b) { return 0; } +static void null_drv_set_baudrate(void* ctx, uint32_t baudrate) { } + +const etx_serial_driver_t null_drv = { + .init = null_drv_init, + .deinit = null_drv_deinit, + .sendByte = null_drv_send_byte, + .sendBuffer = null_drv_send_buffer, .txCompleted = nullptr, .waitForTxCompleted = nullptr, .enableRx = nullptr, - .getByte = _fake_drv_get_byte, + .getByte = null_drv_get_byte, .getLastByte = nullptr, .getBufferedBytes = nullptr, .copyRxBuffer = nullptr, .clearRxBuffer = nullptr, .getBaudrate = nullptr, - .setBaudrate = _fake_drv_set_baudrate, + .setBaudrate = null_drv_set_baudrate, .setPolarity = nullptr, .setHWOption = nullptr, .setReceiveCb = nullptr, @@ -670,14 +635,14 @@ static const etx_serial_driver_t _fake_drv = { #if defined(AUX_SERIAL) #if defined(AUX_SERIAL_PWR_GPIO) - static void _fake_pwr_aux(uint8_t) {} - #define AUX_SERIAL_PWR _fake_pwr_aux + static void simulator_host_pwr_aux(uint8_t) {} + #define AUX_SERIAL_PWR simulator_host_pwr_aux #else #define AUX_SERIAL_PWR nullptr #endif -static const etx_serial_port_t auxSerialPort = { +static etx_serial_port_t auxSerialPort = { "AUX1", - &_fake_drv, + &null_drv, nullptr, AUX_SERIAL_PWR }; @@ -688,14 +653,14 @@ static const etx_serial_port_t auxSerialPort = { #if defined(AUX2_SERIAL) #if defined(AUX_SERIAL_PWR_GPIO) - static void _fake_pwr_aux2(uint8_t) {} - #define AUX2_SERIAL_PWR _fake_pwr_aux2 + static void simulator_host_pwr_aux2(uint8_t) {} + #define AUX2_SERIAL_PWR simulator_host_pwr_aux2 #else #define AUX2_SERIAL_PWR nullptr #endif -static const etx_serial_port_t aux2SerialPort = { +static etx_serial_port_t aux2SerialPort = { "AUX2", - &_fake_drv, + &null_drv, nullptr, AUX2_SERIAL_PWR }; @@ -704,7 +669,7 @@ static const etx_serial_port_t aux2SerialPort = { #define AUX2_SERIAL_PORT nullptr #endif // AUX2_SERIAL -static const etx_serial_port_t* serialPorts[MAX_AUX_SERIAL] = { +etx_serial_port_t* serialPorts[MAX_AUX_SERIAL] = { AUX_SERIAL_PORT, AUX2_SERIAL_PORT, }; diff --git a/tools/setup_buildenv_ubuntu20.04.sh b/tools/setup_buildenv_ubuntu20.04.sh index 02fea607c48..6cd02ff3852 100755 --- a/tools/setup_buildenv_ubuntu20.04.sh +++ b/tools/setup_buildenv_ubuntu20.04.sh @@ -42,7 +42,7 @@ if [[ $PAUSEAFTEREACHLINE == "true" ]]; then fi echo "=== Step $((STEP++)): Installing packages ===" -sudo apt-get -y install build-essential cmake gcc git lib32ncurses-dev lib32z1 libfox-1.6-dev libsdl2-dev qt5-default qtmultimedia5-dev qttools5-dev qttools5-dev-tools qtcreator libqt5svg5-dev software-properties-common wget zip python-pip-whl python-pil libgtest-dev python3-pip python3-tk python3-setuptools clang-7 python-clang-7 libusb-1.0-0-dev stlink-tools openocd npm pv libncurses5:i386 libpython2.7:i386 libclang-6.0-dev python-is-python3 +sudo apt-get -y install build-essential cmake gcc git lib32ncurses-dev lib32z1 libfox-1.6-dev libsdl2-dev qt5-default qtmultimedia5-dev qttools5-dev qttools5-dev-tools qtcreator libqt5svg5-dev libqt5serialport5-dev software-properties-common wget zip python-pip-whl python-pil libgtest-dev python3-pip python3-tk python3-setuptools clang-7 python-clang-7 libusb-1.0-0-dev stlink-tools openocd npm pv libncurses5:i386 libpython2.7:i386 libclang-6.0-dev python-is-python3 if [[ $PAUSEAFTEREACHLINE == "true" ]]; then echo "Step finished. Please check the output above and press Enter to continue or Ctrl+C to stop." read diff --git a/tools/setup_buildenv_ubuntu22.04.sh b/tools/setup_buildenv_ubuntu22.04.sh index 710fcf48a42..cb65ea8e8db 100755 --- a/tools/setup_buildenv_ubuntu22.04.sh +++ b/tools/setup_buildenv_ubuntu22.04.sh @@ -42,7 +42,7 @@ if [[ $PAUSEAFTEREACHLINE == "true" ]]; then fi echo "=== Step $((STEP++)): Installing packages ===" -sudo apt-get -y install build-essential cmake gcc git lib32ncurses-dev lib32z1 libfox-1.6-dev libsdl2-dev qtbase5-dev qt5-qmake qtmultimedia5-dev qttools5-dev qttools5-dev-tools qtcreator libqt5svg5-dev software-properties-common wget zip python3-pip-whl python3-pil libgtest-dev python3-pip python3-tk python3-setuptools clang python3-clang libusb-1.0-0-dev stlink-tools openocd npm pv libncurses5:i386 libpython2.7:i386 libclang-dev python-is-python3 +sudo apt-get -y install build-essential cmake gcc git lib32ncurses-dev lib32z1 libfox-1.6-dev libsdl2-dev qtbase5-dev qt5-qmake qtmultimedia5-dev qttools5-dev qttools5-dev-tools qtcreator libqt5svg5-dev libqt5serialport5-dev software-properties-common wget zip python3-pip-whl python3-pil libgtest-dev python3-pip python3-tk python3-setuptools clang python3-clang libusb-1.0-0-dev stlink-tools openocd npm pv libncurses5:i386 libpython2.7:i386 libclang-dev python-is-python3 if [[ $PAUSEAFTEREACHLINE == "true" ]]; then echo "Step finished. Please check the output above and press Enter to continue or Ctrl+C to stop." read From d62bced0f1c75edefa5200a3381c67e33c2769f5 Mon Sep 17 00:00:00 2001 From: Nigel Williams Date: Mon, 7 Oct 2024 20:09:41 +1100 Subject: [PATCH 2/4] fixup! feat(simu): cross-platform connection of host serial ports to simu radio --- companion/src/simulation/serialportsdialog.cpp | 4 ---- companion/src/simulation/serialportsdialog.h | 2 -- 2 files changed, 6 deletions(-) diff --git a/companion/src/simulation/serialportsdialog.cpp b/companion/src/simulation/serialportsdialog.cpp index 73e79f2bdb7..3d21e706348 100644 --- a/companion/src/simulation/serialportsdialog.cpp +++ b/companion/src/simulation/serialportsdialog.cpp @@ -22,10 +22,6 @@ #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) diff --git a/companion/src/simulation/serialportsdialog.h b/companion/src/simulation/serialportsdialog.h index f24bc81957b..0e7baf966c4 100644 --- a/companion/src/simulation/serialportsdialog.h +++ b/companion/src/simulation/serialportsdialog.h @@ -24,8 +24,6 @@ #include #include #include -#include "appdata.h" -#include "joystick.h" class QComboBox; From bf748accc1edabf6fdaaebf2f8e8f5aae706162c Mon Sep 17 00:00:00 2001 From: Nigel Williams Date: Mon, 7 Oct 2024 20:10:02 +1100 Subject: [PATCH 3/4] fixup! feat(simu): cross-platform connection of host serial ports to simu radio --- companion/src/simulation/serialportsdialog.cpp | 6 +++++- companion/src/simulation/serialportsdialog.h | 5 ++++- companion/src/simulation/simulatormainwindow.cpp | 2 +- radio/src/targets/simu/simpgmspace.cpp | 8 ++++---- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/companion/src/simulation/serialportsdialog.cpp b/companion/src/simulation/serialportsdialog.cpp index 3d21e706348..6c1096a51fd 100644 --- a/companion/src/simulation/serialportsdialog.cpp +++ b/companion/src/simulation/serialportsdialog.cpp @@ -22,8 +22,9 @@ #include "serialportsdialog.h" #include "ui_serialportsdialog.h" -SerialPortsDialog::SerialPortsDialog(QWidget *parent) : +SerialPortsDialog::SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator) : QDialog(parent), + simulator(simulator), ui(new Ui::SerialPortsDialog) { ui->setupUi(this); @@ -33,6 +34,9 @@ SerialPortsDialog::SerialPortsDialog(QWidget *parent) : populateSerialPortCombo(ui->aux1Combo); populateSerialPortCombo(ui->aux2Combo); + + ui->aux1Combo->setEnabled(simulator->getCapability(SimulatorInterface::Capability::CAP_SERIAL_AUX1)); + ui->aux2Combo->setEnabled(simulator->getCapability(SimulatorInterface::Capability::CAP_SERIAL_AUX2)); } SerialPortsDialog::~SerialPortsDialog() diff --git a/companion/src/simulation/serialportsdialog.h b/companion/src/simulation/serialportsdialog.h index 0e7baf966c4..897d38a3224 100644 --- a/companion/src/simulation/serialportsdialog.h +++ b/companion/src/simulation/serialportsdialog.h @@ -25,6 +25,8 @@ #include #include +#include "simulatorinterface.h" + class QComboBox; namespace Ui { @@ -36,10 +38,11 @@ class SerialPortsDialog : public QDialog Q_OBJECT public: - explicit SerialPortsDialog(QWidget *parent = 0); + explicit SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator); ~SerialPortsDialog(); QString aux1; QString aux2; + SimulatorInterface *simulator; private: Ui::SerialPortsDialog *ui; diff --git a/companion/src/simulation/simulatormainwindow.cpp b/companion/src/simulation/simulatormainwindow.cpp index fec93b8c993..707cc6b0970 100644 --- a/companion/src/simulation/simulatormainwindow.cpp +++ b/companion/src/simulation/simulatormainwindow.cpp @@ -482,7 +482,7 @@ void SimulatorMainWindow::openJoystickDialog(bool) void SimulatorMainWindow::openSerialPortsDialog(bool) { - SerialPortsDialog * dialog = new SerialPortsDialog(this); + SerialPortsDialog * dialog = new SerialPortsDialog(this, m_simulator); if (dialog->exec() == QDialog::Accepted && m_simulator) { hostSerialConnector->connectSerialPort(0, dialog->aux1); hostSerialConnector->connectSerialPort(1, dialog->aux2); diff --git a/radio/src/targets/simu/simpgmspace.cpp b/radio/src/targets/simu/simpgmspace.cpp index 4ea957029e0..803c2878229 100644 --- a/radio/src/targets/simu/simpgmspace.cpp +++ b/radio/src/targets/simu/simpgmspace.cpp @@ -631,12 +631,13 @@ const etx_serial_driver_t null_drv = { .setIdleCb = nullptr, .setBaudrateCb = nullptr, }; + +static void null_pwr_aux(uint8_t) {} #endif #if defined(AUX_SERIAL) #if defined(AUX_SERIAL_PWR_GPIO) - static void simulator_host_pwr_aux(uint8_t) {} - #define AUX_SERIAL_PWR simulator_host_pwr_aux + #define AUX_SERIAL_PWR null_pwr_aux #else #define AUX_SERIAL_PWR nullptr #endif @@ -653,8 +654,7 @@ static etx_serial_port_t auxSerialPort = { #if defined(AUX2_SERIAL) #if defined(AUX_SERIAL_PWR_GPIO) - static void simulator_host_pwr_aux2(uint8_t) {} - #define AUX2_SERIAL_PWR simulator_host_pwr_aux2 + #define AUX2_SERIAL_PWR null_pwr_aux #else #define AUX2_SERIAL_PWR nullptr #endif From 097968dfdc636245d7bdfd01894aca2bdfad02a7 Mon Sep 17 00:00:00 2001 From: Nigel Williams Date: Tue, 8 Oct 2024 17:20:45 +1100 Subject: [PATCH 4/4] fixup! feat(simu): cross-platform connection of host serial ports to simu radio --- .../src/simulation/hostserialconnector.cpp | 32 +++++++++++++++---- .../src/simulation/hostserialconnector.h | 6 ++-- .../src/simulation/serialportsdialog.cpp | 24 ++++++++------ companion/src/simulation/serialportsdialog.h | 6 ++-- companion/src/simulation/simulatorinterface.h | 16 +++++----- .../src/simulation/simulatormainwindow.cpp | 2 +- 6 files changed, 58 insertions(+), 28 deletions(-) diff --git a/companion/src/simulation/hostserialconnector.cpp b/companion/src/simulation/hostserialconnector.cpp index 27d531580f0..5bee5921a5e 100644 --- a/companion/src/simulation/hostserialconnector.cpp +++ b/companion/src/simulation/hostserialconnector.cpp @@ -24,8 +24,12 @@ HostSerialConnector::HostSerialConnector(QObject *parent, SimulatorInterface *simulator) : simulator(simulator) { - for (int i = 0; i < MAX_HOST_SERIAL; i++) + 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() @@ -38,6 +42,20 @@ HostSerialConnector::~HostSerialConnector() } } +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) @@ -85,7 +103,7 @@ void HostSerialConnector::sendSerialData(const quint8 index, const QByteArray & port->write(data); } -void HostSerialConnector::setSerialEncoding(const quint8 index, const SimulatorInterface::SerialEncoding encoding) +void HostSerialConnector::setSerialEncoding(const quint8 index, const quint8 encoding) { if (index >= MAX_HOST_SERIAL) return; @@ -99,12 +117,12 @@ void HostSerialConnector::setSerialEncoding(const quint8 index, const SimulatorI return; switch(encoding) { - case SimulatorInterface::SerialEncoding::SERIAL_ENCODING_8N1: + case SERIAL_ENCODING_8N1: port->setDataBits(QSerialPort::Data8); port->setParity(QSerialPort::NoParity); port->setStopBits(QSerialPort::OneStop); break; - case SimulatorInterface::SerialEncoding::SERIAL_ENCODING_8E2: + case SERIAL_ENCODING_8E2: port->setDataBits(QSerialPort::Data8); port->setParity(QSerialPort::EvenParity); port->setStopBits(QSerialPort::TwoStop); @@ -145,8 +163,10 @@ void HostSerialConnector::serialStart(const quint8 index) if (port == nullptr) return; - if (!port->open(QIODevice::ReadWrite)) - qDebug() << "Failed to open host serial " << index; + if (port->open(QIODevice::ReadWrite)) + qDebug() << "Opened host serial " << index; + else + qDebug() << "Failed to open host serial " << index << ": " << port->errorString(); } void HostSerialConnector::serialStop(const quint8 index) diff --git a/companion/src/simulation/hostserialconnector.h b/companion/src/simulation/hostserialconnector.h index 5284799c8aa..b4ab4914df2 100644 --- a/companion/src/simulation/hostserialconnector.h +++ b/companion/src/simulation/hostserialconnector.h @@ -36,10 +36,12 @@ class HostSerialConnector : public QObject 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 SimulatorInterface::SerialEncoding encoding); + 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); @@ -49,7 +51,7 @@ class HostSerialConnector : public QObject QRecursiveMutex hostAuxPortsMutex; QSerialPort * hostAuxPorts[MAX_HOST_SERIAL]; - SimulatorInterface::SerialEncoding hostAuxPortsEncoding[MAX_HOST_SERIAL]; + quint8 hostAuxPortsEncoding[MAX_HOST_SERIAL]; quint32 hostAuxPortsBaudRate[MAX_HOST_SERIAL]; bool hostAuxPortsOpen[MAX_HOST_SERIAL]; }; diff --git a/companion/src/simulation/serialportsdialog.cpp b/companion/src/simulation/serialportsdialog.cpp index 6c1096a51fd..4e14a94ea45 100644 --- a/companion/src/simulation/serialportsdialog.cpp +++ b/companion/src/simulation/serialportsdialog.cpp @@ -22,18 +22,19 @@ #include "serialportsdialog.h" #include "ui_serialportsdialog.h" -SerialPortsDialog::SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator) : +SerialPortsDialog::SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator, HostSerialConnector *connector) : QDialog(parent), simulator(simulator), + connector(connector), ui(new Ui::SerialPortsDialog) { ui->setupUi(this); - aux1 = QString(""); - aux2 = QString(""); + aux1 = connector->getConnectedSerialPortName(0); + aux2 = connector->getConnectedSerialPortName(1); - populateSerialPortCombo(ui->aux1Combo); - populateSerialPortCombo(ui->aux2Combo); + 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)); @@ -44,15 +45,20 @@ SerialPortsDialog::~SerialPortsDialog() delete ui; } -void SerialPortsDialog::populateSerialPortCombo(QComboBox * cb) +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.systemLocation(), portInfo.portName()); + cb->addItem(portInfo.portName(), portInfo.portName()); + if (portInfo.portName() == currentPortName) + cb->setCurrentIndex(i + 1); } } @@ -68,8 +74,8 @@ void SerialPortsDialog::on_okButton_clicked() void SerialPortsDialog::on_refreshButton_clicked() { - populateSerialPortCombo(ui->aux1Combo); - populateSerialPortCombo(ui->aux2Combo); + populateSerialPortCombo(ui->aux1Combo, aux1); + populateSerialPortCombo(ui->aux2Combo, aux2); } void SerialPortsDialog::on_aux1Combo_currentIndexChanged(int index) diff --git a/companion/src/simulation/serialportsdialog.h b/companion/src/simulation/serialportsdialog.h index 897d38a3224..cde7dce96a4 100644 --- a/companion/src/simulation/serialportsdialog.h +++ b/companion/src/simulation/serialportsdialog.h @@ -26,6 +26,7 @@ #include #include "simulatorinterface.h" +#include "hostserialconnector.h" class QComboBox; @@ -38,17 +39,18 @@ class SerialPortsDialog : public QDialog Q_OBJECT public: - explicit SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator); + explicit SerialPortsDialog(QWidget *parent, SimulatorInterface *simulator, HostSerialConnector *connector); ~SerialPortsDialog(); QString aux1; QString aux2; SimulatorInterface *simulator; + HostSerialConnector *connector; private: Ui::SerialPortsDialog *ui; private slots: - void populateSerialPortCombo(QComboBox * cb); + void populateSerialPortCombo(QComboBox * cb, QString currentPortName); void on_cancelButton_clicked(); void on_okButton_clicked(); void on_refreshButton_clicked(); diff --git a/companion/src/simulation/simulatorinterface.h b/companion/src/simulation/simulatorinterface.h index e860dcb979b..b04379b8e2b 100644 --- a/companion/src/simulation/simulatorinterface.h +++ b/companion/src/simulation/simulatorinterface.h @@ -45,6 +45,13 @@ enum SimulatorTelemetryProtocol { SIMU_TELEMETRY_PROTOCOL_COUNT }; +enum SimulatorSerialEncoding { + SERIAL_ENCODING_8N1 = 0, + SERIAL_ENCODING_8E2, + SERIAL_ENCODING_PXX1_PWM, + SERIAL_ENCODING_COUNT +}; + class SimulatorInterface : public QObject { Q_OBJECT @@ -90,13 +97,6 @@ class SimulatorInterface : public QObject CAP_ENUM_COUNT }; - enum SerialEncoding { - SERIAL_ENCODING_8N1, - SERIAL_ENCODING_8E2, - SERIAL_ENCODING_PXX1_PWM, - SERIAL_ENCODING_COUNT - }; - // This allows automatic en/decoding of flight mode + gvarIdx value to/from any int32 struct gVarMode_t { int16_t value; @@ -188,7 +188,7 @@ class SimulatorInterface : public QObject void gVarValueChange(quint8 index, qint32 value); void outputValueChange(int type, quint8 index, qint32 value); void auxSerialSendData(const quint8 port_num, const QByteArray & data); - void auxSerialSetEncoding(const quint8 port_num, const SerialEncoding encoding); + void auxSerialSetEncoding(const quint8 port_num, const quint8 encoding); void auxSerialSetBaudrate(const quint8 port_num, const quint32 baudrate); void auxSerialStart(const quint8 port_num); void auxSerialStop(const quint8 port_num); diff --git a/companion/src/simulation/simulatormainwindow.cpp b/companion/src/simulation/simulatormainwindow.cpp index 707cc6b0970..ea818c820b6 100644 --- a/companion/src/simulation/simulatormainwindow.cpp +++ b/companion/src/simulation/simulatormainwindow.cpp @@ -482,7 +482,7 @@ void SimulatorMainWindow::openJoystickDialog(bool) void SimulatorMainWindow::openSerialPortsDialog(bool) { - SerialPortsDialog * dialog = new SerialPortsDialog(this, m_simulator); + SerialPortsDialog * dialog = new SerialPortsDialog(this, m_simulator, hostSerialConnector); if (dialog->exec() == QDialog::Accepted && m_simulator) { hostSerialConnector->connectSerialPort(0, dialog->aux1); hostSerialConnector->connectSerialPort(1, dialog->aux2);