#Macros and #define - parameter passing

Circuit

Senior Member
I am not quite getting my head around the syntax for parameter passing into macros; I don't see why the following code is invalid;

Code:
[color=Navy]#picaxe [/color][color=Black]40x2[/color]
[color=Blue]symbol [/color][color=Purple]controls[/color][color=DarkCyan]=[/color][color=Purple]b0[/color]
[color=Navy]#define [/color][color=Black]redlight [/color][color=Navy]1
#define [/color][color=Black]greenlight [/color][color=Navy]2
#define [/color][color=Black]bluelight [/color][color=Navy]3
#macro [/color][color=Black]light_on [/color][color=Blue]([/color][color=Black]lightcolour[/color][color=Blue])
      setbit [/color][color=Purple]controls[/color][color=Black],lightcolour[/color]
[color=Navy]#endmacro
#macro [/color][color=Black]light_off [/color][color=Blue]([/color][color=Black]lightcolour[/color][color=Blue])
      clearbit [/color][color=Purple]controls[/color][color=Black],lightcolour[/color]
[color=Navy]#endmacro[/color]

[color=Black]light_on [/color][color=Blue]([/color][color=Black]redlight[/color][color=Blue])[/color]

The variable controls will be passed down a shift-register in another routine to actually switch things physically, but I cannot see why I am messing up on parameter passing. I have no trouble coding this with gosubs and so forth, but I would like to try and learn more about parameter passing in macros.
Can someone put me right?
 

Technical

Technical Support
Staff member
Remove the space before all the ('s (both in #macro and when you use it) and you should be ok.
 

Circuit

Senior Member
Remove the space before all the ('s (both in #macro and when you use it) and you should be ok.
Thank you.
Frustratingly clear...now that you point it out! I really did not see that one coming - and I spent a lot of time trying to locate my error.
Perhaps this limitation could be removed; note that in the program below I have intentionally added space after SERTXD before the parameters are bracketed and this works just fine. This is the way that I normally type up SERTXD, especially as I touch-type and the space just falls in naturally. Having checked this, I don't feel so stupid in placing the spaces before the parameters in the #MACRO statement.

When I look at the on-line help for the #DEFINE directive, I note an extensive paragraph on the inadvertent use of "=". This is very sensible because that is another trap I fell into for a couple of moments before I checked the syntax in the on-line help. I would suggest therefore that an equivalent note on spacing is added to the on-line help for #MACRO because I think that the rather large hole that I fell into may also snare others. Ideally, why not allow spacing just as you do with the SERTXD and its parameters?

For those who wish to try out the program in a corrected and extended form in the simulator, just to get a feel of #DEFINE and #MACRO, here is another version - now working! When I think how far away this program construct is from that of PE5, well, it is simply excellent!

Code:
[color=Navy]#picaxe [/color][color=Black]40x2[/color]
[color=Blue]symbol [/color][color=Purple]controls[/color][color=DarkCyan]=[/color][color=Purple]b0[/color]
[color=Blue]symbol [/color][color=Purple]dcolour[/color][color=DarkCyan]=[/color][color=Purple]b10[/color]
[color=Navy]#define [/color][color=Black]redlight [/color][color=Navy]1
#define [/color][color=Black]greenlight [/color][color=Navy]2
#define [/color][color=Black]bluelight [/color][color=Navy]3
#macro [/color][color=Black]light_on[/color][color=Blue]([/color][color=Black]lightcolour[/color][color=Blue])
      setbit [/color][color=Purple]controls[/color][color=Black],lightcolour
      [/color][color=Blue]let [/color][color=Purple]dcolour[/color][color=DarkCyan]=[/color][color=Black]lightcolour[/color]
[color=Navy]#endmacro
#macro [/color][color=Black]light_off[/color][color=Blue]([/color][color=Black]lightcolour[/color][color=Blue])
      clearbit [/color][color=Purple]controls[/color][color=Black],lightcolour
      [/color][color=Blue]let [/color][color=Purple]dcolour[/color][color=DarkCyan]=[/color][color=Black]lightcolour[/color]
[color=Navy]#endmacro

#macro [/color][color=Black]Display

      [/color][color=Blue]sertxd ( [/color][color=Red]"lightcolour="[/color][color=Black], [/color][color=Purple]dcolour[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf ) 
      sertxd ( [/color][color=Red]"controls="[/color][color=Black], #[/color][color=Purple]bit7[/color][color=Black],#[/color][color=Purple]bit6[/color][color=Black],#[/color][color=Purple]bit5[/color][color=Black],#[/color][color=Purple]bit4[/color][color=Black], #[/color][color=Purple]bit3[/color][color=Black], #[/color][color=Purple]bit2[/color][color=Black], #[/color][color=Purple]bit1[/color][color=Black],#[/color][color=Purple]bit0[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf ) 
      [/color]
[color=Navy]#endmacro[/color]

[color=Black]display
light_on[/color][color=Blue]([/color][color=Black]redlight[/color][color=Blue])[/color]
[color=Black]display
light_on[/color][color=Blue]( [/color][color=Black]greenlight[/color][color=Blue])[/color]
[color=Black]display
light_on[/color][color=Blue]([/color][color=Black]bluelight[/color][color=Blue])[/color]
[color=Black]display
light_off[/color][color=Blue]([/color][color=Black]redlight[/color][color=Blue])[/color]
[color=Black]light_off[/color][color=Blue]([/color][color=Black]bluelight[/color][color=Blue])[/color]
[color=Black]display
light_off[/color][color=Blue]( [/color][color=Black]greenlight[/color][color=Blue])[/color]
[color=Black]display[/color]
One other thing that I have learnt in this exercise is the parameter "lightcolour" can only be passed on to a variable (in this case "dcolour" ,b10) within the macro. Trying to set "dcolour" from "lightcolour" outside the macro does not work.

Another question, if I may; how many #defines may be used in a program?
 

Technical

Technical Support
Staff member
We'll have a look into the whitespace.

There is no limit to the number of #defines you can use. They are not part of the 'program' that is downloaded as the preprocessor converts them all before the program is compiled.
 

johndk

Senior Member
Just a general question here about macros. I had not realized that #macro existed. What is the advantage of using a macro over a sub? From the code it looks about the same to me. One can "pass" parameters by simply referencing the variable. I do this in my programs and use a few variables as param1, param2, etc and set them before calling the sub. I know that parameter passing is more intuitive from a program readability point of view. But is there any other advantage to using a macro over a sub?
 

westaust55

Moderator
What is the advantage of using a macro over a sub? From the code it looks about the same to me. One can "pass" parameters by simply referencing the variable.
:
But is there any other advantage to using a macro over a sub?
If you have a look at the on-line commands section that will provide some information:
http://www.picaxe.com/BASIC-Commands/Directives/hash-macro/

More specifically,
The program lines in a defined Macro are substituted for a Macro name each time found within the program thus the end result will be a program file with a longer file length.

When a subroutine is used, it stays as a single segment of program code with the Gosub/call commands to that start of the subroutine each time called in the program. Thus this will typically result in smaller overall code size to be downloaded into the PICAXE.
 

Technical

Technical Support
Staff member
A macro can also contain a sub and/or gosub, they are not exclusive.

A useful example of Macros in use is in the PE6 samples (File>Open Samples>BASIC) folder called 'Sphero'
 

techElder

Well-known member
Furthering what Westy said about macro lines being multi-included in a program, is this different than other Basic languages or just other languages? I know that the one that touts using library routines has a problem with large program size because the whole library gets included (or so I understand from reading.)

Do multi-included macro lines have an advantage, or is this just another programming style?

Or do macros just take advantage of another feature in PICAXE Basic?
 

Circuit

Senior Member
The program lines in a defined Macro are substituted for a Macro name each time found within the program thus the end result will be a program file with a longer file length.

When a subroutine is used, it stays as a single segment of program code with the Gosub/call commands to that start of the subroutine each time called in the program. Thus this will typically result in smaller overall code size to be downloaded into the PICAXE.
Gosh, and what a difference there is! I didn't realise just how memory-hungry macros could be. I recoded one of the macros in the program that I posted above and used a subroutine instead. The size with the macro is 456 bytes and with the subroutine it is 152 bytes. That's a real shocker...just when I was really getting to like macros as a program construct. Is there any reason why macros couldn't be handled in the tokeniser/interpreter in the same way as subroutines?

Out of interest, the spectacularly more compact version of the program with the one subroutine substituted for the macro is below.
Code:
[color=Navy]#picaxe [/color][color=Black]40x2[/color]
[color=Blue]symbol [/color][color=Purple]controls[/color][color=DarkCyan]=[/color][color=Purple]b0[/color]
[color=Blue]symbol [/color][color=Purple]dcolour[/color][color=DarkCyan]=[/color][color=Purple]b10[/color]

[color=Navy]#define [/color][color=Black]redlight [/color][color=Navy]1
#define [/color][color=Black]greenlight [/color][color=Navy]2
#define [/color][color=Black]bluelight [/color][color=Navy]3

#macro [/color][color=Black]switch_on[/color][color=Blue]([/color][color=Black]lightcolour[/color][color=Blue])
      setbit [/color][color=Purple]controls[/color][color=Black],lightcolour
      [/color][color=Blue]let [/color][color=Purple]dcolour[/color][color=DarkCyan]=[/color][color=Black]lightcolour[/color]
[color=Navy]#endmacro
#macro [/color][color=Black]switch_off[/color][color=Blue]([/color][color=Black]lightcolour[/color][color=Blue])
      clearbit [/color][color=Purple]controls[/color][color=Black],lightcolour
      [/color][color=Blue]let [/color][color=Purple]dcolour[/color][color=DarkCyan]=[/color][color=Black]lightcolour[/color]
[color=Navy]#endmacro[/color]

[color=Black]Display:
      [/color][color=Blue]sertxd( [/color][color=Red]"lightcolour="[/color][color=Black], [/color][color=Purple]dcolour[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf ) 
      sertxd( [/color][color=Red]"controls="[/color][color=Black], #[/color][color=Purple]bit7[/color][color=Black],#[/color][color=Purple]bit6[/color][color=Black],#[/color][color=Purple]bit5[/color][color=Black],#[/color][color=Purple]bit4[/color][color=Black], #[/color][color=Purple]bit3[/color][color=Black], #[/color][color=Purple]bit2[/color][color=Black], #[/color][color=Purple]bit1[/color][color=Black],#[/color][color=Purple]bit0[/color][color=Black], [/color][color=Blue]cr[/color][color=Black], [/color][color=Blue]lf ) 
return

call [/color][color=Black]display
switch_on[/color][color=Blue]([/color][color=Black]redlight[/color][color=Blue])
call [/color][color=Black]display
switch_on[/color][color=Blue]([/color][color=Black]greenlight[/color][color=Blue])
call [/color][color=Black]display
switch_on[/color][color=Blue]([/color][color=Black]bluelight[/color][color=Blue])
call [/color][color=Black]display
switch_off[/color][color=Blue]([/color][color=Black]redlight[/color][color=Blue])
call [/color][color=Black]display
switch_off[/color][color=Blue]([/color][color=Black]greenlight[/color][color=Blue])
call [/color][color=Black]display
switch_off[/color][color=Blue]([/color][color=Black]bluelight[/color][color=Blue])
call [/color][color=Black]display[/color]
 

westaust55

Moderator
The PICAXE defined macro concept is in line with the use of macros in other programming languages and even within applications such as MS Excel.

That is, a block of text/code is created and inserted at each point where the macro name (i.e. a single program statement) is used, with the aim of making the writing of the program less tedious and less error-prone.
 

PieM

Senior Member
I didn't realise just how memory-hungry macros could be.
Out of interest, the spectacularly more compact version of the program with the one subroutine substituted for the macro is below.
And you did'nt realise how time-hungry gosub/return could be ?
 

Technical

Technical Support
Staff member
Gosh, and what a difference there is! I didn't realise just how memory-hungry macros could be.
It's just using them correctly - do you want speed or code compactness? You could still have used

Code:
switch_on(bluelight)
display
switch_on(redlight)
display
with an efficient version of display macro as follows.
Think of macro as a cut'n'paste of the code within it.

Code:
#macro display
gosub display1
#endmacro

[COLOR=Black]display1:
      [/COLOR][COLOR=Blue]sertxd( [/COLOR][COLOR=Red]"lightcolour="[/COLOR][COLOR=Black], [/COLOR][COLOR=Purple]dcolour[/COLOR][COLOR=Black], [/COLOR][COLOR=Blue]cr[/COLOR][COLOR=Black], [/COLOR][COLOR=Blue]lf ) 
      sertxd( [/COLOR][COLOR=Red]"controls="[/COLOR][COLOR=Black], #[/COLOR][COLOR=Purple]bit7[/COLOR][COLOR=Black],#[/COLOR][COLOR=Purple]bit6[/COLOR][COLOR=Black],#[/COLOR][COLOR=Purple]bit5[/COLOR][COLOR=Black],#[/COLOR][COLOR=Purple]bit4[/COLOR][COLOR=Black], #[/COLOR][COLOR=Purple]bit3[/COLOR][COLOR=Black], #[/COLOR][COLOR=Purple]bit2[/COLOR][COLOR=Black], #[/COLOR][COLOR=Purple]bit1[/COLOR][COLOR=Black],#[/COLOR][COLOR=Purple]bit0[/COLOR][COLOR=Black], [/COLOR][COLOR=Blue]cr[/COLOR][COLOR=Black], [/COLOR][COLOR=Blue]lf ) 
return[/COLOR]
 

Circuit

Senior Member
It's just using them correctly - do you want speed or code compactness?
Well, if we are going down that route, I guess one could simply use a one-liner;
Code:
[color=Navy]#define [/color][color=Black]display [/color][color=Blue]call [/color][color=Black]display1 [/color]
Speed of macros vs. subroutines? Makes perfect sense, of course. Speed is not an issue for me so this aspect had not really entered my mind.
This thread is now providing quite a lot of information that is not (=I have not been able to find) documented elsewhere in relation to PICAXE, although Westy's references to such things as macros in Excel do now ring bells.

Therefore, in answer to Tex's question;
Do multi-included macro lines have an advantage, or is this just another programming style?

Or do macros just take advantage of another feature in PICAXE Basic?
The answer would be primarily speed of execution combined with an easy-to-read programming style that does not have to display large blocks of repetitive code.

@TECHNICAL - thank you for the explanations - I hope that I am now correctly on message with the concept.

p.s. Any chance of a PICAXE based upon a Microchip PIC32MX170F256B-50I/SP - my dream PICAXE! Program size and speed issues disappearing into the ether... but I do realise what is involved in adding a 32 bit toy into the toy-box!
 

hippy

Technical Support
Staff member
The answer would be primarily speed of execution combined with an easy-to-read programming style that does not have to display large blocks of repetitive code.
It is perhaps best to think of macros as for saving typing and making things more readable. You get all the code and memory used as if you had typed it out long hand but it can be made to appear much more succinct in the body of the user program. For example, these are the same ...

Code:
SerOut LCD_PIN, N2400, ( 254, $80, "Hello" )
Pause 1000
SerOut LCD_PIN, N2400, ( 254, $80, "World" )
Code:
#Macro LcdOut( text )
  SerOut LCD_PIN, N2400, ( 254, $80, text )
#EndMacro

LcdOut( "Hello" )
Pause 1000
LcdOut( "World" )
p.s. Any chance of a PICAXE based upon a Microchip PIC32MX170F256B-50I/SP - my dream PICAXE! Program size and speed issues disappearing into the ether... but I do realise what is involved in adding a 32 bit toy into the toy-box!
Everything is possible and Rev-Ed do keep track of what is available and consider what may be useful to end users. The 32-bit Microchip architecture is considerably different to previous devices so there would probably be reasonable amount of work to be done if one were to be adopted as PICAXE chip. It would ultimately be a business decision as to whether any particular chip adds value, fills a need, and would make that development work worthwhile.
 

techElder

Well-known member
I see an advantage to using #macro in passing parameters to a subroutine. Takes some of the memory (my memory!) requirements out of the picture! :)
 

johndk

Senior Member
Interesting discussion!

If I follow the thread correctly, it comes down to the compromise between speed and storage. Depending on which you need/have, one will either use a macro (speed) or a sub (footprint). And in some cases, perhaps a combination. I'll keep that in mind for my next coding project.
 

Circuit

Senior Member
I see an advantage to using #macro in passing parameters to a subroutine. Takes some of the memory (my memory!) requirements out of the picture! :)
As I explore macros more and more I can see another major use for them along the same lines; to pass parameters into routines that are derived from #INCLUDE programs.
 

BillyGreen1973

Senior Member
sorry to drag up an old post, but the #macro directive doesn't seem to work in PE 6.0.8.2

The code Hippy posted above..

Code:
#Macro LcdOut( text )
  SerOut B.7, N2400, ( 254, 128, text )
#EndMacro

LcdOut( "Hello" )
Pause 1000
LcdOut( "World" )
wont pass syntax check. It fails at the #macro directive, or am I doing something wrong?
 
Last edited:

hippy

Technical Support
Staff member
Works for me. Check File -> Options -> Compiler -> BASIC Pre-Processor -> Use pre-processor is ticked.

If it is already ticked; what's the exact error message you are getting, which PICAXE type is selected ?
 

BillyGreen1973

Senior Member
Hi Hippy,

well that's strange. just tried it again and it works now. oh well. thanks for the quick reply though.

Maybe it was due to restarting PE6 this morning after installing the new version yesterday.
 
Top