feat(cpn): update telemetry simulation to include FrSky Hub (#5475)

This commit is contained in:
Nigel Williams
2024-08-26 09:44:35 +10:00
committed by GitHub
parent e0a3097620
commit 982660e8c8
8 changed files with 1876 additions and 16 deletions
+1
View File
@@ -14,6 +14,7 @@ set(${PROJECT_NAME}_NAMES
telemetrysimu
telemetryprovidercrossfire
telemetryproviderfrsky
telemetryproviderfrskyhub
trainersimu
widgets/lcdwidget
widgets/radiowidget
@@ -41,6 +41,7 @@ enum SimulatorTelemetryProtocol {
SIMU_TELEMETRY_PROTOCOL_FRSKY_SPORT = 0,
SIMU_TELEMETRY_PROTOCOL_FRSKY_HUB,
SIMU_TELEMETRY_PROTOCOL_CROSSFIRE,
SIMU_TELEMETRY_PROTOCOL_FRSKY_HUB_OOB,
SIMU_TELEMETRY_PROTOCOL_COUNT
};
@@ -0,0 +1,450 @@
/*
* 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 <QMessageBox>
#include <QFileDialog>
#include "appdata.h"
#include "telemetryproviderfrskyhub.h"
#include "ui_telemetryproviderfrskyhub.h"
#include "telem_data.h"
#include "radio/src/telemetry/frsky_defs.h"
template<class t> t LIMIT(t mi, t x, t ma) { return std::min(std::max(mi, x), ma); }
TelemetryProviderFrSkyHub::TelemetryProviderFrSkyHub(QWidget * parent):
QWidget(parent),
ui(new Ui::TelemetryProviderFrSkyHub)
{
ui->setupUi(this);
// Set default values from UI definition into GPS
gps.setLatLon(ui->input_gps->text());
gps.setCourseDegrees(ui->input_hdg->value());
gps.setSpeedKMH(ui->input_gspd->value());
gps.setAltitude(ui->input_galt->value());
gps.setDateTime(ui->input_date->dateTime());
connect(ui->input_hdg, QOverload<double>::of(&QDoubleSpinBox::valueChanged), &gps, &SimulatedGPS::setCourseDegrees);
connect(ui->input_gps, &QLineEdit::textChanged, &gps, &SimulatedGPS::setLatLon);
connect(ui->input_gspd, QOverload<double>::of(&QDoubleSpinBox::valueChanged), &gps, &SimulatedGPS::setSpeedKMH);
connect(ui->input_galt, QOverload<double>::of(&QDoubleSpinBox::valueChanged), &gps, &SimulatedGPS::setAltitude);
connect(&gps, &SimulatedGPS::positionChanged, ui->input_gps, &QLineEdit::setText);
connect(&gps, &SimulatedGPS::courseDegreesChanged, ui->input_hdg, QOverload<double>::of(&QDoubleSpinBox::setValue));
connect(&gps, QOverload<QDateTime>::of(&SimulatedGPS::dateTimeChanged), ui->input_date, &QDateTimeEdit::setDateTime);
// Create this once
supportedLogItems.clear();
supportedLogItems.insert("RSSI", "");
supportedLogItems.insert("A1", "V");
supportedLogItems.insert("A2", "V");
supportedLogItems.insert("TRSS", "dB");
supportedLogItems.insert("RQly", "");
supportedLogItems.insert("TQly", "");
supportedLogItems.insert("RPM", "rpm");
supportedLogItems.insert("Fuel", "%");
supportedLogItems.insert("Tmp1", "°C");
supportedLogItems.insert("Tmp2", "°C");
supportedLogItems.insert("VFAS", "V");
supportedLogItems.insert("Curr", "A");
supportedLogItems.insert("VSpd", "m/s");
supportedLogItems.insert("Alt", "m");
supportedLogItems.insert("GPS", "");
supportedLogItems.insert("GSpd", "kts");
supportedLogItems.insert("Hdg", "°");
supportedLogItems.insert("GAlt", "m");
supportedLogItems.insert("Date", "");
supportedLogItems.insert("AccX", "g");
supportedLogItems.insert("AccY", "g");
supportedLogItems.insert("AccZ", "g");
}
TelemetryProviderFrSkyHub::~TelemetryProviderFrSkyHub()
{
delete ui;
}
QHash<QString, QString> * TelemetryProviderFrSkyHub::getSupportedLogItems()
{
return &supportedLogItems;
}
QString TelemetryProviderFrSkyHub::getLogfileIdentifier()
{
return QString("TELEMETRY_DATA: FrSky Hub");
}
void TelemetryProviderFrSkyHub::loadItemFromLog(QString item, QString value)
{
if (item == "RSSI") ui->input_rssi->setValue(value.toInt());
if (item == "A1") ui->input_a1->setValue(value.toDouble());
if (item == "A2") ui->input_a2->setValue(value.toDouble());
if (item == "TRSS") ui->input_trss->setValue(value.toInt());
if (item == "RQly") ui->input_rqly->setValue(value.toInt());
if (item == "TQly") ui->input_tqly->setValue(value.toInt());
if (item == "RPM") ui->input_rpm->setValue(value.toInt());
if (item == "Fuel") ui->input_fuel->setValue(value.toInt());
if (item == "Tmp1") ui->input_tmp1->setValue(value.toInt());
if (item == "Tmp2") ui->input_tmp2->setValue(value.toInt());
if (item == "VFAS") ui->input_vfas->setValue(value.toDouble());
if (item == "Curr") ui->input_curr->setValue(value.toDouble());
if (item == "VSpd") ui->input_vspd->setValue(value.toDouble());
if (item == "Alt") ui->input_alt->setValue(value.toDouble());
if (item == "GPS") ui->input_gps->setText(value);
if (item == "GSpd") ui->input_gspd->setValue(value.toDouble());
if (item == "Hdg") ui->input_hdg->setValue(value.toInt());
if (item == "GAlt") ui->input_galt->setValue(value.toDouble());
if (item == "Date") ui->input_date->setDateTime(QDateTime::fromString(value));
if (item == "AccX") ui->input_accx->setValue(value.toDouble());
if (item == "AccY") ui->input_accy->setValue(value.toDouble());
if (item == "AccZ") ui->input_accz->setValue(value.toDouble());
}
void TelemetryProviderFrSkyHub::resetRssi()
{
sendLinkFrame(0, 0, 0, 0, 0, 0);
}
void TelemetryProviderFrSkyHub::loadUiFromSimulator(SimulatorInterface * simulator)
{
// Nothing to do for FrSky Hub
}
void TelemetryProviderFrSkyHub::generateTelemetryFrame(SimulatorInterface *simulator)
{
static int item = 0;
switch (item++) {
case 0:
// Always generate link stats
if (true) {
// just want a block here to put these variables in
int rssi = ui->input_rssi->value();
double a1 = ui->input_a1->value();
double a2 = ui->input_a2->value();
int trss = ui->input_trss->value();
int rqly = ui->input_rqly->value();
int tqly = ui->input_tqly->value();
sendLinkFrame(rssi, a1, a2, trss, rqly, tqly);
}
break;
case 1:
if (ui->enabled_rpm->isChecked()) {
sendRPMFrame(ui->input_rpm->value());
}
case 2:
if (ui->enabled_fuel->isChecked()) {
sendFuelFrame(ui->input_fuel->value());
}
case 3:
if (ui->enabled_temps->isChecked()) {
sendTempsFrame(ui->input_tmp1->value(), ui->input_tmp2->value());
}
case 4:
if (ui->enabled_battery->isChecked()) {
sendBatteryFrame(ui->input_vfas->value(), ui->input_curr->value());
}
case 5:
if (ui->enabled_baro->isChecked()) {
sendBaroFrame(ui->input_vspd->value(), ui->input_alt->value());
}
case 6:
if (ui->enabled_accel->isChecked()) {
sendAccelFrame(ui->input_accx->value(), ui->input_accy->value(), ui->input_accz->value());
}
case 7:
if (ui->enabled_gps->isChecked()) {
sendGPSFrame(gps);
}
default:
item = 0;
return;
}
}
void TelemetryProviderFrSkyHub::sendLongLinkFrame(int rssi, double a1, double a2, int trss, int rqly, int tqly)
{
// A1 & A2 are an unsigned byte measuring 0V (0) to 13.2V (255)
uint8_t a1_encoded = static_cast<uint8_t>((a1 / 13.2) * 255);
uint8_t a2_encoded = static_cast<uint8_t>((a2 / 13.2) * 255);
uint8_t rssi_encoded = static_cast<uint8_t>(rssi);
uint8_t trss_encoded = static_cast<uint8_t>(trss);
uint8_t rqly_encoded = static_cast<uint8_t>(rqly);
uint8_t tqly_encoded = static_cast<uint8_t>(tqly);
uint8_t packet[7] = { 0xfe, a1_encoded, a2_encoded, rssi_encoded, trss_encoded, rqly_encoded, tqly_encoded};
QByteArray ba((char *)packet, 7);
emit telemetryDataChanged(SIMU_TELEMETRY_PROTOCOL_FRSKY_HUB, ba);
}
void TelemetryProviderFrSkyHub::sendShortLinkFrame(int rssi, double a1, double a2)
{
// A1 & A2 are an unsigned byte measuring 0V (0) to 13.2V (255)
uint8_t a1_encoded = static_cast<uint8_t>((a1 / 13.2) * 255);
uint8_t a2_encoded = static_cast<uint8_t>((a2 / 13.2) * 255);
uint8_t rssi_encoded = static_cast<uint8_t>(rssi);
uint8_t packet[4] = { 0xfe, a1_encoded, a2_encoded, rssi_encoded};
QByteArray ba((char *)packet, 4);
emit telemetryDataChanged(SIMU_TELEMETRY_PROTOCOL_FRSKY_HUB, ba);
}
void TelemetryProviderFrSkyHub::sendLinkFrame(int rssi, double a1, double a2, int trss, int rqly, int tqly)
{
if (ui->enabled_multi->isChecked())
sendLongLinkFrame(rssi, a1, a2, trss << 1, rqly, tqly);
else
sendShortLinkFrame(rssi, a1, a2);
}
void TelemetryProviderFrSkyHub::sendSensorPacket(uint8_t id, uint16_t value)
{
uint8_t packet[3] = { id, static_cast<uint8_t>(value & 0xff), static_cast<uint8_t>((value >> 8) & 0xff) };
QByteArray ba((char *)packet, 3);
emit telemetryDataChanged(SIMU_TELEMETRY_PROTOCOL_FRSKY_HUB_OOB, ba);
}
void TelemetryProviderFrSkyHub::sendRPMFrame(int rpm)
{
uint16_t rpm_60 = rpm / 60;
sendSensorPacket(RPM_ID, rpm_60);
}
void TelemetryProviderFrSkyHub::sendFuelFrame(int fuelpercent)
{
sendSensorPacket(FUEL_ID, fuelpercent);
}
void TelemetryProviderFrSkyHub::sendTempsFrame(int temp1, int temp2)
{
sendSensorPacket(TEMP1_ID, temp1);
sendSensorPacket(TEMP2_ID, temp2);
}
void TelemetryProviderFrSkyHub::sendBatteryFrame(double vfas, double curr)
{
/*
// There are a couple of voltage sensors that could be used in a
// FrSky Hub setup. We will use the high precision one as that's
// easier, but if you _really_ want to simulate VFAS from the sensor
// that reports in units of 0.52381 volts, go ahead and use this
// snippet instead.
double scaled_vfas = vfas * (110.0 / 210.0);
int16_t bp = scaled_vfas;
int16_t ap = (scaled_vfas - bp) * 10;
sendSensorPacket(VOLTS_BP_ID, bp);
sendSensorPacket(VOLTS_AP_ID, ap);
*/
sendSensorPacket(VFAS_ID, 2000 + (vfas * 100));
sendSensorPacket(CURRENT_ID, curr * 10);
}
void TelemetryProviderFrSkyHub::sendBaroFrame(double vspd, double alt)
{
sendSensorPacket(VARIO_ID, vspd * 100);
sendSensorPacket(BARO_ALT_BP_ID, alt);
sendSensorPacket(BARO_ALT_AP_ID, (alt - floor(alt)) * 10);
}
void TelemetryProviderFrSkyHub::sendAccelFrame(double accx, double accy, double accz)
{
sendSensorPacket(ACCEL_X_ID, accx * 1000);
sendSensorPacket(ACCEL_Y_ID, accy * 1000);
sendSensorPacket(ACCEL_Z_ID, accz * 1000);
}
void TelemetryProviderFrSkyHub::sendGPSFrame(SimulatedGPS & gps)
{
double speedKnots = gps.speedKMH * 0.539957;
uint16_t bp, ap;
uint16_t degrees;
double decimal_minutes;
degrees = floor(abs(gps.lat));
decimal_minutes = (abs(gps.lat) - degrees) * 60;
bp = degrees * 100 + floor(decimal_minutes);
ap = (decimal_minutes - floor(decimal_minutes)) * 10000;
// MUST send these in BP, AP, NS order
sendSensorPacket(GPS_LAT_BP_ID, bp);
sendSensorPacket(GPS_LAT_AP_ID, ap);
sendSensorPacket(GPS_LAT_NS_ID, gps.lat < 0 ? 'S' : 'N');
degrees = floor(abs(gps.lon));
decimal_minutes = (abs(gps.lon) - degrees) * 60;
bp = degrees * 100 + floor(decimal_minutes);
ap = (decimal_minutes - floor(decimal_minutes)) * 10000;
// MUST send these in BP, AP, EW order
sendSensorPacket(GPS_LONG_BP_ID, bp);
sendSensorPacket(GPS_LONG_AP_ID, ap);
sendSensorPacket(GPS_LONG_EW_ID, gps.lon < 0 ? 'W' : 'E');
// The _after decimal point_ packets are ignored by the telemetry parser, so don't bother sending them.
sendSensorPacket(GPS_ALT_BP_ID, gps.altitude);
sendSensorPacket(GPS_SPEED_BP_ID, speedKnots);
sendSensorPacket(GPS_COURS_BP_ID, gps.courseDegrees);
// Date and Time
QDate date = gps.dt.date();
QTime time = gps.dt.time();
sendSensorPacket(GPS_YEAR_ID, date.year());
sendSensorPacket(GPS_DAY_MONTH_ID, (date.month() << 8) + date.day());
sendSensorPacket(GPS_HOUR_MIN_ID, (time.minute() << 8) + time.hour());
sendSensorPacket(GPS_SEC_ID, time.second());
}
void TelemetryProviderFrSkyHub::on_button_gpsRunStop_clicked()
{
if (gps.running) {
gps.stop();
ui->button_gpsRunStop->setText(tr("Run"));
} else {
gps.start();
ui->button_gpsRunStop->setText(tr("Stop"));
}
}
void TelemetryProviderFrSkyHub::on_button_saveTelemetryValues_clicked()
{
QString fldr = g.backupDir().trimmed();
if (fldr.isEmpty())
fldr = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QString idFileNameAndPath = QFileDialog::getSaveFileName(this, tr("Save Telemetry"), fldr % "/telemetry.tlm", tr(".tlm Files (*.tlm)"));
if (idFileNameAndPath.isEmpty())
return;
QFile file(idFileNameAndPath);
if (!file.open(QIODevice::WriteOnly)){
QMessageBox::critical(this, CPN_STR_APP_NAME, tr("Unable to open file for writing.\n%1").arg(file.errorString()));
return;
}
QTextStream out(&file);
out << getLogfileIdentifier() << "\r\n";
out << ui->input_rssi->text() << "\r\n";
out << ui->input_a1->text() << "\r\n";
out << ui->input_a2->text() << "\r\n";
out << ui->input_trss->text() << "\r\n";
out << ui->input_rqly->text() << "\r\n";
out << ui->input_tqly->text() << "\r\n";
out << ui->input_rpm->text() << "\r\n";
out << ui->input_fuel->text() << "\r\n";
out << ui->input_tmp1->text() << "\r\n";
out << ui->input_tmp2->text() << "\r\n";
out << ui->input_vfas->text() << "\r\n";
out << ui->input_curr->text() << "\r\n";
out << ui->input_vspd->text() << "\r\n";
out << ui->input_alt->text() << "\r\n";
out << ui->input_gps->text() << "\r\n";
out << ui->input_gspd->text() << "\r\n";
out << ui->input_hdg->text() << "\r\n";
out << ui->input_galt->text() << "\r\n";
out << ui->input_date->dateTime().toString(Qt::ISODate) << "\r\n";
out << ui->input_accx->text() << "\r\n";
out << ui->input_accy->text() << "\r\n";
out << ui->input_accz->text() << "\r\n";
out << ui->enabled_multi->isChecked() << "\r\n";
out << ui->enabled_rpm->isChecked() << "\r\n";
out << ui->enabled_fuel->isChecked() << "\r\n";
out << ui->enabled_temps->isChecked() << "\r\n";
out << ui->enabled_battery->isChecked() << "\r\n";
out << ui->enabled_baro->isChecked() << "\r\n";
out << ui->enabled_gps->isChecked() << "\r\n";
out << ui->enabled_accel->isChecked() << "\r\n";
file.flush();
file.close();
}
void TelemetryProviderFrSkyHub::on_button_loadTelemetryValues_clicked()
{
QString fldr = g.backupDir().trimmed();
if (fldr.isEmpty())
fldr = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QString idFileNameAndPath = QFileDialog::getOpenFileName(this, tr("Open Telemetry File"), fldr % "/telemetry.tlm", tr(".tlm Files (*.tlm)"));
if (idFileNameAndPath.isEmpty())
return;
QFile file(idFileNameAndPath);
if (!file.open(QIODevice::ReadOnly)){
QMessageBox::critical(this, CPN_STR_APP_NAME, tr("Unable to open file for reading.\n%1").arg(file.errorString()));
return;
}
QTextStream in(&file);
QString inputText;
QDateTime inputDatetime;
double inputDouble;
int inputInt;
inputText = in.readLine();
if (inputText != getLogfileIdentifier()) {
QMessageBox::critical(this, CPN_STR_APP_NAME, tr("Not a FrSky Hub telemetry values file."));
return;
}
inputText = in.readLine(); inputInt = inputText.toInt(); ui->input_rssi->setValue(inputInt);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_a1->setValue(inputDouble);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_a2->setValue(inputDouble);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->input_trss->setValue(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->input_rqly->setValue(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->input_tqly->setValue(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->input_rpm->setValue(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->input_fuel->setValue(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->input_tmp1->setValue(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->input_tmp2->setValue(inputInt);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_vfas->setValue(inputDouble);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_curr->setValue(inputDouble);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_vspd->setValue(inputDouble);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_alt->setValue(inputDouble);
inputText = in.readLine(); ui->input_gps->setText(inputText);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_gspd->setValue(inputDouble);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_hdg->setValue(inputDouble);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_galt->setValue(inputDouble);
inputText = in.readLine(); inputDatetime = QDateTime::fromString(inputText, Qt::ISODate); ui->input_date->setDateTime(inputDatetime);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_accx->setValue(inputDouble);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_accy->setValue(inputDouble);
inputText = in.readLine(); inputDouble = inputText.toDouble(); ui->input_accz->setValue(inputDouble);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->enabled_multi->setChecked(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->enabled_rpm->setChecked(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->enabled_fuel->setChecked(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->enabled_temps->setChecked(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->enabled_battery->setChecked(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->enabled_baro->setChecked(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->enabled_gps->setChecked(inputInt);
inputText = in.readLine(); inputInt = inputText.toInt(); ui->enabled_accel->setChecked(inputInt);
file.close();
}
@@ -0,0 +1,81 @@
/*
* 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 <QWidget>
#include <QDateTime>
#include "simulatorinterface.h"
#include "telemetryprovider.h"
#include "simulatedgps.h"
// Max telemetry packet size
#define FRSKY_HUB_MAX_PACKET_SIZE 16
namespace Ui {
class TelemetryProviderFrSkyHub;
}
class TelemetryProviderFrSkyHub : public QWidget, public TelemetryProvider
{
Q_OBJECT
public:
explicit TelemetryProviderFrSkyHub(QWidget * parent);
virtual ~TelemetryProviderFrSkyHub();
signals:
void telemetryDataChanged(const quint8 protocol, const QByteArray data);
public slots:
void resetRssi();
QHash<QString, QString> * getSupportedLogItems();
void loadItemFromLog(QString itemName, QString value);
QString getLogfileIdentifier();
protected slots:
void generateTelemetryFrame(SimulatorInterface * simulator);
void loadUiFromSimulator(SimulatorInterface * simulator);
protected:
Ui::TelemetryProviderFrSkyHub * ui;
SimulatedGPS gps;
QHash<QString, QString> supportedLogItems;
private slots:
void on_button_gpsRunStop_clicked();
void on_button_saveTelemetryValues_clicked();
void on_button_loadTelemetryValues_clicked();
void sendLongLinkFrame(int rssi, double a1, double a2, int trss, int rqly, int tqly);
void sendShortLinkFrame(int rssi, double a1, double a2);
void sendLinkFrame(int rssi, double a1, double a2, int trss, int rqly, int tqly);
void sendSensorPacket(uint8_t id, uint16_t value);
void sendRPMFrame(int rpm);
void sendFuelFrame(int fuelpercent);
void sendTempsFrame(int temp1, int temp2);
void sendBatteryFrame(double vfas, double curr);
void sendBaroFrame(double vspd, double alt);
void sendAccelFrame(double accx, double accy, double accz);
void sendGPSFrame(SimulatedGPS & gps);
};
File diff suppressed because it is too large Load Diff
+23 -12
View File
@@ -26,6 +26,7 @@
#include "telem_data.h"
#include "radio/src/telemetry/frsky_defs.h"
#include "telemetryproviderfrsky.h"
#include "telemetryproviderfrskyhub.h"
#include "telemetryprovidercrossfire.h"
#include <QRegularExpression>
@@ -159,6 +160,28 @@ TelemetryProvider * TelemetrySimulator::newTelemetryProviderFromDropdownChoice(i
case 0:
return NULL;
case 1:
{
TelemetryProviderCrossfire * newProvider = new TelemetryProviderCrossfire(parent);
parent->setWidget(newProvider);
if (isExternal) {
connect(newProvider, &TelemetryProviderCrossfire::telemetryDataChanged, this, &TelemetrySimulator::onExternalTelemetryProviderDataChanged);
} else {
connect(newProvider, &TelemetryProviderCrossfire::telemetryDataChanged, this, &TelemetrySimulator::onInternalTelemetryProviderDataChanged);
}
return newProvider;
}
case 2:
{
TelemetryProviderFrSkyHub * newProvider = new TelemetryProviderFrSkyHub(parent);
parent->setWidget(newProvider);
if (isExternal) {
connect(newProvider, &TelemetryProviderFrSkyHub::telemetryDataChanged, this, &TelemetrySimulator::onExternalTelemetryProviderDataChanged);
} else {
connect(newProvider, &TelemetryProviderFrSkyHub::telemetryDataChanged, this, &TelemetrySimulator::onInternalTelemetryProviderDataChanged);
}
return newProvider;
}
case 3:
{
TelemetryProviderFrSky * newProvider = new TelemetryProviderFrSky(parent);
parent->setWidget(newProvider);
@@ -169,18 +192,6 @@ TelemetryProvider * TelemetrySimulator::newTelemetryProviderFromDropdownChoice(i
}
// FrSky provider needs to set up sensor instances from the model's telemetry configuration
newProvider->loadUiFromSimulator(simulator);
return newProvider;
}
case 2:
{
TelemetryProviderCrossfire * newProvider = new TelemetryProviderCrossfire(parent);
parent->setWidget(newProvider);
if (isExternal) {
connect(newProvider, &TelemetryProviderCrossfire::telemetryDataChanged, this, &TelemetrySimulator::onExternalTelemetryProviderDataChanged);
} else {
connect(newProvider, &TelemetryProviderCrossfire::telemetryDataChanged, this, &TelemetrySimulator::onInternalTelemetryProviderDataChanged);
}
return newProvider;
}
default:
+14 -4
View File
@@ -495,12 +495,17 @@ Timestamp</string>
</item>
<item>
<property name="text">
<string>FrSky S.Port</string>
<string>CRSF / ELRS</string>
</property>
</item>
<item>
<property name="text">
<string>CRSF / ELRS</string>
<string>FrSky Hub</string>
</property>
</item>
<item>
<property name="text">
<string>FrSky S.Port</string>
</property>
</item>
</widget>
@@ -598,12 +603,17 @@ Timestamp</string>
</item>
<item>
<property name="text">
<string>FrSky S.Port</string>
<string>CRSF / ELRS</string>
</property>
</item>
<item>
<property name="text">
<string>CRSF / ELRS</string>
<string>FrSky Hub</string>
</property>
</item>
<item>
<property name="text">
<string>FrSky S.Port</string>
</property>
</item>
</widget>
@@ -419,6 +419,25 @@ void OpenTxSimulator::sendTelemetry(const uint8_t module, const uint8_t protocol
(uint8_t *)data.constData(),
data.count());
break;
case SIMU_TELEMETRY_PROTOCOL_FRSKY_HUB_OOB:
// FrSky D telemetry is a stream which can span multiple
// packets. The telemetry parser _could_ be in the middle of a
// user packet when we want to inject telemetry, so we can't just
// call frskyDProcessPacket() with a USRPKT (at least not safely!)
// Instead we will bypass the telemetry stream parser and inject
// out of band into processHubPacket(). This way we also don't
// have to mess with byte stuffing and variable length packets.
//
// Note this doesn't take into account which module it's from, but
// that's how it works in the radio too if you have two frsky D
// modules running at once, so ¯\_(ツ)_/¯
{
uint8_t id = data[0];
uint16_t value = ((uint8_t)(data[2]) << 8) + (uint8_t)(data[1]);
processHubPacket(id, value);
}
break;
case SIMU_TELEMETRY_PROTOCOL_CROSSFIRE:
processCrossfireTelemetryFrame(module,
(uint8_t *)data.constData(),