diff --git a/include/SDL_events.h b/include/SDL_events.h index 1836fc06c..240a8a8ba 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -474,6 +474,7 @@ typedef struct SDL_ControllerSensorEvent SDL_JoystickID which; /**< The joystick instance id */ Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */ float data[3]; /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */ + Uint64 timestamp_us; /**< The timestamp of the sensor reading in microseconds, if the hardware provides this information. */ } SDL_ControllerSensorEvent; /** @@ -565,6 +566,7 @@ typedef struct SDL_SensorEvent Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */ Sint32 which; /**< The instance ID of the sensor */ float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */ + Uint64 timestamp_us; /**< The timestamp of the sensor reading in microseconds, if the hardware provides this information. */ } SDL_SensorEvent; /** diff --git a/include/SDL_gamecontroller.h b/include/SDL_gamecontroller.h index ace1c163f..e32d3e8f7 100644 --- a/include/SDL_gamecontroller.h +++ b/include/SDL_gamecontroller.h @@ -895,6 +895,23 @@ extern DECLSPEC float SDLCALL SDL_GameControllerGetSensorDataRate(SDL_GameContro */ extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values); +/** + * Get the current state of a game controller sensor with the timestamp of the last update. + * + * The number of values and interpretation of the data is sensor dependent. + * See SDL_sensor.h for the details for each type of sensor. + * + * \param gamecontroller The controller to query + * \param type The type of sensor to query + * \param timestamp A pointer filled with the timestamp in microseconds of the current sensor reading if available, or 0 if not + * \param data A pointer filled with the current sensor state + * \param num_values The number of values to write to data + * \return 0 or -1 if an error occurred. + * + * \since This function is available since SDL 2.26.0. + */ +extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorDataWithTimestamp(SDL_GameController *gamecontroller, SDL_SensorType type, Uint64 *timestamp, float *data, int num_values); + /** * Start a rumble effect on a game controller. * diff --git a/include/SDL_sensor.h b/include/SDL_sensor.h index 6b07183ea..823cbbb70 100644 --- a/include/SDL_sensor.h +++ b/include/SDL_sensor.h @@ -267,7 +267,22 @@ extern DECLSPEC SDL_SensorID SDLCALL SDL_SensorGetInstanceID(SDL_Sensor *sensor) * * \since This function is available since SDL 2.0.9. */ -extern DECLSPEC int SDLCALL SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values); +extern DECLSPEC int SDLCALL SDL_SensorGetData(SDL_Sensor *sensor, float *data, int num_values); + +/** + * Get the current state of an opened sensor with the timestamp of the last update. + * + * The number of values and interpretation of the data is sensor dependent. + * + * \param sensor The SDL_Sensor object to query + * \param timestamp A pointer filled with the timestamp in microseconds of the current sensor reading if available, or 0 if not + * \param data A pointer filled with the current sensor state + * \param num_values The number of values to write to data + * \returns 0 or -1 if an error occurred. + * + * \since This function is available since SDL 2.0.9. + */ +extern DECLSPEC int SDLCALL SDL_SensorGetDataWithTimestamp(SDL_Sensor *sensor, Uint64 *timestamp, float *data, int num_values); /** * Close a sensor previously opened with SDL_SensorOpen(). @@ -276,7 +291,7 @@ extern DECLSPEC int SDLCALL SDL_SensorGetData(SDL_Sensor * sensor, float *data, * * \since This function is available since SDL 2.0.9. */ -extern DECLSPEC void SDLCALL SDL_SensorClose(SDL_Sensor * sensor); +extern DECLSPEC void SDLCALL SDL_SensorClose(SDL_Sensor *sensor); /** * Update the current state of the open sensors. diff --git a/src/dynapi/SDL2.exports b/src/dynapi/SDL2.exports index d9e3545c3..c2e903ecb 100644 --- a/src/dynapi/SDL2.exports +++ b/src/dynapi/SDL2.exports @@ -863,3 +863,5 @@ ++'_SDL_SetPrimarySelectionText'.'SDL2.dll'.'SDL_SetPrimarySelectionText' ++'_SDL_GetPrimarySelectionText'.'SDL2.dll'.'SDL_GetPrimarySelectionText' ++'_SDL_HasPrimarySelectionText'.'SDL2.dll'.'SDL_HasPrimarySelectionText' +++'_SDL_GameControllerGetSensorDataWithTimestamp'.'SDL2.dll'.'SDL_GameControllerGetSensorDataWithTimestamp' +++'_SDL_SensorGetDataWithTimestamp'.'SDL2.dll'.'SDL_SensorGetDataWithTimestamp' diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index 2e982b81b..fc9255cdd 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -889,3 +889,5 @@ #define SDL_SetPrimarySelectionText SDL_SetPrimarySelectionText_REAL #define SDL_GetPrimarySelectionText SDL_GetPrimarySelectionText_REAL #define SDL_HasPrimarySelectionText SDL_HasPrimarySelectionText_REAL +#define SDL_GameControllerGetSensorDataWithTimestamp SDL_GameControllerGetSensorDataWithTimestamp_REAL +#define SDL_SensorGetDataWithTimestamp SDL_SensorGetDataWithTimestamp_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index b40effffc..f8d858ddc 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -972,3 +972,5 @@ SDL_DYNAPI_PROC(void,SDL_GetJoystickGUIDInfo,(SDL_JoystickGUID a, Uint16 *b, Uin SDL_DYNAPI_PROC(int,SDL_SetPrimarySelectionText,(const char *a),(a),return) SDL_DYNAPI_PROC(char*,SDL_GetPrimarySelectionText,(void),(),return) SDL_DYNAPI_PROC(SDL_bool,SDL_HasPrimarySelectionText,(void),(),return) +SDL_DYNAPI_PROC(int,SDL_GameControllerGetSensorDataWithTimestamp,(SDL_GameController *a, SDL_SensorType b, Uint64 *c, float *d, int e),(a,b,c,d,e),return) +SDL_DYNAPI_PROC(int,SDL_SensorGetDataWithTimestamp,(SDL_Sensor *a, Uint64 *b, float *c, int d),(a,b,c,d),return) diff --git a/src/joystick/SDL_gamecontroller.c b/src/joystick/SDL_gamecontroller.c index 204ae965b..b764980e9 100644 --- a/src/joystick/SDL_gamecontroller.c +++ b/src/joystick/SDL_gamecontroller.c @@ -2440,6 +2440,15 @@ SDL_GameControllerGetSensorDataRate(SDL_GameController *gamecontroller, SDL_Sens */ int SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values) +{ + return SDL_GameControllerGetSensorDataWithTimestamp(gamecontroller, type, NULL, data, num_values); +} + +/* + * Get the current state of a game controller sensor. + */ +int +SDL_GameControllerGetSensorDataWithTimestamp(SDL_GameController *gamecontroller, SDL_SensorType type, Uint64 *timestamp, float *data, int num_values) { SDL_Joystick *joystick = SDL_GameControllerGetJoystick(gamecontroller); int i; @@ -2454,6 +2463,9 @@ SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorTy if (sensor->type == type) { num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); SDL_memcpy(data, sensor->data, num_values*sizeof(*data)); + if (timestamp) { + *timestamp = sensor->timestamp_us; + } return 0; } } diff --git a/src/joystick/SDL_joystick.c b/src/joystick/SDL_joystick.c index dc890266c..a42951ce1 100644 --- a/src/joystick/SDL_joystick.c +++ b/src/joystick/SDL_joystick.c @@ -2983,7 +2983,7 @@ int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger return posted; } -int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const float *data, int num_values) +int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, Uint64 timestamp_us, const float *data, int num_values) { int i; int posted = 0; @@ -3004,6 +3004,7 @@ int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const /* Update internal sensor state */ SDL_memcpy(sensor->data, data, num_values*sizeof(*data)); + sensor->timestamp_us = timestamp_us; /* Post the event, if desired */ #if !SDL_EVENTS_DISABLED @@ -3015,6 +3016,7 @@ int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, SDL_SensorType type, const num_values = SDL_min(num_values, SDL_arraysize(event.csensor.data)); SDL_memset(event.csensor.data, 0, sizeof(event.csensor.data)); SDL_memcpy(event.csensor.data, data, num_values*sizeof(*data)); + event.csensor.timestamp_us = timestamp_us; posted = SDL_PushEvent(&event) == 1; } #endif /* !SDL_EVENTS_DISABLED */ diff --git a/src/joystick/SDL_joystick_c.h b/src/joystick/SDL_joystick_c.h index 82311a078..7ed3e6318 100644 --- a/src/joystick/SDL_joystick_c.h +++ b/src/joystick/SDL_joystick_c.h @@ -160,7 +160,7 @@ extern int SDL_PrivateJoystickButton(SDL_Joystick *joystick, extern int SDL_PrivateJoystickTouchpad(SDL_Joystick *joystick, int touchpad, int finger, Uint8 state, float x, float y, float pressure); extern int SDL_PrivateJoystickSensor(SDL_Joystick *joystick, - SDL_SensorType type, const float *data, int num_values); + SDL_SensorType type, Uint64 timestamp_us, const float *data, int num_values); extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick *joystick, SDL_JoystickPowerLevel ePowerLevel); diff --git a/src/joystick/SDL_sysjoystick.h b/src/joystick/SDL_sysjoystick.h index 34a17429f..a0400c6ff 100644 --- a/src/joystick/SDL_sysjoystick.h +++ b/src/joystick/SDL_sysjoystick.h @@ -64,6 +64,7 @@ typedef struct _SDL_JoystickSensorInfo SDL_bool enabled; float rate; float data[3]; /* If this needs to expand, update SDL_ControllerSensorEvent */ + Uint64 timestamp_us; } SDL_JoystickSensorInfo; struct _SDL_Joystick diff --git a/src/joystick/hidapi/SDL_hidapi_ps3.c b/src/joystick/hidapi/SDL_hidapi_ps3.c index a90d4a3bf..49913d9df 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps3.c +++ b/src/joystick/hidapi/SDL_hidapi_ps3.c @@ -487,7 +487,7 @@ HIDAPI_DriverPS3_HandleStatePacket(SDL_Joystick *joystick, SDL_DriverPS3_Context sensor_data[0] = HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[41], data[42])); sensor_data[1] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[45], data[46])); sensor_data[2] = -HIDAPI_DriverPS3_ScaleAccel(LOAD16(data[43], data[44])); - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, sensor_data, SDL_arraysize(sensor_data)); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, 0, sensor_data, SDL_arraysize(sensor_data)); } SDL_memcpy(ctx->last_state, data, SDL_min(size, sizeof(ctx->last_state))); diff --git a/src/joystick/hidapi/SDL_hidapi_ps4.c b/src/joystick/hidapi/SDL_hidapi_ps4.c index 6b4fee3ab..40884dade 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps4.c +++ b/src/joystick/hidapi/SDL_hidapi_ps4.c @@ -84,23 +84,24 @@ typedef struct Uint8 ucLeftJoystickY; Uint8 ucRightJoystickX; Uint8 ucRightJoystickY; - Uint8 rgucButtonsHatAndCounter[ 3 ]; + Uint8 rgucButtonsHatAndCounter[3]; Uint8 ucTriggerLeft; Uint8 ucTriggerRight; - Uint8 _rgucPad0[ 3 ]; + Uint8 rgucTimestamp[2]; + Uint8 _rgucPad0[1]; Uint8 rgucGyroX[2]; Uint8 rgucGyroY[2]; Uint8 rgucGyroZ[2]; Uint8 rgucAccelX[2]; Uint8 rgucAccelY[2]; Uint8 rgucAccelZ[2]; - Uint8 _rgucPad1[ 5 ]; + Uint8 _rgucPad1[5]; Uint8 ucBatteryLevel; - Uint8 _rgucPad2[ 4 ]; + Uint8 _rgucPad2[4]; Uint8 ucTouchpadCounter1; - Uint8 rgucTouchpadData1[ 3 ]; + Uint8 rgucTouchpadData1[3]; Uint8 ucTouchpadCounter2; - Uint8 rgucTouchpadData2[ 3 ]; + Uint8 rgucTouchpadData2[3]; } PS4StatePacket_t; typedef struct @@ -147,6 +148,8 @@ typedef struct { Uint8 led_red; Uint8 led_green; Uint8 led_blue; + Uint16 last_timestamp; + Uint64 timestamp; PS4StatePacket_t last_state; } SDL_DriverPS4_Context; @@ -807,6 +810,7 @@ HIDAPI_DriverPS4_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joysti HIDAPI_DriverPS4_LoadCalibrationData(device); } ctx->report_sensors = enabled; + ctx->timestamp = 0; return 0; } @@ -944,17 +948,38 @@ HIDAPI_DriverPS4_HandleStatePacket(SDL_Joystick *joystick, SDL_hid_device *dev, } if (ctx->report_sensors) { + Uint16 timestamp; + Uint64 timestamp_us; float data[3]; + timestamp = LOAD16(packet->rgucTimestamp[0], packet->rgucTimestamp[1]); + if (ctx->timestamp) { + Uint16 delta; + + if (ctx->last_timestamp > timestamp) { + delta = (SDL_MAX_UINT16 - ctx->last_timestamp + timestamp + 1); + } else { + delta = (timestamp - ctx->last_timestamp); + } + ctx->timestamp += delta; + } else { + ctx->timestamp = timestamp; + } + ctx->last_timestamp = timestamp; + + /* Sensor timestamp is in 5.33us units */ + timestamp_us = (ctx->timestamp * 16) / 3; + + data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1])); data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1])); data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 2, LOAD16(packet->rgucGyroZ[0], packet->rgucGyroZ[1])); - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, timestamp_us, data, 3); data[0] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 3, LOAD16(packet->rgucAccelX[0], packet->rgucAccelX[1])); data[1] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 4, LOAD16(packet->rgucAccelY[0], packet->rgucAccelY[1])); data[2] = HIDAPI_DriverPS4_ApplyCalibrationData(ctx, 5, LOAD16(packet->rgucAccelZ[0], packet->rgucAccelZ[1])); - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, timestamp_us, data, 3); } SDL_memcpy(&ctx->last_state, packet, sizeof(ctx->last_state)); diff --git a/src/joystick/hidapi/SDL_hidapi_ps5.c b/src/joystick/hidapi/SDL_hidapi_ps5.c index 3892764a1..0e41d2e5a 100644 --- a/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -94,6 +94,7 @@ typedef struct Uint8 rgucAccelX[2]; /* 21 */ Uint8 rgucAccelY[2]; /* 23 */ Uint8 rgucAccelZ[2]; /* 25 */ + Uint8 rgucSensorTimestamp[4]; /* 27 - 32 bit little endian */ } PS5StatePacketCommon_t; @@ -114,8 +115,8 @@ typedef struct Uint8 rgucAccelX[2]; /* 21 */ Uint8 rgucAccelY[2]; /* 23 */ Uint8 rgucAccelZ[2]; /* 25 */ - Uint8 rgucTimer1[4]; /* 27 - 32 bit little endian */ - Uint8 ucBatteryTemp; /* 31 */ + Uint8 rgucSensorTimestamp[4]; /* 27 - 32 bit little endian */ + Uint8 ucSensorTemp; /* 31 */ Uint8 ucTouchpadCounter1; /* 32 - high bit clear + counter */ Uint8 rgucTouchpadData1[3]; /* 33 - X/Y, 12 bits per axis */ Uint8 ucTouchpadCounter2; /* 36 - high bit clear + counter */ @@ -145,7 +146,7 @@ typedef struct Uint8 rgucAccelX[2]; /* 21 */ Uint8 rgucAccelY[2]; /* 23 */ Uint8 rgucAccelZ[2]; /* 25 */ - Uint8 rgucUnknown1[4]; /* 27 */ + Uint8 rgucSensorTimestamp[4]; /* 27 - 32 bit little endian */ Uint8 ucTouchpadCounter1; /* 31 - high bit clear + counter */ Uint8 rgucTouchpadData1[3]; /* 32 - X/Y, 12 bits per axis */ Uint8 ucTouchpadCounter2; /* 35 - high bit clear + counter */ @@ -225,6 +226,8 @@ typedef struct { Uint8 led_green; Uint8 led_blue; EDS5LEDResetState led_reset_state; + Uint32 last_timestamp; + Uint64 timestamp; union { PS5SimpleStatePacket_t simple; @@ -706,21 +709,21 @@ HIDAPI_DriverPS5_CheckPendingLEDReset(SDL_HIDAPI_Device *device) SDL_DriverPS5_Context *ctx = (SDL_DriverPS5_Context *)device->context; SDL_bool led_reset_complete = SDL_FALSE; - if (ctx->use_alternate_report) { - /* We don't know how to check the timer, just assume it's complete for now */ - led_reset_complete = SDL_TRUE; - } else { - const PS5StatePacket_t *packet = &ctx->last_state.full_state; + if (ctx->sensors_supported) { + const PS5StatePacketCommon_t *packet = &ctx->last_state.state; /* Check the timer to make sure the Bluetooth connection LED animation is complete */ const Uint32 connection_complete = 10200000; - Uint32 timer = ((Uint32)packet->rgucTimer1[0] << 0) | - ((Uint32)packet->rgucTimer1[1] << 8) | - ((Uint32)packet->rgucTimer1[2] << 16) | - ((Uint32)packet->rgucTimer1[3] << 24); - if (SDL_TICKS_PASSED(timer, connection_complete)) { + Uint32 timestamp = LOAD32(packet->rgucSensorTimestamp[0], + packet->rgucSensorTimestamp[1], + packet->rgucSensorTimestamp[2], + packet->rgucSensorTimestamp[3]); + if (SDL_TICKS_PASSED(timestamp, connection_complete)) { led_reset_complete = SDL_TRUE; } + } else { + /* We don't know how to check the timer, just assume it's complete for now */ + led_reset_complete = SDL_TRUE; } if (led_reset_complete) { @@ -759,8 +762,14 @@ HIDAPI_DriverPS5_SetEnhancedMode(SDL_HIDAPI_Device *device, SDL_Joystick *joysti ctx->report_touchpad = SDL_TRUE; } if (ctx->sensors_supported) { - SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 250.0f); - SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 250.0f); + if (device->is_bluetooth) { + /* Bluetooth sensor update rate appears to be 1000 Hz */ + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 1000.0f); + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 1000.0f); + } else { + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, 250.0f); + SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, 250.0f); + } } /* Switch into enhanced report mode */ @@ -989,6 +998,7 @@ HIDAPI_DriverPS5_SetJoystickSensorsEnabled(SDL_HIDAPI_Device *device, SDL_Joysti HIDAPI_DriverPS5_LoadCalibrationData(device); } ctx->report_sensors = enabled; + ctx->timestamp = 0; return 0; } @@ -1180,17 +1190,40 @@ HIDAPI_DriverPS5_HandleStatePacketCommon(SDL_Joystick *joystick, SDL_hid_device SDL_PrivateJoystickAxis(joystick, SDL_CONTROLLER_AXIS_RIGHTY, axis); if (ctx->report_sensors) { + Uint32 timestamp; + Uint64 timestamp_us; float data[3]; + timestamp = LOAD32(packet->rgucSensorTimestamp[0], + packet->rgucSensorTimestamp[1], + packet->rgucSensorTimestamp[2], + packet->rgucSensorTimestamp[3]); + if (ctx->timestamp) { + Uint32 delta; + + if (ctx->last_timestamp > timestamp) { + delta = (SDL_MAX_UINT32 - ctx->last_timestamp + timestamp + 1); + } else { + delta = (timestamp - ctx->last_timestamp); + } + ctx->timestamp += delta; + } else { + ctx->timestamp = timestamp; + } + ctx->last_timestamp = timestamp; + + /* Sensor timestamp is in 0.33us units */ + timestamp_us = ctx->timestamp / 3; + data[0] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 0, LOAD16(packet->rgucGyroX[0], packet->rgucGyroX[1])); data[1] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 1, LOAD16(packet->rgucGyroY[0], packet->rgucGyroY[1])); data[2] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 2, LOAD16(packet->rgucGyroZ[0], packet->rgucGyroZ[1])); - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, timestamp_us, data, 3); data[0] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 3, LOAD16(packet->rgucAccelX[0], packet->rgucAccelX[1])); data[1] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 4, LOAD16(packet->rgucAccelY[0], packet->rgucAccelY[1])); data[2] = HIDAPI_DriverPS5_ApplyCalibrationData(ctx, 5, LOAD16(packet->rgucAccelZ[0], packet->rgucAccelZ[1])); - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, timestamp_us, data, 3); } } diff --git a/src/joystick/hidapi/SDL_hidapi_steam.c b/src/joystick/hidapi/SDL_hidapi_steam.c index 6df6512b3..9f4bb72ba 100644 --- a/src/joystick/hidapi/SDL_hidapi_steam.c +++ b/src/joystick/hidapi/SDL_hidapi_steam.c @@ -1241,12 +1241,12 @@ HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device) values[0] = (ctx->m_state.sGyroX / 32768.0f) * (2000.0f * (M_PI / 180.0f)); values[1] = (ctx->m_state.sGyroZ / 32768.0f) * (2000.0f * (M_PI / 180.0f)); values[2] = (ctx->m_state.sGyroY / 32768.0f) * (2000.0f * (M_PI / 180.0f)); - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, values, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, 0, values, 3); values[0] = (ctx->m_state.sAccelX / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; values[1] = (ctx->m_state.sAccelZ / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; values[2] = (-ctx->m_state.sAccelY / 32768.0f) * 2.0f * SDL_STANDARD_GRAVITY; - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, values, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, 0, values, 3); } ctx->m_last_state = ctx->m_state; diff --git a/src/joystick/hidapi/SDL_hidapi_switch.c b/src/joystick/hidapi/SDL_hidapi_switch.c index 8a7c9f0cb..55641d7e2 100644 --- a/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/src/joystick/hidapi/SDL_hidapi_switch.c @@ -1797,7 +1797,7 @@ static void SendSensorUpdate(SDL_Joystick *joystick, SDL_DriverSwitch_Context *c data[0] = -tmp; } - SDL_PrivateJoystickSensor(joystick, type, data, 3); + SDL_PrivateJoystickSensor(joystick, type, 0, data, 3); } static void HandleCombinedControllerStateL(SDL_Joystick *joystick, SDL_DriverSwitch_Context *ctx, SwitchStatePacket_t *packet) diff --git a/src/joystick/hidapi/SDL_hidapi_wii.c b/src/joystick/hidapi/SDL_hidapi_wii.c index fbf8a83c4..3f40fcc44 100644 --- a/src/joystick/hidapi/SDL_hidapi_wii.c +++ b/src/joystick/hidapi/SDL_hidapi_wii.c @@ -1151,7 +1151,7 @@ static void HandleNunchuckButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *j values[0] = -((float)x / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY; values[1] = ((float)z / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY; values[2] = ((float)y / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY; - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL_L, values, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL_L, 0, values, 3); } } @@ -1191,7 +1191,7 @@ static void HandleMotionPlusData(SDL_DriverWii_Context *ctx, SDL_Joystick *joyst values[0] = -((float)z / GYRO_RES_PER_DEGREE) * (float)M_PI / 180.0f; values[1] = ((float)x / GYRO_RES_PER_DEGREE) * (float)M_PI / 180.0f; values[2] = ((float)y / GYRO_RES_PER_DEGREE) * (float)M_PI / 180.0f; - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, values, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, 0, values, 3); } } @@ -1212,7 +1212,7 @@ static void HandleWiiRemoteAccelData(SDL_DriverWii_Context *ctx, SDL_Joystick *j values[0] = -((float)x / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY; values[1] = ((float)z / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY; values[2] = ((float)y / ACCEL_RES_PER_G) * SDL_STANDARD_GRAVITY; - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, values, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, 0, values, 3); } static void HandleButtonData(SDL_DriverWii_Context *ctx, SDL_Joystick *joystick, WiiButtonData *data) diff --git a/src/joystick/iphoneos/SDL_mfijoystick.m b/src/joystick/iphoneos/SDL_mfijoystick.m index dbd1d8c09..72f2ffb63 100644 --- a/src/joystick/iphoneos/SDL_mfijoystick.m +++ b/src/joystick/iphoneos/SDL_mfijoystick.m @@ -1064,14 +1064,14 @@ IOS_MFIJoystickUpdate(SDL_Joystick *joystick) data[0] = rate.x; data[1] = rate.z; data[2] = -rate.y; - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, data, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_GYRO, 0, data, 3); } if (motion.hasGravityAndUserAcceleration) { GCAcceleration accel = motion.acceleration; data[0] = -accel.x * SDL_STANDARD_GRAVITY; data[1] = -accel.y * SDL_STANDARD_GRAVITY; data[2] = -accel.z * SDL_STANDARD_GRAVITY; - SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, data, 3); + SDL_PrivateJoystickSensor(joystick, SDL_SENSOR_ACCEL, 0, data, 3); } } } diff --git a/src/sensor/SDL_sensor.c b/src/sensor/SDL_sensor.c index 161026bd2..ba86528e4 100644 --- a/src/sensor/SDL_sensor.c +++ b/src/sensor/SDL_sensor.c @@ -307,7 +307,7 @@ SDL_SensorFromInstanceID(SDL_SensorID instance_id) * Checks to make sure the sensor is valid. */ static int -SDL_PrivateSensorValid(SDL_Sensor * sensor) +SDL_PrivateSensorValid(SDL_Sensor *sensor) { int valid; @@ -325,7 +325,7 @@ SDL_PrivateSensorValid(SDL_Sensor * sensor) * Get the friendly name of this sensor */ const char * -SDL_SensorGetName(SDL_Sensor * sensor) +SDL_SensorGetName(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return NULL; @@ -338,7 +338,7 @@ SDL_SensorGetName(SDL_Sensor * sensor) * Get the type of this sensor */ SDL_SensorType -SDL_SensorGetType(SDL_Sensor * sensor) +SDL_SensorGetType(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return SDL_SENSOR_INVALID; @@ -351,7 +351,7 @@ SDL_SensorGetType(SDL_Sensor * sensor) * Get the platform dependent type of this sensor */ int -SDL_SensorGetNonPortableType(SDL_Sensor * sensor) +SDL_SensorGetNonPortableType(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return -1; @@ -364,7 +364,7 @@ SDL_SensorGetNonPortableType(SDL_Sensor * sensor) * Get the instance id for this opened sensor */ SDL_SensorID -SDL_SensorGetInstanceID(SDL_Sensor * sensor) +SDL_SensorGetInstanceID(SDL_Sensor *sensor) { if (!SDL_PrivateSensorValid(sensor)) { return -1; @@ -377,7 +377,16 @@ SDL_SensorGetInstanceID(SDL_Sensor * sensor) * Get the current state of this sensor */ int -SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values) +SDL_SensorGetData(SDL_Sensor *sensor, float *data, int num_values) +{ + return SDL_SensorGetDataWithTimestamp(sensor, NULL, data, num_values); +} + +/* + * Get the current state of this sensor + */ +int +SDL_SensorGetDataWithTimestamp(SDL_Sensor *sensor, Uint64 *timestamp, float *data, int num_values) { if (!SDL_PrivateSensorValid(sensor)) { return -1; @@ -385,6 +394,9 @@ SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values) num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); SDL_memcpy(data, sensor->data, num_values*sizeof(*data)); + if (timestamp) { + *timestamp = sensor->timestamp_us; + } return 0; } @@ -392,7 +404,7 @@ SDL_SensorGetData(SDL_Sensor * sensor, float *data, int num_values) * Close a sensor previously opened with SDL_SensorOpen() */ void -SDL_SensorClose(SDL_Sensor * sensor) +SDL_SensorClose(SDL_Sensor *sensor) { SDL_Sensor *sensorlist; SDL_Sensor *sensorlistprev; @@ -478,7 +490,7 @@ SDL_SensorQuit(void) /* These are global for SDL_syssensor.c and SDL_events.c */ int -SDL_PrivateSensorUpdate(SDL_Sensor *sensor, float *data, int num_values) +SDL_PrivateSensorUpdate(SDL_Sensor *sensor, Uint64 timestamp_us, float *data, int num_values) { int posted; @@ -487,6 +499,7 @@ SDL_PrivateSensorUpdate(SDL_Sensor *sensor, float *data, int num_values) /* Update internal sensor state */ num_values = SDL_min(num_values, SDL_arraysize(sensor->data)); SDL_memcpy(sensor->data, data, num_values*sizeof(*data)); + sensor->timestamp_us = timestamp_us; /* Post the event, if desired */ posted = 0; @@ -498,6 +511,7 @@ SDL_PrivateSensorUpdate(SDL_Sensor *sensor, float *data, int num_values) num_values = SDL_min(num_values, SDL_arraysize(event.sensor.data)); SDL_memset(event.sensor.data, 0, sizeof(event.sensor.data)); SDL_memcpy(event.sensor.data, data, num_values*sizeof(*data)); + event.sensor.timestamp_us = timestamp_us; posted = SDL_PushEvent(&event) == 1; } #endif /* !SDL_EVENTS_DISABLED */ diff --git a/src/sensor/SDL_sensor_c.h b/src/sensor/SDL_sensor_c.h index f116a065a..92b93fe81 100644 --- a/src/sensor/SDL_sensor_c.h +++ b/src/sensor/SDL_sensor_c.h @@ -37,7 +37,7 @@ extern int SDL_SensorInit(void); extern void SDL_SensorQuit(void); /* Internal event queueing functions */ -extern int SDL_PrivateSensorUpdate(SDL_Sensor *sensor, float *data, int num_values); +extern int SDL_PrivateSensorUpdate(SDL_Sensor *sensor, Uint64 timestamp_us, float *data, int num_values); #endif /* SDL_sensor_c_h_ */ diff --git a/src/sensor/SDL_syssensor.h b/src/sensor/SDL_syssensor.h index cabbab675..6e601a278 100644 --- a/src/sensor/SDL_syssensor.h +++ b/src/sensor/SDL_syssensor.h @@ -37,6 +37,7 @@ struct _SDL_Sensor SDL_SensorType type; /* Type of the sensor */ int non_portable_type; /* Platform dependent type of the sensor */ + Uint64 timestamp_us; /* The timestamp of the last sensor update */ float data[16]; /* The current state of the sensor */ struct _SDL_SensorDriver *driver; diff --git a/src/sensor/android/SDL_androidsensor.c b/src/sensor/android/SDL_androidsensor.c index e6cfc2302..27fb04cdf 100644 --- a/src/sensor/android/SDL_androidsensor.c +++ b/src/sensor/android/SDL_androidsensor.c @@ -174,7 +174,7 @@ SDL_ANDROID_SensorUpdate(SDL_Sensor *sensor) if (ALooper_pollAll(0, NULL, &events, (void**)&source) == LOOPER_ID_USER) { SDL_zero(event); while (ASensorEventQueue_getEvents(sensor->hwdata->eventqueue, &event, 1) > 0) { - SDL_PrivateSensorUpdate(sensor, event.data, SDL_arraysize(event.data)); + SDL_PrivateSensorUpdate(sensor, 0, event.data, SDL_arraysize(event.data)); } } } diff --git a/src/sensor/coremotion/SDL_coremotionsensor.m b/src/sensor/coremotion/SDL_coremotionsensor.m index 7165f6aec..735ecf54d 100644 --- a/src/sensor/coremotion/SDL_coremotionsensor.m +++ b/src/sensor/coremotion/SDL_coremotionsensor.m @@ -162,7 +162,7 @@ SDL_COREMOTION_SensorUpdate(SDL_Sensor *sensor) data[1] = -acceleration.y * SDL_STANDARD_GRAVITY; data[2] = -acceleration.z * SDL_STANDARD_GRAVITY; if (SDL_memcmp(data, sensor->hwdata->data, sizeof(data)) != 0) { - SDL_PrivateSensorUpdate(sensor, data, SDL_arraysize(data)); + SDL_PrivateSensorUpdate(sensor, 0, data, SDL_arraysize(data)); SDL_memcpy(sensor->hwdata->data, data, sizeof(data)); } } @@ -178,7 +178,7 @@ SDL_COREMOTION_SensorUpdate(SDL_Sensor *sensor) data[1] = rotationRate.y; data[2] = rotationRate.z; if (SDL_memcmp(data, sensor->hwdata->data, sizeof(data)) != 0) { - SDL_PrivateSensorUpdate(sensor, data, SDL_arraysize(data)); + SDL_PrivateSensorUpdate(sensor, 0, data, SDL_arraysize(data)); SDL_memcpy(sensor->hwdata->data, data, sizeof(data)); } } diff --git a/src/sensor/vita/SDL_vitasensor.c b/src/sensor/vita/SDL_vitasensor.c index 5235e9b11..a04981171 100644 --- a/src/sensor/vita/SDL_vitasensor.c +++ b/src/sensor/vita/SDL_vitasensor.c @@ -154,7 +154,24 @@ SDL_VITA_SensorUpdate(SDL_Sensor *sensor) { if (sensor->hwdata->counter < motionState[i].counter) { + unsigned int timestamp = motionState[i].timestamp; + sensor->hwdata->counter = motionState[i].counter; + + if (sensor->hwdata->timestamp_us) { + unsigned int delta; + if (sensor->hwdata->last_timestamp > timestamp) { + SDL_COMPILE_TIME_ASSERT(sizeof(timestamp) == sizeof(Uint32)); + delta = (SDL_MAX_UINT32 - sensor->hwdata->last_timestamp + timestamp + 1); + } else { + delta = (timestamp - sensor->hwdata->last_timestamp); + } + sensor->hwdata->timestamp_us += delta; + } else { + sensor->hwdata->timestamp_us = timestamp; + } + sensor->hwdata->last_timestamp = timestamp; + switch (sensor->type) { case SDL_SENSOR_ACCEL: @@ -163,10 +180,7 @@ SDL_VITA_SensorUpdate(SDL_Sensor *sensor) data[0] = motionState[i].accelerometer.x * SDL_STANDARD_GRAVITY; data[1] = motionState[i].accelerometer.y * SDL_STANDARD_GRAVITY; data[2] = motionState[i].accelerometer.z * SDL_STANDARD_GRAVITY; - if (SDL_memcmp(data, sensor->hwdata->data, sizeof(data)) != 0) { - SDL_PrivateSensorUpdate(sensor, data, SDL_arraysize(data)); - SDL_memcpy(sensor->hwdata->data, data, sizeof(data)); - } + SDL_PrivateSensorUpdate(sensor, sensor->hwdata->timestamp_us, data, SDL_arraysize(data)); } break; case SDL_SENSOR_GYRO: @@ -175,10 +189,7 @@ SDL_VITA_SensorUpdate(SDL_Sensor *sensor) data[0] = motionState[i].gyro.x; data[1] = motionState[i].gyro.y; data[2] = motionState[i].gyro.z; - if (SDL_memcmp(data, sensor->hwdata->data, sizeof(data)) != 0) { - SDL_PrivateSensorUpdate(sensor, data, SDL_arraysize(data)); - SDL_memcpy(sensor->hwdata->data, data, sizeof(data)); - } + SDL_PrivateSensorUpdate(sensor, sensor->hwdata->timestamp_us, data, SDL_arraysize(data)); } break; default: diff --git a/src/sensor/vita/SDL_vitasensor.h b/src/sensor/vita/SDL_vitasensor.h index 2fca628fd..a7d6d295e 100644 --- a/src/sensor/vita/SDL_vitasensor.h +++ b/src/sensor/vita/SDL_vitasensor.h @@ -23,8 +23,9 @@ /* The private structure used to keep track of a sensor */ struct sensor_hwdata { - float data[3]; Uint32 counter; + unsigned int last_timestamp; + Uint64 timestamp_us; }; /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/sensor/windows/SDL_windowssensor.c b/src/sensor/windows/SDL_windowssensor.c index 21b119d22..b2edffce0 100644 --- a/src/sensor/windows/SDL_windowssensor.c +++ b/src/sensor/windows/SDL_windowssensor.c @@ -171,7 +171,7 @@ static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnDataUpdated(ISensorEvents * values[0] = (float)valueX.dblVal * SDL_STANDARD_GRAVITY; values[1] = (float)valueY.dblVal * SDL_STANDARD_GRAVITY; values[2] = (float)valueZ.dblVal * SDL_STANDARD_GRAVITY; - SDL_PrivateSensorUpdate(SDL_sensors[i].sensor_opened, values, 3); + SDL_PrivateSensorUpdate(SDL_sensors[i].sensor_opened, 0, values, 3); } break; case SDL_SENSOR_GYRO: @@ -186,7 +186,7 @@ static HRESULT STDMETHODCALLTYPE ISensorEventsVtbl_OnDataUpdated(ISensorEvents * values[0] = (float)valueX.dblVal * DEGREES_TO_RADIANS; values[1] = (float)valueY.dblVal * DEGREES_TO_RADIANS; values[2] = (float)valueZ.dblVal * DEGREES_TO_RADIANS; - SDL_PrivateSensorUpdate(SDL_sensors[i].sensor_opened, values, 3); + SDL_PrivateSensorUpdate(SDL_sensors[i].sensor_opened, 0, values, 3); } break; default: diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c index 8ecdcd163..93942b16e 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -592,12 +592,13 @@ loop(void *arg) #define VERBOSE_SENSORS #ifdef VERBOSE_SENSORS case SDL_CONTROLLERSENSORUPDATE: - SDL_Log("Controller %d sensor %s: %.2f, %.2f, %.2f\n", + SDL_Log("Controller %d sensor %s: %.2f, %.2f, %.2f (%"SDL_PRIu64")\n", event.csensor.which, GetSensorName((SDL_SensorType)event.csensor.sensor), event.csensor.data[0], event.csensor.data[1], - event.csensor.data[2]); + event.csensor.data[2], + event.csensor.timestamp_us); break; #endif /* VERBOSE_SENSORS */