PDA

View Full Version : A question for the Macro experts....



forgie
- 28th August 2005, 20:50
Hi there.
On my current project I am sending data out to my PC by using HSEROUT. I am sending data from a 12-bit ADC, so to transmit it I use:
<code>
HSEROUT [Data / 100, Data // 100]
</code>

I use this method so that I can reserve numbers above 100 for communication messages. I'm wondering if it is possible to write a macro that does the above that I could use like this:
<code>
@ TRANSMIT _Data
</code>

Any tips from the masters would be much appreciated. (I have written a few simple macros, some fully asm, some a mix of asm and PBP, but I could never work out how to use an argument with a macro and then use that argument with a PBP command inside the macro)

Darrel Taylor
- 28th August 2005, 21:15
Hi forgie,

Give this a try...
Data VAR WORD
Temp VAR WORD

@TRANSMIT macro Variable
@ MOVE?WW Variable, _Temp
HSEROUT [Temp / 100, Temp // 100]
@ endm

@ TRANSMIT _Data

Darrel Taylor
- 28th August 2005, 21:26
OR, this one will use less Code Space on each use of the TRANSMIT macro.
Data VAR WORD
Temp VAR WORD

TX_Code:
HSEROUT [Temp / 100, Temp // 100]
RETURN

ASM
TRANSMIT macro Variable
MOVE?WW Variable, _Temp
L?CALL _TX_Code
endm
ENDASM

@ TRANSMIT _Data

mister_e
- 28th August 2005, 21:49
Sorry, i'm not an expert but you could try something like


DEFINE OSC 20

DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_SPBRG 129 ' 9600 Bauds

wData var word SYSTEM
ADCData var word SYSTEM
xyzData var word SYSTEM

GOTO START

ASM
TRANSMIT macro ToSend
MOVE?WW ToSend, wData
L?CALL UTransmit
endm

UTransmit
endasm
HSEROUT [wdata / 100, wdata // 100]
return

START:
adcdata=1024
@ TRANSMIT ADCData
xyzdata = 500
@ TRANSMIT xyzData

PAUSE 500
GOTO START

mister_e
- 28th August 2005, 21:51
OUPS!!! didn't see ya Darrel... Sorry.

mm it looks quite the same BTW... i still learn

Darrel Taylor
- 28th August 2005, 22:05
No Problem,

That's what happens when both our brains are grinding at the same time.

It also gives forgie some confirmation that they will probably work, since 2 people came up with almost the same thing independantly.

:) :) :)
<br>

mister_e
- 28th August 2005, 22:13
Hehe, i agree.

Just a question. Is there any possible problem by using


wData var word SYSTEM

against


wData var word

Darrel Taylor
- 29th August 2005, 01:04
Well, can't say for sure, but I've never had any problems with SYSTEM.

PBP tries to protect against duplicate variable names by adding an underscore "_" in front of everything that's specified by the user.

The only thing that "SYSTEM" does, is prevent that underscore from being added.

It could cause a Naming Conflict with other things being used at the ASM level, but when that happens, the compiler will let you know.

It does make things look nicer without all those _'s. &nbsp;&nbsp;But then, those _'s can make it easier to differentiate between what's PBP and what's ASM variables, when it's debugging time.

It's hard to say which way is better.
<br>

forgie
- 29th August 2005, 10:19
Thanks guys, that's exactly what I needed, and it works great. Now to make things more tricky..... the data I'm sending out is in an array, and I normally use this macro inside a for loop that's cycling through the array.

The old code:
<code>
For Sample = 0 to (N_SAMPLES - 1)
Hserout [Sample_Array[Sample] / 100, Sample_Array[Sample] // 100]
Next
</code>


For obvious reasons, I can't just write:
<code>
@ Transmit _Sample_Array[_Sample]
</code>

I will rewrite the macro to so that the argument is the Index of the Sample_Array array, so the macro will be dedicated to using that one array, like such:
<code>
@ Transmit _Sample
</code>

I'll post my macro when I've finished writing it, but just for discussions sake, is there some easy way to call a member of an array using a macro? I could use something like:
<code>
Addr = Sample_Array + (2 * Sample)
@ Transmit _Addr
</code>
To do the same thing, right? This doesn't help much since my aim is to improve readability here.

I guess I could use a macro that takes a word array and an index as arguments:
<code>
@ TX_Array _Sample_Array, _Sample
</code>

Hmmm. I seem to be answering my own questions by writing it down. Macros now seem much more useful. How would I write the above macro, but have it be able to take Word and Byte arrays? In other words, how do you use If statements in macros?

Thanks guys,
forgie

forgie
- 29th August 2005, 10:20
Oh and, how do you post code like you guys do? I have been using < code>.... whats the tag to put it in a nice little grey box?

Luciano
- 29th August 2005, 10:52
BBCode:

http://www.phpbb.com/phpBB/faq.php?mode=bbcode

Luciano

forgie
- 29th August 2005, 11:00
Thanks, Luciano
My macro now looks like thus:


TXArray var Sample_Array
TXIndex var word SYSTEM
TXData var word SYSTEM
@TX_Sample macro index
@ MOVE?WW index, TXIndex
TXData = TXArray[TXIndex]
Hserout [TXData / 100, TXData // 100]
@ endm


(Sample_Array is a word array that I'm using to store my data in).

This works great, and I can call it like this:


@ TX_Sample _Sample


Thanks for the pointers, fellow PBPers. The only thing I couldn't do was get it to take both the array and the index as arguments.... I have to nut out the whole memory addressing thing in my head before I can get it to work.

mister_e
- 29th August 2005, 14:29
Good job guy. i just want to remind you something. Every time a macro is called, that duplicate his whole code. so, by using the following


asm
TX_Sample macro index
MOVE?WW index, TXIndex
L?CALL TXnow
endm
TXnow
ENDASM
TXData = TXArray[TXIndex]
Hserout [TXData / 100, TXData // 100]
RETURN

this will generate less code everytime you call the macro.

Here's another method to send a specific index of Word array var.


DEFINE LOADER_USED 1
DEFINE OSC 20
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_SPBRG 129 ' 9600 Bauds

TXData var WORD SYSTEM
aVar var word[4] SYSTEM

avar[0]=0
avar[1]=100
avar[2]=1000
avar[3]=10000
goto start

asm
Usend macro index
MOVE?WW aVar + (index*2) , TXData
L?CALL TXnow
endm
TXnow
ENDASM
Hserout [dec TXData,13,10]
RETURN
start:
@ Usend 0
@ Usend 1
@ Usend 2
@ Usend 3
pause 500
goto start

there's probably tons of way like using AOUT?xxx macro too.. well still unsure of that one AOUT?xxx

Darrel Taylor
- 29th August 2005, 18:54
Macro's can be usefull. &nbsp;But, they're not always the best choice.
TRANSMIT:
Temp = Sample_Array(Index)
HSEROUT [Temp / 100, Temp // 100]
RETURN

Index = 2 : GOSUB TRANSMIT

<br>

forgie
- 30th August 2005, 06:57
Yes, I was aware of that after reading one of your earlier posts. I am sitting slightly under 50% of my available code space (on an 18f452), and on top of that the data sending routines are used in a part of the code where speed is preferable (but not critical). To use the fastest method I would have to find out what macros HSEROUT calls, and call them directly somehow.... and the smallest code version would be something along the same lines using gosubs. Anyway if the timing becomes more important or code space is an issue then I will rewrite the macro. But for the meantime, I have improved readability by a large degree. Thanks for the ideas/wisdom guys, it's great to know that there's such a concentrated pool of knowledge in this forum to ask when I have a tough PBP question.....

forgie
- 30th August 2005, 06:59
Also.... the macro method makes me feel like my code is more 'modular,' and more like a functional language, which makes me feel warm inside :)

mister_e
- 30th August 2005, 16:43
If you want to shrink your code, the best way is to see if you can use the internal ressource instead of the PBP pre-made function.

By example, instead of using ADCIN, write/read directly to the register, same for HSEROUT, HSERIN and how much others.

For a simple HSEROUT



DEFINE LOADER_USED 1
DEFINE OSC 20
RCSTA =$90
TXSTA =$24
SPBRG= 129 ' 9600 Bauds

aVar var BYTE[7]
a var byte

avar[0]="H"
avar[1]="E"
avar[2]="L"
avar[3]="L"
avar[4]="O"
AVAR[5]=13
AVAR[6]=10
A=0
start:
REPEAT
TXREG=AVAR[A]
NotEmpty: if TXSTA.1=0 then notempty
A=A+1
UNTIL A=7
A=0
PAUSE 500
goto start

compile 89 words




DEFINE LOADER_USED 1
DEFINE OSC 20
RCSTA =$90
TXSTA =$24
SPBRG= 129 ' 9600 Bauds

aVar var BYTE[7]

avar[0]="H"
avar[1]="E"
avar[2]="L"
avar[3]="L"
avar[4]="O"
AVAR[5]=13
AVAR[6]=10

start:
HSEROUT[STR AVAR]
PAUSE 500
goto start

compile 103 words.




DEFINE LOADER_USED 1
DEFINE OSC 20
DEFINE HSER_RCSTA 90h
DEFINE HSER_TXSTA 24h
DEFINE HSER_SPBRG 129 ' 9600 Bauds

aVar var BYTE[7]

avar[0]="H"
avar[1]="E"
avar[2]="L"
avar[3]="L"
avar[4]="O"
AVAR[5]=13
AVAR[6]=10

start:
HSEROUT[STR AVAR]
PAUSE 500
goto start

almost the same as the previous but using PBP DEFINE HSER compile 95 words

No big improvement so far... i should find a better example next time :)

BTW it's always case by case. Scroll your program and look wich statement you call the most, do a SUB with them and TADA. Just be sure to avoid too much nested gosub and it should gives you good results.

BUT there's always a midpoint between a readable code, and a tight one. Choose your own comfort zone and work with.