This is a reading routine similar to the "old mouse" "ball", and also used on machines that were common in "arcade", usually racing cars, where a round bulkhead with small cuts or holes was placed in front of 2 optical sensors for steering wheel reading. It could very well be used on a mat, with white and black squares providing optical reading, or mechanical contacts.
The sensors are positioned in a "quadrature" configuration, where their sequence accurately determines whether the movement is clockwise or clockwise, according to the sequence of "zeros and ones".
Mathematically, it is important to understand operators <<
and >>
, which have already been discussed on other issues.
What are the operators for | & << >>?
How the bit offset in C/C works++?
Taking the explanations of the above questions, using binary representation, let’s look at the first line of the question:
int encoded = (MSB << 1) | LSB;
Assuming that MSB is 01
, the operator <<
effectively shifts the value to the left, and the result is 10
Once done, the operator |
(or binary) "merges" the LSB with the MSB. Assuming that the LSB is 1
, the final result will be 11
Similarly, in the next line:
int sum = (lastEncoded << 2) | encoded;
we’re taking the 11
previous, and moving two houses to the left, ie transforming the value into 1100
.
Finally, we took the data from the previous reading (obtained in the same way as steps 1 and 2) and merged with the value of the current reading. Assuming the current reading is 01
and the previous 10
, we have the final value 0110
.
With this, just consult the quadrature table to know if the value should be incremented or decreased.
About the "mechanics" of reading
The secret of the reading is in the arrangement of the sensors, arranged so that the hole and the closed parts, or electrical contacts occupy exactly the distance of the two sensors, so that the following happens:
- 1 and 2 are the sensors
- AA is the bulkhead (light does not pass and sensor indicates 0)
- BB is opening (light passes and sensor indicates 1)
Starting from a hypothetical initial position:
AABBAABBAABBAABB
12 Leitura: 00
Let’s say I turn the wheel slightly to the right:
ABBAABBAABBAABBA
12 Leitura 01
Turning a little more to the right:
BBAABBAABBAABBAA
12 Leitura 11
And a little more:
BAABBAABBAABBAAB
12 Leitura 10
Next time, we’re back to 00
.
In this case, any pair of the sequence 00
01
11
10
indicates a step to the right.
Assuming otherwise, the sequence would be 00
10
11
01
, and any combination of these pairs indicates a step to the left.
Going further:
if I’m in position 00
, I know the next step can only be 01
(right), or 10
(left);
if I’m in position 01
, I know the next step can only be 11
(right), or 00
(left);
if I’m in position 11
, I know the next step can only be 10
(right), or 01
(left);
finally, if I’m in position 10
, I know the next step can only be 00
(right), or 11
(left);
What the author of the above code did was to take these rules and simplify a "tabelinha", to know when to increment or when to decrement the variable.
Of curiosity, you can notice that, according to the explanations given, there is no variation in the table of the original code from 00 to 11, nor from 10 to 01 or vice versa, because obligatorily, by the mechanical arrangement of the sensor, a pair in an equal state is always replaced by a pair in a different state, and a different pair is always replaced by an equal pair if there is movement.