Re: Using Multiple Controler Buttons with ROBOT C
The reason this:
solved the problem is that joy1Btn is not a Function, but a Macro, defined using #define, and that causes some unexpected operator precedence problems.
There is a #define like
#define joy1Btn(btn) joystick.joy1_Buttons & (1 << (btn - 1))
When you use a #define instead of a function, the text is Literally substituted in where you use the name of the macro.
That means, when you type
if(joy1Btn(2) != 0)
the first thing the compiler will do is substitute the definition of joy1Btn like this:
if(joystick.joy1_Buttons & (1 << (2 - 1)) != 0)
When the compiler evaluates the resulting expression, it groups operations according to "operator precedence", http://www.difranco.net/cop2220/op-prec.htm
From that table, you can see that != has higher precedence than &, which means the operations will be performed as if you had put parenthesis like this:
if(joystick.joy1_Buttons & ((1 << (2 - 1)) != 0))
which simplifies to
if(joystick.joy1_Buttons & 1)
which is NOT what you wanted. You were hoping for this:
if((joystick.joy1_Buttons & ((1 << (2 - 1))) != 0))
which simplifies to
if (joystick.joy1_Buttons & 2)
Thus whenever you push button 1, that "if" is true.
The way experienced C programmers avoid problems like this is to overparenthesize the definitions of macros to prevent unexpected associations when they are expanded. For example, I would have written the #define like this:
#define joy1Btn(btn) (joystick.joy1_Buttons & (1 << (btn - 1)))
or maybe even like this, if I am worried that someone might invoke it like if (joy1Btn(4<<2))
#define joy1Btn(btn) (joystick.joy1_Buttons & (1 << ((btn) - 1)))
because without the parens around btn, it would expand like this:
if (joystick.joy1_Buttons & (1 << (4<<2 - 1)))
which due to the operator precedence table would give you
if (joystick.joy1_Buttons & (1 << (4<<(2 - 1))))
which is button 8, but you asked for button 16 (or something like that).
The moral of the story is that Parenthesis are free and you should use them, ESPECIALLY in #defines.
Perhaps the good people at CMU will update the JoystickDriver.c file with some extra parens, but in the meantime you can do it yourself or you can revise your code as suggested by Timothy Friez, or you can put extra parens at the point of invocation:
if((joy1Btn(2)) != 0)
which will look goofy and ignorant, but will insulate you from evil that lurks in #include'd files.
Mentor, Team 1001
Charles F. Brush High School
South Euclid-Lyndhurst, Ohio USA