gotzl / hid-fanatecff

Driver to support FANATEC input devices, in particular ForceFeedback of various wheel-bases
GNU General Public License v2.0
151 stars 19 forks source link

Setting force feedback gain with FF_GAIN #45

Closed dtran11 closed 8 months ago

dtran11 commented 8 months ago

Does the driver support setting FF_GAIN? I am creating a non-gaming software in python3:evdev with a GT DD PRO. I am able to control FF_PERIODIC and FF_SPRING. However, setting the FF_GAIN field doesn't do anything. This is how I'm doing it:

device = InputDevice(INPUT_PATH)
device.write(ecodes.EV_FF, ecodes.FF_GAIN, 100)
# device.write(ecodes.EV_FF, ecodes.FF_GAIN, 1)

Any help is appreciated. Thanks

gotzl commented 8 months ago

Hey there, FF_GAIN is not implemented. However, AFAIU setting this field wouldn't have an immediate effect but just scales the strengths of effects. Maybe you want FF_CONSTANT ? That said, I can implement FF_GAIN when I find some time ...

dat-tran-halo commented 8 months ago

Do you know if GAIN is set to 100% as default or bootup? If so it wouldn't help me much then. I use the FF_SPRING effect and my user says the maximum strength of 32767 is not enough. I was hoping to increase the gain to see if it spring constant can increase. Thanks for your help.

gotzl commented 8 months ago

From the driver side the gain is 100% per default. Ie, if you call FF_SPRING with the max value, then the driver will also send the max value to the wheel. (This is, if there is nothing buggy in the driver ;)) Can you show me the call to FF_SPRING so that I maybe can confirm that the max value is correctly propagating?

Then there is also a 'gain' setting on the device side. In case of the CSL Elite there is the 'tuning menu', which is accessible on the wheel directly. This has again a setting for the general strength which is 100% in my case. Not sure how this looks like for the GT DD Pro, but I guess there should be s.t. simliar.

dtran11 commented 8 months ago

Seems like the FF gain on the wheel tuning menu (basic mode) is 100% already. Here is my test script for FF_SPRING. Thanks

#!/usr/bin/env python3

import os
import sys
import time
import evdev
from evdev import ecodes, InputDevice, ff

INPUT_PATH = '/dev/input/by-id/usb-Fanatec_FANATEC_Wheel-event-joystick'
MAX_STRENGTH = 32767
MIN_STRENGTH = 5000
PRINT_POSITIONS = False

EFFECT_DIR_DOWN  = 0x0000
EFFECT_DIR_LEFT  = 0x4000
EFFECT_DIR_UP    = 0x8000
EFFECT_DIR_RIGHT = 0xC000

def upload_spring_effect(device, strength=MIN_STRENGTH, effect_id=-1):
    duration = 0  # indefinitely
    strength = int(max(MIN_STRENGTH, min(MAX_STRENGTH, strength)))
    #print("spring strength: " + str(strength))

    condition = ff.Condition(32767,  # right saturation
                             32767,  # left saturation
                             strength,  # right coeff
                             strength,  # left coeff
                             0,      # deadband
                             0)      # center
    effect = ff.Effect(
        ecodes.FF_SPRING,
        effect_id,
        0,
        ff.Trigger(0, 0),
        ff.Replay(duration * 1000, 0),
        ff.EffectType(ff_condition_effect=(condition, condition))
    )
    return device.upload_effect(effect)

def main():
    device = InputDevice(INPUT_PATH)
    #print(device.capabilities(verbose=True))

    spring_eid = upload_spring_effect(device, MAX_STRENGTH, -1)
    if (spring_eid >= 0):
        device.write(ecodes.EV_FF, spring_eid, 1)
    else:
        raise RuntimeError('spring effect id = ' + str(spring_eid))

    try:
        while True:
            time.sleep(.1)
    except Exception as ex:
        print(ex)
    except KeyboardInterrupt:
        pass

    print("Clear effects")
    device.erase_effect(spring_eid)

if __name__ == '__main__':
    main()
gotzl commented 8 months ago

Hey, thanks for the script. So, I could confirm that with your script, the saturation is only half of its maximum. However, if I put 0xffff for left/right saturation, the saturation sent to the device is maxed. And I also think that I feel a difference ;) Does this work for you?

Edit: Note that saturation is uint16, so max is 0xffff while coeff is int16, so max is 0x7fff.

dtran11 commented 8 months ago

That does make a difference. Thank You!