-
-
Notifications
You must be signed in to change notification settings - Fork 302
Description
Expectation:
The intended zero point value of 128 should produce an XInput value of zero, and Input values of equivalent distance from the zero point should produce XInput values of equivalent magnitude.
128 -> 0
128 + X -> XInputValue
128 - X -> -XInputValue
Problem:
The existing calculation for converting the uint_8 input from 0 : 255 to -32768 : 32767 does not properly map the intended zero point value of 128 to (0, 0) on the resulting analog stick, and values of equivalent distance from the zero point have an magnitude difference that increases as the distance decreases.
This is the current code
_report.lx = (_outputs.leftStickX - 128) * 65535 / 255 + 128;
This simplifies to
_report.lx = (_outputs.leftStickX) * 257 - 32768;
This follows the slope-intercept form of defining a line, y = mx + b
This calculation maximizes the range of 0 : 255 to across the full range, from -32768 to 32767, with only a small magnitude difference
0 * 257 - 32768 = -32768
255 * 257 - 32768 = 32767
However, as the input values approach the zero point 128, this calculation results magnitude difference of 256 between the two points closest to the zero point
127 * 257 - 32768 = -129
129 * 257 - 32768 = 385
Solution:
Instead of prioritizing hitting the maximum range, the values can be evenly balanced and also have an x-intercept of zero.
y = 258x - 33024
The code values can be adjusted like so:
_report.lx = (_outputs.leftStickX) * 258 - 33024;
The magnitude difference for each value of equal distance from the zero point becomes zero, including the zero point itself.
The tradeoff is that the calculation becomes constrained from converting 1 : 255 to -32766 : 32766.
Restricting the input minimum value to 1 instead of 0 actually balances out the positive and negative value ranges, because there are now an equivalent (127) number of integers on each side, instead of 128 negative values (0 to 127) and 127 positive values (129 to 255).
Magnitude becomes zero at the zero point
128 * 258 - 33024 = 0
Magnitudes are matched near the zero point
127 * 258 - 33024 = -258
129 * 258 - 33024 = 258
Magnitudes are matched at the maximum points
1 * 258 - 33024 = -32766
255 * 258 - 33024 = 32766
Implementation Note:
This code works seamlessly with any existing modes, with the requirement that the minimum analog value must be restricted to 1, instead of 0 as some modes have occasionally been configured. This value loss is inconsequential, as it only serves to match the negative range resolution to the positive range resolution.