]> Devoid-pointer.net GitWeb - KLGD_FF_plugin.git/commitdiff
Handle direction and magnitude of rumble effects in the same fashion as
authorMichal Malý <madcatxster@devoid-pointer.net>
Sun, 27 Sep 2015 22:46:35 +0000 (00:46 +0200)
committerMichal Malý <madcatxster@devoid-pointer.net>
Sun, 27 Sep 2015 22:46:35 +0000 (00:46 +0200)
direction and level of constant force effects.

plugin/klgd_ff_plugin.c
plugin/klgd_ff_plugin.h
testmod/klgdff.c

index b40dfca326f37da4fd17ab104d26542bc48c9cc2..51a99223d2a1f1959417c66ea1593e80cdc6eba8 100644 (file)
@@ -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)
index 546b2ea57f270f3eb2c718d77b638e2c806eea2a..3b6b9ce6449c752153c0bbb8e7c3a41109f904cd 100644 (file)
@@ -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 */
index ffcbb025913cded99ba5b0279cc7503ab7e509ad..a838e45f1156edc019b1c3cde85752f0720ee077 100644 (file)
@@ -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);