Malcolm said:
Hi,
I have the following which fails with "disagreement in number of macro
arguments" when compiling with Imagecraft ICCAVR. Has anyone got any
ideas - its not vital but would make the code a lot nicer to read:
#define SET(x,y) (x |=(1<<y))
#define PIEZO PORTB,5
then in code it fails when I do:
SET(PIEZO);
Others have explained the problem. The macro processing is more subtle
than many realize because of the distinct order in which substitution
and rescanning is done.
Here is a solution I have used for similar applications:
/* Demonstrate field extraction of complex macros */
#define SET(bi) (PORT bi |= 1u<<PBIT bi )
#define PORT(p,b) p /* extract port name */
#define PBIT(p,b) b /* extract bit number */
#define PIEZO (PORTB,5)
#define SOUND PIEZO /* demonstrates reassigning
** macro, which also works */
unsigned int PORTB;
int main(void) {
SET(PIEZO);
SET(SOUND);
return 0;
}
You write extraction macros to get the field within the compound that
you want. Using that technique, I have written a set of macros that can
be used to logically set or reset a specified port bit. Another
parameter of the signal definition macro is whether the signal is low
true or high true, so that I can define a macro SETTRUE, for example,
which looks at the encoding in the signal specification and decides
whether to set or clear the bit. Add more parameters and you can set
groups of bits, such as a keyboard row number, where the macro knows the
number of bits and the offset within the byte. Similar macros can be
used for testing input bits or reading input fields.
Other code that you might want to include in your macro is saving output
bytes/words in a "shadow" array, so that if you cannot read the output
port directly (as you apparently can in your example), it will combine
the new output bit(s) with the current value of other bits in the output
port.
The nice parts about writing such macros is that you can define your I/O
bit assignments IN ONE PLACE. If you change assignments, there is
only one place that needs to be changed. Since the operand of the
macros are usually compile-time constants, as in this example, the
compiler optimizes the result as if you had hard coded the port and bit
specifications.
Thad