legoEv3/evdev/ff.py
# encoding: utf-8
import ctypes
from evdev import ecodes
_u8 = ctypes.c_uint8
_u16 = ctypes.c_uint16
_u32 = ctypes.c_uint32
_s16 = ctypes.c_int16
class Replay(ctypes.Structure):
'''
Defines scheduling of the force-feedback effect
@length: duration of the effect
@delay: delay before effect should start playing
'''
_fields_ = [
('length', _u16),
('delay', _u16),
]
class Trigger(ctypes.Structure):
'''
Defines what triggers the force-feedback effect
@button: number of the button triggering the effect
@interval: controls how soon the effect can be re-triggered
'''
_fields_ = [
('button', _u16),
('interval', _u16),
]
class Envelope(ctypes.Structure):
'''
Generic force-feedback effect envelope
@attack_length: duration of the attack (ms)
@attack_level: level at the beginning of the attack
@fade_length: duration of fade (ms)
@fade_level: level at the end of fade
The @attack_level and @fade_level are absolute values; when applying
envelope force-feedback core will convert to positive/negative
value based on polarity of the default level of the effect.
Valid range for the attack and fade levels is 0x0000 - 0x7fff
'''
_fields_ = [
('attach_length', _u16),
('attack_level', _u16),
('fade_length', _u16),
('fade_level', _u16),
]
class Constant(ctypes.Structure):
'''
Defines parameters of a constant force-feedback effect
@level: strength of the effect; may be negative
@envelope: envelope data
'''
_fields_ = [
('level', _s16),
('ff_envelope', Envelope),
]
class Ramp(ctypes.Structure):
'''
Defines parameters of a ramp force-feedback effect
@start_level: beginning strength of the effect; may be negative
@end_level: final strength of the effect; may be negative
@envelope: envelope data
'''
_fields_ = [
('start_level', _s16),
('end_level', _s16),
('ff_envelope', Envelope),
]
class Condition(ctypes.Structure):
'''
Defines a spring or friction force-feedback effect
@right_saturation: maximum level when joystick moved all way to the right
@left_saturation: same for the left side
@right_coeff: controls how fast the force grows when the joystick moves to the right
@left_coeff: same for the left side
@deadband: size of the dead zone, where no force is produced
@center: position of the dead zone
'''
_fields_ = [
('right_saturation', _u16),
('left_saturation', _u16),
('right_coeff', _s16),
('left_foeff', _s16),
('deadband', _u16),
('center', _s16),
]
class Periodic(ctypes.Structure):
'''
Defines parameters of a periodic force-feedback effect
@waveform: kind of the effect (wave)
@period: period of the wave (ms)
@magnitude: peak value
@offset: mean value of the wave (roughly)
@phase: 'horizontal' shift
@envelope: envelope data
@custom_len: number of samples (FF_CUSTOM only)
@custom_data: buffer of samples (FF_CUSTOM only)
'''
_fields_ = [
('waveform', _u16),
('period', _u16),
('magnitude', _s16),
('offset', _s16),
('phase', _u16),
('envelope', Envelope),
('custom_len', _u32),
('custom_data', ctypes.POINTER(_s16)),
]
class Rumble(ctypes.Structure):
'''
Defines parameters of a periodic force-feedback effect
@strong_magnitude: magnitude of the heavy motor
@weak_magnitude: magnitude of the light one
Some rumble pads have two motors of different weight. Strong_magnitude
represents the magnitude of the vibration generated by the heavy one.
'''
_fields_ = [
('strong_magnitude', _u16),
('weak_magnitude', _u16),
]
class EffectType(ctypes.Union):
_fields_ = [
('ff_constant_effect', Constant),
('ff_ramp_effect', Ramp),
('ff_periodic_effect', Periodic),
('ff_condition_effect', Condition * 2), # one for each axis
('ff_rumble_effect', Rumble),
]
class Effect(ctypes.Structure):
_fields_ = [
('type', _u16),
('id', _s16),
('direction', _u16),
('ff_trigger', Trigger),
('ff_replay', Replay),
('u', EffectType)
]
# ff_types = {
# ecodes.FF_CONSTANT,
# ecodes.FF_PERIODIC,
# ecodes.FF_RAMP,
# ecodes.FF_SPRING,
# ecodes.FF_FRICTION,
# ecodes.FF_DAMPER,
# ecodes.FF_RUMBLE,
# ecodes.FF_INERTIA,
# ecodes.FF_CUSTOM,
# }