I am currently developing a custom Giga R1 WiFi racing sim project for BeamNG.drive. Currently, my joystick inputs are fully functional and responding correctly, but I am having significant difficulties implementing Force Feedback (FFB).
Specifically, I am struggling to interpret the example descriptor (pid1_01, ~pg. 30) and adapt it to my own needs (I need Constant Force, Damper, Friction, & Inertia effect types, of which Friction is not even defined in the document).
I have attempted to generate descriptors using Waratah , but it hasn’t proved to be that useful because my challenge is not generating a syntactically correct descriptor, but understanding where to start, and how to structure & test it.
Here is my current joystick report descriptor:
0x05, 0x01, // UsagePage(Generic Desktop[0x0001])
0x09, 0x04, // UsageId(Joystick[0x0004])
0xA1, 0x01, // Collection(Application)
0x85, 0x01, // ReportId(1)
0x09, 0x30, // UsageId(X[0x0030])
0x15, 0x81, // LogicalMinimum(-127)
0x25, 0x7F, // LogicalMaximum(127)
0x95, 0x01, // ReportCount(1)
0x75, 0x08, // ReportSize(8)
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0x05, 0x02, // UsagePage(Simulation Controls[0x0002])
0x09, 0xBB, // UsageId(Throttle[0x00BB])
0x09, 0xBA, // UsageId(Rudder[0x00BA])
0x95, 0x02, // ReportCount(2)
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0x05, 0x01, // UsagePage(Generic Desktop[0x0001])
0x09, 0x31, // UsageId(Y[0x0031])
0x95, 0x01, // ReportCount(1)
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0x09, 0x39, // UsageId(Hat Switch[0x0039])
0x46, 0x3B, 0x01, // PhysicalMaximum(315)
0x65, 0x14, // Unit('degrees', EnglishRotation, Degrees:1)
0x15, 0x00, // LogicalMinimum(0)
0x25, 0x07, // LogicalMaximum(7)
0x75, 0x03, // ReportSize(3)
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0x75, 0x04, // ReportSize(4)
0x81, 0x03, // Input(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0x05, 0x09, // UsagePage(Button[0x0009])
0x19, 0x01, // UsageIdMin(Button 1[0x0001])
0x29, 0x20, // UsageIdMax(Button 32[0x0020])
0x45, 0x00, // PhysicalMaximum(0)
0x65, 0x00, // Unit(None)
0x25, 0x01, // LogicalMaximum(1)
0x95, 0x20, // ReportCount(32)
0x75, 0x01, // ReportSize(1)
0x81, 0x02, // Input(Data, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0x95, 0x01, // ReportCount(1)
0x81, 0x03, // Input(Constant, Variable, Absolute, NoWrap, Linear, PreferredState, NoNullPosition, BitField)
0xC0, // EndCollection()
The mappings are:
X —> Steering (-127, 127)
Y —> Clutch Pedal (-127, 127)
Throttle —> Gas Pedal (-127, 127 : but only 0 - 127 is used)
Rudder —> Brake Pedal (-127, 127 : but only 0 - 127 is used)
HAT + 32 Buttons —> Custom H-pattern/Sequential Setup (+ accessories)