···11-// Copyright 2022, Collabora, Ltd.
11+// Copyright 2022-2023, Collabora, Ltd.
22// SPDX-License-Identifier: BSL-1.0
33/*!
44 * @file
55 * @brief Interface for vive data sources
66 * @author Mateo de Mayo <mateo.demayo@collabora.com>
77+ * @author Jakob Bornecrantz <jakob@collabora.com>
78 * @ingroup drv_vive
89 */
910···16171718#include "util/u_deque.h"
1819#include "util/u_logging.h"
2020+#include "util/u_trace_marker.h"
19212022#include "vive.h"
2123···143145vive_source_receive_imu_sample(struct xrt_imu_sink *sink, struct xrt_imu_sample *s)
144146{
145147 struct vive_source *vs = container_of(sink, struct vive_source, imu_sink);
146146- s->timestamp_ns = m_clock_offset_a2b(IMU_FREQUENCY, s->timestamp_ns, os_monotonic_get_ns(), &vs->hw2mono);
148148+147149 timepoint_ns ts = s->timestamp_ns;
148150 struct xrt_vec3_f64 a = s->accel_m_s2;
149151 struct xrt_vec3_f64 w = s->gyro_rad_secs;
···206208}
207209208210void
209209-vive_source_push_imu_packet(struct vive_source *vs, timepoint_ns t, struct xrt_vec3 a, struct xrt_vec3 g)
211211+vive_source_push_imu_packet(struct vive_source *vs, uint32_t age, timepoint_ns t, struct xrt_vec3 a, struct xrt_vec3 g)
210212{
211211- struct xrt_vec3_f64 a64 = {a.x, a.y, a.z};
212212- struct xrt_vec3_f64 g64 = {g.x, g.y, g.z};
213213- struct xrt_imu_sample sample = {.timestamp_ns = t, .accel_m_s2 = a64, .gyro_rad_secs = g64};
213213+ /*
214214+ * We want the samples to be on sometime in the past, not future. This
215215+ * is due to USB latency, which we don't know, so we are guessing here.
216216+ * We also don't know if the timestamp given for the start of the sample
217217+ * or the end.
218218+ *
219219+ * We picked 2 here because that's about what the best gaming mice can
220220+ * do, it also seems to feel good with what seems to be reasonable
221221+ * present to display offset in the compositor.
222222+ *
223223+ * We also adjust for the "age" of a sample, the vive sends out 3
224224+ * samples per packet, most often only one is a new sample. But
225225+ * sometimes we get up to 3 new samples in one packet. So if age is
226226+ * greater then 0, adjust with that many MS (1000Hz sampler rate).
227227+ */
228228+229229+ // 2 ms in value.
230230+ const timepoint_ns t2ms_ns = U_TIME_1MS_IN_NS * 2;
231231+232232+ // Extra in the past for age.
233233+ timepoint_ns age_diff_ns = age * U_TIME_1MS_IN_NS;
234234+235235+ // Now.
236236+ timepoint_ns now_ns = (timepoint_ns)os_monotonic_get_ns();
237237+238238+ // Calculated sample point.
239239+ timepoint_ns sample_point = now_ns - t2ms_ns - age_diff_ns;
240240+241241+ // Time adjustment.
242242+ t = m_clock_offset_a2b(IMU_FREQUENCY, t, sample_point, &vs->hw2mono);
243243+244244+ // Finished sample.
245245+ struct xrt_imu_sample sample = {
246246+ .timestamp_ns = t,
247247+ .accel_m_s2 = (struct xrt_vec3_f64){a.x, a.y, a.z},
248248+ .gyro_rad_secs = (struct xrt_vec3_f64){g.x, g.y, g.z},
249249+ };
250250+251251+ // Push it out!
214252 xrt_sink_push_imu(&vs->imu_sink, &sample);
253253+254254+ // Only do this if we are really debugging stuff.
255255+#ifdef XRT_FEATURE_TRACING
256256+ timepoint_ns diff_ns = t - (now_ns - age_diff_ns);
257257+ static timepoint_ns last_ns = 0;
258258+ if (last_ns == 0) {
259259+ last_ns = t;
260260+ }
261261+262262+ double now_diff_ms = time_ns_to_ms_f(diff_ns);
263263+ double last_diff_ms = time_ns_to_ms_f(t - last_ns);
264264+ last_ns = t;
265265+266266+#ifdef U_TRACE_TRACY
267267+ TracyCPlot("Vive IMU to now(ms)", now_diff_ms);
268268+ TracyCPlot("Vive IMU to last(ms)", last_diff_ms);
269269+ TracyCPlot("Vive IMU age", age);
270270+#endif
271271+272272+ VIVE_TRACE(vs, "Sample diffs, now: %+.4fms, last: %+.4f, age: %u", now_diff_ms, last_diff_ms, age);
273273+#endif
215274}
216275217276void