summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-12-22 13:35:24 -0500
committerGitHub <noreply@github.com>2025-12-22 13:35:24 -0500
commit07d071a0b889ac1a7c2e6cc2d03db57cc2fd81e5 (patch)
treee7ba80352c6c30a561db840be8bf3483c5598732 /Source/Core
parent8aabaf8b63b67e4af2b4001e77135e6ff83c23ea (diff)
parent80da48f631952a82c387c261f7cd94f31fea4cb5 (diff)
Merge pull request #14158 from jordan-woyak/gcadapter-poll-rate-display
GCAdapter: Calculate poll rate for display in UI.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp20
-rw-r--r--Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h2
-rw-r--r--Source/Core/InputCommon/GCAdapter.cpp27
-rw-r--r--Source/Core/InputCommon/GCAdapter.h3
4 files changed, 43 insertions, 9 deletions
diff --git a/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp b/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp
index 82b39d28e3..08fa295741 100644
--- a/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp
+++ b/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.cpp
@@ -6,10 +6,10 @@
#include <QCheckBox>
#include <QDialogButtonBox>
#include <QLabel>
+#include <QTimer>
#include <QVBoxLayout>
#include "Core/Config/MainSettings.h"
-#include "Core/ConfigManager.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "InputCommon/GCAdapter.h"
@@ -23,27 +23,25 @@ GCPadWiiUConfigDialog::GCPadWiiUConfigDialog(int port, QWidget* parent)
ConnectWidgets();
}
-GCPadWiiUConfigDialog::~GCPadWiiUConfigDialog()
-{
- GCAdapter::SetAdapterCallback(nullptr);
-}
-
void GCPadWiiUConfigDialog::CreateLayout()
{
setWindowTitle(tr("GameCube Controller Adapter at Port %1").arg(m_port + 1));
m_layout = new QVBoxLayout();
m_status_label = new QLabel();
+ m_poll_rate_label = new QLabel;
m_rumble = new QCheckBox(tr("Enable Rumble"));
m_simulate_bongos = new QCheckBox(tr("Simulate DK Bongos"));
m_button_box = new QDialogButtonBox(QDialogButtonBox::Ok);
UpdateAdapterStatus();
- auto callback = [this] { QueueOnObject(this, &GCPadWiiUConfigDialog::UpdateAdapterStatus); };
- GCAdapter::SetAdapterCallback(callback);
+ auto* const timer = new QTimer{this};
+ connect(timer, &QTimer::timeout, this, &GCPadWiiUConfigDialog::UpdateAdapterStatus);
+ timer->start(std::chrono::milliseconds{500});
m_layout->addWidget(m_status_label);
+ m_layout->addWidget(m_poll_rate_label);
m_layout->addWidget(m_rumble);
m_layout->addWidget(m_simulate_bongos);
m_layout->addWidget(m_button_box);
@@ -79,6 +77,12 @@ void GCPadWiiUConfigDialog::UpdateAdapterStatus()
m_status_label->setText(status_text);
+ const auto poll_rate = GCAdapter::GetCurrentPollRate();
+ if (poll_rate != 0)
+ m_poll_rate_label->setText(tr("Poll Rate: %1 Hz").arg(poll_rate, 0, 'f', 2));
+ else
+ m_poll_rate_label->clear();
+
m_rumble->setEnabled(detected);
m_simulate_bongos->setEnabled(detected);
}
diff --git a/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h b/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h
index f18510d3c5..d71d237618 100644
--- a/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h
+++ b/Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h
@@ -15,7 +15,6 @@ class GCPadWiiUConfigDialog final : public QDialog
Q_OBJECT
public:
explicit GCPadWiiUConfigDialog(int port, QWidget* parent = nullptr);
- ~GCPadWiiUConfigDialog() override;
private:
void LoadSettings();
@@ -31,6 +30,7 @@ private:
QVBoxLayout* m_layout;
QLabel* m_status_label;
+ QLabel* m_poll_rate_label;
QDialogButtonBox* m_button_box;
// Checkboxes
diff --git a/Source/Core/InputCommon/GCAdapter.cpp b/Source/Core/InputCommon/GCAdapter.cpp
index df212e8f4e..5ec245a56d 100644
--- a/Source/Core/InputCommon/GCAdapter.cpp
+++ b/Source/Core/InputCommon/GCAdapter.cpp
@@ -163,6 +163,8 @@ static std::optional<Config::ConfigChangedCallbackID> s_config_callback_id = std
static bool s_is_adapter_wanted = false;
static std::array<bool, SerialInterface::MAX_SI_CHANNELS> s_config_rumble_enabled{};
+static std::atomic<double> s_adapter_poll_rate{};
+
static void ReadThreadFunc()
{
Common::SetCurrentThreadName("GCAdapter Read Thread");
@@ -199,6 +201,11 @@ static void ReadThreadFunc()
// Reset rumble once on initial reading
ResetRumble();
+ // Measure poll rate for display in UI.
+ constexpr int POLL_RATE_MEASUREMENT_SAMPLE_COUNT = 50;
+ auto poll_rate_measurement_start_time = Clock::now();
+ int poll_rate_measurement_count = 0;
+
while (s_read_adapter_thread_running.IsSet())
{
#if GCADAPTER_USE_LIBUSB_IMPLEMENTATION
@@ -242,6 +249,19 @@ static void ReadThreadFunc()
}
#endif
+ // Update poll rate measurement.
+ if (++poll_rate_measurement_count == POLL_RATE_MEASUREMENT_SAMPLE_COUNT)
+ {
+ const auto now = Clock::now();
+
+ const auto poll_rate =
+ POLL_RATE_MEASUREMENT_SAMPLE_COUNT / DT_s(now - poll_rate_measurement_start_time).count();
+ s_adapter_poll_rate.store(poll_rate, std::memory_order_relaxed);
+
+ poll_rate_measurement_start_time = now;
+ poll_rate_measurement_count = 0;
+ }
+
Common::YieldCPU();
}
@@ -259,6 +279,8 @@ static void ReadThreadFunc()
s_detected = false;
#endif
+ s_adapter_poll_rate.store(0.0, std::memory_order_relaxed);
+
NOTICE_LOG_FMT(CONTROLLERINTERFACE, "GCAdapter read thread stopped");
}
@@ -1013,4 +1035,9 @@ bool IsDetected(const char** error_message)
#endif
}
+double GetCurrentPollRate()
+{
+ return s_adapter_poll_rate.load(std::memory_order_relaxed);
+}
+
} // namespace GCAdapter
diff --git a/Source/Core/InputCommon/GCAdapter.h b/Source/Core/InputCommon/GCAdapter.h
index e6f62e035b..50e24ae940 100644
--- a/Source/Core/InputCommon/GCAdapter.h
+++ b/Source/Core/InputCommon/GCAdapter.h
@@ -28,4 +28,7 @@ bool DeviceConnected(int chan);
void ResetDeviceType(int chan);
bool UseAdapter();
+// Callable from any thread. Returns 0 when the adapter is not detected.
+double GetCurrentPollRate();
+
} // namespace GCAdapter