Maths on #macro parameters

oracacle

Senior Member
#1
I am working with some APA102 LEDs. One of the variable functions is the brightness.
To get the correct set of bit to send to the LEDs a number between 0 and 31 is or with %11100000

Code:
alter_bright = brightness | %11100000
it did dawn on me that instead of having this before calling the send macro, I could add this to the macro itself
is there any known reason why this wont work, it compiles but I can't test until a few days time and I am wondering if anyone can shed any light on it

Code:
[color=Navy]#macro [/color][color=Black]sendPacket[/color][color=Blue]( [/color][color=Black]n1, n2, n3, n4 [/color][color=Blue])
      [/color][color=Purple]sendbyte [/color][color=DarkCyan]= [/color][color=Black]n1 | [/color][color=Navy]%11100000 [/color][color=Black]: [/color][color=Blue]gosub [/color][color=Black]send_byte
      [/color][color=Purple]sendbyte [/color][color=DarkCyan]= [/color][color=Black]n2 : [/color][color=Blue]gosub [/color][color=Black]send_byte
      [/color][color=Purple]sendbyte [/color][color=DarkCyan]= [/color][color=Black]n3 : [/color][color=Blue]gosub [/color][color=Black]send_byte
      [/color][color=Purple]sendbyte [/color][color=DarkCyan]= [/color][color=Black]n4 : [/color][color=Blue]gosub [/color][color=Black]send_byte[/color]
[color=Navy]#endmacro[/color]
I did try:
Code:
[color=Navy]#macro [/color][color=Black]sendPacket[/color][color=Blue]( [/color][color=Black]n1, n2, n3, n4 [/color][color=Blue])
      [/color][color=Black]n1 [/color][color=DarkCyan]= [/color][color=Black]n1 | [/color][color=Navy]%11100000
      [/color][color=Purple]sendbyte [/color][color=DarkCyan]= [/color][color=Black]n1 : [/color][color=Blue]gosub [/color][color=Black]send_byte
      [/color][color=Purple]sendbyte [/color][color=DarkCyan]= [/color][color=Black]n2 : [/color][color=Blue]gosub [/color][color=Black]send_byte
      [/color][color=Purple]sendbyte [/color][color=DarkCyan]= [/color][color=Black]n3 : [/color][color=Blue]gosub [/color][color=Black]send_byte
      [/color][color=Purple]sendbyte [/color][color=DarkCyan]= [/color][color=Black]n4 : [/color][color=Blue]gosub [/color][color=Black]send_byte[/color]
[color=Navy]#endmacro[/color]
and get a syntax error despite being basically the same

Also is it possible to pass number out as well? so if I pass BXX into n1, add or subtract one, then pass it back out to BXX. BXX is going to be at least 3 different variables, maybe 4
 

PieM

Senior Member
#3
Hi,
n1 is not a variable!
This code work :
Code:
[COLOR=Blue]symbol [/COLOR][COLOR=Purple]sendbyte [/COLOR][COLOR=DarkCyan]= [/COLOR][COLOR=Purple]b10[/COLOR]
[COLOR=Navy]#macro [/COLOR][COLOR=Black]sendPacket[/COLOR][COLOR=Blue]( [/COLOR][COLOR=Black]n1,n2,n3,n4 [/COLOR][COLOR=Blue])

     [/COLOR][COLOR=Purple]sendbyte [/COLOR][COLOR=DarkCyan]= [/COLOR][COLOR=Black]n1 | [/COLOR][COLOR=Navy]%11100000 [/COLOR][COLOR=Black]: [/COLOR][COLOR=Blue]gosub [/COLOR][COLOR=Black]send_byte
     [/COLOR][COLOR=Purple]sendbyte [/COLOR][COLOR=DarkCyan]= [/COLOR][COLOR=Black]n2 : [/COLOR][COLOR=Blue]gosub [/COLOR][COLOR=Black]send_byte
     [/COLOR][COLOR=Purple]sendbyte [/COLOR][COLOR=DarkCyan]= [/COLOR][COLOR=Black]n3 : [/COLOR][COLOR=Blue]gosub [/COLOR][COLOR=Black]send_byte
     [/COLOR][COLOR=Purple]sendbyte [/COLOR][COLOR=DarkCyan]= [/COLOR][COLOR=Black]n4 : [/COLOR][COLOR=Blue]gosub [/COLOR][COLOR=Black]send_byte[/COLOR]
[COLOR=Navy]#endmacro[/COLOR]

[COLOR=Black]main:
sendPacket[/COLOR][COLOR=Blue]( [/COLOR][COLOR=Navy]2[/COLOR][COLOR=Black],[/COLOR][COLOR=Navy]3[/COLOR][COLOR=Black],[/COLOR][COLOR=Navy]4[/COLOR][COLOR=Black],[/COLOR][COLOR=Navy]5[/COLOR][COLOR=Blue])
end[/COLOR]

[COLOR=Black]send_byte:[/COLOR]
[COLOR=Purple]@bptrinc [/COLOR][COLOR=DarkCyan]= [/COLOR][COLOR=Purple]sendbyte[/COLOR]
[COLOR=Blue]return[/COLOR]
You get
b0 = 226 ( 2 | %11100000)
b1 = 3
b2 = 4
b3 = 5
 

hippy

Technical Support
Staff member
#5
As PieM notes; "n1 is not a variable!". A simpler example is ...

Code:
#Macro Send(n1)
  sendByte = n1 : Gosub Do_Send
#endMacro
Send(b1)
Send(1)
Remembering that parameter names in the #MACRO are simply replaced by the parameter specified when the macro is invoked; that generates ...

Code:
  sendByte = b1 : Gosub Do_Send
  sendByte = 1  : Gosub Do_Send
All fine and dandy. Now we want to Or with %11100000 ...

Code:
#Macro Send(n1)
  sendByte = n1 | %11100000 : Gosub Do_Send
#endMacro
Send(b1)
Send(1)
That generates ...

Code:
  sendByte = b1 | %11100000 : Gosub Do_Send
  sendByte = 1  | %11100000 : Gosub Do_Send
Again, all fine and dandy. But if we try ...

Code:
#Macro Send(n1)
  n1 = n1 | %1110000 : sendByte = n1 : Gosub Do_Send
#endMacro
Send(b1)
Send(1)
That generates ...

Code:
  b1 = b1 | %11100000 : sendByte = b1 : Gosub Do_Send
  1  = 1  | %11100000 : sendByte = 1  : Gosub Do_Send
The first with a variable works but with a constant "1 = 1 | %11100000" is meaningless, hence a syntax error.
 

oracacle

Senior Member
#6
OK
could instead use something like
Code:
temp_byte = n1                  ;load n1 in variable
sendbyte = temp_byte | %11100000 : gosub do_send    ;now send the corrected information
I suppose N1 could actually be ignored completely. That value isn't updated very often, the information is kept in a variable with the code itself any way meaning that the temp_byte = n1 could be dropped
Code:
#macro sendPacket( n1, n2, n3, n4 )
      sendbyte = BXX | %11100000 : gosub send_byte
      sendbyte = n2 : gosub send_byte
      sendbyte = n3 : gosub send_byte
      sendbyte = n4 : gosub send_byte
#endmacro
where BXX is the working variable

I do find it a little surprising that that trying to is a parameter as a variable doesn't get flagged during a syntax check.
 

hippy

Technical Support
Staff member
#7
I do find it a little surprising that that trying to is a parameter as a variable doesn't get flagged during a syntax check.
If the way you are doing things is entirely acceptable to the compiler there will be no syntax error.

It is not clear exactly what you are trying to achieve overall. Yes, you can do as your second example ...

Code:
#macro sendPacket( n1, n2, n3, n4 )
      sendbyte = BXX | %11100000 : gosub send_byte
      sendbyte = n2 : gosub send_byte
      sendbyte = n3 : gosub send_byte
      sendbyte = n4 : gosub send_byte
#endmacro
Making BXX a global variable, but it would make sense to remove the 'n1' parameter and update the 'SendPacket' invocations ...

Code:
#macro sendPacket( n2, n3, n4 )
      sendbyte = BXX | %11100000 : gosub send_byte
      sendbyte = n2 : gosub send_byte
      sendbyte = n3 : gosub send_byte
      sendbyte = n4 : gosub send_byte
#endmacro

SendPacket( x, y, z )
Or you could keep things as they are and simply update the 'SendPacket' invocations to have BXX as the first parameter ...

Code:
#macro sendPacket( n1, n2, n3, n4 )
      sendbyte = n1 | %11100000 : gosub send_byte
      sendbyte = n2 : gosub send_byte
      sendbyte = n3 : gosub send_byte
      sendbyte = n4 : gosub send_byte
#endmacro

SendPacket( BXX, x, y, z )
Both are entirely valid and the choice is down to your own preference. Both will generate exactly the same code.

You could even do this ...

Code:
#macro sendPacket( n1, n2, n3, n4 )
      sendbyte = n1 : gosub send_byte
      sendbyte = n2 : gosub send_byte
      sendbyte = n3 : gosub send_byte
      sendbyte = n4 : gosub send_byte
#endmacro

SendPacket( BXX | %11100000, x, y, z )
I would favour keeping things as they originally were, putting BXX as the first parameter, because then BXX can always be kept with its top bits set and that only needs to be altered when it's changed. That will use less memory than having an Or operation in every macro expansion.

The fundamental things to remember are that macros are not subroutines, are not a means of creating local or temporary variables, are simply a text substitution when the compiler encounters them.

In PE6, under the File -> Options menu, on the Diagnostics page, there's a "Display pre-processor output" option which might be worth enabling temporarily so you can see what the results of macro expansion are. That may help make things clearer.
 
Top