Skip to content

Commit

Permalink
PsychHID/OSX: Fix conversion of HID event timestamps to GetSecs time.
Browse files Browse the repository at this point in the history
Timestamps delivered by the HID subsystem are in mach time units, arbitrary units for a given
machines clock hardware. On Intel based Macs, the units happened to be fixed across all machines
to be Nanoseconds, so a simple division by 1e9 did the conversion. On Apple Silicon ARM Macs, the
units are no longer Nanoseconds, but something odd - probably something like bus frequency or
whatever. Therefore we need to use a proper adaptive conversion, which is querying the mach
timebase frequency, via PsychGetKernelTimebaseFrequencyHz() and then dividing by that.

This provides proper conversion and fixes the input event timestamps of keyboard queues -
KbQueueDemo now prints proper keypress times.

When we are at it, make PsychGetKernelTimebaseFrequencyHz() a tad more efficient.
  • Loading branch information
Mario Kleiner authored and kleinerm committed Dec 2, 2024
1 parent ccd5cd1 commit a439d92
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 7 deletions.
12 changes: 6 additions & 6 deletions PsychSourceGL/Source/OSX/Base/PsychTimeGlue.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ double PsychYieldIntervalSeconds(double delaySecs)

double PsychGetKernelTimebaseFrequencyHz(void)
{
long double clockPeriodNSecs;
mach_timebase_info_data_t tbinfo;
if (!isKernelTimebaseFrequencyHzInitialized) {
long double clockPeriodNSecs;
mach_timebase_info_data_t tbinfo;

if(!isKernelTimebaseFrequencyHzInitialized){
// Retrieve the mach absolute time timebase. The kernel expresses the period in two integers, the ratio of which is the clock period.
// Retrieve the mach absolute time timebase. The kernel expresses the period in two integers, the ratio of which is the clock period.
mach_timebase_info(&tbinfo);

// Calculate the mach timebase period from values reported from the mach kernel.
Expand All @@ -120,10 +120,10 @@ double PsychGetKernelTimebaseFrequencyHz(void)
// Frequency in Hz is a convenient form because it makes converting from a period in seconds into a period in mach timebase units easy:
// time_interval_in_mach_units= time_interval_in_seconds * clockFrequencyHz;
kernelTimebaseFrequencyHz = 1000000000.0 / clockPeriodNSecs;
isKernelTimebaseFrequencyHzInitialized=TRUE;
isKernelTimebaseFrequencyHzInitialized = TRUE;
}

return((double)kernelTimebaseFrequencyHz);
return((double) kernelTimebaseFrequencyHz);
}

/* Called at Module init time: */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ enum { kHID2VKCSize = sizeof kHID2VKC / sizeof kHID2VKC[0] };
// Convert uint64 time in nanoseconds to double value in GetSecs() seconds:
static double convertTime(uint64_t timeUInt64) {
double timeDouble = (double) timeUInt64;
return timeDouble / 1000000000;
return timeDouble / PsychGetKernelTimebaseFrequencyHz();
}

static void PsychHIDKbQueueCallbackFunction(void *target, IOReturn result, void *sender)
Expand Down

0 comments on commit a439d92

Please sign in to comment.