Extending PICAXE named variables by 300% or more!

mrburnette

Senior Member
There has been several posts of recent about the named variables limitations: that is, B0-B27 in the case of an 08M2. But, as has been noted there is additional RAM in the 08M2, but it is not "named" and therefore PEEK/POKE are the access methods.

What if we consider the 08M2 RAM as 4 banks with only the lower BANK0 having variable names: B0-B27 / W0-W13... so the scenario will apply to other chips in the PICAXE line, but they will simply contain more banks since the 08M2 has the least amount of RAM of the currently shipping chips.

Problem to solve: Have more simple-to-use variables without having to keep track of PEEK/POKE addresses

A solution: Consider extended RAM, above that directly addressable with variable names, as banks of RAM

Implementation:
Code:
' DEMO of saving named variables and restoring... 3 levels deep
' M. Ray Burnette, 09 Nov 2011
' Refer to Manual 2, page 11 and other parts as appropriate
'
' Fill lower RAM addresses: B0 - B27 (W0 - W13) ... For this DEMO this will be RAM Bank 0
for bptr = 0 to 27 : @bptr = bptr : next

' Copy Bank 0, named variables B0 thru B27 (main memory) into a higher partition
' Select one of the following RAM OFFSET INDEXES: 28, 56, or 84
'
bptr = 0
' BANK 1 _____________________________________>
Poke 28, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc

bptr = 0
' BANK 2 _____________________________________>
Poke 56, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc

bptr = 0
' BANK 3 _____________________________________>
Poke 84, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc
'
'
' For this DEMO, let's clear Bank 0 before each restore
for bptr = 0 to 27 : @bptr = 0 : next
'
' Now restore Bank 1, 2, 3 into Bank 0 (named variables)
bptr = 0
' BANK 1 _____________________________________>
Peek 28, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc
'
for bptr = 0 to 27 : @bptr = 0 : next
'
bptr = 0
' BANK 2 _____________________________________>
Peek 56, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc
'
for bptr = 0 to 27 : @bptr = 0 : next
'
bptr = 0
' BANK 3 _____________________________________>
Peek 84, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc, @bptrinc


END
View attachment 9565

Explanation and possible usage:
Run the code snippet in the Simulator and watch the Memory map (see JPG example above) fill as the Simulator walks the DEMO code.
The POKE to starting locations 28, 56, and 84 represent the beginning of a memory block. IF we call lower memory represented by B0-B27 as BANK0, then locations 28/56/84 would represent BANK 1/2/3 respectively.

To use this concept, write modular code. Before each subroutine call, swap main memory, BANK0 with a holding location BANK1, BANK2, or BANK3. Save your subroutine state if necessary and restore BANK0 before the RETURN statement.

If you need a few PUBLIC variables to communicate across routines, etc. then just modify the PEEK/POKE statements accordingly along with the BANK indexes so that the entire BANK0 is not saved/restored.

Same concept could be applied to chip models with scratchpad memory to form an even deeper stack.
- Ray
 

Armp

Senior Member
Ray - I started a thread http://www.picaxeforum.co.uk/showthread.php?19910-Maintaining-and-Reusing-Code to try to identify the need for functions to facilitate stacks on the Picaxe.

I've suggested multiple 'bptr' type pointers, along with corresponding @wptrinc/dec word variables to get/save WORDs and inc/dec pointer by 2.

Or PUSH(w0,w9,w12...) to quickly save a number of variables - along with POP of course.

Really I'd like to see all unnamed RAM become named on the bigger parts. On the 20M2 I have 512 bytes just sitting there waiting to be used! But there are technical reasons apparently for not doing this...

The response to the thread has largely been 'why would you want to do this?' or 'reuse variables'. I guess the target user isn't interested in reusing code, or modularity.

Hippy has been somewhat receptive - but needs to see a real benefit to consider any mods.

Please take a look if you haven't already.

Chris
 
Last edited:

mrburnette

Senior Member
Armp;bt73 said:
Ray - I started a thread http://www.picaxeforum.co.uk/showthread.php?19910-Maintaining-and-Reusing-Code to try to identify the need for functions to facilitate stacks on the Picaxe.
<...>
Please take a look if you haven't already.

Chris
Chris,
Yes, I have seen and read the thread and I deleted two responses because I struggled (and still do) with an appropriate answer; which is to say, that both camps have valid arguments.

When viewed from your point of view, the need is obvious. When viewed from the RevEd POV, the need to standardize across the range of available chips and this means that they are working with a complex interpreter model and make a better-than-fair attempt to provide new functionality with new models of hardware architecture (microchips.) But, because RevEd is geared to marketing primarily for education, I ultimately lean more to their camp since I understand the challenges to rework the codebase. Technical and Hippy and others have noted the extremes that RevEd goes through just to compress the existing numeric values and variables and extensions are not a minor change.

What I believe is critical (and RevEd does a great job) is to provide a range of compatible chips that use the same Basic syntax starting with the current 08M2 and moving up to more capable chips, both in RAM and I/O. Your needs are easily satisfied by moving away from the PICAXE line to raw uC and utilizing a fully compiled Basic (or C or...); something on the order of: PICBASIC PRO, as a singular example. I feel that to fully utilize modular code one must be able to compile procedures/functions into a library - the library function then becomes an abstraction and variables can be passed by value or by reference. I think that just naming all of the internal PICAXE memory locations provides but a small step toward modular code; which is to say, I don't think that even with a new and more flexible indirect addressing architecture that enough software engineering would gain full code re-usability primarily because naming conventions alone do not support an object model when all of the variables are public; which is to say, variable scope must be considered as a logical extension of the thinking process and such scoping is extremely intensive in an interpretative model with limited resources within the uC.

When all is said and done, RevEd is a business and must maintain focus on their strong user base in education while supporting a growing and diverse need in the hobby use of the chips (and maybe small commercial ventures.) To this end, I say they have done very well. If I had a personal wish for advancing the power users of the product, I would wish for an intelligent, multi-pass compiler optimized for the PICAXE language with advance library functions for variable scoping, strings, function calls, and object inheritance in a FREE compiler/linker with a small bootloader based upon their current bootloader technology. By using a granular library, the limited resources of the PICAXE are consumed by only "program referenced" code and by using a very similar instruction set and syntax, knowledge gained in the interpreter is extended... let's call that knowledge recycling and reuse.

I've been programming since 1973 in machine language, Cobol, Fortran, and all through fad-languages and into the object oriented days until today. Unlike the Land of Mordor, there is not one ring to rule them all... no magic language; each has strength and weaknesses. We pretty much get what we get from the manufacturers and adapt our needs around a product or product suite. I sometimes think that formally trained programmers are like classically trained musicians that one day just decide to do Rock 'n Roll... it can leave the mind scrambled like eggs.

- Ray
 

Armp

Senior Member
I've been programming since 1973 in machine language, Cobol, Fortran, and all through fad-languages and into the object oriented days until today.
You're just a kid! I got 10yrs on you - I first programmed on the Ferranti Pegasus at Southampton Uni in 1963. Punch tape and vacuum tubes/valves.... Then Asm, Fortran, Forth, PL1, APL, Lisp, Logo, Chip8, Basic, C , Pascal, Oberon - done them all as a hobbyist and IBM programmer.

My first home micro was the 1975 ish Motorola D2 6800 board with 128 bytes, then the Jolt 6502, Sinclair ZX81, Radio Shack 6809, MIT 68HC11 miniboard, and finally the ARM LPC2103 boards. The same subroutines and algorithms have progressed along easily with me - until we hit the Picaxe! I love it as a cheap complement to my $9.50 ARM boards with free Keil C Compiler ( http://www.teamfdi.com/development-tools-kits/products/4/DB-LQFP48-LPC2103), but it is a dog to program with only 14 variables, no parentheses, no 2s complement, lack of stacks, local variables or indirect addressing..

I shall continue to use it as a $3 solution to very small problems, but it could be so much more... Just take a look at what Sinclair did with 1K RAM on the zx81.

Back down into my hole - Peace....

Chris
 

Armp

Senior Member
If I had a personal wish for advancing the power users of the product, I would wish for an intelligent, multi-pass compiler optimized for the PICAXE language with advance library functions for variable scoping, strings, function calls, and object inheritance in a FREE compiler/linker with a small bootloader based upon their current bootloader technology.
Coridium have some nice products based on the ARM family in the form of ARMmite/ARMbasic.
( http://www.coridiumcorp.com/Products.php )

Coridium preprogram the ARM chip is with a bootloader and some hooks. The free compiler produces code that can only be downloaded onto such a preprogrammed chip - available on their boards, as preprogrammed chips or by licence $$$. Not unlike the RevEd business model.

I've used a number of these boards successfully in the past for quick prototypes, and still do. The problems for me are the Arduino form factor and lack of Xtal.
 

Armp

Senior Member
ME??

No - I was shooting for the smallest code size initially. Whatever the delay for the ultra simple approach can be reduced significantly by swapping only a subset of variables, w10-w13 in my application, and doing it in one go rather than looping.
 

mrburnette

Senior Member
geoff07;bt78 said:
Have you done any timings on the bank switching?
I have not. As long as the 08M2 is being used in single program mode, swap routines could be done at 32MHz, assuming the subroutine in question did not have frequency-centric requirements. There are also subtle time differences associated in how the swapping is done: looping vs Peek/Poke with the indirect pointer, @bptrinc ... as shown in my demo code... Alas, timing impact: it is an interesting question that begs an answer.

As the technique evolves into more formal uses, swap-times would be of interest, I'm sure. I've spent the last 15 years as a Technical Architect and not an Engineer, so most of the time I'm thinking in terms of 'concepts' and not 'implementation'... guess I need to put on an Engineering hat and breadboard a timing circuit.

However, flexibility and enhanced memory access (simple, named variable access) may outweigh the swap-time penalty... like on a computer, all modern OS's use a physical swapfile for virtual memory... it's just a given that there is some latency associated with this architecture.

- Ray
 
Top