Moving Ram To Ram

techElder

Well-known member
Is there a better way to move bytes in ram to other places in ram? I would like to do it without using any named variables, but that seems impossible.

Code:
[color=Blue]symbol [/color][color=Purple]i [/color][color=DarkCyan]= [/color][color=Purple]b10[/color]
[color=Blue]symbol [/color][color=Purple]ii [/color][color=DarkCyan]= [/color][color=Purple]b11[/color]
[color=Blue]symbol [/color][color=Black]Bhigh [/color][color=DarkCyan]= [/color][color=Navy]$F8[/color]
[color=Blue]symbol [/color][color=Black]Blow [/color][color=DarkCyan]= [/color][color=Navy]$38

#macro [/color][color=Black]bufRamBytes[/color][color=Blue]([/color][color=Black]Bhigh,Blow,[/color][color=Purple]i[/color][color=Blue])
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Black]Bhigh            [/color][color=Green]; from ram
   [/color][color=Purple]i [/color][color=DarkCyan]= [/color][color=Black]Blow [/color][color=DarkCyan]+ [/color][color=Purple]i [/color][color=DarkCyan]- [/color][color=Navy]1        [/color][color=Green]; number of bytes (indexed to zero)
   [/color][color=Blue]for [/color][color=Purple]ii [/color][color=DarkCyan]= [/color][color=Black]Blow [/color][color=Blue]to [/color][color=Purple]i      [/color][color=Green]; to ram
      [/color][color=Blue]poke [/color][color=Purple]ii[/color][color=Black], [/color][color=Purple]@bptrinc
   [/color][color=Blue]next [/color][color=Purple]ii[/color]
[color=Navy]#endm[/color]

[color=Purple]i [/color][color=DarkCyan]= [/color][color=Navy]8[/color]
[color=Blue]poke [/color][color=Black]Blow, [/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color]
[color=Blue]poke [/color][color=Black]Bhigh, [/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color]

[color=Black]bufRamBytes[/color][color=Blue]([/color][color=Black]Bhigh,Blow,[/color][color=Purple]i[/color][color=Blue])

end[/color]
 

Goeytex

Senior Member
Maybe .....

#Picaxe 28X2

Symbol NewMemoryLocation = B0

Poke 96, 255,254,253,252,251,250,249,248 '// write 8 bytes data to memory locations 96-103

'// Copy data from locations 90-103 to locations 112 - 249

BPTR = 96
For NewMemoryLocation = 112 to 120
Poke NewMemoryLocation, @BPTRINC
Next
 

lbenson

Senior Member
Untested, and assuming ptr on x2, but
Code:
#macro bufRamBytes(Bhigh,Blow,Bend)
  ptr = Bhigh
  for bptr = Blow to Bend
    poke ptr, @btpr
    inc ptr
  next bptr
Oops, lunch calls--can't check out.
 

AllyCat

Senior Member
Hi,

AFAIK you may need one (named) variable, but perhaps you can cheat by using (e.g.) ptr in an X2 like this? :

Code:
bptr = DESTINATION
for ptr = START to END
PEEK ptr , @bptrinc
next
Don't forget there are at least 6 extra variables like s_w1 in an M2. ;)

Cheers, Alan.
 

stan74

Senior Member
I doubt this works with picaxe even though it compiles. I've only used scratch pad memory. I'll look up @bptr
Code:
[color=Purple]b0[/color][color=DarkCyan]=[/color][color=Navy]20[/color][color=Green];number of bytes[/color]
[color=Purple]w1[/color][color=DarkCyan]=[/color][color=Navy]$F8[/color][color=Green];start[/color]
[color=Purple]w2[/color][color=DarkCyan]=[/color][color=Navy]$38[/color][color=Green];destination[/color]
[color=Blue]do
      peek [/color][color=Purple]b1[/color][color=Black],[/color][color=Purple]w1
      [/color][color=Blue]poke [/color][color=Purple]w2[/color][color=Black],[/color][color=Purple]b1
      [/color][color=Blue]inc [/color][color=Purple]w1[/color][color=Black]:[/color][color=Blue]inc [/color][color=Purple]w2[/color][color=Black]:[/color][color=Blue]dec [/color][color=Purple]b0[/color]
[color=Blue]loop until [/color][color=Purple]b0[/color][color=DarkCyan]=[/color][color=Navy]0[/color]
[color=Blue]end[/color]
 

stan74

Senior Member
1st prize a weekend in disney land.
2nd prize 2 weeks in disney land.
The z80 did ld hl,start:ld de,destination:ld bc,number of bytes:ldir. That would move a screen buffer to screen ram fast. The stack pointer and pop worked fast as well. do pics have a stack pointer or program counter?
 

Goeytex

Senior Member
No competition. Just sometimes more than one way to skin a cat. Using PTR is "clever" and it works. But sometimes cleverness can get you in trouble. I think a single working variable may be a better idea as the Macro code will be portable across M2/X2 and there is no chance of messing up the scratchpad memory if it should be used.

This works ok in the simulator.

Code:
[color=Navy]#Picaxe [/color][color=Black]28X2[/color]

[color=Blue]Poke [/color][color=Navy]96[/color][color=Black], [/color][color=Navy]255[/color][color=Black],[/color][color=Navy]254[/color][color=Black],[/color][color=Navy]253[/color][color=Black],[/color][color=Navy]252[/color][color=Black],[/color][color=Navy]253[/color][color=Black],[/color][color=Navy]252[/color][color=Black],[/color][color=Navy]250[/color][color=Black],[/color][color=Navy]249   [/color][color=Green]'// write 8 bytes data to memory locations 96-103[/color]

[color=Navy]#macro [/color][color=Black]CopyRam[/color][color=Blue]( [/color][color=Black]StartLoc, EndLoc, ToLoc [/color][color=Blue]) 
    [/color][color=Purple]BPTR [/color][color=DarkCyan]= [/color][color=Black]ToLoc
    [/color][color=Blue]For [/color][color=Purple]B0 [/color][color=DarkCyan]= [/color][color=Black]StartLoc [/color][color=Blue]to [/color][color=Black]EndLoc
      [/color][color=Blue]Peek [/color][color=Purple]B0[/color][color=Black], [/color][color=Purple]@BPTRINC
    [/color][color=Blue]next[/color]
[color=Navy]#endmacro[/color]

[color=Black]CopyRam[/color][color=Blue]( [/color][color=Navy]96[/color][color=Black], [/color][color=Navy]103[/color][color=Black], [/color][color=Navy]120 [/color][color=Blue])


Do
      
Loop[/color]
 

Goeytex

Senior Member
do pics have a stack pointer or program counter?
Yes, but not generally accessible with Picaxe Chips. See the related PIC datasheet and Look in the section "Memory Organization"
 

Goeytex

Senior Member
All you Texas guys are in cahoots and downright geniuses in my book.
No genius here. I struggle with this stuff at times, but seldom give up till it's figured out. I have also been spending quite a bit of time in the last couple of years, writing drivers, libraries, functions, bootloaders, etc for another BASIC compiler. This has forced me to develop some new programming skills.
 

stan74

Senior Member
"All you Texas guys are in cahoots and downright geniuses in my book." I think it's called a posse.
"Yes, but not generally accessible with Picaxe Chips. See the related PIC datasheet and Look in the section "Memory Organization""
Easy bedtime reading. Nice if the program could change itself.Just 1 byte. eg change xor to or.That would save me using 2 identical speed optimised subs, difference being or/xor and an if then is not allowed as it's at the most used part of the code.
So many songs about Cal. and Texas guess my surname. https://www.youtube.com/watch?v=KAs4Og3x6is
 

lbenson

Senior Member
No competition. Just sometimes more than one way to skin a cat. Using PTR is "clever" and it works. But sometimes cleverness can get you in trouble. I think a single working variable may be a better idea as the Macro code will be portable across M2/X2 and there is no chance of messing up the scratchpad memory if it should be used.

This works ok in the simulator.

Code:
[color=Navy]#Picaxe [/color][color=Black]28X2[/color]

[color=Blue]Poke [/color][color=Navy]96[/color][color=Black], [/color][color=Navy]255[/color][color=Black],[/color][color=Navy]254[/color][color=Black],[/color][color=Navy]253[/color][color=Black],[/color][color=Navy]252[/color][color=Black],[/color][color=Navy]253[/color][color=Black],[/color][color=Navy]252[/color][color=Black],[/color][color=Navy]250[/color][color=Black],[/color][color=Navy]249   [/color][color=Green]'// write 8 bytes data to memory locations 96-103[/color]

[color=Navy]#macro [/color][color=Black]CopyRam[/color][color=Blue]( [/color][color=Black]StartLoc, EndLoc, ToLoc [/color][color=Blue]) 
    [/color][color=Purple]BPTR [/color][color=DarkCyan]= [/color][color=Black]ToLoc
    [/color][color=Blue]For [/color][color=Purple]B0 [/color][color=DarkCyan]= [/color][color=Black]StartLoc [/color][color=Blue]to [/color][color=Black]EndLoc
      [/color][color=Blue]Peek [/color][color=Purple]B0[/color][color=Black], [/color][color=Purple]@BPTRINC
    [/color][color=Blue]next[/color]
[color=Navy]#endmacro[/color]

[color=Black]CopyRam[/color][color=Blue]( [/color][color=Navy]96[/color][color=Black], [/color][color=Navy]103[/color][color=Black], [/color][color=Navy]120 [/color][color=Blue])


Do
      
Loop[/color]
The problem with using b0 is that bptr can exceed 255--up to 511 for 18M2+, 14M2, 20M2.

So for those M2 parts, perhaps use a system variable if you are working with addresses greater than 255, e.g., s_w1
Code:
#picaxe 20M2

symbol FromLoc=257
symbol EndLoc=272
symbol ToLoc = 480

for bptr = FromLoc to EndLoc
  @bptr = bptr            ' load some data; will be truncated to 1-16
next bptr

s_w1 = ToLoc
for bptr = FromLoc to EndLoc
  poke s_w1, @bptr    ' move it to high ram starting at byte 480
  inc s_w1
next bptr
poke s_w1,0 ' null terminate

bptr = ToLoc
do while @bptr <> 0
  sertxd(#@bptrinc," ") ' output the numbers
loop
sertxd(cr,lf)
move in upper ram.jpg
Output is "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16"
 

Goeytex

Senior Member
Nice if the program could change itself.Just 1 byte. eg change xor to or.That would save me using 2 identical speed optimised subs, difference being or/xor and an if then is not allowed as it's at the most used part of the code.
Most Midrange and above PIC Chips support Low Voltage Programming (LVP) which means they are capable of Self-Programming the Non-Volatile Ram (Flash Memory) where the program resides. So yes the program CAN change itself given the proper code and compiler.

However you would gain very little (if anything at all) and would probably rather quickly exceed the life cycle of the flash memory (100,000 writes). not to mention the cost in extra instruction cycles. It takes many fewer instruction cycles to do a conditional branch than to write to NVRAM, so I am rather baffled as to why you would want to do that. But this is all rather moot since it is irrelevant to Picaxe.
 

inglewoodpete

Senior Member
The title of this thread is "Moving RAM to RAM". How hard and fast are the RAM requirements for both source and destination? If you are using an X2 chip, you could consider using the scratchpad RAM for storage. Than use code like:
Code:
[color=Purple]ptr [/color][color=DarkCyan]= [/color][color=Navy]100[/color]
[color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Navy]56[/color]
[color=Blue]Do
   [/color][color=Purple]@bptrInc [/color][color=DarkCyan]= [/color][color=Purple]@ptrInc[/color]
[color=Blue]Loop Until [/color][color=Purple]ptr [/color][color=DarkCyan]= [/color][color=Navy]120    [/color][color=Green]'Move 20 bytes[/color]
 

techElder

Well-known member
"Ram to Ram" I'm exploring using an independent area in high ram where I will have buffers for serial I/O and several locations (both 1 and 2 byte) for "internal" variables. I want to impact the named variable area as little as possible. The buffers and "internal" variables will be accessed with constant pointers.

Of course, I always have a few "general purpose" variables that I use in every program, but I just wanted to minimize the impact on the program.

Using the scratchpad means limiting to X2. Using "ptr" variable has the same problem; limiting the parts that this will work on.

I like using "s_w1" in that it is available (for now) on current parts. (I don't like the unknown that RevEd has indicated about that system variable, but they've been indicating that for a long time.) The parts that use bPtr up to 511 seem to be 14M2 and 18M2, so that makes me lean to using "s_w1" also. The other parameters of the macro are constants so the 511 problem is ok there. (There could also be a limit placed on the location of this block of ram to keep the highest location within one byte. That is less than optimal, though.)

I like Goeytex's method of using bPtr on the destination / target location and using peek with @bPtrinc to effect the transfer. I think that is a minimal approach. What I don't like about it is having to specify the ending ram pointer. I don't find a way to avoid that, though (without adding another variable to calculate the end location).

I could never find a way (without adding another variable to calculate the end location) to code Stan's asm example in PICAXE Basic:

The z80 did ld hl,start:ld de,destination:ld bc,number of bytes:ldir.

LD hl start
LD de destination
LD bc numberOfBytes
LDIR
Code:
[color=Blue]symbol Bstart [/color][color=DarkCyan]= [/color][color=Navy]$F8[/color]
[color=Blue]symbol Bstop [/color][color=DarkCyan]= [/color][color=Blue]Bstart [/color][color=DarkCyan]+ [/color][color=Navy]7[/color]
[color=Blue]symbol Btarget [/color][color=DarkCyan]= [/color][color=Navy]$38

#macro [/color][color=Black]bufRam2byte[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Btarget) [/color][color=Green]' 12 bytes compiled
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]Bstart
   poke Btarget[/color][color=Black], [/color][color=Purple]@bptrinc[/color][color=Black], [/color][color=Purple]@bptr[/color]
[color=Navy]#endm

#macro [/color][color=Black]bufRam1byte[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Btarget) [/color][color=Green]' 9 bytes compiled
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]Bstart
   poke Btarget[/color][color=Black], [/color][color=Purple]@bptr[/color]
[color=Navy]#endm

#macro [/color][color=Black]bufRamBytes[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Bstop[/color][color=Black],[/color][color=Blue]Btarget) [/color][color=Green]' 17 bytes compiled
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]Btarget
   for [/color][color=Purple]s_w1 [/color][color=DarkCyan]= [/color][color=Blue]Bstart to Bstop
      peek [/color][color=Purple]s_w1[/color][color=Black], [/color][color=Purple]@bptrinc
   [/color][color=Blue]next [/color][color=Purple]s_w1[/color]
[color=Navy]#endm[/color]

[color=Blue]poke Btarget[/color][color=Black], [/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color]
[color=Blue]poke Bstart[/color][color=Black], [/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color]

[color=Black]bufRamBytes[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Bstop[/color][color=Black],[/color][color=Blue]Btarget)[/color]
 

lbenson

Senior Member
Nice

Lots of ways to skin this cat*.

*Note: no animals were harmed in the performance of this macro.
 

hippy

Technical Support
Staff member
I would probably use the 's_w' variables -

Code:
#Macro CopyRam( fromLoc, toLoc, length )
  bPtr = toLoc
  s_w1 = fromLoc + length - 1
  For s_w2 = fromLoc To s_w1
    Peek s_w2, @bPtrInc
  Next
#EndMacro

CopyRam( 0, 10, 5 )
CopyRam( 5, 15, 5 )
While the 's_w' variables are marked as "reserved for future use", so long as the functionality which would use those in future is not used the code should still work in future. Pragmatically it's either that or use named variables.

Using named variables which are used elsewhere in the program could be mitigated by saving the variable values before the copy code and restoring them after.

There probably is no single solution which would work for all PICAXE in all situations and tailoring will likely be necessary. There may be optimisations to be had if locations and length are always numeric constants or held in word variables.

It may even work out better to have separate code to do particular moves rather than try and create a generic, usable for all situations, solution.

One thing to note is that if the source and destination RAM areas being copied overlap - which they probably do not in the case we are discussing - care has to be taken in the order / direction of the bytes being copied to avoid overwriting and losing data which later needs to be copied.
 

stan74

Senior Member
Intrigued..no named variables
Code:
[color=Purple]ptr[/color][color=DarkCyan]=[/color][color=Navy]10[/color]
[color=Green];end = 20[/color]
[color=Blue]do
push [/color][color=Purple]@ptrinc[/color]
[color=Blue]loop until [/color][color=Purple]ptr[/color][color=DarkCyan]=[/color][color=Navy]20[/color]

[color=Blue]end[/color]
Pop them somewhere else??
 
Last edited:

stan74

Senior Member
Is this the difference between a macro and a gosub? Does the macro use less code and run faster?
#Macro CopyRam( fromLoc, toLoc, length )
bPtr = toLoc
s_w1 = fromLoc + length - 1
For s_w2 = fromLoc To s_w1
Peek s_w2, @bPtrInc
Next
#EndMacro

CopyRam( 0, 10, 5 )
CopyRam( 5, 15, 5 )
__________________
fromLoc=0: toLoc=10: length=5
Gosub CopyRam
CopyRam:
bPtr = toLoc
s_w1 = fromLoc + length - 1
For s_w2 = fromLoc To s_w1
Peek s_w2, @bPtrInc
Next
return
 

oracacle

Senior Member
I am intrigued by the no named variables. I normally hold b0 and b1 for software bit flags, then have at least 2 byte variables for temporary use. With that I normally try and use two in the same word variable so that the it can be used as a temporary word variable as well - so w1 would be temp_word_0 with b2 and b3 being temp_byte_0 and temp_byte_1 respectively.

Its also worth noting that variables can be named more than once - this can help keep track of where things are moving. there is also no reason you can't use a symbol to refer to a ptr location either. so while there are some very good solutions here already you can move something from a named variable to a ptr location, use the variable for counting/tracking address and then move the original data back afterwords.
 

BESQUEUT

Senior Member
Is this the difference between a macro and a gosub? Does the macro use less code and run faster?
Using a macro is exactly the same thing as writing code inline.
If you use a macro only one time, code size is exactly same.
Each time you use a macro, you add it code size to the total code size. So generaly macro use more code memory.
GOSUB is time consuming, macro not.
Passing arguments (fromLoc=0: toLoc=10: length=5) is also time consuming.
So within a loop, replacing a GOSUB by a macro may make your code running faster.

Also note that with the GOSUB version, you have to declare
fromLoc, toLoc and length
If you are "short memory" this can be another problem...

IHMO :
CopyRam( 0, 10, 5 )
is more readable than
fromLoc=0: toLoc=10: length=5: Gosub CopyRam
 
Last edited:

stan74

Senior Member
Using a macro is exactly the same thing as writing code inline.
If you use a macro only one time, code size is exactly same.
Each time you use a macro, you add it code size to the total code size. So macro use more code memory.
GOSUB is time consuming, macro not.
Passing arguments (fromLoc=0: toLoc=10: length=5) is also time consuming.
So within a loop, replacing a GOSUB by a macro may make your code running faster.

Also note that with the GOSUB version, you have to declare
fromLoc, toLoc and length
If you are "short memory" this can be another problem...
Got it finally! Wonder how many people know that. I'll use in-line code as and when and think gosubs are easier to read ie CopyRam( 5, 15, 5 ) doesn't say much about what it does 'till you look at the macro. Thanks BESQUEUT.
 

techElder

Well-known member
Stan, you must understand that a #Macro is just a way to define a group of basic statements to the preprocessor/compiler.

The defining of the #Macro doesn't do anything to a program in itself. It is just a way to tell the preprocessor/compiler what lines of code to add, where to place values and where to place the lines of code.

Substitution is the word of the day. The preprocessor/compiler substitutes the lines of code in the #Macro definition into the program where the #Macro name is placed. There is no sense of "calling" a macro in the way you would "call" a subroutine.

Here's a major difference. A #Macro can pass a literal string like "ABC" or "28X2" to the lines contained in the #Macro. Perhaps you wanted to send that string of characters via the serial port.

You can't do that anywhere else in PICAXE Basic. It's the only place that I know of where there is the concept of a string of characters. I use this feature with the LOOKUP function all the time.

Just remember substitution when you are trying to understand the #Macro.

PS. Also, don't forget that a #Macro has no impact on your program until you actually reference it there. So? Well, that implies that you can keep all of your #Macros in a #Include file to use in all of your programs. Sort of like a "library."

Just remember, no impact until you use it.
 
Last edited:

lbenson

Senior Member
A #Macro can pass a literal string like "ABC" or "28X2" to the lines contained in the #Macro.
That is a really useful insight. I hadn't realized that before. I have often wished that you could use something like POKE ADR, "Some Text" (and don't really know any reason why you shouldn't be able to, since you can POKE ADR,"S","o","m","e").

Can you provide an example of how you use this?
 

inglewoodpete

Senior Member
That is a really useful insight. I hadn't realized that before. I have often wished that you could use something like POKE ADR, "Some Text" (and don't really know any reason why you shouldn't be able to, since you can POKE ADR,"S","o","m","e").

Can you provide an example of how you use this?
Even when you use a macro, you ultimately need to use PICAXE Basic's byte or word variables to do the work. The following code can be run in the simulator:
Code:
[color=Navy]#macro [/color][color=Black]Poke2Buffer[/color][color=Blue]([/color][color=Black]sMsg[/color][color=Blue])[/color]
[color=Purple]b11 [/color][color=DarkCyan]= [/color][color=Navy]100         [/color][color=Green]'Start of RAM buffer[/color]
[color=Blue]For [/color][color=Purple]b10 [/color][color=DarkCyan]= [/color][color=Navy]0 [/color][color=Blue]To [/color][color=Navy]5
   [/color][color=Blue]LookUp [/color][color=Purple]b10[/color][color=Black], [/color][color=Blue]([/color][color=Black]sMsg[/color][color=Blue])[/color][color=Black], [/color][color=Purple]b12
   [/color][color=Blue]Poke [/color][color=Purple]b11[/color][color=Black], [/color][color=Purple]b12
   [/color][color=Blue]Inc [/color][color=Purple]b11[/color]
[color=Blue]Next [/color][color=Purple]b10[/color]
[color=Navy]#endmacro[/color]

[color=Black]TestCode:   Poke2Buffer[/color][color=Blue]([/color][color=Red]"abcdef"[/color][color=Blue])   [/color][color=Green]'Store a string using a macro
            '
            [/color][color=Blue]For [/color][color=Purple]b10 [/color][color=DarkCyan]= [/color][color=Navy]100 [/color][color=Blue]To [/color][color=Navy]105    [/color][color=Green]'Read it back without a macro.
               [/color][color=Blue]Peek [/color][color=Purple]b10[/color][color=Black], [/color][color=Purple]b11
               [/color][color=Blue]SerTxd([/color][color=Purple]b11[/color][color=Blue])
            Next [/color][color=Purple]b10
            [/color][color=Blue]SerTxd(CR[/color][color=Black], [/color][color=Blue]LF[/color][color=Black], [/color][color=Red]"Done"[/color][color=Blue])[/color]
 

techElder

Well-known member
There ya go. IWP has saved the day! The lookup command in IWP's code is exactly like what I use, and I'm sure it is "Thanks!" to Hippy somewhere along the line.

Where I use this "string manipulation" through a #Macro, is in transferring the static portion of a string of characters to a buffer that will ultimately be "transmitted" somewhere.
 

hippy

Technical Support
Staff member
A more generic string poking macro is below. This will cater for variable length strings -

Code:
#Macro PokeString( toLoc, string )
  bPtr = toLoc
  b0 = 0
  Do
    Lookup b0, ( string, 0 ), b1
    If b1 <> 0 Then
      @bPtrInc = b1
      b0 = b0 + 1
   End If
   Loop Until b1 = 0
#EndMacro

PokeString( 10, "Some" )
 

techElder

Well-known member
Ram to Ram UPDATE to #Macro routines

Here's a bit of an update to the original #Macro routines:

Code:
[color=Blue]symbol Bstart [/color][color=DarkCyan]= [/color][color=Navy]$F8[/color]
[color=Blue]symbol Bbytes [/color][color=DarkCyan]= [/color][color=Navy]8[/color]
[color=Blue]symbol Bstop [/color][color=DarkCyan]= [/color][color=Blue]Bstart [/color][color=DarkCyan]+ [/color][color=Navy]7[/color]
[color=Blue]symbol Btarget [/color][color=DarkCyan]= [/color][color=Navy]$38

#macro [/color][color=Black]bufRam2byte[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Btarget) [/color][color=Green]' 12 bytes compiled
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]Bstart
   poke Btarget[/color][color=Black], [/color][color=Purple]@bptrinc[/color][color=Black], [/color][color=Purple]@bptr[/color]
[color=Navy]#endm

#macro [/color][color=Black]bufRam1byte[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Btarget) [/color][color=Green]' 9 bytes compiled
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]Bstart
   poke Btarget[/color][color=Black], [/color][color=Purple]@bptr[/color]
[color=Navy]#endm

#macro [/color][color=Black]bufRamBytes[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Bstop[/color][color=Black],[/color][color=Blue]Btarget) [/color][color=Green]' 17 bytes compiled
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]Btarget
   for [/color][color=Purple]s_w1 [/color][color=DarkCyan]= [/color][color=Blue]Bstart to Bstop
      peek [/color][color=Purple]s_w1[/color][color=Black], [/color][color=Purple]@bptrinc
   [/color][color=Blue]next [/color][color=Purple]s_w1[/color]
[color=Navy]#endm

#macro [/color][color=Black]bufRamNumBytes[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Bbytes[/color][color=Black],[/color][color=Blue]Btarget) [/color][color=Green]' 24 bytes compiled
   ' M2 change s_w0 to s_w2 if multi-tasking
   ' X2 s_w2 conflicts with adcsetup2. Use s_w0.
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]Btarget
   [/color][color=Purple]s_w0 [/color][color=DarkCyan]= [/color][color=Blue]Bstart [/color][color=DarkCyan]+ [/color][color=Blue]Bbytes [/color][color=DarkCyan]- [/color][color=Navy]1
   [/color][color=Blue]for [/color][color=Purple]s_w1 [/color][color=DarkCyan]= [/color][color=Blue]Bstart to [/color][color=Purple]s_w0
      [/color][color=Blue]peek [/color][color=Purple]s_w1[/color][color=Black], [/color][color=Purple]@bptrinc
   [/color][color=Blue]next [/color][color=Purple]s_w1[/color]
[color=Navy]#endm

#macro [/color][color=Black]bufRamZterm[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Btarget) [/color][color=Green]' 24 bytes compiled
   ' moves the zero terminated string from start to target
   ' assumes a string of at least one byte zero terminated
   ' will wrap around looking for a zero termination!
   ' stops at "end of memory" location (your mileage may vary :D)
   ' M2 change s_w0 to s_w2 if multi-tasking
   ' X2 s_w2 conflicts with adcsetup2. Use s_w0.
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]Bstart
   [/color][color=Purple]s_w0 [/color][color=DarkCyan]= [/color][color=Blue]Btarget
   do
      poke [/color][color=Purple]s_w0[/color][color=Black], [/color][color=Purple]@bptrinc
      [/color][color=Blue]inc [/color][color=Purple]s_w0
   [/color][color=Blue]loop while [/color][color=Purple]@bptr [/color][color=DarkCyan]<> [/color][color=Navy]$00 [/color][color=DarkCyan]and [/color][color=Purple]s_w0 [/color][color=DarkCyan]< [/color][color=Navy]256 [/color][color=Green]' "end of memory"[/color]
[color=Navy]#endm[/color]

[color=Blue]poke Btarget[/color][color=Black], [/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]1[/color]
[color=Blue]poke Bstart[/color][color=Black], [/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$FF[/color][color=Black],[/color][color=Navy]$00[/color]

[color=Black]bufRamZterm[/color][color=Blue](Bstart[/color][color=Black],[/color][color=Blue]Btarget)[/color]
 

lbenson

Senior Member
LookUp b10, (sMsg), b12
Ah, so LOOKUP (in a loop) does the string handling magic.

Now I understand.

Where I use this "string manipulation" through a #Macro, is in transferring the static portion of a string of characters to a buffer that will ultimately be "transmitted" somewhere.
Exactly my intended use.

Thanks. Very useful.

Now to make the same function easier to use we just need the SERTXD_P and SERTXD_B commands to write formatted strings to scratchpad or ram respectively.
 
Top