mirror of https://github.com/f4exb/sdrangel.git
Rotator Controller: Add gamepad input controller support.
This commit is contained in:
parent
fc923ebbed
commit
a1c1308580
|
@ -610,7 +610,9 @@ else()
|
|||
MultimediaWidgets
|
||||
Positioning
|
||||
Charts
|
||||
SerialPort)
|
||||
SerialPort
|
||||
OPTIONAL_COMPONENTS
|
||||
Gamepad)
|
||||
endif()
|
||||
|
||||
# for the server we don't need OpenGL/Qt Quick components
|
||||
|
|
|
@ -38,17 +38,27 @@ if(NOT SERVER_MODE)
|
|||
gs232controllergui.ui
|
||||
dfmstatusdialog.cpp
|
||||
dfmstatusdialog.ui
|
||||
inputcontroller.cpp
|
||||
)
|
||||
set(gs232controller_HEADERS
|
||||
${gs232controller_HEADERS}
|
||||
gs232controllergui.h
|
||||
dfmstatusdialog.h
|
||||
inputcontroller.h
|
||||
)
|
||||
|
||||
set(TARGET_NAME featuregs232controller)
|
||||
set(TARGET_LIB Qt::Widgets)
|
||||
set(TARGET_LIB_GUI "sdrgui")
|
||||
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
|
||||
|
||||
if(Qt${QT_DEFAULT_MAJOR_VERSION}Gamepad_FOUND)
|
||||
add_compile_definitions(QT_GAMEPAD_FOUND)
|
||||
set(TARGET_LIB ${TARGET_LIB} Qt::Gamepad)
|
||||
set(gs232controller_SOURCES ${gs232controller_SOURCES} gamepadinputcontroller.cpp)
|
||||
set(gs232controller_HEADERS ${gs232controller_HEADERS} gamepadinputcontroller.h)
|
||||
endif()
|
||||
|
||||
else()
|
||||
set(TARGET_NAME featuregs232controllersrv)
|
||||
set(TARGET_LIB "")
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QDebug>
|
||||
#include <QGamepadManager>
|
||||
|
||||
#include "gamepadinputcontroller.h"
|
||||
|
||||
GamepadInputController::GamepadInputController(int deviceId) :
|
||||
m_gamepad(deviceId),
|
||||
m_rightX(0.0),
|
||||
m_rightY(0.0),
|
||||
m_leftX(0.0),
|
||||
m_leftY(0.0)
|
||||
{
|
||||
connect(&m_gamepad, &QGamepad::axisRightXChanged, this, &GamepadInputController::axisRightXChanged);
|
||||
connect(&m_gamepad, &QGamepad::axisRightYChanged, this, &GamepadInputController::axisRightYChanged);
|
||||
connect(&m_gamepad, &QGamepad::axisLeftXChanged, this, &GamepadInputController::axisLeftXChanged);
|
||||
connect(&m_gamepad, &QGamepad::axisLeftYChanged, this, &GamepadInputController::axisLeftYChanged);
|
||||
}
|
||||
|
||||
double GamepadInputController::getAxisValue(int axis)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case 0:
|
||||
return m_rightX;
|
||||
case 1:
|
||||
return m_rightY;
|
||||
case 2:
|
||||
return m_leftX;
|
||||
case 3:
|
||||
return m_leftY;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
int GamepadInputController::getNumberOfAxes() const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
void GamepadInputController::axisRightXChanged(double value)
|
||||
{
|
||||
m_rightX = value;
|
||||
}
|
||||
|
||||
void GamepadInputController::axisRightYChanged(double value)
|
||||
{
|
||||
m_rightY = value;
|
||||
}
|
||||
|
||||
void GamepadInputController::axisLeftXChanged(double value)
|
||||
{
|
||||
m_leftX = value;
|
||||
}
|
||||
|
||||
void GamepadInputController::axisLeftYChanged(double value)
|
||||
{
|
||||
m_leftY = value;
|
||||
}
|
||||
|
||||
QStringList GamepadInputController::getAllControllers()
|
||||
{
|
||||
QStringList names;
|
||||
QGamepadManager *gamepadManager = QGamepadManager::instance();
|
||||
|
||||
if (gamepadManager)
|
||||
{
|
||||
const QList<int> gamepads = gamepadManager->connectedGamepads();
|
||||
for (const auto gamepad : gamepads)
|
||||
{
|
||||
QString name;
|
||||
if (gamepadManager->gamepadName(gamepad).isEmpty()) {
|
||||
name = QString("Gamepad %1").arg(gamepad);
|
||||
} else {
|
||||
name = gamepadManager->gamepadName(gamepad);
|
||||
}
|
||||
qDebug() << "GamepadInputController::getAllControllers: Gamepad: " << gamepad << "name:" << gamepadManager->gamepadName(gamepad) << " connected " << gamepadManager->isGamepadConnected(gamepad);
|
||||
names.append(name);
|
||||
}
|
||||
if (gamepads.size() == 0) {
|
||||
qDebug() << "GamepadInputController::getAllControllers: No gamepads";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "GamepadInputController::getAllControllers: No gamepad manager";
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
GamepadInputController* GamepadInputController::open(const QString& name)
|
||||
{
|
||||
GamepadInputController *inputController = nullptr;
|
||||
QGamepadManager *gamepadManager = QGamepadManager::instance();
|
||||
|
||||
if (gamepadManager)
|
||||
{
|
||||
const QList<int> gamepads = gamepadManager->connectedGamepads();
|
||||
for (const auto gamepad : gamepads)
|
||||
{
|
||||
QString gamepadName;
|
||||
if (gamepadManager->gamepadName(gamepad).isEmpty()) {
|
||||
gamepadName = QString("Gamepad %1").arg(gamepad);
|
||||
} else {
|
||||
gamepadName = gamepadManager->gamepadName(gamepad);
|
||||
}
|
||||
if (name == gamepadName)
|
||||
{
|
||||
inputController = new GamepadInputController(gamepad);
|
||||
if (inputController)
|
||||
{
|
||||
qDebug() << "GamepadInputController::open: Opened gamepad " << name;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "GamepadInputController::open: Failed to open gamepad: " << gamepad;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return inputController;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_FEATURE_GAMEPADINPUTCONTROLLER_H_
|
||||
#define INCLUDE_FEATURE_GAMEPADINPUTCONTROLLER_H_
|
||||
|
||||
#include "inputcontroller.h"
|
||||
|
||||
#include <QGamepad>
|
||||
|
||||
class GamepadInputController : public InputController {
|
||||
|
||||
public:
|
||||
|
||||
GamepadInputController(int deviceId);
|
||||
double getAxisValue(int axis) override;
|
||||
int getNumberOfAxes() const override;
|
||||
|
||||
static QStringList getAllControllers();
|
||||
static GamepadInputController* open(const QString& name);
|
||||
|
||||
private slots:
|
||||
|
||||
void axisRightXChanged(double value);
|
||||
void axisRightYChanged(double value);
|
||||
void axisLeftXChanged(double value);
|
||||
void axisLeftYChanged(double value);
|
||||
|
||||
private:
|
||||
|
||||
QGamepad m_gamepad;
|
||||
double m_rightX;
|
||||
double m_rightY;
|
||||
double m_leftX;
|
||||
double m_leftY;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_GAMEPADINPUTCONTROLLER_H_
|
||||
|
|
@ -491,6 +491,8 @@ void GS232Controller::webapiFormatFeatureSettings(
|
|||
response.getGs232ControllerSettings()->setProtocol(settings.m_protocol);
|
||||
response.getGs232ControllerSettings()->setPrecision(settings.m_precision);
|
||||
response.getGs232ControllerSettings()->setCoordinates((int)settings.m_coordinates);
|
||||
response.getGs232ControllerSettings()->setInputController(new QString(settings.m_inputController));
|
||||
response.getGs232ControllerSettings()->setInputSensitivity(settings.m_inputSensitivity);
|
||||
|
||||
if (response.getGs232ControllerSettings()->getTitle()) {
|
||||
*response.getGs232ControllerSettings()->getTitle() = settings.m_title;
|
||||
|
@ -585,6 +587,12 @@ void GS232Controller::webapiUpdateFeatureSettings(
|
|||
if (featureSettingsKeys.contains("coordinates")) {
|
||||
settings.m_coordinates = (GS232ControllerSettings::Coordinates)response.getGs232ControllerSettings()->getCoordinates();
|
||||
}
|
||||
if (featureSettingsKeys.contains("inputController")) {
|
||||
settings.m_inputController = *response.getGs232ControllerSettings()->getInputController();
|
||||
}
|
||||
if (featureSettingsKeys.contains("inputSensitivity")) {
|
||||
settings.m_inputSensitivity = response.getGs232ControllerSettings()->getInputSensitivity();
|
||||
}
|
||||
if (featureSettingsKeys.contains("title")) {
|
||||
settings.m_title = *response.getGs232ControllerSettings()->getTitle();
|
||||
}
|
||||
|
@ -676,6 +684,12 @@ void GS232Controller::webapiReverseSendSettings(const QList<QString>& featureSet
|
|||
if (featureSettingsKeys.contains("coordinates") || force) {
|
||||
swgGS232ControllerSettings->setCoordinates(settings.m_coordinates);
|
||||
}
|
||||
if (featureSettingsKeys.contains("inputController") || force) {
|
||||
swgGS232ControllerSettings->setInputController(new QString(settings.m_inputController));
|
||||
}
|
||||
if (featureSettingsKeys.contains("inputSensitivity") || force) {
|
||||
swgGS232ControllerSettings->setInputSensitivity(settings.m_inputSensitivity);
|
||||
}
|
||||
if (featureSettingsKeys.contains("title") || force) {
|
||||
swgGS232ControllerSettings->setTitle(new QString(settings.m_title));
|
||||
}
|
||||
|
|
|
@ -216,7 +216,13 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu
|
|||
m_doApplySettings(true),
|
||||
m_lastFeatureState(0),
|
||||
m_lastOnTarget(false),
|
||||
m_dfmStatusDialog()
|
||||
m_dfmStatusDialog(),
|
||||
m_inputController(nullptr),
|
||||
m_inputCoord1(0.0),
|
||||
m_inputCoord2(0.0),
|
||||
m_inputAzOffset(0.0),
|
||||
m_inputElOffset(0.0),
|
||||
m_inputUpdate(false)
|
||||
{
|
||||
m_feature = feature;
|
||||
setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
|
@ -246,6 +252,10 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu
|
|||
|
||||
m_settings.setRollupState(&m_rollupState);
|
||||
|
||||
updateInputControllerList();
|
||||
connect(InputControllerManager::instance(), &InputControllerManager::controllersChanged, this, &GS232ControllerGUI::updateInputControllerList);
|
||||
connect(&m_inputTimer, &QTimer::timeout, this, &GS232ControllerGUI::checkInputController);
|
||||
|
||||
displaySettings();
|
||||
applySettings(true);
|
||||
makeUIConnections();
|
||||
|
@ -256,6 +266,123 @@ GS232ControllerGUI::GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featu
|
|||
new DialogPositioner(&m_dfmStatusDialog, true);
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::updateInputControllerList()
|
||||
{
|
||||
ui->inputController->blockSignals(true);
|
||||
ui->inputController->clear();
|
||||
ui->inputController->addItem("None");
|
||||
|
||||
QStringList controllers = InputControllerManager::getAllControllers();
|
||||
for (const auto& controller : controllers) {
|
||||
ui->inputController->addItem(controller);
|
||||
}
|
||||
ui->inputController->blockSignals(false);
|
||||
int index = ui->inputController->findText(m_settings.m_inputController);
|
||||
ui->inputController->setCurrentIndex(index);
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::updateInputController()
|
||||
{
|
||||
delete m_inputController;
|
||||
m_inputController = nullptr;
|
||||
|
||||
bool enabled = false;
|
||||
if (m_settings.m_inputController != "None")
|
||||
{
|
||||
m_inputController = InputControllerManager::open(m_settings.m_inputController);
|
||||
if (m_inputController)
|
||||
{
|
||||
m_inputTimer.start(20);
|
||||
enabled = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inputTimer.stop();
|
||||
}
|
||||
|
||||
ui->inputSensitivityLabel->setEnabled(enabled);
|
||||
ui->inputSensitivity->setEnabled(enabled);
|
||||
ui->inputSensitivityText->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::checkInputController()
|
||||
{
|
||||
if (m_inputController)
|
||||
{
|
||||
// If our input device has two sticks (four axes), we use one for target and one for offset
|
||||
// If only one stick (two axes), it's used both for target when not tracking and offset, when tracking
|
||||
// Use separate variables rather than values in UI, to allow for higher precision
|
||||
|
||||
if (!m_settings.m_track)
|
||||
{
|
||||
m_inputCoord1 += m_settings.m_inputSensitivity * m_inputController->getAxisValue(0);
|
||||
m_inputCoord2 += m_settings.m_inputSensitivity * -m_inputController->getAxisValue(1);
|
||||
|
||||
if (m_settings.m_coordinates == GS232ControllerSettings::AZ_EL)
|
||||
{
|
||||
m_inputCoord1 = std::max(m_inputCoord1, (double) m_settings.m_azimuthMin);
|
||||
m_inputCoord1 = std::min(m_inputCoord1, (double) m_settings.m_azimuthMax);
|
||||
m_inputCoord2 = std::max(m_inputCoord2, (double) m_settings.m_elevationMin);
|
||||
m_inputCoord2 = std::min(m_inputCoord2, (double) m_settings.m_elevationMax);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_inputCoord1 = std::max(m_inputCoord1, -90.0);
|
||||
m_inputCoord1 = std::min(m_inputCoord1, 90.0);
|
||||
m_inputCoord2 = std::max(m_inputCoord2, -90.0);
|
||||
m_inputCoord2 = std::min(m_inputCoord2, 90.0);
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_inputController->getNumberOfAxes() < 4) && m_settings.m_track)
|
||||
{
|
||||
m_inputAzOffset += m_settings.m_inputSensitivity * m_inputController->getAxisValue(0);
|
||||
m_inputElOffset += m_settings.m_inputSensitivity * -m_inputController->getAxisValue(1);
|
||||
}
|
||||
else if (m_inputController->getNumberOfAxes() >= 4)
|
||||
{
|
||||
m_inputAzOffset += m_settings.m_inputSensitivity * m_inputController->getAxisValue(2);
|
||||
m_inputElOffset += m_settings.m_inputSensitivity * -m_inputController->getAxisValue(3);
|
||||
}
|
||||
m_inputAzOffset = std::max(m_inputAzOffset, -360.0);
|
||||
m_inputAzOffset = std::min(m_inputAzOffset, 360.0);
|
||||
m_inputElOffset = std::max(m_inputElOffset, -180.0);
|
||||
m_inputElOffset = std::min(m_inputElOffset, 180.0);
|
||||
|
||||
m_inputUpdate = true;
|
||||
if (!m_settings.m_track)
|
||||
{
|
||||
ui->coord1->setValue(m_inputCoord1);
|
||||
ui->coord2->setValue(m_inputCoord2);
|
||||
}
|
||||
if (((m_inputController->getNumberOfAxes() < 4) && m_settings.m_track) || (m_inputController->getNumberOfAxes() >= 4))
|
||||
{
|
||||
ui->azimuthOffset->setValue(m_inputAzOffset);
|
||||
ui->elevationOffset->setValue(m_inputElOffset);
|
||||
}
|
||||
m_inputUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_inputController_currentIndexChanged(int index)
|
||||
{
|
||||
// Don't update settings if set to -1
|
||||
if (index >= 0)
|
||||
{
|
||||
m_settings.m_inputController = ui->inputController->currentText();
|
||||
applySettings();
|
||||
updateInputController();
|
||||
}
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_inputSensitivty_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_inputSensitivity = value / 1000.0;
|
||||
ui->inputSensitivityText->setText(QString("%1%").arg(m_settings.m_inputSensitivity * 100.0));
|
||||
applySettings();
|
||||
}
|
||||
|
||||
GS232ControllerGUI::~GS232ControllerGUI()
|
||||
{
|
||||
m_dfmStatusDialog.close();
|
||||
|
@ -302,6 +429,9 @@ void GS232ControllerGUI::displaySettings()
|
|||
ui->elevationMin->setValue(m_settings.m_elevationMin);
|
||||
ui->elevationMax->setValue(m_settings.m_elevationMax);
|
||||
ui->tolerance->setValue(m_settings.m_tolerance);
|
||||
ui->inputController->setCurrentText(m_settings.m_inputController);
|
||||
ui->inputSensitivity->setValue((int) (m_settings.m_inputSensitivity * 1000.0));
|
||||
ui->inputSensitivityText->setText(QString("%1%").arg(m_settings.m_inputSensitivity * 100.0));
|
||||
ui->dfmTrack->setChecked(m_settings.m_dfmTrackOn);
|
||||
ui->dfmLubePumps->setChecked(m_settings.m_dfmLubePumpsOn);
|
||||
ui->dfmBrakes->setChecked(m_settings.m_dfmBrakesOn);
|
||||
|
@ -543,18 +673,27 @@ void GS232ControllerGUI::on_port_valueChanged(int value)
|
|||
|
||||
void GS232ControllerGUI::on_coord1_valueChanged(double value)
|
||||
{
|
||||
if (!m_inputUpdate) {
|
||||
m_inputCoord1 = value;
|
||||
}
|
||||
displayToAzEl(value, ui->coord2->value());
|
||||
ui->targetName->setText("");
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_coord2_valueChanged(double value)
|
||||
{
|
||||
if (!m_inputUpdate) {
|
||||
m_inputCoord2 = value;
|
||||
}
|
||||
displayToAzEl(ui->coord1->value(), value);
|
||||
ui->targetName->setText("");
|
||||
}
|
||||
|
||||
void GS232ControllerGUI::on_azimuthOffset_valueChanged(int value)
|
||||
{
|
||||
if (!m_inputUpdate) {
|
||||
m_inputAzOffset = value;
|
||||
}
|
||||
m_settings.m_azimuthOffset = value;
|
||||
m_settingsKeys.append("azimuthOffset");
|
||||
applySettings();
|
||||
|
@ -562,6 +701,9 @@ void GS232ControllerGUI::on_azimuthOffset_valueChanged(int value)
|
|||
|
||||
void GS232ControllerGUI::on_elevationOffset_valueChanged(int value)
|
||||
{
|
||||
if (!m_inputUpdate) {
|
||||
m_inputElOffset = value;
|
||||
}
|
||||
m_settings.m_elevationOffset = value;
|
||||
m_settingsKeys.append("elevationOffset");
|
||||
applySettings();
|
||||
|
@ -805,6 +947,8 @@ void GS232ControllerGUI::makeUIConnections()
|
|||
QObject::connect(ui->tolerance, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &GS232ControllerGUI::on_tolerance_valueChanged);
|
||||
QObject::connect(ui->precision, qOverload<int>(&QSpinBox::valueChanged), this, &GS232ControllerGUI::on_precision_valueChanged);
|
||||
QObject::connect(ui->coordinates, qOverload<int>(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_coordinates_currentIndexChanged);
|
||||
QObject::connect(ui->inputController, qOverload<int>(&QComboBox::currentIndexChanged), this, &GS232ControllerGUI::on_inputController_currentIndexChanged);
|
||||
QObject::connect(ui->inputSensitivity, qOverload<int>(&QSlider::valueChanged), this, &GS232ControllerGUI::on_inputSensitivty_valueChanged);
|
||||
QObject::connect(ui->dfmTrack, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmTrack_clicked);
|
||||
QObject::connect(ui->dfmLubePumps, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmLubePumps_clicked);
|
||||
QObject::connect(ui->dfmBrakes, &QToolButton::toggled, this, &GS232ControllerGUI::on_dfmBrakes_clicked);
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include "gs232controllersettings.h"
|
||||
#include "dfmstatusdialog.h"
|
||||
#include "inputcontroller.h"
|
||||
|
||||
class PluginAPI;
|
||||
class FeatureUISet;
|
||||
|
@ -68,6 +69,14 @@ private:
|
|||
|
||||
DFMStatusDialog m_dfmStatusDialog;
|
||||
|
||||
InputController *m_inputController;
|
||||
QTimer m_inputTimer;
|
||||
double m_inputCoord1;
|
||||
double m_inputCoord2;
|
||||
double m_inputAzOffset;
|
||||
double m_inputElOffset;
|
||||
bool m_inputUpdate;
|
||||
|
||||
explicit GS232ControllerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *feature, QWidget* parent = nullptr);
|
||||
virtual ~GS232ControllerGUI();
|
||||
|
||||
|
@ -84,6 +93,7 @@ private:
|
|||
void makeUIConnections();
|
||||
void azElToDisplay(float az, float el, float& coord1, float& coord2) const;
|
||||
void displayToAzEl(float coord1, float coord2);
|
||||
void updateInputController();
|
||||
|
||||
private slots:
|
||||
void onMenuDialogCalled(const QPoint &p);
|
||||
|
@ -115,6 +125,10 @@ private slots:
|
|||
void on_dfmDrives_clicked(bool checked=false);
|
||||
void on_dfmShowStatus_clicked();
|
||||
void updateStatus();
|
||||
void on_inputController_currentIndexChanged(int index);
|
||||
void on_inputSensitivty_valueChanged(int value);
|
||||
void updateInputControllerList();
|
||||
void checkInputController();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FEATURE_GS232CONTROLLERGUI_H_
|
||||
|
|
|
@ -306,7 +306,7 @@
|
|||
<x>10</x>
|
||||
<y>140</y>
|
||||
<width>341</width>
|
||||
<height>191</height>
|
||||
<height>201</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -330,6 +330,84 @@
|
|||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="settingsGridLayout">
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="baudRateLabel">
|
||||
<property name="text">
|
||||
<string>Baud rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QComboBox" name="inputController">
|
||||
<property name="toolTip">
|
||||
<string>Gamepad / joystick to use</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="azimuthMin">
|
||||
<property name="maximum">
|
||||
<number>450</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="elevationOffsetLabel">
|
||||
<property name="text">
|
||||
<string>Elevation offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="azimuthMaxLabel">
|
||||
<property name="text">
|
||||
<string>Azimuth max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Coordinates</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="azimuthMinLabel">
|
||||
<property name="text">
|
||||
<string>Azimuth min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QSpinBox" name="elevationMax">
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLabel" name="inputSensitivityLabel">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Sensitivity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="elevationMaxLabel">
|
||||
<property name="text">
|
||||
<string>Elevation max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="azimuthOffsetLabel">
|
||||
<property name="text">
|
||||
|
@ -337,6 +415,56 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QSpinBox" name="elevationOffset">
|
||||
<property name="toolTip">
|
||||
<string>Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-180</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="protocol">
|
||||
<property name="toolTip">
|
||||
<string>Command protocol</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>GS-232</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SPID</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>rotctld</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DFM</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="portLabel">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="3">
|
||||
<widget class="QSpinBox" name="precision">
|
||||
<property name="enabled">
|
||||
|
@ -353,64 +481,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="host">
|
||||
<property name="toolTip">
|
||||
<string>Hostname / IP address of computer to connect to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QSpinBox" name="azimuthMax">
|
||||
<property name="maximum">
|
||||
<number>450</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="toleranceLabel">
|
||||
<property name="text">
|
||||
<string>Tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="serialPort">
|
||||
<property name="toolTip">
|
||||
<string>Name of serial port to use to connect to the rotator</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="azimuthOffset">
|
||||
<property name="toolTip">
|
||||
<string>Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-360</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>360</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="azimuthMaxLabel">
|
||||
<property name="text">
|
||||
<string>Azimuth max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="connectionLabel">
|
||||
<property name="text">
|
||||
<string>Connection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QSpinBox" name="port">
|
||||
<property name="toolTip">
|
||||
|
@ -421,110 +491,13 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="baudRateLabel">
|
||||
<property name="text">
|
||||
<string>Baud rate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QComboBox" name="connection">
|
||||
<property name="toolTip">
|
||||
<string>The type of connection to use to the rotator</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Serial</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>TCP</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="serialPortLabel">
|
||||
<property name="text">
|
||||
<string>Serial Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tolerance">
|
||||
<property name="toolTip">
|
||||
<string>Tolerance in degrees</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="azimuthMin">
|
||||
<item row="4" column="3">
|
||||
<widget class="QSpinBox" name="azimuthMax">
|
||||
<property name="maximum">
|
||||
<number>450</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="hostLabel">
|
||||
<property name="text">
|
||||
<string>Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="portLabel">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="elevationMaxLabel">
|
||||
<property name="text">
|
||||
<string>Elevation max</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="elevationMinLabel">
|
||||
<property name="text">
|
||||
<string>Elevation min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3">
|
||||
<widget class="QSpinBox" name="elevationMax">
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="azimuthMinLabel">
|
||||
<property name="text">
|
||||
<string>Azimuth min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="elevationOffsetLabel">
|
||||
<property name="text">
|
||||
<string>Elevation offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="elevationMin">
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QComboBox" name="baudRate">
|
||||
<property name="toolTip">
|
||||
|
@ -585,6 +558,61 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="connectionLabel">
|
||||
<property name="text">
|
||||
<string>Connection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QComboBox" name="connection">
|
||||
<property name="toolTip">
|
||||
<string>The type of connection to use to the rotator</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Serial</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>TCP</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="serialPort">
|
||||
<property name="toolTip">
|
||||
<string>Name of serial port to use to connect to the rotator</string>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="hostLabel">
|
||||
<property name="text">
|
||||
<string>Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="elevationMin">
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="host">
|
||||
<property name="toolTip">
|
||||
<string>Hostname / IP address of computer to connect to</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="precisionLabel">
|
||||
<property name="enabled">
|
||||
|
@ -595,49 +623,6 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="protocol">
|
||||
<property name="toolTip">
|
||||
<string>Command protocol</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>GS-232</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>SPID</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>rotctld</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>DFM</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QSpinBox" name="elevationOffset">
|
||||
<property name="toolTip">
|
||||
<string>Specify an offset angle in degrees that will be added to the target elevation to correct for misalignment</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-180</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>180</number>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="protocolLabel">
|
||||
<property name="text">
|
||||
|
@ -645,6 +630,50 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="elevationMinLabel">
|
||||
<property name="text">
|
||||
<string>Elevation min</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="azimuthOffset">
|
||||
<property name="toolTip">
|
||||
<string>Specify an offset angel in degrees that will be added to the target azimuth to correct for misalignment</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-360</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>360</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QDoubleSpinBox" name="tolerance">
|
||||
<property name="toolTip">
|
||||
<string>Tolerance in degrees</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="serialPortLabel">
|
||||
<property name="text">
|
||||
<string>Serial Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="toleranceLabel">
|
||||
<property name="text">
|
||||
<string>Tolerance</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QComboBox" name="coordinates">
|
||||
<property name="toolTip">
|
||||
|
@ -667,13 +696,52 @@
|
|||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="inputControllerLabel">
|
||||
<property name="text">
|
||||
<string>Coordinates</string>
|
||||
<string>Input Control</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="3">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSlider" name="inputSensitivity">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Input controller sensitivity</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2000</number>
|
||||
</property>
|
||||
<property name="pageStep">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>25</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="inputSensitivityText">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>100%</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
|
|
@ -64,6 +64,8 @@ void GS232ControllerSettings::resetToDefaults()
|
|||
m_connection = SERIAL;
|
||||
m_precision = 0;
|
||||
m_coordinates = AZ_EL;
|
||||
m_inputController = "None";
|
||||
m_inputSensitivity = 0.25;
|
||||
m_dfmTrackOn = false;
|
||||
m_dfmLubePumpsOn = false;
|
||||
m_dfmBrakesOn = false;
|
||||
|
@ -119,6 +121,8 @@ QByteArray GS232ControllerSettings::serialize() const
|
|||
s.writeBool(32, m_dfmLubePumpsOn);
|
||||
s.writeBool(33, m_dfmBrakesOn);
|
||||
s.writeBool(34, m_dfmDrivesOn);
|
||||
s.writeString(35, m_inputController);
|
||||
s.writeFloat(36, m_inputSensitivity);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
|
@ -187,6 +191,8 @@ bool GS232ControllerSettings::deserialize(const QByteArray& data)
|
|||
d.readBool(32, &m_dfmLubePumpsOn);
|
||||
d.readBool(33, &m_dfmBrakesOn);
|
||||
d.readBool(34, &m_dfmDrivesOn);
|
||||
d.readString(35, &m_inputController, "None");
|
||||
d.readFloat(36, &m_inputSensitivity, 0.25);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -271,6 +277,12 @@ void GS232ControllerSettings::applySettings(const QStringList& settingsKeys, con
|
|||
if (settingsKeys.contains("coordinates")) {
|
||||
m_coordinates = settings.m_coordinates;
|
||||
}
|
||||
if (settingsKeys.contains("inputController")) {
|
||||
m_inputController = settings.m_inputController;
|
||||
}
|
||||
if (settingsKeys.contains("inputSensitivity")) {
|
||||
m_inputSensitivity = settings.m_inputSensitivity;
|
||||
}
|
||||
if (settingsKeys.contains("dfmTrackOn")) {
|
||||
m_dfmTrackOn = settings.m_dfmTrackOn;
|
||||
}
|
||||
|
@ -370,6 +382,12 @@ QString GS232ControllerSettings::getDebugString(const QStringList& settingsKeys,
|
|||
if (settingsKeys.contains("coordinates") || force) {
|
||||
ostr << " m_coordinates: " << m_precision;
|
||||
}
|
||||
if (settingsKeys.contains("inputController") || force) {
|
||||
ostr << " m_inputController: " << m_inputController.toStdString();
|
||||
}
|
||||
if (settingsKeys.contains("inputSensitivity") || force) {
|
||||
ostr << " m_inputSensitivity: " << m_inputSensitivity;
|
||||
}
|
||||
if (settingsKeys.contains("title") || force) {
|
||||
ostr << " m_title: " << m_title.toStdString();
|
||||
}
|
||||
|
@ -397,4 +415,3 @@ QString GS232ControllerSettings::getDebugString(const QStringList& settingsKeys,
|
|||
|
||||
return QString(ostr.str().c_str());
|
||||
}
|
||||
|
||||
|
|
|
@ -62,6 +62,8 @@ struct GS232ControllerSettings
|
|||
enum Connection { SERIAL, TCP } m_connection;
|
||||
int m_precision;
|
||||
enum Coordinates { AZ_EL, X_Y_85, X_Y_30 } m_coordinates;
|
||||
QString m_inputController;
|
||||
float m_inputSensitivity;
|
||||
|
||||
bool m_dfmTrackOn;
|
||||
bool m_dfmLubePumpsOn;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef QT_GAMEPAD_FOUND
|
||||
#include <QGamepadManager>
|
||||
#include "gamepadinputcontroller.h"
|
||||
#endif
|
||||
|
||||
#include "inputcontroller.h"
|
||||
|
||||
InputControllerManager* InputControllerManager::m_instance = nullptr;
|
||||
|
||||
QStringList InputControllerManager::getAllControllers()
|
||||
{
|
||||
#ifdef QT_GAMEPAD_FOUND
|
||||
return GamepadInputController::getAllControllers();
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
InputController* InputControllerManager::open(const QString& name)
|
||||
{
|
||||
#ifdef QT_GAMEPAD_FOUND
|
||||
return GamepadInputController::open(name);
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
InputControllerManager* InputControllerManager::instance()
|
||||
{
|
||||
if (!m_instance) {
|
||||
m_instance = new InputControllerManager();
|
||||
}
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
InputControllerManager::InputControllerManager()
|
||||
{
|
||||
#ifdef QT_GAMEPAD_FOUND
|
||||
connect(QGamepadManager::instance(), &QGamepadManager::connectedGamepadsChanged, this, &InputControllerManager::connectedGamepadsChanged);
|
||||
#endif
|
||||
}
|
||||
|
||||
void InputControllerManager::connectedGamepadsChanged()
|
||||
{
|
||||
emit controllersChanged();
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2023 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// 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 V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDE_FEATURE_INPUTCONTROLLER_H_
|
||||
#define INCLUDE_FEATURE_INPUTCONTROLLER_H_
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class InputController : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
// Called every ~50ms
|
||||
// axis 0-3. 0=Az/X, 1=El/Y, 2=Az Offset, 3=El Offset
|
||||
// value returned should be current axis position in range [-1,1]
|
||||
virtual double getAxisValue(int axis) = 0;
|
||||
virtual int getNumberOfAxes() const = 0;
|
||||
|
||||
};
|
||||
|
||||
class InputControllerManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
static QStringList getAllControllers();
|
||||
static InputController* open(const QString& name);
|
||||
static InputControllerManager* instance();
|
||||
|
||||
signals:
|
||||
|
||||
void controllersChanged();
|
||||
|
||||
private slots:
|
||||
void connectedGamepadsChanged();
|
||||
|
||||
private:
|
||||
InputControllerManager();
|
||||
|
||||
static InputControllerManager *m_instance;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // INCLUDE_FEATURE_INPUTCONTROLLER_H_
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
<h2>Introduction</h2>
|
||||
|
||||
The Rotator Controller feature plugin allows SDRangel to send commands to GS-232 and SPID rotators as well as hamlib's rotctld, via a serial or TCP connection.
|
||||
The Rotator Controller feature plugin allows SDRangel to send commands to GS-232 and SPID rotators as well as hamlib's rotctld, via a serial or TCP connection.
|
||||
This allows SDRangel to point antennas mounted on a rotator to a specified azimuth and elevation.
|
||||
|
||||
Azimuth and elevation can be set manually by a user in the GUI, via the REST API, or via another plugin, such as the Map Feature, the ADS-B Demodulator, or the Star Tracker.
|
||||
Azimuth and elevation can be set manually by a user in the GUI, via the REST API, via another plugin, such as the Map Feature, the ADS-B Demodulator, or the Star Tracker, or by controller/gamepads (such as an XBox Controller).
|
||||
|
||||
<h2>Interface</h2>
|
||||
|
||||
|
@ -107,6 +107,20 @@ Specifies the coordinate system used by the GUI for entry and display of the pos
|
|||
|
||||
Equations for translating between these coordinate systems can be found [here](https://ntrs.nasa.gov/citations/19670030005).
|
||||
|
||||
<h3>22: Input Control</h3>
|
||||
|
||||
Specifies a controller/gamepad (such as an XBox Wireless Controller) that can be used to specify target coordinates or azimuth and elevation offset.
|
||||
|
||||
When a controller with 2 sticks (4 axes) such as the XBox Wireless Controller is used, the right stick is used for controlling target coordinates,
|
||||
while the left stick is for controlling azimuth and elevation offset.
|
||||
If a controller only has 2 axes, target coordinates will be controlled when not tracking (6) and offset will be controlled when tracking.
|
||||
|
||||
The [Qt Gamepad](https://doc.qt.io/qt-5/qtgamepad-index.html) library is used to implement gamepad support.
|
||||
|
||||
<h3>23: Sensitivity</h3>
|
||||
|
||||
Specifies the sensitivity on the input controls (22). The higher the value, the faster coordinates will change for a given control stick movement.
|
||||
|
||||
<h2>Protocol Implementations</h2>
|
||||
|
||||
<h3>GS-232 Protocol Implementation Notes</h3>
|
||||
|
|
|
@ -58,6 +58,13 @@ GS232ControllerSettings:
|
|||
coordinates:
|
||||
description: (0 Az/El, 1 X/Y 85, 2 X/Y 30)
|
||||
type: integer
|
||||
inputController:
|
||||
description: Name of input controller
|
||||
type: string
|
||||
inputSensitivity:
|
||||
description: Input controller sensitivity
|
||||
type: number
|
||||
format: float
|
||||
title:
|
||||
type: string
|
||||
rgbColor:
|
||||
|
|
|
@ -64,6 +64,10 @@ SWGGS232ControllerSettings::SWGGS232ControllerSettings() {
|
|||
m_precision_isSet = false;
|
||||
coordinates = 0;
|
||||
m_coordinates_isSet = false;
|
||||
input_controller = nullptr;
|
||||
m_input_controller_isSet = false;
|
||||
input_sensitivity = 0.0f;
|
||||
m_input_sensitivity_isSet = false;
|
||||
title = nullptr;
|
||||
m_title_isSet = false;
|
||||
rgb_color = 0;
|
||||
|
@ -124,6 +128,10 @@ SWGGS232ControllerSettings::init() {
|
|||
m_precision_isSet = false;
|
||||
coordinates = 0;
|
||||
m_coordinates_isSet = false;
|
||||
input_controller = new QString("");
|
||||
m_input_controller_isSet = false;
|
||||
input_sensitivity = 0.0f;
|
||||
m_input_sensitivity_isSet = false;
|
||||
title = new QString("");
|
||||
m_title_isSet = false;
|
||||
rgb_color = 0;
|
||||
|
@ -168,6 +176,10 @@ SWGGS232ControllerSettings::cleanup() {
|
|||
|
||||
|
||||
|
||||
if(input_controller != nullptr) {
|
||||
delete input_controller;
|
||||
}
|
||||
|
||||
if(title != nullptr) {
|
||||
delete title;
|
||||
}
|
||||
|
@ -231,6 +243,10 @@ SWGGS232ControllerSettings::fromJsonObject(QJsonObject &pJson) {
|
|||
|
||||
::SWGSDRangel::setValue(&coordinates, pJson["coordinates"], "qint32", "");
|
||||
|
||||
::SWGSDRangel::setValue(&input_controller, pJson["inputController"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&input_sensitivity, pJson["inputSensitivity"], "float", "");
|
||||
|
||||
::SWGSDRangel::setValue(&title, pJson["title"], "QString", "QString");
|
||||
|
||||
::SWGSDRangel::setValue(&rgb_color, pJson["rgbColor"], "qint32", "");
|
||||
|
@ -317,6 +333,12 @@ SWGGS232ControllerSettings::asJsonObject() {
|
|||
if(m_coordinates_isSet){
|
||||
obj->insert("coordinates", QJsonValue(coordinates));
|
||||
}
|
||||
if(input_controller != nullptr && *input_controller != QString("")){
|
||||
toJsonValue(QString("inputController"), input_controller, obj, QString("QString"));
|
||||
}
|
||||
if(m_input_sensitivity_isSet){
|
||||
obj->insert("inputSensitivity", QJsonValue(input_sensitivity));
|
||||
}
|
||||
if(title != nullptr && *title != QString("")){
|
||||
toJsonValue(QString("title"), title, obj, QString("QString"));
|
||||
}
|
||||
|
@ -525,6 +547,26 @@ SWGGS232ControllerSettings::setCoordinates(qint32 coordinates) {
|
|||
this->m_coordinates_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGGS232ControllerSettings::getInputController() {
|
||||
return input_controller;
|
||||
}
|
||||
void
|
||||
SWGGS232ControllerSettings::setInputController(QString* input_controller) {
|
||||
this->input_controller = input_controller;
|
||||
this->m_input_controller_isSet = true;
|
||||
}
|
||||
|
||||
float
|
||||
SWGGS232ControllerSettings::getInputSensitivity() {
|
||||
return input_sensitivity;
|
||||
}
|
||||
void
|
||||
SWGGS232ControllerSettings::setInputSensitivity(float input_sensitivity) {
|
||||
this->input_sensitivity = input_sensitivity;
|
||||
this->m_input_sensitivity_isSet = true;
|
||||
}
|
||||
|
||||
QString*
|
||||
SWGGS232ControllerSettings::getTitle() {
|
||||
return title;
|
||||
|
@ -664,6 +706,12 @@ SWGGS232ControllerSettings::isSet(){
|
|||
if(m_coordinates_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(input_controller && *input_controller != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(m_input_sensitivity_isSet){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
if(title && *title != QString("")){
|
||||
isObjectUpdated = true; break;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,12 @@ public:
|
|||
qint32 getCoordinates();
|
||||
void setCoordinates(qint32 coordinates);
|
||||
|
||||
QString* getInputController();
|
||||
void setInputController(QString* input_controller);
|
||||
|
||||
float getInputSensitivity();
|
||||
void setInputSensitivity(float input_sensitivity);
|
||||
|
||||
QString* getTitle();
|
||||
void setTitle(QString* title);
|
||||
|
||||
|
@ -179,6 +185,12 @@ private:
|
|||
qint32 coordinates;
|
||||
bool m_coordinates_isSet;
|
||||
|
||||
QString* input_controller;
|
||||
bool m_input_controller_isSet;
|
||||
|
||||
float input_sensitivity;
|
||||
bool m_input_sensitivity_isSet;
|
||||
|
||||
QString* title;
|
||||
bool m_title_isSet;
|
||||
|
||||
|
|
Loading…
Reference in New Issue