summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2016-03-25 21:07:21 -0400
committerGravatar bunnei2016-03-25 21:07:21 -0400
commit39da819b5564a495db78f869062123fbab5fec3d (patch)
tree09d2667918cb0111b7bcb5f9cd9d5ce1b4b7b7ff
parentMerge pull request #1566 from MerryMage/audio-codec (diff)
parentimplement GyroscopeCalibrateParam (diff)
downloadyuzu-39da819b5564a495db78f869062123fbab5fec3d.tar.gz
yuzu-39da819b5564a495db78f869062123fbab5fec3d.tar.xz
yuzu-39da819b5564a495db78f869062123fbab5fec3d.zip
Merge pull request #1549 from wwylele/acc_gyro
hid: implement accelerometer and gyroscope back-end
Diffstat (limited to '')
-rw-r--r--src/common/emu_window.h48
-rw-r--r--src/core/hle/service/hid/hid.cpp92
-rw-r--r--src/core/hle/service/hid/hid.h78
-rw-r--r--src/core/hle/service/hid/hid_spvr.cpp20
-rw-r--r--src/core/hle/service/hid/hid_user.cpp20
5 files changed, 235 insertions, 23 deletions
diff --git a/src/common/emu_window.h b/src/common/emu_window.h
index a0ae4c9fa..b6b7bfd26 100644
--- a/src/common/emu_window.h
+++ b/src/common/emu_window.h
@@ -121,6 +121,54 @@ public:
121 } 121 }
122 122
123 /** 123 /**
124 * Gets the current accelerometer state (acceleration along each three axis).
125 * Axis explained:
126 * +x is the same direction as LEFT on D-pad.
127 * +y is normal to the touch screen, pointing outward.
128 * +z is the same direction as UP on D-pad.
129 * Units:
130 * 1 unit of return value = 1/512 g (measured by hw test),
131 * where g is the gravitational acceleration (9.8 m/sec2).
132 * @note This should be called by the core emu thread to get a state set by the window thread.
133 * @todo Implement accelerometer input in front-end.
134 * @return std::tuple of (x, y, z)
135 */
136 std::tuple<s16, s16, s16> GetAccelerometerState() const {
137 // stubbed
138 return std::make_tuple(0, -512, 0);
139 }
140
141 /**
142 * Gets the current gyroscope state (angular rates about each three axis).
143 * Axis explained:
144 * +x is the same direction as LEFT on D-pad.
145 * +y is normal to the touch screen, pointing outward.
146 * +z is the same direction as UP on D-pad.
147 * Orientation is determined by right-hand rule.
148 * Units:
149 * 1 unit of return value = (1/coef) deg/sec,
150 * where coef is the return value of GetGyroscopeRawToDpsCoefficient().
151 * @note This should be called by the core emu thread to get a state set by the window thread.
152 * @todo Implement gyroscope input in front-end.
153 * @return std::tuple of (x, y, z)
154 */
155 std::tuple<s16, s16, s16> GetGyroscopeState() const {
156 // stubbed
157 return std::make_tuple(0, 0, 0);
158 }
159
160 /**
161 * Gets the coefficient for units conversion of gyroscope state.
162 * The conversion formula is r = coefficient * v,
163 * where v is angular rate in deg/sec,
164 * and r is the gyroscope state.
165 * @return float-type coefficient
166 */
167 f32 GetGyroscopeRawToDpsCoefficient() const {
168 return 14.375f; // taken from hw test, and gyroscope's document
169 }
170
171 /**
124 * Returns currently active configuration. 172 * Returns currently active configuration.
125 * @note Accesses to the returned object need not be consistent because it may be modified in another thread 173 * @note Accesses to the returned object need not be consistent because it may be modified in another thread
126 */ 174 */
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index cb4fd38e2..b27ab6d9b 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -33,6 +33,11 @@ static Kernel::SharedPtr<Kernel::Event> event_debug_pad;
33 33
34static u32 next_pad_index; 34static u32 next_pad_index;
35static u32 next_touch_index; 35static u32 next_touch_index;
36static u32 next_accelerometer_index;
37static u32 next_gyroscope_index;
38
39static int enable_accelerometer_count = 0; // positive means enabled
40static int enable_gyroscope_count = 0; // positive means enabled
36 41
37const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = {{ 42const std::array<Service::HID::PadState, Settings::NativeInput::NUM_INPUTS> pad_mapping = {{
38 Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y, 43 Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y,
@@ -120,6 +125,58 @@ void Update() {
120 // Signal both handles when there's an update to Pad or touch 125 // Signal both handles when there's an update to Pad or touch
121 event_pad_or_touch_1->Signal(); 126 event_pad_or_touch_1->Signal();
122 event_pad_or_touch_2->Signal(); 127 event_pad_or_touch_2->Signal();
128
129 // Update accelerometer
130 if (enable_accelerometer_count > 0) {
131 mem->accelerometer.index = next_accelerometer_index;
132 next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
133
134 AccelerometerDataEntry& accelerometer_entry = mem->accelerometer.entries[mem->accelerometer.index];
135 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z)
136 = VideoCore::g_emu_window->GetAccelerometerState();
137
138 // Make up "raw" entry
139 // TODO(wwylele):
140 // From hardware testing, the raw_entry values are approximately,
141 // but not exactly, as twice as corresponding entries (or with a minus sign).
142 // It may caused by system calibration to the accelerometer.
143 // Figure out how it works, or, if no game reads raw_entry,
144 // the following three lines can be removed and leave raw_entry unimplemented.
145 mem->accelerometer.raw_entry.x = -2 * accelerometer_entry.x;
146 mem->accelerometer.raw_entry.z = 2 * accelerometer_entry.y;
147 mem->accelerometer.raw_entry.y = -2 * accelerometer_entry.z;
148
149 // If we just updated index 0, provide a new timestamp
150 if (mem->accelerometer.index == 0) {
151 mem->accelerometer.index_reset_ticks_previous = mem->accelerometer.index_reset_ticks;
152 mem->accelerometer.index_reset_ticks = (s64)CoreTiming::GetTicks();
153 }
154
155 event_accelerometer->Signal();
156 }
157
158 // Update gyroscope
159 if (enable_gyroscope_count > 0) {
160 mem->gyroscope.index = next_gyroscope_index;
161 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
162
163 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
164 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z)
165 = VideoCore::g_emu_window->GetGyroscopeState();
166
167 // Make up "raw" entry
168 mem->gyroscope.raw_entry.x = gyroscope_entry.x;
169 mem->gyroscope.raw_entry.z = -gyroscope_entry.y;
170 mem->gyroscope.raw_entry.y = gyroscope_entry.z;
171
172 // If we just updated index 0, provide a new timestamp
173 if (mem->gyroscope.index == 0) {
174 mem->gyroscope.index_reset_ticks_previous = mem->gyroscope.index_reset_ticks;
175 mem->gyroscope.index_reset_ticks = (s64)CoreTiming::GetTicks();
176 }
177
178 event_gyroscope->Signal();
179 }
123} 180}
124 181
125void GetIPCHandles(Service::Interface* self) { 182void GetIPCHandles(Service::Interface* self) {
@@ -139,40 +196,69 @@ void GetIPCHandles(Service::Interface* self) {
139void EnableAccelerometer(Service::Interface* self) { 196void EnableAccelerometer(Service::Interface* self) {
140 u32* cmd_buff = Kernel::GetCommandBuffer(); 197 u32* cmd_buff = Kernel::GetCommandBuffer();
141 198
199 ++enable_accelerometer_count;
142 event_accelerometer->Signal(); 200 event_accelerometer->Signal();
143 201
144 cmd_buff[1] = RESULT_SUCCESS.raw; 202 cmd_buff[1] = RESULT_SUCCESS.raw;
145 203
146 LOG_WARNING(Service_HID, "(STUBBED) called"); 204 LOG_DEBUG(Service_HID, "called");
147} 205}
148 206
149void DisableAccelerometer(Service::Interface* self) { 207void DisableAccelerometer(Service::Interface* self) {
150 u32* cmd_buff = Kernel::GetCommandBuffer(); 208 u32* cmd_buff = Kernel::GetCommandBuffer();
151 209
210 --enable_accelerometer_count;
152 event_accelerometer->Signal(); 211 event_accelerometer->Signal();
153 212
154 cmd_buff[1] = RESULT_SUCCESS.raw; 213 cmd_buff[1] = RESULT_SUCCESS.raw;
155 214
156 LOG_WARNING(Service_HID, "(STUBBED) called"); 215 LOG_DEBUG(Service_HID, "called");
157} 216}
158 217
159void EnableGyroscopeLow(Service::Interface* self) { 218void EnableGyroscopeLow(Service::Interface* self) {
160 u32* cmd_buff = Kernel::GetCommandBuffer(); 219 u32* cmd_buff = Kernel::GetCommandBuffer();
161 220
221 ++enable_gyroscope_count;
162 event_gyroscope->Signal(); 222 event_gyroscope->Signal();
163 223
164 cmd_buff[1] = RESULT_SUCCESS.raw; 224 cmd_buff[1] = RESULT_SUCCESS.raw;
165 225
166 LOG_WARNING(Service_HID, "(STUBBED) called"); 226 LOG_DEBUG(Service_HID, "called");
167} 227}
168 228
169void DisableGyroscopeLow(Service::Interface* self) { 229void DisableGyroscopeLow(Service::Interface* self) {
170 u32* cmd_buff = Kernel::GetCommandBuffer(); 230 u32* cmd_buff = Kernel::GetCommandBuffer();
171 231
232 --enable_gyroscope_count;
172 event_gyroscope->Signal(); 233 event_gyroscope->Signal();
173 234
174 cmd_buff[1] = RESULT_SUCCESS.raw; 235 cmd_buff[1] = RESULT_SUCCESS.raw;
175 236
237 LOG_DEBUG(Service_HID, "called");
238}
239
240void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self) {
241 u32* cmd_buff = Kernel::GetCommandBuffer();
242
243 cmd_buff[1] = RESULT_SUCCESS.raw;
244
245 f32 coef = VideoCore::g_emu_window->GetGyroscopeRawToDpsCoefficient();
246 memcpy(&cmd_buff[2], &coef, 4);
247}
248
249void GetGyroscopeLowCalibrateParam(Service::Interface* self) {
250 u32* cmd_buff = Kernel::GetCommandBuffer();
251
252 cmd_buff[1] = RESULT_SUCCESS.raw;
253
254 const s16 param_unit = 6700; // an approximate value taken from hw
255 GyroscopeCalibrateParam param = {
256 { 0, param_unit, -param_unit },
257 { 0, param_unit, -param_unit },
258 { 0, param_unit, -param_unit },
259 };
260 memcpy(&cmd_buff[2], &param, sizeof(param));
261
176 LOG_WARNING(Service_HID, "(STUBBED) called"); 262 LOG_WARNING(Service_HID, "(STUBBED) called");
177} 263}
178 264
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 517f4f2ae..170d19ea8 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -78,6 +78,24 @@ struct TouchDataEntry {
78}; 78};
79 79
80/** 80/**
81 * Structure of a single entry of accelerometer state history within HID shared memory
82 */
83struct AccelerometerDataEntry {
84 s16 x;
85 s16 y;
86 s16 z;
87};
88
89/**
90 * Structure of a single entry of gyroscope state history within HID shared memory
91 */
92struct GyroscopeDataEntry {
93 s16 x;
94 s16 y;
95 s16 z;
96};
97
98/**
81 * Structure of data stored in HID shared memory 99 * Structure of data stored in HID shared memory
82 */ 100 */
83struct SharedMem { 101struct SharedMem {
@@ -112,6 +130,46 @@ struct SharedMem {
112 130
113 std::array<TouchDataEntry, 8> entries; ///< Last 8 touch entries, in pixel coordinates 131 std::array<TouchDataEntry, 8> entries; ///< Last 8 touch entries, in pixel coordinates
114 } touch; 132 } touch;
133
134 /// Accelerometer data
135 struct {
136 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
137 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
138 u32 index; ///< Index of the last updated accelerometer entry
139
140 INSERT_PADDING_WORDS(0x1);
141
142 AccelerometerDataEntry raw_entry;
143 INSERT_PADDING_BYTES(2);
144
145 std::array<AccelerometerDataEntry, 8> entries;
146 } accelerometer;
147
148 /// Gyroscope data
149 struct {
150 s64 index_reset_ticks; ///< CPU tick count for when HID module updated entry index 0
151 s64 index_reset_ticks_previous; ///< Previous `index_reset_ticks`
152 u32 index; ///< Index of the last updated accelerometer entry
153
154 INSERT_PADDING_WORDS(0x1);
155
156 GyroscopeDataEntry raw_entry;
157 INSERT_PADDING_BYTES(2);
158
159 std::array<GyroscopeDataEntry, 32> entries;
160 } gyroscope;
161};
162
163/**
164 * Structure of calibrate params that GetGyroscopeLowCalibrateParam returns
165 */
166struct GyroscopeCalibrateParam {
167 struct {
168 // TODO (wwylele): figure out the exact meaning of these params
169 s16 zero_point;
170 s16 positive_unit_point;
171 s16 negative_unit_point;
172 } x, y, z;
115}; 173};
116 174
117// TODO: MSVC does not support using offsetof() on non-static data members even though this 175// TODO: MSVC does not support using offsetof() on non-static data members even though this
@@ -222,6 +280,26 @@ void DisableGyroscopeLow(Interface* self);
222 */ 280 */
223void GetSoundVolume(Interface* self); 281void GetSoundVolume(Interface* self);
224 282
283/**
284 * HID::GetGyroscopeLowRawToDpsCoefficient service function
285 * Inputs:
286 * None
287 * Outputs:
288 * 1 : Result of function, 0 on success, otherwise error code
289 * 2 : float output value
290 */
291void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self);
292
293/**
294 * HID::GetGyroscopeLowCalibrateParam service function
295 * Inputs:
296 * None
297 * Outputs:
298 * 1 : Result of function, 0 on success, otherwise error code
299 * 2~6 (18 bytes) : struct GyroscopeCalibrateParam
300 */
301void GetGyroscopeLowCalibrateParam(Service::Interface* self);
302
225/// Checks for user input updates 303/// Checks for user input updates
226void Update(); 304void Update();
227 305
diff --git a/src/core/hle/service/hid/hid_spvr.cpp b/src/core/hle/service/hid/hid_spvr.cpp
index c50f597eb..046e65b11 100644
--- a/src/core/hle/service/hid/hid_spvr.cpp
+++ b/src/core/hle/service/hid/hid_spvr.cpp
@@ -9,16 +9,16 @@ namespace Service {
9namespace HID { 9namespace HID {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x000A0000, GetIPCHandles, "GetIPCHandles"}, 12 {0x000A0000, GetIPCHandles, "GetIPCHandles"},
13 {0x000B0000, nullptr, "StartAnalogStickCalibration"}, 13 {0x000B0000, nullptr, "StartAnalogStickCalibration"},
14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, 14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, 15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"},
16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, 16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"},
17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, 17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, 18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"},
19 {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"}, 19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"},
20 {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"}, 20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"},
21 {0x00170000, GetSoundVolume, "GetSoundVolume"}, 21 {0x00170000, GetSoundVolume, "GetSoundVolume"},
22}; 22};
23 23
24HID_SPVR_Interface::HID_SPVR_Interface() { 24HID_SPVR_Interface::HID_SPVR_Interface() {
diff --git a/src/core/hle/service/hid/hid_user.cpp b/src/core/hle/service/hid/hid_user.cpp
index bbdde2abb..bb157b83d 100644
--- a/src/core/hle/service/hid/hid_user.cpp
+++ b/src/core/hle/service/hid/hid_user.cpp
@@ -9,16 +9,16 @@ namespace Service {
9namespace HID { 9namespace HID {
10 10
11const Interface::FunctionInfo FunctionTable[] = { 11const Interface::FunctionInfo FunctionTable[] = {
12 {0x000A0000, GetIPCHandles, "GetIPCHandles"}, 12 {0x000A0000, GetIPCHandles, "GetIPCHandles"},
13 {0x000B0000, nullptr, "StartAnalogStickCalibration"}, 13 {0x000B0000, nullptr, "StartAnalogStickCalibration"},
14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"}, 14 {0x000E0000, nullptr, "GetAnalogStickCalibrateParam"},
15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"}, 15 {0x00110000, EnableAccelerometer, "EnableAccelerometer"},
16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"}, 16 {0x00120000, DisableAccelerometer, "DisableAccelerometer"},
17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"}, 17 {0x00130000, EnableGyroscopeLow, "EnableGyroscopeLow"},
18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"}, 18 {0x00140000, DisableGyroscopeLow, "DisableGyroscopeLow"},
19 {0x00150000, nullptr, "GetGyroscopeLowRawToDpsCoefficient"}, 19 {0x00150000, GetGyroscopeLowRawToDpsCoefficient, "GetGyroscopeLowRawToDpsCoefficient"},
20 {0x00160000, nullptr, "GetGyroscopeLowCalibrateParam"}, 20 {0x00160000, GetGyroscopeLowCalibrateParam, "GetGyroscopeLowCalibrateParam"},
21 {0x00170000, GetSoundVolume, "GetSoundVolume"}, 21 {0x00170000, GetSoundVolume, "GetSoundVolume"},
22}; 22};
23 23
24HID_U_Interface::HID_U_Interface() { 24HID_U_Interface::HID_U_Interface() {