Hi,
Am I right in thinking that once you've poked data into a RAM space then you can't do any maths on it until you peek it back out?
No, actually you can, but first you need to remember that PEEK and POKE basically just Read and Write individual
Bytes into the RAM (memory) space. To understand better, forget about Symbol names (for now) and work with the Basic Registers (Variables) and Numbers (Constants). So a Basic command is for example:
POKE 20 , b2 where the 20 is a "pointer" to memory location number 20. In this case, that's the same as
b20 = b2 (i.e. copy the value in b2 into b20), but the difference is that you can keep going past location 27 (b27) up to 127 (08M2), 255 (X2s) or 511 (M2s).
Then, you can extend the command by giving a "list" of variables (and/or constants when POKEing), for example
POKE 20 , b2 , b3 which copies b2 to location 20 and b3 to 21
(i.e. in this case, it's the same as w10 = w1) that is my preferred method of copying Words to (or from) the "Extended RAM" area. The WORD qualifier (e.g.
POKE 20 , WORD w1) is a convenient way to make the compiler do the same thing (i.e. transfer two bytes to/from the RAM) but there are several "hazards". Firstly it is often slower (and uses more bytes of program space), but also, if you "forget" the WORD qualifier, then the program will still compile and run, but only the Low byte is copied (i.e.
POKE 30 , w1 does exactly the same as
POKE 30 , b2 ). That's not a problem if w1 happens to contain a value below 256 (which is why it's not flagged as an "error"), but will give "bad" results if the value is larger.
Also, the S_Wx registers don't have access separately to their High byte; PE5 flags an error if you try to use them, but PE6 (at least its simulator) just "loses" the High byte even if WORD is included.
Next, the "pointer" can itself be a variable (register) so you can write e.g:.
FOR b1 = 10 to 27 : POKE b1 , 0 : NEXT which will clear (i.e. set to zero, or any other chosen value) all the bytes between 10 and 27; that's an example where you might POKE the normal registers area (being much more convenient than listing b10 = 0 : b11 = 0 , ............ , b27 = 0). Any variable can be used as a Pointer, but there is also a "special" one named
bptr , which is always the correct "size" for the PICaxe, i.e. it will wrap around (back to zero, which can be tested) when incrementing past 127 in an 08M2 or 511 in the other M2s.
Thus you can write
POKE bptr , 123 and
PEEK bptr , b1 etc., but once a value has been written into bptr, there is another variable called
@bptr , so that the two previous commands can be written as
@bptr = 123 and
b1 = @bptr . The advantage of this is that
@bptr can be included in more complex mathematical operations, for example
@bptr = @bptr * 2 will double the value of a byte stored anywhere in RAM, without the need to "read" or "write" (PEEK / POKE) it. But it's important to note that
@bptr is a specific variable name, you CANNOT attach the @ to any other variable.
There are also "automatic" INCrement and DECrement bptr operations (@bptrinc and @bptrdec) which can be very useful and efficient, but these are too complex for the present time.
Finally, a brief comment on the naming of Symbols, because it's important not to confuse Pointers, Variables and Constants
(nor of course Byte and Word variables in byte-oriented operations such as PEEK/POKE , READ/WRITE and SEROUT , etc.). Some programmers use for example a "p" prefix on the names, but I often declare Constants in Capital letters and Variables in lower-case (perhaps with an initial Capital letter). Thus I might Symbolise
DATE = 30 (i.e. a pointer to a location in extended memory) and
Day = b2 : Month = b3 : Year = b4 . Then in a program, I could write
POKE DATE , 10 , 11 , 20 and later read the values back with
PEEK DATE , Day , Month , Year (or vice versa). But beware that the Program Editor is not case-sensitive, so
DAY and
day mean exactly the same thing ; an error will be flagged if you try to declare both, but a single mis-typed character can cause confusion.
Cheers, Alan.