summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/core_timing.cpp2
-rw-r--r--src/core/core_timing.h1
-rw-r--r--src/core/hle/service/hid/hid.cpp148
-rw-r--r--src/core/hle/service/hid/hid.h3
-rw-r--r--src/core/hw/gpu.cpp6
5 files changed, 96 insertions, 64 deletions
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index a437d0823..276ecfdf6 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -13,7 +13,7 @@
13#include "core/core.h" 13#include "core/core.h"
14#include "core/core_timing.h" 14#include "core/core_timing.h"
15 15
16int g_clock_rate_arm11 = 268123480; 16int g_clock_rate_arm11 = BASE_CLOCK_RATE_ARM11;
17 17
18// is this really necessary? 18// is this really necessary?
19#define INITIAL_SLICE_LENGTH 20000 19#define INITIAL_SLICE_LENGTH 20000
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index b72a1b500..d2f85cd4d 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -21,6 +21,7 @@
21// inside callback: 21// inside callback:
22// ScheduleEvent(periodInCycles - cycles_late, callback, "whatever") 22// ScheduleEvent(periodInCycles - cycles_late, callback, "whatever")
23 23
24constexpr int BASE_CLOCK_RATE_ARM11 = 268123480;
24extern int g_clock_rate_arm11; 25extern int g_clock_rate_arm11;
25 26
26inline s64 msToCycles(int ms) { 27inline s64 msToCycles(int ms) {
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 676154bd4..9bca97c1c 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -35,6 +35,15 @@ static u32 next_gyroscope_index;
35static int enable_accelerometer_count = 0; // positive means enabled 35static int enable_accelerometer_count = 0; // positive means enabled
36static int enable_gyroscope_count = 0; // positive means enabled 36static int enable_gyroscope_count = 0; // positive means enabled
37 37
38static int pad_update_event;
39static int accelerometer_update_event;
40static int gyroscope_update_event;
41
42// Updating period for each HID device. These empirical values are measured from a 11.2 3DS.
43constexpr u64 pad_update_ticks = BASE_CLOCK_RATE_ARM11 / 234;
44constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE_ARM11 / 104;
45constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE_ARM11 / 101;
46
38static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) { 47static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
39 // 30 degree and 60 degree are angular thresholds for directions 48 // 30 degree and 60 degree are angular thresholds for directions
40 constexpr float TAN30 = 0.577350269f; 49 constexpr float TAN30 = 0.577350269f;
@@ -65,14 +74,9 @@ static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
65 return state; 74 return state;
66} 75}
67 76
68void Update() { 77static void UpdatePadCallback(u64 userdata, int cycles_late) {
69 SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer()); 78 SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
70 79
71 if (mem == nullptr) {
72 LOG_DEBUG(Service_HID, "Cannot update HID prior to mapping shared memory!");
73 return;
74 }
75
76 PadState state = VideoCore::g_emu_window->GetPadState(); 80 PadState state = VideoCore::g_emu_window->GetPadState();
77 81
78 // Get current circle pad position and update circle pad direction 82 // Get current circle pad position and update circle pad direction
@@ -131,59 +135,68 @@ void Update() {
131 event_pad_or_touch_1->Signal(); 135 event_pad_or_touch_1->Signal();
132 event_pad_or_touch_2->Signal(); 136 event_pad_or_touch_2->Signal();
133 137
134 // Update accelerometer 138 // Reschedule recurrent event
135 if (enable_accelerometer_count > 0) { 139 CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
136 mem->accelerometer.index = next_accelerometer_index; 140}
137 next_accelerometer_index = 141
138 (next_accelerometer_index + 1) % mem->accelerometer.entries.size(); 142static void UpdateAccelerometerCallback(u64 userdata, int cycles_late) {
139 143 SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
140 AccelerometerDataEntry& accelerometer_entry = 144
141 mem->accelerometer.entries[mem->accelerometer.index]; 145 mem->accelerometer.index = next_accelerometer_index;
142 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) = 146 next_accelerometer_index = (next_accelerometer_index + 1) % mem->accelerometer.entries.size();
143 VideoCore::g_emu_window->GetAccelerometerState();
144
145 // Make up "raw" entry
146 // TODO(wwylele):
147 // From hardware testing, the raw_entry values are approximately,
148 // but not exactly, as twice as corresponding entries (or with a minus sign).
149 // It may caused by system calibration to the accelerometer.
150 // Figure out how it works, or, if no game reads raw_entry,
151 // the following three lines can be removed and leave raw_entry unimplemented.
152 mem->accelerometer.raw_entry.x = -2 * accelerometer_entry.x;
153 mem->accelerometer.raw_entry.z = 2 * accelerometer_entry.y;
154 mem->accelerometer.raw_entry.y = -2 * accelerometer_entry.z;
155
156 // If we just updated index 0, provide a new timestamp
157 if (mem->accelerometer.index == 0) {
158 mem->accelerometer.index_reset_ticks_previous = mem->accelerometer.index_reset_ticks;
159 mem->accelerometer.index_reset_ticks = (s64)CoreTiming::GetTicks();
160 }
161 147
162 event_accelerometer->Signal(); 148 AccelerometerDataEntry& accelerometer_entry =
149 mem->accelerometer.entries[mem->accelerometer.index];
150 std::tie(accelerometer_entry.x, accelerometer_entry.y, accelerometer_entry.z) =
151 VideoCore::g_emu_window->GetAccelerometerState();
152
153 // Make up "raw" entry
154 // TODO(wwylele):
155 // From hardware testing, the raw_entry values are approximately, but not exactly, as twice as
156 // corresponding entries (or with a minus sign). It may caused by system calibration to the
157 // accelerometer. Figure out how it works, or, if no game reads raw_entry, the following three
158 // lines can be removed and leave raw_entry unimplemented.
159 mem->accelerometer.raw_entry.x = -2 * accelerometer_entry.x;
160 mem->accelerometer.raw_entry.z = 2 * accelerometer_entry.y;
161 mem->accelerometer.raw_entry.y = -2 * accelerometer_entry.z;
162
163 // If we just updated index 0, provide a new timestamp
164 if (mem->accelerometer.index == 0) {
165 mem->accelerometer.index_reset_ticks_previous = mem->accelerometer.index_reset_ticks;
166 mem->accelerometer.index_reset_ticks = (s64)CoreTiming::GetTicks();
163 } 167 }
164 168
165 // Update gyroscope 169 event_accelerometer->Signal();
166 if (enable_gyroscope_count > 0) {
167 mem->gyroscope.index = next_gyroscope_index;
168 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
169 170
170 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index]; 171 // Reschedule recurrent event
171 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) = 172 CoreTiming::ScheduleEvent(accelerometer_update_ticks - cycles_late, accelerometer_update_event);
172 VideoCore::g_emu_window->GetGyroscopeState(); 173}
173 174
174 // Make up "raw" entry 175static void UpdateGyroscopeCallback(u64 userdata, int cycles_late) {
175 mem->gyroscope.raw_entry.x = gyroscope_entry.x; 176 SharedMem* mem = reinterpret_cast<SharedMem*>(shared_mem->GetPointer());
176 mem->gyroscope.raw_entry.z = -gyroscope_entry.y;
177 mem->gyroscope.raw_entry.y = gyroscope_entry.z;
178 177
179 // If we just updated index 0, provide a new timestamp 178 mem->gyroscope.index = next_gyroscope_index;
180 if (mem->gyroscope.index == 0) { 179 next_gyroscope_index = (next_gyroscope_index + 1) % mem->gyroscope.entries.size();
181 mem->gyroscope.index_reset_ticks_previous = mem->gyroscope.index_reset_ticks; 180
182 mem->gyroscope.index_reset_ticks = (s64)CoreTiming::GetTicks(); 181 GyroscopeDataEntry& gyroscope_entry = mem->gyroscope.entries[mem->gyroscope.index];
183 } 182 std::tie(gyroscope_entry.x, gyroscope_entry.y, gyroscope_entry.z) =
183 VideoCore::g_emu_window->GetGyroscopeState();
184
185 // Make up "raw" entry
186 mem->gyroscope.raw_entry.x = gyroscope_entry.x;
187 mem->gyroscope.raw_entry.z = -gyroscope_entry.y;
188 mem->gyroscope.raw_entry.y = gyroscope_entry.z;
184 189
185 event_gyroscope->Signal(); 190 // If we just updated index 0, provide a new timestamp
191 if (mem->gyroscope.index == 0) {
192 mem->gyroscope.index_reset_ticks_previous = mem->gyroscope.index_reset_ticks;
193 mem->gyroscope.index_reset_ticks = (s64)CoreTiming::GetTicks();
186 } 194 }
195
196 event_gyroscope->Signal();
197
198 // Reschedule recurrent event
199 CoreTiming::ScheduleEvent(gyroscope_update_ticks - cycles_late, gyroscope_update_event);
187} 200}
188 201
189void GetIPCHandles(Service::Interface* self) { 202void GetIPCHandles(Service::Interface* self) {
@@ -204,7 +217,11 @@ void EnableAccelerometer(Service::Interface* self) {
204 u32* cmd_buff = Kernel::GetCommandBuffer(); 217 u32* cmd_buff = Kernel::GetCommandBuffer();
205 218
206 ++enable_accelerometer_count; 219 ++enable_accelerometer_count;
207 event_accelerometer->Signal(); 220
221 // Schedules the accelerometer update event if the accelerometer was just enabled
222 if (enable_accelerometer_count == 1) {
223 CoreTiming::ScheduleEvent(accelerometer_update_ticks, accelerometer_update_event);
224 }
208 225
209 cmd_buff[1] = RESULT_SUCCESS.raw; 226 cmd_buff[1] = RESULT_SUCCESS.raw;
210 227
@@ -215,7 +232,11 @@ void DisableAccelerometer(Service::Interface* self) {
215 u32* cmd_buff = Kernel::GetCommandBuffer(); 232 u32* cmd_buff = Kernel::GetCommandBuffer();
216 233
217 --enable_accelerometer_count; 234 --enable_accelerometer_count;
218 event_accelerometer->Signal(); 235
236 // Unschedules the accelerometer update event if the accelerometer was just disabled
237 if (enable_accelerometer_count == 0) {
238 CoreTiming::UnscheduleEvent(accelerometer_update_event, 0);
239 }
219 240
220 cmd_buff[1] = RESULT_SUCCESS.raw; 241 cmd_buff[1] = RESULT_SUCCESS.raw;
221 242
@@ -226,7 +247,11 @@ void EnableGyroscopeLow(Service::Interface* self) {
226 u32* cmd_buff = Kernel::GetCommandBuffer(); 247 u32* cmd_buff = Kernel::GetCommandBuffer();
227 248
228 ++enable_gyroscope_count; 249 ++enable_gyroscope_count;
229 event_gyroscope->Signal(); 250
251 // Schedules the gyroscope update event if the gyroscope was just enabled
252 if (enable_gyroscope_count == 1) {
253 CoreTiming::ScheduleEvent(gyroscope_update_ticks, gyroscope_update_event);
254 }
230 255
231 cmd_buff[1] = RESULT_SUCCESS.raw; 256 cmd_buff[1] = RESULT_SUCCESS.raw;
232 257
@@ -237,7 +262,11 @@ void DisableGyroscopeLow(Service::Interface* self) {
237 u32* cmd_buff = Kernel::GetCommandBuffer(); 262 u32* cmd_buff = Kernel::GetCommandBuffer();
238 263
239 --enable_gyroscope_count; 264 --enable_gyroscope_count;
240 event_gyroscope->Signal(); 265
266 // Unschedules the gyroscope update event if the gyroscope was just disabled
267 if (enable_gyroscope_count == 0) {
268 CoreTiming::UnscheduleEvent(gyroscope_update_event, 0);
269 }
241 270
242 cmd_buff[1] = RESULT_SUCCESS.raw; 271 cmd_buff[1] = RESULT_SUCCESS.raw;
243 272
@@ -298,6 +327,15 @@ void Init() {
298 event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer"); 327 event_accelerometer = Event::Create(ResetType::OneShot, "HID:EventAccelerometer");
299 event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope"); 328 event_gyroscope = Event::Create(ResetType::OneShot, "HID:EventGyroscope");
300 event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad"); 329 event_debug_pad = Event::Create(ResetType::OneShot, "HID:EventDebugPad");
330
331 // Register update callbacks
332 pad_update_event = CoreTiming::RegisterEvent("HID::UpdatePadCallback", UpdatePadCallback);
333 accelerometer_update_event =
334 CoreTiming::RegisterEvent("HID::UpdateAccelerometerCallback", UpdateAccelerometerCallback);
335 gyroscope_update_event =
336 CoreTiming::RegisterEvent("HID::UpdateGyroscopeCallback", UpdateGyroscopeCallback);
337
338 CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event);
301} 339}
302 340
303void Shutdown() { 341void Shutdown() {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 7904e7355..21e66dfe0 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -296,9 +296,6 @@ void GetGyroscopeLowRawToDpsCoefficient(Service::Interface* self);
296 */ 296 */
297void GetGyroscopeLowCalibrateParam(Service::Interface* self); 297void GetGyroscopeLowCalibrateParam(Service::Interface* self);
298 298
299/// Checks for user input updates
300void Update();
301
302/// Initialize HID service 299/// Initialize HID service
303void Init(); 300void Init();
304 301
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 1a1ee90b2..fa8c13d36 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -15,7 +15,6 @@
15#include "common/vector_math.h" 15#include "common/vector_math.h"
16#include "core/core_timing.h" 16#include "core/core_timing.h"
17#include "core/hle/service/gsp_gpu.h" 17#include "core/hle/service/gsp_gpu.h"
18#include "core/hle/service/hid/hid.h"
19#include "core/hw/gpu.h" 18#include "core/hw/gpu.h"
20#include "core/hw/hw.h" 19#include "core/hw/hw.h"
21#include "core/memory.h" 20#include "core/memory.h"
@@ -33,7 +32,7 @@ namespace GPU {
33Regs g_regs; 32Regs g_regs;
34 33
35/// 268MHz CPU clocks / 60Hz frames per second 34/// 268MHz CPU clocks / 60Hz frames per second
36const u64 frame_ticks = 268123480ull / 60; 35const u64 frame_ticks = BASE_CLOCK_RATE_ARM11 / 60;
37/// Event id for CoreTiming 36/// Event id for CoreTiming
38static int vblank_event; 37static int vblank_event;
39/// Total number of frames drawn 38/// Total number of frames drawn
@@ -551,9 +550,6 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
551 Service::GSP::SignalInterrupt(Service::GSP::InterruptId::PDC0); 550 Service::GSP::SignalInterrupt(Service::GSP::InterruptId::PDC0);
552 Service::GSP::SignalInterrupt(Service::GSP::InterruptId::PDC1); 551 Service::GSP::SignalInterrupt(Service::GSP::InterruptId::PDC1);
553 552
554 // Check for user input updates
555 Service::HID::Update();
556
557 if (!Settings::values.use_vsync && Settings::values.toggle_framelimit) { 553 if (!Settings::values.use_vsync && Settings::values.toggle_framelimit) {
558 FrameLimiter(); 554 FrameLimiter();
559 } 555 }