From 7dbaaecaf96e7581a30b9206ba8019a85353611a Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Sun, 23 Jun 2024 11:19:14 +0200 Subject: constant and periodic effect documentation update --- docs/FFBEFFECTS.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index 558e720..4cca1f3 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -125,7 +125,7 @@ have model specific peculiarities, though. 60 00 - standard header 01 - ID 6a - new constant effect(?) - fe ff - strength *** + fe ff - strength between ff bf (-16385) and fd 3f (16381) *** 00 00 - attack_length 00 00 - attack_level *** 00 00 - fade_length @@ -149,7 +149,7 @@ have model specific peculiarities, though. 60 00 - standard header 01 - ID 0a - modify constant force - 05 16 - constant force *** + 05 16 - constant force between ff bf (-16385) and fd 3f (16381) *** 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -364,10 +364,11 @@ Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA) 60 00 - standard header 01 - ID 6b - new periodic effect - 00 00 - magnitude *** - fe ff - offset (up/down) - 00 00 - phase (left/right) - e8 03 - period + 00 00 - magnitude between 00 00 and fc 7f (32764) *** + fe ff - offset (up/down) between ff bf (-16385) and fd 3f (16381) + 00 00 - phase (left/right) between 00 00 and 4a f7 (32586) + meaning is 0 to ~359 deg phase shift in 5b steps + e8 03 - period between 00 00 and ff ff (in milliseconds) 00 80 00 00 - attack_length 00 00 - attack_level *** @@ -393,7 +394,7 @@ Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA) 60 00 02 - ID 0e 01 - 64 35 - value, signed (between 00 00 and ff 7f?) + 64 35 - value, between 00 00 and fc 7f (32764) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -403,7 +404,7 @@ Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA) 60 00 02 - ID 0e 02 - 64 35 - value, signed (between 00 00 and ff 7f?) + 64 35 - value, between ff bf (-16385) and fd 3f (16381) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -413,7 +414,8 @@ Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA) 60 00 02 - ID 0e 04 - 64 35 - value, signed (between 80 01 and ff 7f?) + 64 35 - value, between 00 00 and 4a f7 (32586) in 5b steps + meaning is 0 to 359 deg phase shift 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -423,8 +425,7 @@ Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA) 60 00 02 - ID 0e 08 - 64 35 - value, signed (between 00 00 and I guess ff 7f?) (max value in - wireshark is 0d 07, but I don't know if that's a driver or program issue) + 64 35 - value, between 00 00 and ff ff (in milliseconds) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -- cgit v1.3 From 250b83649a3d2799a069ac9aedea8c50d457d890 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Sun, 23 Jun 2024 12:14:25 +0200 Subject: condition effect documentation update --- docs/FFBEFFECTS.md | 108 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 38 deletions(-) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index 4cca1f3..bdd542f 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -262,45 +262,34 @@ Ramps seem to follow triangle wave parameters. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` -#### Offset: `N/A` +#### Offset: `N/A` -## FF_SPRING: -### Init: -``` - 60 00 - standard header - 01 - ID - 64 - new conditional effect - fc 7f - positive coefficient (right?) - fc 7f - negative coefficient (left?) - fe ff - deadband (left?) (deadband + offset) (fe ff means no deadband) - fe ff - deadband (right?) (deadband + offset) - a6 6a a6 6a fe ff fe ff fe ff fe ff df 58 a6 6a 06 - some weird hard-coded - values to do with springs? - - 4f - f7 17 - duration - 00 00 - 00 00 - offset - 00 ff ff - end of init - 00 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -``` - -### Modifying: -Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA) - -## FF_DAMPER + FF_FRICTION + FF_INERTIA: +## FF_DAMPER + FF_FRICTION + FF_INERTIA + FF_SPRING: ### Init: ``` 60 00 - standard header 02 -ID - 64 - new conditional effect - fc 7f - positive coefficient (right?) - fc 7f - negative coefficient (left?) - fe ff - deadband (left?) (deadband + offset) (fe ff means no deadband) - fe ff - deadband (right?) (deadband + offset) - fc 7f fc 7f fe ff fe ff fe ff fe ff fc 7f fc 7f 07 - some weird hard-coded - values to do with friction? + 64 - new conditional effect (sometimes e4) + fc 7f - positive coefficient (right) + between 01 80 (-32767) and fc 7f (32764) + fc 7f - negative coefficient (left) + between 01 80 (-32767) and fc 7f (32764) + fe ff - deadband right (offset + deadband) + between 01 80 (-32767) and ff 7f (32767) + fe ff - deadband left (offset - deadband) + between 01 80 (-32767) and ff 7f (32767) + fc 7f - positive saturation (right) + between 00 00 and fc 7f (32764) or a6 6a (27302) + fc 7f - negative saturation (left) + between 00 00 and fc 7f (32764) or a6 6a (27302) + fe ff fe ff fe ff fe ff - some weird hard-coded + values to do with friction? + fc 7f - max positive saturation (type 07 - fc 7f + type 06 - a6 6a) + fc 7f - max negative saturation (type 07 - fc 7f + type 06 - a6 6a) + 07 - type (damper, friction, inertia - 07 + spring - 06) 4f f7 17 - duration 00 00 @@ -316,7 +305,7 @@ Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA) 60 00 02 - ID 0e 41 - 64 35 - value, signed (between 00 00 and 01 80?) + 64 35 - value, signed, between 01 80 (-32767) and fc 7f (32764) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 @@ -326,18 +315,61 @@ Same as below (FF_DAMPER + FF_FRICTION + FF_INERTIA) 60 00 02 - ID 0e 42 - 64 35 - value, signed (between 00 00 and ff 7f?) + 64 35 - value, signed, between 01 80 (-32767) and fc 7f (32764) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + positive and negative coefficient: + 60 00 + 01 - ID + 0e 43 + ab 67 - right coefficient, signed, between 01 80 (-32767) and fc 7f (32764) + 50 18 - left coefficient, signed, between 01 80 (-32767) and fc 7f (32764) + 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + deadband/offset: 60 00 02 - ID 0e 4c - 64 35 - deadband (right?) (deadband + offset) (fe ff means no deadband) - 00 00 - deadband (left?) (deadband + offset) + 64 35 - deadband right (offset + deadband) + between 01 80 (-32767) and ff 7f (32767) + 00 00 - deadband left (offset - deadband) + between 01 80 (-32767) and ff 7f (32767) + 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + positive saturation + 60 00 + 01 - ID + 0e 50 + fc 7f - value between 00 00 and fc 7f or a6 6a (defined in init) + 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + negative saturation + 60 00 + 01 - ID + 0e 60 + fc 7f - value between 00 00 and fc 7f or a6 6a (defined in init) + 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 60 00 + 01 - ID + 0e 70 + da 5d - right saturation between 00 00 and fc 7f or a6 6a (defined in init) + b9 0b - left saturation between 00 00 and fc 7f or a6 6a (defined in init) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -- cgit v1.3 From a78fbc2d38d676fe8846b771412c81061bcbb03e Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Mon, 24 Jun 2024 15:39:35 +0200 Subject: fix condition effect handling - unified handling of all condition effects for uploads and updates - added new saturation parameters - added right, left, and right&left update type for saturation - added right&left update type for coefficient --- src/tmt300rs/hid-tmt300rs.c | 308 ++++++++++++++++++++++++++------------------ 1 file changed, 181 insertions(+), 127 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 9b5d22d..4921e17 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -330,18 +330,9 @@ static u8 t300rs_rdesc_ps4_fixed[] = { 0xc0, }; -static u8 spring_values[] = { - 0xa6, 0x6a, 0xa6, 0x6a, 0xfe, - 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xfe, 0xff, 0xdf, 0x58, 0xa6, - 0x6a, 0x06 -}; - -static u8 damper_values[] = { - 0xfc, 0x7f, 0xfc, 0x7f, 0xfe, - 0xff, 0xfe, 0xff, 0xfe, 0xff, - 0xfe, 0xff, 0xfc, 0x7f, 0xfc, - 0x7f, 0x07 +static u8 condition_values[] = { + 0xfe, 0xff, 0xfe, 0xff, 0xfe, + 0xff, 0xfe, 0xff }; static void t300rs_calculate_periodic_values(struct ff_effect *effect) @@ -370,6 +361,63 @@ static void t300rs_calculate_periodic_values(struct ff_effect *effect) periodic->offset = clamp(periodic->offset, -headroom, headroom); } +static uint16_t t300rs_condition_max_saturation(uint16_t effect_type) +{ + if(effect_type == FF_SPRING) + return 0x6AA6; + + return 0x7FFC; +} + +static uint16_t t300rs_condition_effect_type(uint16_t effect_type) +{ + if(effect_type == FF_SPRING) + return 0x06; + + return 0x07; +} + +static int16_t t300rs_calculate_coefficient(int16_t coeff, uint16_t effect_type) +{ + uint8_t input_level; + + switch (effect_type) + { + case FF_SPRING: + input_level = spring_level; + break; + case FF_DAMPER: + input_level = damper_level; + break; + case FF_FRICTION: + input_level = friction_level; + break; + default: + input_level = 100; + break; + } + + return coeff * input_level / 100; +} + +static uint16_t t300rs_calculate_saturation(uint16_t sat, uint16_t effect_type) +{ + uint16_t max = t300rs_condition_max_saturation(effect_type); + + if(sat == 0) + return max; + + return sat * max / 0xFFFF; +} + +static void t300rs_calculate_deadband(int16_t *out_rband, int16_t *out_lband, uint16_t deadband, int16_t offset) +{ + /* max deadband value is 0x7FFF in either direction */ + /* deadband is the width of the deadzone, one direction is half of it */ + *out_rband = clamp(offset + (deadband / 2), -0x7FFF, 0x7FFF); + *out_lband = clamp(offset - (deadband / 2), -0x7FFF, 0x7FFF); +} + int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len) { int i; @@ -772,81 +820,129 @@ error: return ret; } -static int t300rs_update_damper(struct t300rs_device_entry *t300rs, +static int t300rs_update_condition(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; struct ff_effect old = state->old; - struct ff_condition_effect damper = effect.u.condition[0]; - struct ff_condition_effect damper_old = old.u.condition[0]; - struct __packed t300rs_packet_mod_damper { + struct ff_condition_effect cond = effect.u.condition[0]; + struct ff_condition_effect cond_old = old.u.condition[0]; + struct __packed t300rs_packet_mod_condition { struct t300rs_packet_header header; uint8_t attribute; uint16_t value0; uint16_t value1; - } *packet_mod_damper = (struct t300rs_packet_mod_damper *)t300rs->send_buffer; + } *packet_mod_condition = (struct t300rs_packet_mod_condition *)t300rs->send_buffer; - int ret, input_level; + int ret; + uint16_t right_sat, right_sat_old, left_sat, left_sat_old; + uint16_t right_coeff, right_coeff_old, left_coeff, left_coeff_old; + int16_t right_deadband, right_deadband_old, left_deadband, left_deadband_old; - input_level = damper_level; - if (state->effect.type == FF_FRICTION) - input_level = friction_level; + right_coeff = t300rs_calculate_coefficient(cond.right_coeff, effect.type); + right_coeff_old = t300rs_calculate_coefficient(cond_old.right_coeff, old.type); - if (state->effect.type == FF_SPRING) - input_level = spring_level; + left_coeff = t300rs_calculate_coefficient(cond.left_coeff, effect.type); + left_coeff_old = t300rs_calculate_coefficient(cond_old.left_coeff, old.type); + + t300rs_calculate_deadband(&right_deadband, &left_deadband, cond.deadband, cond.center); + t300rs_calculate_deadband(&right_deadband_old, &left_deadband_old, cond_old.deadband, cond_old.center); + + right_sat = t300rs_calculate_saturation(cond.right_saturation, effect.type); + right_sat_old = t300rs_calculate_saturation(cond_old.right_saturation, old.type); - if (damper.right_coeff != damper_old.right_coeff) { - int16_t coeff = damper.right_coeff * input_level / 100; + left_sat = t300rs_calculate_saturation(cond.left_saturation, effect.type); + left_sat_old = t300rs_calculate_saturation(cond_old.left_saturation, old.type); - t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); - packet_mod_damper->attribute = 0x41; - packet_mod_damper->value0 = cpu_to_le16(coeff); + if (right_coeff != right_coeff_old + && left_coeff != left_coeff_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x43; + packet_mod_condition->value0 = cpu_to_le16(right_coeff); + packet_mod_condition->value1 = cpu_to_le16(left_coeff); ret = t300rs_send_int(t300rs); if (ret) { - hid_err(t300rs->hdev, "failed modifying damper rc\n"); + hid_err(t300rs->hdev, "failed modifying condition coeff\n"); goto error; } + } + else if (right_coeff != right_coeff_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x41; + packet_mod_condition->value0 = cpu_to_le16(right_coeff); + ret = t300rs_send_int(t300rs); + if (ret) { + hid_err(t300rs->hdev, "failed modifying condition right coeff\n"); + goto error; + } } + else if (left_coeff != left_coeff_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x42; + packet_mod_condition->value0 = cpu_to_le16(left_coeff); - if (damper.left_coeff != damper_old.left_coeff) { - int16_t coeff = damper.left_coeff * input_level / 100; + ret = t300rs_send_int(t300rs); + if (ret) { + hid_err(t300rs->hdev, "failed modifying condition left coeff\n"); + goto error; + } + } - t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); - packet_mod_damper->attribute = 0x42; - packet_mod_damper->value0 = cpu_to_le16(coeff); + if ((right_deadband != right_deadband_old) + || (left_deadband != left_deadband_old)) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x4c; + packet_mod_condition->value0 = cpu_to_le16(right_deadband); + packet_mod_condition->value1 = cpu_to_le16(left_deadband); ret = t300rs_send_int(t300rs); if (ret) { - hid_err(t300rs->hdev, "failed modifying damper lc\n"); + hid_err(t300rs->hdev, "failed modifying condition deadband\n"); goto error; } - } - if ((damper.deadband != damper_old.deadband) - || (damper.center != damper_old.center)) { - - uint16_t right_deadband = 0xfffe - damper.deadband - damper.center; - uint16_t left_deadband = 0xfffe - damper.deadband + damper.center; + if (right_sat != right_sat_old + && left_sat != left_sat_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x70; + packet_mod_condition->value0 = cpu_to_le16(right_sat); + packet_mod_condition->value1 = cpu_to_le16(left_sat); - t300rs_fill_header(&packet_mod_damper->header, effect.id, 0x0e); - packet_mod_damper->attribute = 0x4c; - packet_mod_damper->value0 = cpu_to_le16(right_deadband); - packet_mod_damper->value1 = cpu_to_le16(left_deadband); + ret = t300rs_send_int(t300rs); + if (ret) { + hid_err(t300rs->hdev, "failed modifying condition saturation\n"); + goto error; + } + } + else if (right_sat != right_sat_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x50; + packet_mod_condition->value0 = cpu_to_le16(right_sat); ret = t300rs_send_int(t300rs); if (ret) { - hid_err(t300rs->hdev, "failed modifying damper deadband\n"); + hid_err(t300rs->hdev, "failed modifying condition right saturation\n"); goto error; } + } + else if (left_sat != left_sat_old) { + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); + packet_mod_condition->attribute = 0x60; + packet_mod_condition->value0 = cpu_to_le16(left_sat); + ret = t300rs_send_int(t300rs); + if (ret) { + hid_err(t300rs->hdev, "failed modifying condition left saturation\n"); + goto error; + } } ret = t300rs_update_simple_duration(t300rs, state, 0x06); if (ret) { - hid_err(t300rs->hdev, "failed modifying damper duration\n"); + hid_err(t300rs->hdev, "failed modifying condition duration\n"); goto error; } @@ -854,12 +950,6 @@ error: return ret; } -static int t300rs_update_spring(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - return t300rs_update_damper(t300rs, state); -} - static int t300rs_update_periodic(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { @@ -1060,95 +1150,61 @@ static int t300rs_upload_ramp(struct t300rs_device_entry *t300rs, return ret; } -static int t300rs_upload_spring(struct t300rs_device_entry *t300rs, +static int t300rs_upload_condition(struct t300rs_device_entry *t300rs, struct tmff2_effect_state *state) { struct ff_effect effect = state->effect; /* we only care about the first axis */ - struct ff_condition_effect spring = state->effect.u.condition[0]; - struct __packed t300rs_packet_spring { + struct ff_condition_effect cond = state->effect.u.condition[0]; + struct __packed t300rs_packet_condition { struct t300rs_packet_header header; - uint16_t right_coeff; - uint16_t left_coeff; - uint16_t right_deadband; - uint16_t left_deadband; - uint8_t spring_start[17]; + int16_t right_coeff; + int16_t left_coeff; + int16_t right_deadband; + int16_t left_deadband; + uint16_t right_saturation; + uint16_t left_saturation; + uint8_t hardcoded[ARRAY_SIZE(condition_values)]; + uint16_t max_right_saturation; + uint16_t max_left_saturation; + uint8_t type; struct t300rs_packet_timing timing; - } *packet_spring = (struct t300rs_packet_spring *)t300rs->send_buffer; + } *packet_condition = (struct t300rs_packet_condition *)t300rs->send_buffer; int ret; - uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; + uint16_t duration, right_sat, left_sat, right_coeff, left_coeff, max_sat, offset; + int16_t right_deadband, left_deadband; - duration = effect.replay.length - 1; - - right_coeff = spring.right_coeff * spring_level / 100; - left_coeff = spring.left_coeff * spring_level / 100; - - right_deadband = 0xfffe - spring.deadband - spring.center; - left_deadband = 0xfffe - spring.deadband + spring.center; - - offset = effect.replay.delay; + right_coeff = t300rs_calculate_coefficient(cond.right_coeff, effect.type); + left_coeff = t300rs_calculate_coefficient(cond.left_coeff, effect.type); - t300rs_fill_header(&packet_spring->header, effect.id, 0x64); + t300rs_calculate_deadband(&right_deadband, &left_deadband, cond.deadband, cond.center); - packet_spring->right_coeff = cpu_to_le16(right_coeff); - packet_spring->left_coeff = cpu_to_le16(left_coeff); - packet_spring->right_deadband = cpu_to_le16(right_deadband); - packet_spring->left_deadband = cpu_to_le16(left_deadband); - - memcpy(&packet_spring->spring_start, spring_values, ARRAY_SIZE(spring_values)); - t300rs_fill_timing(&packet_spring->timing, duration, offset); - - ret = t300rs_send_int(t300rs); - if (ret) - hid_err(t300rs->hdev, "failed uploading spring\n"); - - return ret; -} - -static int t300rs_upload_damper(struct t300rs_device_entry *t300rs, - struct tmff2_effect_state *state) -{ - - struct ff_effect effect = state->effect; - /* we only care about the first axis */ - struct ff_condition_effect spring = state->effect.u.condition[0]; - struct __packed t300rs_packet_damper { - struct t300rs_packet_header header; - uint16_t right_coeff; - uint16_t left_coeff; - uint16_t right_deadband; - uint16_t left_deadband; - uint8_t damper_start[17]; - struct t300rs_packet_timing timing; - } *packet_damper = (struct t300rs_packet_damper *)t300rs->send_buffer; - - int ret, input_level; - uint16_t duration, right_coeff, left_coeff, right_deadband, left_deadband, offset; + right_sat = t300rs_calculate_saturation(cond.right_saturation, effect.type); + left_sat = t300rs_calculate_saturation(cond.left_saturation, effect.type); duration = effect.replay.length - 1; - input_level = damper_level; - if (state->effect.type == FF_FRICTION) - input_level = friction_level; - - right_coeff = spring.right_coeff * input_level / 100; - left_coeff = spring.left_coeff * input_level / 100; + offset = effect.replay.delay; - right_deadband = 0xfffe - spring.deadband - spring.center; - left_deadband = 0xfffe - spring.deadband + spring.center; + t300rs_fill_header(&packet_condition->header, effect.id, 0x64); - offset = effect.replay.delay; + packet_condition->right_coeff = cpu_to_le16(right_coeff); + packet_condition->left_coeff = cpu_to_le16(left_coeff); + packet_condition->right_deadband = cpu_to_le16(right_deadband); + packet_condition->left_deadband = cpu_to_le16(left_deadband); + packet_condition->right_saturation = cpu_to_le16(right_sat); + packet_condition->left_saturation = cpu_to_le16(left_sat); - t300rs_fill_header(&packet_damper->header, effect.id, 0x64); + memcpy(&packet_condition->hardcoded, condition_values, ARRAY_SIZE(condition_values)); - packet_damper->right_coeff = cpu_to_le16(right_coeff); - packet_damper->left_coeff = cpu_to_le16(left_coeff); - packet_damper->right_deadband = cpu_to_le16(right_deadband); - packet_damper->left_deadband = cpu_to_le16(left_deadband); + max_sat = t300rs_condition_max_saturation(effect.type); + /* it seems that the maximum values do not affect the wheel. */ + packet_condition->max_right_saturation = cpu_to_le16(max_sat); + packet_condition->max_left_saturation = cpu_to_le16(max_sat); + packet_condition->type = t300rs_condition_effect_type(effect.type); - memcpy(&packet_damper->damper_start, damper_values, ARRAY_SIZE(damper_values)); - t300rs_fill_timing(&packet_damper->timing, duration, offset); + t300rs_fill_timing(&packet_condition->timing, duration, offset); ret = t300rs_send_int(t300rs); if (ret) @@ -1219,11 +1275,10 @@ int t300rs_update_effect(void *data, struct tmff2_effect_state *state) case FF_RAMP: return t300rs_update_ramp(t300rs, state); case FF_SPRING: - return t300rs_update_spring(t300rs, state); case FF_DAMPER: case FF_FRICTION: case FF_INERTIA: - return t300rs_update_damper(t300rs, state); + return t300rs_update_condition(t300rs, state); case FF_PERIODIC: return t300rs_update_periodic(t300rs, state); default: @@ -1242,11 +1297,10 @@ int t300rs_upload_effect(void *data, struct tmff2_effect_state *state) case FF_RAMP: return t300rs_upload_ramp(t300rs, state); case FF_SPRING: - return t300rs_upload_spring(t300rs, state); case FF_DAMPER: case FF_FRICTION: case FF_INERTIA: - return t300rs_upload_damper(t300rs, state); + return t300rs_upload_condition(t300rs, state); case FF_PERIODIC: return t300rs_upload_periodic(t300rs, state); default: -- cgit v1.3 From 7b09697d060eda19dbf2cc7678550ecbcdab8b42 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Thu, 27 Jun 2024 22:37:55 +0200 Subject: add missing packet name --- docs/FFBEFFECTS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index bdd542f..61cb7b3 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -365,6 +365,7 @@ Ramps seem to follow triangle wave parameters. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + positive and negative saturation 60 00 01 - ID 0e 70 -- cgit v1.3 From ec34b4defb8a3c43f68b95c100f8b84e424fec32 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Thu, 27 Jun 2024 22:38:43 +0200 Subject: document the discovered bit field for condition effects --- docs/FFBEFFECTS.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index 61cb7b3..f94b3cb 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -300,6 +300,27 @@ Ramps seem to follow triangle wave parameters. ``` ### Modifying: + +``` +4th byte 5th byte hex +00001110 01000001 0e 41 positive coefficient +00001110 01000010 0e 42 negative coefficient +00001110 01000011 0e 43 both coefficint +00001110 01001100 0e 4c right and left deadband +00001110 01010000 0e 50 positive saturation +00001110 01100000 0e 60 negative saturation +00001110 01110000 0e 70 both saturation +00001110 01001111 0e 4f coefficient + deadband +00001110 01111100 0e 7c deadband + saturation +00001110 01110011 0e 73 coefficient + saturation +00001110 01101101 0e 6d positive coefficient + deadband + negative saturation +00001100 0c everything +``` + +Any combination that makes sense is possible, not restricted to the list above. + +The order of the fields are defined in the `everything` packet example below. + ``` positive coefficient: 60 00 @@ -375,6 +396,20 @@ Ramps seem to follow triangle wave parameters. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + everything + 60 00 + 01 - ID + 0c + fe 1f - positive coefficient + 98 19 - negative coefficient + 96 59 - right deadband + fe 3f - left deadband + 65 26 - positive saturation + 98 19 - negative saturation + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ``` ### Duration: -- cgit v1.3 From 40f91142d4307f67a324bb4c2d167b89e7befa04 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Sat, 29 Jun 2024 23:19:31 +0200 Subject: always update all condition effect parameters --- src/tmt300rs/hid-tmt300rs.c | 136 +++++++++++++------------------------------- 1 file changed, 41 insertions(+), 95 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 4921e17..4231600 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -364,9 +364,9 @@ static void t300rs_calculate_periodic_values(struct ff_effect *effect) static uint16_t t300rs_condition_max_saturation(uint16_t effect_type) { if(effect_type == FF_SPRING) - return 0x6AA6; + return 0x6aa6; - return 0x7FFC; + return 0x7ffc; } static uint16_t t300rs_condition_effect_type(uint16_t effect_type) @@ -827,14 +827,23 @@ static int t300rs_update_condition(struct t300rs_device_entry *t300rs, struct ff_effect old = state->old; struct ff_condition_effect cond = effect.u.condition[0]; struct ff_condition_effect cond_old = old.u.condition[0]; - struct __packed t300rs_packet_mod_condition { + struct __packed t300rs_packet_mod_condition + { struct t300rs_packet_header header; - uint8_t attribute; - uint16_t value0; - uint16_t value1; + uint16_t right_coeff; + uint16_t left_coeff; + uint16_t right_deadband; + uint16_t left_deadband; + uint16_t right_saturation; + uint16_t left_saturation; + uint8_t effect_type; + uint8_t update_type; + uint16_t duration; + uint16_t delay; } *packet_mod_condition = (struct t300rs_packet_mod_condition *)t300rs->send_buffer; - int ret; + int ret = 0; + uint16_t duration, duration_old; uint16_t right_sat, right_sat_old, left_sat, left_sat_old; uint16_t right_coeff, right_coeff_old, left_coeff, left_coeff_old; int16_t right_deadband, right_deadband_old, left_deadband, left_deadband_old; @@ -854,99 +863,36 @@ static int t300rs_update_condition(struct t300rs_device_entry *t300rs, left_sat = t300rs_calculate_saturation(cond.left_saturation, effect.type); left_sat_old = t300rs_calculate_saturation(cond_old.left_saturation, old.type); - if (right_coeff != right_coeff_old - && left_coeff != left_coeff_old) { - t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); - packet_mod_condition->attribute = 0x43; - packet_mod_condition->value0 = cpu_to_le16(right_coeff); - packet_mod_condition->value1 = cpu_to_le16(left_coeff); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying condition coeff\n"); - goto error; - } - } - else if (right_coeff != right_coeff_old) { - t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); - packet_mod_condition->attribute = 0x41; - packet_mod_condition->value0 = cpu_to_le16(right_coeff); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying condition right coeff\n"); - goto error; - } - } - else if (left_coeff != left_coeff_old) { - t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); - packet_mod_condition->attribute = 0x42; - packet_mod_condition->value0 = cpu_to_le16(left_coeff); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying condition left coeff\n"); - goto error; - } - } - - if ((right_deadband != right_deadband_old) - || (left_deadband != left_deadband_old)) { - t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); - packet_mod_condition->attribute = 0x4c; - packet_mod_condition->value0 = cpu_to_le16(right_deadband); - packet_mod_condition->value1 = cpu_to_le16(left_deadband); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying condition deadband\n"); - goto error; - } - } - - if (right_sat != right_sat_old - && left_sat != left_sat_old) { - t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); - packet_mod_condition->attribute = 0x70; - packet_mod_condition->value0 = cpu_to_le16(right_sat); - packet_mod_condition->value1 = cpu_to_le16(left_sat); - - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying condition saturation\n"); - goto error; - } - } - else if (right_sat != right_sat_old) { - t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); - packet_mod_condition->attribute = 0x50; - packet_mod_condition->value0 = cpu_to_le16(right_sat); + duration = effect.replay.length - 1; + duration_old = old.replay.length - 1; - ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying condition right saturation\n"); - goto error; - } - } - else if (left_sat != left_sat_old) { - t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x0e); - packet_mod_condition->attribute = 0x60; - packet_mod_condition->value0 = cpu_to_le16(left_sat); + if (right_coeff != right_coeff_old + || left_coeff != left_coeff_old + || right_deadband != right_deadband_old + || left_deadband != left_deadband_old + || right_sat != right_sat_old + || left_sat != left_sat_old + || duration != duration_old + || effect.replay.delay != old.replay.delay) { + + packet_mod_condition->right_coeff = cpu_to_le16(right_coeff); + packet_mod_condition->left_coeff = cpu_to_le16(left_coeff); + packet_mod_condition->right_deadband = cpu_to_le16(right_deadband); + packet_mod_condition->left_deadband = cpu_to_le16(left_deadband); + packet_mod_condition->right_saturation = cpu_to_le16(right_sat); + packet_mod_condition->left_saturation = cpu_to_le16(left_sat); + packet_mod_condition->effect_type = 0x06; + packet_mod_condition->update_type = 0x45; + packet_mod_condition->duration = cpu_to_le16(duration); + packet_mod_condition->delay = cpu_to_le16(effect.replay.delay); + + t300rs_fill_header(&packet_mod_condition->header, effect.id, 0x4c); ret = t300rs_send_int(t300rs); - if (ret) { - hid_err(t300rs->hdev, "failed modifying condition left saturation\n"); - goto error; - } - } - - ret = t300rs_update_simple_duration(t300rs, state, 0x06); - if (ret) { - hid_err(t300rs->hdev, "failed modifying condition duration\n"); - goto error; + if (ret) + hid_err(t300rs->hdev, "failed modifying condition effect\n"); } -error: return ret; } -- cgit v1.3 From f595adeeca291e37260ea731fbfaa90be376deb8 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Sun, 30 Jun 2024 14:49:34 +0200 Subject: document new condition effect duration update --- docs/FFBEFFECTS.md | 45 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/docs/FFBEFFECTS.md b/docs/FFBEFFECTS.md index f94b3cb..93dbb80 100644 --- a/docs/FFBEFFECTS.md +++ b/docs/FFBEFFECTS.md @@ -314,12 +314,15 @@ Ramps seem to follow triangle wave parameters. 00001110 01111100 0e 7c deadband + saturation 00001110 01110011 0e 73 coefficient + saturation 00001110 01101101 0e 6d positive coefficient + deadband + negative saturation -00001100 0c everything +01001110 01000001 4e 41 positive coefficient + duration +00001100 0c all effect specific parameters +01001001 49 duration +01001100 4c all effect specific parameters + duration ``` Any combination that makes sense is possible, not restricted to the list above. -The order of the fields are defined in the `everything` packet example below. +The order of the fields are defined in the `all effect specific parameters + duration` packet example below. ``` positive coefficient: @@ -397,7 +400,7 @@ The order of the fields are defined in the `everything` packet example below. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - everything + all effect specific parameters 60 00 01 - ID 0c @@ -410,15 +413,47 @@ The order of the fields are defined in the `everything` packet example below. 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + all effect specific parameters + duration + 60 00 + 01 - ID + 4c + 30 73 - positive coefficient + 30 73 - negative coefficient + ff 7f - right deadband + fc ff - left deadband + fd 5f - positive saturation + fd 5f - negative saturation + 06 - effect type (condition)? + 45 - update type, see below + 10 27 - length in milliseconds + 00 00 - offset in milliseconds + 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + ``` ### Duration: + +Update type: + +``` +6th byte hex +01000001 41 length +01000100 44 offset +01000101 45 length + offset +``` + ``` 60 00 - standard header 01 - ID - 49 06 41 - modify timing? + 49 + 06 - effect type (condition)? + 45 - update type 6c 20 - length in milliseconds - 00 00 00 00 00 00 00 00 + 00 00 - offset in milliseconds + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -- cgit v1.3 From 5798d1ebe14ce69028cf351c9b82ef52f9f76372 Mon Sep 17 00:00:00 2001 From: MmAaXx500 Date: Sat, 13 Jul 2024 15:32:49 +0200 Subject: style fixes --- src/tmt300rs/hid-tmt300rs.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/tmt300rs/hid-tmt300rs.c b/src/tmt300rs/hid-tmt300rs.c index 4231600..40be801 100644 --- a/src/tmt300rs/hid-tmt300rs.c +++ b/src/tmt300rs/hid-tmt300rs.c @@ -355,7 +355,7 @@ static void t300rs_calculate_periodic_values(struct ff_effect *effect) /* the interval [0; 32677[ is used by the wheel for the [0; 360[ degree phase shift */ periodic->phase = periodic->phase * 32677 / 0x10000; - headroom = 0x7FFF - periodic->magnitude; + headroom = 0x7fff - periodic->magnitude; /* magnitude + offset cannot be outside the valid magnitude range, */ /* otherwise the wheel behaves incorrectly */ periodic->offset = clamp(periodic->offset, -headroom, headroom); @@ -365,7 +365,7 @@ static uint16_t t300rs_condition_max_saturation(uint16_t effect_type) { if(effect_type == FF_SPRING) return 0x6aa6; - + return 0x7ffc; } @@ -396,7 +396,7 @@ static int16_t t300rs_calculate_coefficient(int16_t coeff, uint16_t effect_type) input_level = 100; break; } - + return coeff * input_level / 100; } @@ -406,16 +406,17 @@ static uint16_t t300rs_calculate_saturation(uint16_t sat, uint16_t effect_type) if(sat == 0) return max; - - return sat * max / 0xFFFF; + + return sat * max / 0xffff; } -static void t300rs_calculate_deadband(int16_t *out_rband, int16_t *out_lband, uint16_t deadband, int16_t offset) +static void t300rs_calculate_deadband(int16_t *out_rband, int16_t *out_lband, + uint16_t deadband, int16_t offset) { - /* max deadband value is 0x7FFF in either direction */ + /* max deadband value is 0x7fff in either direction */ /* deadband is the width of the deadzone, one direction is half of it */ - *out_rband = clamp(offset + (deadband / 2), -0x7FFF, 0x7FFF); - *out_lband = clamp(offset - (deadband / 2), -0x7FFF, 0x7FFF); + *out_rband = clamp(offset + (deadband / 2), -0x7fff, 0x7fff); + *out_lband = clamp(offset - (deadband / 2), -0x7fff, 0x7fff); } int t300rs_send_buf(struct t300rs_device_entry *t300rs, u8 *send_buffer, size_t len) @@ -854,8 +855,10 @@ static int t300rs_update_condition(struct t300rs_device_entry *t300rs, left_coeff = t300rs_calculate_coefficient(cond.left_coeff, effect.type); left_coeff_old = t300rs_calculate_coefficient(cond_old.left_coeff, old.type); - t300rs_calculate_deadband(&right_deadband, &left_deadband, cond.deadband, cond.center); - t300rs_calculate_deadband(&right_deadband_old, &left_deadband_old, cond_old.deadband, cond_old.center); + t300rs_calculate_deadband(&right_deadband, &left_deadband, + cond.deadband, cond.center); + t300rs_calculate_deadband(&right_deadband_old, &left_deadband_old, + cond_old.deadband, cond_old.center); right_sat = t300rs_calculate_saturation(cond.right_saturation, effect.type); right_sat_old = t300rs_calculate_saturation(cond_old.right_saturation, old.type); @@ -866,7 +869,7 @@ static int t300rs_update_condition(struct t300rs_device_entry *t300rs, duration = effect.replay.length - 1; duration_old = old.replay.length - 1; - if (right_coeff != right_coeff_old + if (right_coeff != right_coeff_old || left_coeff != left_coeff_old || right_deadband != right_deadband_old || left_deadband != left_deadband_old @@ -1124,7 +1127,8 @@ static int t300rs_upload_condition(struct t300rs_device_entry *t300rs, right_coeff = t300rs_calculate_coefficient(cond.right_coeff, effect.type); left_coeff = t300rs_calculate_coefficient(cond.left_coeff, effect.type); - t300rs_calculate_deadband(&right_deadband, &left_deadband, cond.deadband, cond.center); + t300rs_calculate_deadband(&right_deadband, &left_deadband, + cond.deadband, cond.center); right_sat = t300rs_calculate_saturation(cond.right_saturation, effect.type); left_sat = t300rs_calculate_saturation(cond.left_saturation, effect.type); @@ -1142,7 +1146,8 @@ static int t300rs_upload_condition(struct t300rs_device_entry *t300rs, packet_condition->right_saturation = cpu_to_le16(right_sat); packet_condition->left_saturation = cpu_to_le16(left_sat); - memcpy(&packet_condition->hardcoded, condition_values, ARRAY_SIZE(condition_values)); + memcpy(&packet_condition->hardcoded, condition_values, + ARRAY_SIZE(condition_values)); max_sat = t300rs_condition_max_saturation(effect.type); /* it seems that the maximum values do not affect the wheel. */ @@ -1154,7 +1159,7 @@ static int t300rs_upload_condition(struct t300rs_device_entry *t300rs, ret = t300rs_send_int(t300rs); if (ret) - hid_err(t300rs->hdev, "failed uploading spring\n"); + hid_err(t300rs->hdev, "failed uploading condition\n"); return ret; } -- cgit v1.3