summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/frontend/input.h20
-rw-r--r--src/core/hle/service/hid/hid.cpp32
-rw-r--r--src/core/settings.h1
3 files changed, 48 insertions, 5 deletions
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h
index 0a5713dc0..a8be49440 100644
--- a/src/core/frontend/input.h
+++ b/src/core/frontend/input.h
@@ -11,6 +11,7 @@
11#include <utility> 11#include <utility>
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "common/param_package.h" 13#include "common/param_package.h"
14#include "common/vector_math.h"
14 15
15namespace Input { 16namespace Input {
16 17
@@ -107,4 +108,23 @@ using ButtonDevice = InputDevice<bool>;
107 */ 108 */
108using AnalogDevice = InputDevice<std::tuple<float, float>>; 109using AnalogDevice = InputDevice<std::tuple<float, float>>;
109 110
111/**
112 * A motion device is an input device that returns a tuple of accelerometer state vector and
113 * gyroscope state vector.
114 *
115 * For accelerometer state vector:
116 * x+ is the same direction as LEFT on D-pad.
117 * y+ is normal to the touch screen, pointing outward.
118 * z+ is the same direction as UP on D-pad.
119 * Units: measured in unit of gravitational acceleration
120 *
121 * For gyroscope state vector:
122 * x+ is the same direction as LEFT on D-pad.
123 * y+ is normal to the touch screen, pointing outward.
124 * z+ is the same direction as UP on D-pad.
125 * Orientation is determined by right-hand rule.
126 * Units: deg/sec
127 */
128using MotionDevice = InputDevice<std::tuple<Math::Vec3<float>, Math::Vec3<float>>>;
129
110} // namespace Input 130} // namespace Input
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 2014b8461..a13b72e88 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -7,6 +7,7 @@
7#include <cmath> 7#include <cmath>
8#include <memory> 8#include <memory>
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/core.h"
10#include "core/core_timing.h" 11#include "core/core_timing.h"
11#include "core/frontend/emu_window.h" 12#include "core/frontend/emu_window.h"
12#include "core/frontend/input.h" 13#include "core/frontend/input.h"
@@ -50,10 +51,14 @@ constexpr u64 pad_update_ticks = BASE_CLOCK_RATE_ARM11 / 234;
50constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE_ARM11 / 104; 51constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE_ARM11 / 104;
51constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE_ARM11 / 101; 52constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE_ARM11 / 101;
52 53
54constexpr float accelerometer_coef = 512.0f; // measured from hw test result
55constexpr float gyroscope_coef = 14.375f; // got from hwtest GetGyroscopeLowRawToDpsCoefficient call
56
53static std::atomic<bool> is_device_reload_pending; 57static std::atomic<bool> is_device_reload_pending;
54static std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> 58static std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
55 buttons; 59 buttons;
56static std::unique_ptr<Input::AnalogDevice> circle_pad; 60static std::unique_ptr<Input::AnalogDevice> circle_pad;
61static std::unique_ptr<Input::MotionDevice> motion_device;
57 62
58DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y) { 63DirectionState GetStickDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
59 // 30 degree and 60 degree are angular thresholds for directions 64 // 30 degree and 60 degree are angular thresholds for directions
@@ -90,6 +95,7 @@ static void LoadInputDevices() {
90 buttons.begin(), Input::CreateDevice<Input::ButtonDevice>); 95 buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
91 circle_pad = Input::CreateDevice<Input::AnalogDevice>( 96 circle_pad = Input::CreateDevice<Input::AnalogDevice>(
92 Settings::values.analogs[Settings::NativeAnalog::CirclePad]); 97 Settings::values.analogs[Settings::NativeAnalog::CirclePad]);
98 motion_device = Input::CreateDevice<Input::MotionDevice>(Settings::values.motion_device);
93} 99}
94 100
95static void UnloadInputDevices() { 101static void UnloadInputDevices() {
@@ -97,6 +103,7 @@ static void UnloadInputDevices() {
97 button.reset(); 103 button.reset();
98 } 104 }
99 circle_pad.reset(); 105 circle_pad.reset();
106 motion_device.reset();
100} 107}
101 108
102static void UpdatePadCallback(u64 userdata, int cycles_late) { 109static void UpdatePadCallback(u64 userdata, int cycles_late) {
@@ -193,10 +200,19 @@ static void UpdateAccelerometerCallback(u64 userdata, int cycles_late) {
193 mem->accelerometer.index = next_accelerometer_index; 200 mem->accelerometer.index = next_accelerometer_index;
194 next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size(); 201 next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
195 202
203 Math::Vec3<float> accel;
204 std::tie(accel, std::ignore) = motion_device->GetStatus();
205 accel *= accelerometer_coef;
206 // TODO(wwylele): do a time stretch as it in UpdateGyroscopeCallback
207 // The time stretch formula should be like
208 // stretched_vector = (raw_vector - gravity) * stretch_ratio + gravity
209
196 AccelerometerDataEntry& accelerometer_entry = 210 AccelerometerDataEntry& accelerometer_entry =
197 mem->accelerometer.entries[mem->accelerometer.index]; 211 mem->accelerometer.entries[mem->accelerometer.index];
198 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) = 212
199 VideoCore::g_emu_window->GetAccelerometerState(); 213 accelerometer_entry.x = static_cast<s16>(accel.x);
214 accelerometer_entry.y = static_cast<s16>(accel.y);
215 accelerometer_entry.z = static_cast<s16>(accel.z);
200 216
201 // Make up "raw" entry 217 // Make up "raw" entry
202 // TODO(wwylele): 218 // TODO(wwylele):
@@ -227,8 +243,14 @@ static void UpdateGyroscopeCallback(u64 userdata, int cycles_late) {
227 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size(); 243 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
228 244
229 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index]; 245 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
230 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) = 246
231 VideoCore::g_emu_window->GetGyroscopeState(); 247 Math::Vec3<float> gyro;
248 std::tie(std::ignore, gyro) = motion_device->GetStatus();
249 float stretch = Core::System::GetInstance().perf_stats.GetLastFrameTimeScale();
250 gyro *= gyroscope_coef * stretch;
251 gyroscope_entry.x = static_cast<s16>(gyro.x);
252 gyroscope_entry.y = static_cast<s16>(gyro.y);
253 gyroscope_entry.z = static_cast<s16>(gyro.z);
232 254
233 // Make up "raw" entry 255 // Make up "raw" entry
234 mem->gyroscope.raw_entry.x = gyroscope_entry.x; 256 mem->gyroscope.raw_entry.x = gyroscope_entry.x;
@@ -326,7 +348,7 @@ void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self) {
326 348
327 cmd_buff[1] = RESULT_SUCCESS.raw; 349 cmd_buff[1] = RESULT_SUCCESS.raw;
328 350
329 f32 coef = VideoCore::g_emu_window->GetGyroscopeRawToDpsCoefficient(); 351 f32 coef = gyroscope_coef;
330 memcpy(&cmd_buff[2], &coef, 4); 352 memcpy(&cmd_buff[2], &coef, 4);
331} 353}
332 354
diff --git a/src/core/settings.h b/src/core/settings.h
index ee16bb90a..7e15b119b 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -79,6 +79,7 @@ struct Values {
79 // Controls 79 // Controls
80 std::array<std::string, NativeButton::NumButtons> buttons; 80 std::array<std::string, NativeButton::NumButtons> buttons;
81 std::array<std::string, NativeAnalog::NumAnalogs> analogs; 81 std::array<std::string, NativeAnalog::NumAnalogs> analogs;
82 std::string motion_device;
82 83
83 // Core 84 // Core
84 bool use_cpu_jit; 85 bool use_cpu_jit;