Subtle effects missing due to int overflow in CalcGain #46
Description
While testing in FEdit I noticed that there was a very nonlinear response when varying constant force and sine. Below about 30% the effects are not perceptible at all. Crossing 50% there is a big jump in output response. This means that subtle effects in games, such as engine vibrations, pavement bumps, gear shifts and pre-stall flutter are not felt unless the effect gain can be adjusted high in the game menus.
The cause is a bug in CalcGain that results in an effect magnitude of 0-50% to be mapped to 0-25% force and 50%-100% to be mapped to 75%-100%. This function is used for constant force magnitude, sine magnitude and effect envelope attack and fade.
Current code in ffb.c:
uint8_t CalcGain(uint8_t usbValue, uint8_t gain)
{
int16_t v = usbValue;
return (((v * gain) / 256) >> 2 ) & 0x7f;
}
v needs to be modified to an unsigned integer in order to avoid an overflow when multiplying two 8 bit unsigned integers
Then >> 2 is equivalent to division by 4. The output needs to have a range of 0x00 to 0x7f (=128) so this should be >> 1.
I've tested the following:
uint8_t CalcGain(uint8_t usbValue, uint8_t gain)
{
uint16_t v = usbValue;
return (((v * gain) / 255) >> 1 ) & 0x7f;
}
And suddenly those subtle effects are there.
Note: I also found with the modified code that I get about a 1s lag on stick response and Windows freezes every time a message is sent to the stick. This is obviously unplayable. But I have debug enable and it only happens when I do not have a terminal open monitoring the USB COM port. With the terminal open it works fine. I'm not certain whether this was the case with the previous hex - I haven't gone back. I can't see why the change would make any difference but I saw in the commit log there was a 5ms delay introduced when responding to USB, so maybe there is a timing sensitivity - too fast or too slow? So needs some testing still.