From: Michal MalĂ˝ Date: Sun, 27 Sep 2015 22:46:35 +0000 (+0200) Subject: Handle direction and magnitude of rumble effects in the same fashion as X-Git-Url: https://gitweb.devoid-pointer.net/?a=commitdiff_plain;h=33fcc2c95a3548ff394abc8d90c714bd75305410;p=KLGD_FF_plugin.git Handle direction and magnitude of rumble effects in the same fashion as direction and level of constant force effects. --- diff --git a/plugin/klgd_ff_plugin.c b/plugin/klgd_ff_plugin.c index b40dfca..51a9922 100644 --- a/plugin/klgd_ff_plugin.c +++ b/plugin/klgd_ff_plugin.c @@ -415,80 +415,79 @@ static void ffpl_recalc_combined_cf(struct klgd_plugin_private *priv, const unsi cb_latest->direction); } -static u16 ffpl_calculate_rumble_direction(const u32 total_mag, const u16 total_dir, - const u32 new_mag, const u16 new_dir) +static u16 ffpl_set_rumble_direction(const u16 strong_dir, const u16 weak_dir) { - if (!new_mag) - return total_dir; - if (!total_mag) - return new_dir; - return (((total_dir >> 1) * total_mag + - (new_dir >> 1) * new_mag) / - (total_mag + new_mag)) << 1; -} - -static void ffpl_add_rumble(const struct ff_effect *ueff, u32 *strong_mag, - u32 *weak_mag, u16 *dir) -{ - *dir += ffpl_calculate_rumble_direction(*strong_mag, *dir, - ueff->u.rumble.strong_magnitude, - ueff->direction); - *dir += ffpl_calculate_rumble_direction(*weak_mag, *dir, - ueff->u.rumble.weak_magnitude, - ueff->direction); -} - -static void ffpl_add_emul_periodic(const struct ffpl_effect *eff, - u32 *strong_mag, u32 *weak_mag, - u16 *dir, const unsigned long now) -{ - const u32 level = abs(ffpl_apply_envelope(eff, now)); + u16 dir = 0; - *dir = ffpl_calculate_rumble_direction(*strong_mag, *dir, - level, eff->active.direction); - *dir = ffpl_calculate_rumble_direction(*weak_mag, *dir, - level, eff->active.direction); + if (strong_dir >= 0x8000) + dir |= FFPL_RUMBLE_STRONG_RIGHT; + if (weak_dir >= 0x8000) + dir |= FFPL_RUMBLE_WEAK_RIGHT; + if (strong_dir >= 0x4000 && strong_dir < 0xc000) + dir |= FFPL_RUMBLE_STRONG_UP; + if (weak_dir >= 0x4000 && weak_dir < 0xc000) + dir |= FFPL_RUMBLE_WEAK_UP; - *strong_mag += level; - *weak_mag += level; + return dir; } static void ffpl_recalc_combined_rumble(struct klgd_plugin_private *priv, const unsigned long now, const bool handle_periodic) { size_t idx; struct ff_effect *cb_latest = &priv->combined_effect_rumble.latest; - u32 strong_mag = 0; - u32 weak_mag = 0; - u16 dir = 0; + s32 strong_x = 0; + s32 strong_y = 0; + s32 weak_x = 0; + s32 weak_y = 0; + /* Resulting overall values expressed as direction and magnitude */ + s16 strong_mag; + u16 strong_dir; + s16 weak_mag; + u16 weak_dir; for (idx = 0; idx < priv->effect_count; idx++) { struct ffpl_effect *eff = &priv->effects[idx]; struct ff_effect *ueff = &eff->active; + s32 _strong_x; + s32 _strong_y; + s32 _weak_x; + s32 _weak_y; if (eff->state != FFPL_STARTED) continue; switch (ueff->type) { case FF_RUMBLE: - ffpl_add_rumble(ueff, &strong_mag, &weak_mag, &dir); + ffpl_lvl_dir_to_x_y(ueff->u.rumble.strong_magnitude / 2, ueff->direction, &_strong_x, &_strong_y); + ffpl_lvl_dir_to_x_y(ueff->u.rumble.weak_magnitude / 2, ueff->direction, &_weak_x, &_weak_y); break; case FF_PERIODIC: - ffpl_add_emul_periodic(eff, &strong_mag, &weak_mag, &dir, now); + { + u32 new_level; if (!handle_periodic) break; + + new_level = abs(ffpl_apply_envelope(eff, now)); + ffpl_lvl_dir_to_x_y(new_level, ueff->direction, &_strong_x, &_strong_y); + ffpl_lvl_dir_to_x_y(new_level, ueff->direction, &_weak_x, &_weak_y); break; + } default: continue; break; } + strong_x += _strong_x; + strong_y += _strong_y; + weak_x += _weak_x; + weak_y += _weak_y; } - cb_latest->direction = dir; - cb_latest->u.rumble.strong_magnitude = strong_mag; - cb_latest->u.rumble.weak_magnitude = weak_mag; + ffpl_x_y_to_lvl_dir(strong_x, strong_y, &strong_mag, &strong_dir); + ffpl_x_y_to_lvl_dir(weak_x, weak_y, &weak_mag, &weak_dir); + cb_latest->direction = ffpl_set_rumble_direction(strong_dir, weak_dir); + cb_latest->u.rumble.strong_magnitude = (u16)strong_mag * 2; + cb_latest->u.rumble.weak_magnitude = (u16)weak_mag * 2; cb_latest->type = FF_RUMBLE; - printk(KERN_NOTICE "KLGDFF: Resulting combined rumble effect > strong: %u, weak: %u, direction: %u\n", - cb_latest->u.rumble.strong_magnitude, cb_latest->u.rumble.weak_magnitude, cb_latest->direction); } static int ffpl_erase_effect(struct klgd_plugin_private *priv, struct klgd_command_stream *s, struct ffpl_effect *eff) diff --git a/plugin/klgd_ff_plugin.h b/plugin/klgd_ff_plugin.h index 546b2ea..3b6b9ce 100644 --- a/plugin/klgd_ff_plugin.h +++ b/plugin/klgd_ff_plugin.h @@ -3,6 +3,35 @@ #define FFPL_EFBIT(x) BIT(x - FF_EFFECT_MIN) +/* + * Preserving full direction for FF_RUMBLE effects is not necessary + * since the rumble motors can effectively spin in only two directions. + * The information about direction of rumble effects is reduced to + * up, down, left and right. These values are stored as individual + * bits in the effect.direction field as follows: + * + * BIT 0: 0 => Strong magnitude is turning left + * BIT 0: 1 => Strong magnitude is turning right + * BIT 1: 0 => Strong magnitude is turning down + * BIT 1: 1 => Strong magnitide is turning up + * BIT 2: 0 => Weak magnitude is turning left + * BIT 2: 1 => Weak magnitude is turning right + * BIT 3: 0 => Weak magnitude is turning down + * BIT 3: 1 => Weak magnitide is turning up + * + * The scheme above stores directions for both strong and weak magnitude + * in terms of quadrants. This is necessary when effect combining is used + * and multiple effects are squashed together into one overall effect. + * + * Note that the scheme above is used ONLY when combining of rumble effects + * is active. "Uncombined" rumble effects retain full information about + * their direction. + */ +#define FFPL_RUMBLE_STRONG_RIGHT BIT(0) +#define FFPL_RUMBLE_STRONG_UP BIT(1) +#define FFPL_RUMBLE_WEAK_RIGHT BIT(2) +#define FFPL_RUMBLE_WEAK_UP BIT(3) + /* Allowed flag bits */ #define FFPL_HAS_EMP_TO_SRT BIT(0) /* Device supports direct "upload and start" */ #define FFPL_HAS_SRT_TO_EMP BIT(1) /* Device supports direct "stop and erase" */ @@ -24,6 +53,7 @@ #define FFPL_HAS_NATIVE_GAIN BIT(15) /* Device can adjust the gain by itself */ + enum ffpl_control_command { /* Force feedback state transitions */ FFPL_EMP_TO_UPL, /* Upload to empty slot */ diff --git a/testmod/klgdff.c b/testmod/klgdff.c index ffcbb02..a838e45 100644 --- a/testmod/klgdff.c +++ b/testmod/klgdff.c @@ -16,6 +16,35 @@ static u16 gain; static u16 autocenter; static u32 test_user = 0xC001CAFE; +static char *klgdff_combined_rumble_dir(const u16 dir) +{ + static char dir_str[32]; + + dir_str[0] = '\0'; + + strcat(dir_str, "STRONG: "); + if (dir & FFPL_RUMBLE_STRONG_UP) + strcat(dir_str, "Up "); + else + strcat(dir_str, "Down "); + if (dir & FFPL_RUMBLE_STRONG_RIGHT) + strcat(dir_str, "Right "); + else + strcat(dir_str, "Left "); + + strcat(dir_str, "WEAK: "); + if (dir & FFPL_RUMBLE_WEAK_UP) + strcat(dir_str, "Up "); + else + strcat(dir_str, "Down "); + if (dir & FFPL_RUMBLE_WEAK_RIGHT) + strcat(dir_str, "Right "); + else + strcat(dir_str, "Left "); + + return dir_str; +} + static int klgdff_erase(struct klgd_command_stream *s, const struct ff_effect *effect) { char *text = kasprintf(GFP_KERNEL, "Erasing effect, type %d, id %d", effect->type, effect->id); @@ -123,8 +152,8 @@ static int klgdff_start(struct klgd_command_stream *s, const struct ff_effect *e break; } case FF_RUMBLE: - text = kasprintf(GFP_KERNEL, "Playing FF_RUMBLE, strong: %u, weak: %u, direction: %u\n", effect->u.rumble.strong_magnitude, - effect->u.rumble.weak_magnitude, effect->direction); + text = kasprintf(GFP_KERNEL, "Playing FF_RUMBLE, strong: %u, weak: %u, direction: %s\n", effect->u.rumble.strong_magnitude, + effect->u.rumble.weak_magnitude, klgdff_combined_rumble_dir(effect->direction)); break; default: text = kasprintf(GFP_KERNEL, "Playing effect, type %d, id %d, repeat %d", effect->type, effect->id, repeat); @@ -174,8 +203,8 @@ static int klgdff_update(struct klgd_command_stream *s, const struct ff_effect * break; } case FF_RUMBLE: - text = kasprintf(GFP_KERNEL, "Updating FF_RUMBLE, strong: %u, weak: %u, direction: %u\n", effect->u.rumble.strong_magnitude, - effect->u.rumble.weak_magnitude, effect->direction); + text = kasprintf(GFP_KERNEL, "Updating FF_RUMBLE, strong: %u, weak: %u, direction: %s\n", effect->u.rumble.strong_magnitude, + effect->u.rumble.weak_magnitude, klgdff_combined_rumble_dir(effect->direction)); break; default: text = kasprintf(GFP_KERNEL, "Updating, type %d, id %d", effect->type, effect->id); @@ -225,8 +254,8 @@ static int klgdff_up_start(struct klgd_command_stream *s, const struct ff_effect break; } case FF_RUMBLE: - text = kasprintf(GFP_KERNEL, "Uploading and starting FF_RUMBLE, strong: %u, weak: %u, direction: %u\n", effect->u.rumble.strong_magnitude, - effect->u.rumble.weak_magnitude, effect->direction); + text = kasprintf(GFP_KERNEL, "Uploading and starting FF_RUMBLE, strong: %u, weak: %u, direction: %s\n", effect->u.rumble.strong_magnitude, + effect->u.rumble.weak_magnitude, klgdff_combined_rumble_dir(effect->direction)); break; default: text = kasprintf(GFP_KERNEL, "Uploading and starting effect, type %d, id %d, repeat %d", effect->type, effect->id, repeat);