From f84a0cdbb58d89c9537f5e0785f39d9cee0eeafd Mon Sep 17 00:00:00 2001 From: Edgar Simo Date: Tue, 1 Jul 2008 10:44:42 +0000 Subject: [PATCH] More comments. Clamped values in struct ff_effect. Added waveforms. --- include/SDL_haptic.h | 45 ++++++++++++++++++---- src/haptic/linux/SDL_syshaptic.c | 64 +++++++++++++++++++++----------- 2 files changed, 80 insertions(+), 29 deletions(-) diff --git a/include/SDL_haptic.h b/include/SDL_haptic.h index 6576d090a..13e4e1b6a 100644 --- a/include/SDL_haptic.h +++ b/include/SDL_haptic.h @@ -57,9 +57,38 @@ typedef struct _SDL_Haptic SDL_Haptic; #define SDL_HAPTIC_GAIN (1<<8) #define SDL_HAPTIC_AUTOCENTER (1<<9) +typedef enum SDL_waveform { + SDL_WAVEFORM_SINE, + SDL_WAVEFORM_SQUARE, + SDL_WAVEFORM_TRIANGLE, + SDL_WAVEFORM_SAWTOOTHUP, + SDL_WAVEFORM_SAWTOOTHDOWN +} SDL_waveform; + + +/* + * All values max at 32767 (0x7fff). Signed values also can be negative. + * Time values unless specified otherwise are in milliseconds. + * + * Common parts: + * + * Replay: + * Uint16 length; Duration of effect. + * Uint16 delay; Delay before starting effect. + * + * Trigger: + * Uint16 button; Button that triggers effect. + * Uint16 interval; How soon before effect can be triggered again. + * + * Envelope: + * Uint16 attack_length; Duration of the attack. + * Uint16 attack_level; Level at the start of the attack. + * Uint16 fade_length; Duration of the fade out. + * Uint16 fade_level; Level at the end of the fade. + */ typedef struct SDL_HapticConstant { /* Header */ - Uint16 type; + Uint16 type; /* SDL_HAPTIC_CONSTANT */ Uint16 direction; /* Replay */ @@ -71,7 +100,7 @@ typedef struct SDL_HapticConstant { Uint16 interval; /* Constant */ - Sint16 level; + Sint16 level; /* Strength of the constant effect. */ /* Envelope */ Uint16 attack_length; @@ -81,7 +110,7 @@ typedef struct SDL_HapticConstant { } SDL_HapticConstant; typedef struct SDL_HapticPeriodic { /* Header */ - Uint16 type; + Uint16 type; /* SDL_HAPTIC_PERIODIC */ Uint16 direction; /* Replay */ @@ -93,11 +122,11 @@ typedef struct SDL_HapticPeriodic { Uint16 interval; /* Periodic */ - Uint16 waveform; - Uint16 period; - Sint16 magnitude; - Sint16 offset; - Uint16 phase; + SDL_waveform waveform; /* Type of effect */ + Uint16 period; /* Period of the wave */ + Sint16 magnitude; /* Peak value */ + Sint16 offset; /* Mean value of the wave */ + Uint16 phase; /* Horizontal shift */ /* Envelope */ Uint16 attack_length; diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c index 9212d41b6..917d583a5 100644 --- a/src/haptic/linux/SDL_syshaptic.c +++ b/src/haptic/linux/SDL_syshaptic.c @@ -271,8 +271,10 @@ SDL_SYS_HapticQuit(void) SDL_hapticlist[0].fname = NULL; } +#define CLAMP(x) (((x) > 32767) ? 32767 : x) /* * Initializes the linux effect struct from a haptic_effect. + * Values above 32767 (for unsigned) are unspecified so we must clamp. */ static int SDL_SYS_ToFFEffect( struct ff_effect * dest, SDL_HapticEffect * src ) @@ -289,24 +291,24 @@ SDL_SYS_ToFFEffect( struct ff_effect * dest, SDL_HapticEffect * src ) /* Header */ dest->type = FF_CONSTANT; - dest->direction = constant->direction; + dest->direction = CLAMP(constant->direction); /* Replay */ - dest->replay.length = constant->length; - dest->replay.delay = constant->delay; + dest->replay.length = CLAMP(constant->length); + dest->replay.delay = CLAMP(constant->delay); /* Trigger */ - dest->trigger.button = constant->button; - dest->trigger.interval = constant->interval; + dest->trigger.button = CLAMP(constant->button); + dest->trigger.interval = CLAMP(constant->interval); /* Constant */ dest->u.constant.level = constant->level; /* Envelope */ - dest->u.constant.envelope.attack_length = constant->attack_length; - dest->u.constant.envelope.attack_level = constant->attack_level; - dest->u.constant.envelope.fade_length = constant->fade_length; - dest->u.constant.envelope.fade_level = constant->fade_level; + dest->u.constant.envelope.attack_length = CLAMP(constant->attack_length); + dest->u.constant.envelope.attack_level = CLAMP(constant->attack_level); + dest->u.constant.envelope.fade_length = CLAMP(constant->fade_length); + dest->u.constant.envelope.fade_level = CLAMP(constant->fade_level); break; @@ -315,28 +317,48 @@ SDL_SYS_ToFFEffect( struct ff_effect * dest, SDL_HapticEffect * src ) /* Header */ dest->type = FF_PERIODIC; - dest->direction = periodic->direction; + dest->direction = CLAMP(periodic->direction); /* Replay */ - dest->replay.length = periodic->length; - dest->replay.delay = periodic->delay; + dest->replay.length = CLAMP(periodic->length); + dest->replay.delay = CLAMP(periodic->delay); /* Trigger */ - dest->trigger.button = periodic->button; - dest->trigger.interval = periodic->interval; + dest->trigger.button = CLAMP(periodic->button); + dest->trigger.interval = CLAMP(periodic->interval); /* Constant */ - dest->u.periodic.waveform = periodic->waveform; - dest->u.periodic.period = periodic->period; + switch (periodic->waveform) { + case SDL_WAVEFORM_SINE: + dest->u.periodic.waveform = FF_SINE; + break; + case SDL_WAVEFORM_SQUARE: + dest->u.periodic.waveform = FF_SQUARE; + break; + case SDL_WAVEFORM_TRIANGLE: + dest->u.periodic.waveform = FF_TRIANGLE; + break; + case SDL_WAVEFORM_SAWTOOTHUP: + dest->u.periodic.waveform = FF_SAW_UP; + break; + case SDL_WAVEFORM_SAWTOOTHDOWN: + dest->u.periodic.waveform = FF_SAW_DOWN; + break; + + default: + SDL_SetError("Unknown waveform."); + return -1; + } + dest->u.periodic.period = CLAMP(periodic->period); dest->u.periodic.magnitude = periodic->magnitude; dest->u.periodic.offset = periodic->offset; - dest->u.periodic.phase = periodic->phase; + dest->u.periodic.phase = CLAMP(periodic->phase); /* Envelope */ - dest->u.periodic.envelope.attack_length = periodic->attack_length; - dest->u.periodic.envelope.attack_level = periodic->attack_level; - dest->u.periodic.envelope.fade_length = periodic->fade_length; - dest->u.periodic.envelope.fade_level = periodic->fade_level; + dest->u.periodic.envelope.attack_length = CLAMP(periodic->attack_length); + dest->u.periodic.envelope.attack_level = CLAMP(periodic->attack_level); + dest->u.periodic.envelope.fade_length = CLAMP(periodic->fade_length); + dest->u.periodic.envelope.fade_level = CLAMP(periodic->fade_level); break;