diff options
| author | JMC47 <JMC4789@gmail.com> | 2025-12-22 13:35:24 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-22 13:35:24 -0500 |
| commit | 07d071a0b889ac1a7c2e6cc2d03db57cc2fd81e5 (patch) | |
| tree | e7ba80352c6c30a561db840be8bf3483c5598732 /Source/Core | |
| parent | 8aabaf8b63b67e4af2b4001e77135e6ff83c23ea (diff) | |
| parent | 80da48f631952a82c387c261f7cd94f31fea4cb5 (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.cpp | 20 | ||||
| -rw-r--r-- | Source/Core/DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h | 2 | ||||
| -rw-r--r-- | Source/Core/InputCommon/GCAdapter.cpp | 27 | ||||
| -rw-r--r-- | Source/Core/InputCommon/GCAdapter.h | 3 |
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 |
