-
Notifications
You must be signed in to change notification settings - Fork 65
Description
The method FilterOnePole::input(float) starts with these statements:
long time = micros();
ElapsedUS = float(time - LastUS); // cast to float here, for mathWhen micros() reaches 231, which happens roughly 35.8 minutes after the program starts, time becomes a large negative number, and the subtraction time - LastUS overflows.
In C and C++, arithmetic overflow of signed integral types is undefined behavior. This means the program is incorrect, and anything can happen, including (but not limited to) the subtraction giving the expected result. Just for illustration, here is a recent example of the kind of surprises you can get with integer overflows.
The same bug is present in FilterTwoPole.cpp and in FilterDerivative.cpp.
The fix is very simple: all variables holding timestamps (LastUS, LastTimeUS, thisUS, time and now) should be declared unsigned long. This is the type returned by micros(), and it is not a coincidence that it is the right type for timing calculations. Unlike signed integers, the arithmetics on unsigned integers are specified by the C and C++ standards to be done modulo MAX(type)+1. This guarantees that the subtraction will yield the correct result even across a micros() rollover.