Maintaining and Reusing Code

Armp

Senior Member
Like others before I'm running into the problem of reusing code and keeping track of variables in biggish programs. There's a lot of very good info in http://www.picaxeforum.co.uk/showthread.php?9299-Writing-Maintainable-Picaxe-Code&highlight=modular and I'm using several of the techniques in my 20M2 GPS program.
But maintaining stacks and pointers with only peek/poke/bptr ends up pretty clumsy and rather slow.

A couple of thoughts:
Would it be possible to extend the range of variables w0-w13 to say w32, w64 - or even w255 on the M2?
I assume the answer is no, or you would have done it already :).

Maybe extend bptr by providing @wptrinc/dec to handle words, rather than having to do byte-by-byte?
Probably easier to implement than a 'real' stack - PUSH(w0,w3,w5), [do stuff using these regs] , POP(w0,w3,w5).
POP(w5,w3,w0) would be more traditional, but also confusing to some.

A couple more 'bptr' like pointers for indirect addressing would also be very useful IMHO!

(Hardhat on - ducking for cover!)
 
Last edited:

Jamster

Senior Member
I think the main reason they dont extend the general variables is because "b2" requires two bytes to store 1 byte of information (Name and Data) and a scratchpad variable only takes up 1 byte (Data). Therefore you would find you have only half the storage space as you do today.

If you duck we'll only aim lower. ;)
 

srnet

Senior Member
As some of the nifty techniques outlined on here come from technical support, I would assume they fully understand the limitations of a PCIAXE and also the additional features that would extend the capability.

So if these changes\extensions are not implemented, I presume there are good reasons why not.
 

Armp

Senior Member
As some of the nifty techniques outlined on here come from technical support, I would assume they fully understand the limitations of a PCIAXE and also the additional features that would extend the capability.

So if these changes\extensions are not implemented, I presume there are good reasons why not.
I'm sure you're right.. But worth discussing I hope?
 

Armp

Senior Member
Last edited:

hippy

Ex-Staff (retired)
So if these changes\extensions are not implemented, I presume there are good reasons why not.
I'm sure you're right.. But worth discussing I hope?
Absolutely.

The main considerations for any change is how useful it is and how it affects the existing internal architecture; how much more complicated it makes the firmware and compilers. A seemingly insignificant change can actually have considerable knock-on impact.

Those changes can also have a knock-on for user programs, for example adding @wptr and related variables would likely need the tokens reallocating so existing code may take up more program space, so we also have to balance whether it's a good thing or bad for the majority of users.
 

Armp

Senior Member
Thanks Hippy....

One of the reasons the Arduino is so popular is that the code IS reusable.. IMHO- If Rev-Ed want to grab a modestly bigger market share they have to take steps to make the code modular and reusable .

I have a bunch of GPS subroutines that I would love to share - but can't as they use defined variables rather than passing parameters into them. And if I add the overhead of pushing/popping registers they become bloated and unwieldy.

Is expanding variables from w13 to wxxx a really big problem?

C'mon Jeremy Leach et al - let's be hearing from ya....

(In the trenches)
 
Last edited:

g6ejd

Senior Member
If your using a lot of variables then it's probably a function of coding techniques, unless you really do have a lot of variables you need to keep a track of (unlikely), I suggest you write your routines with psuedo local variables, this helps to force you to use the same variables addresses over again. Example keep redefining the same variable address, like this:
DIM a : b0
DIM b : b0

print_numbers:
REM DIM a : b0
FOR a = 1 to 10
Print a
Next a

Print_names:
REM DIM b : b0
For b = 1 to 10
Print names$
next b

You don't need a different variable for most applications, so when you import them / re-use them your comments in your code should guide you.

That's how I do it anyway.
 

Armp

Senior Member
If your using a lot of variables then it's probably a function of coding techniques, unless you really do have a lot of variables you need to keep a track of (unlikely)
I have a State machine with 5 major 'states', and 17 subroutines so far.
Close to 1500 bytes, and struggling to make it fit the 20M2.

Most subs have a couple of parameters passed into them, and require a couple of local variables to hold partial results.
That's something like 60 variables floating around. I use 2 string buffers, and a pseudo stack as well.

Results in pages of notes to keep track of whats going on.
 

g6ejd

Senior Member
Well I guess you could use a 24LC16 or 64 external EEPROM if speed was within your range, then you would have plenty of variable space, but you'd need to manage them between PICAXE variables and EEPROM variables. I see your problem...
 

cravenhaven

Senior Member
The X2 parts have twice as many defined variables. I ended up changing from the 20X2 to the 28X2 because my program got too big and I ended up making use of the extra program slots available in the 28X2.
 

westaust55

Moderator
For larger projects it would still be relatively rare that all variables are required to retain the values throughout the program thus allowing variables to be re-used.
When necessary there is the approach put forward by member mrburnette as already linked by eclectic at post 5.

Re-use of code snippets/routines can be relatively simple if SYMBOL statements are provided with the code. Then the recipient need only review the SYMBOL statements and not troll through possibly extensive code.

At the following post is an example spreadsheet I have prepared previously which aimed to guide others in the reuse of variables within my programs:
See post 28 here (where only 28 byte variables available): http://www.picaxeforum.co.uk/showthread.php?10014-Siemens-A55-C55-LCD-graphics-display/page3



Adding more variables means a need to add at least another bit to the variable parameters which will amongst other things require more program space. There is some information here about the structure of tokens as used for the PICAXE programs:
http://www.picaxeforum.co.uk/showthread.php?17782-PICAXE-program-Size-Optimisations-and-Speed
 

Jamster

Senior Member
I discovered yesterday that you can define more than one name for variables with SYMBOL, obviously this could get confusing so prehaps prefixing it with the names or abbreviations of the routines it is used in may help to reduce confusion.
 

srnet

Senior Member
The 'limited' amount of RAM available for variables does tend to force you to be more organised, both in program writing and documentation.

No bad thing given that (I guess) a major part of REV Eds market is the Education sector.
 

Armp

Senior Member
The 'limited' amount of RAM available for variables does tend to force you to be more organised, both in program writing and documentation.
The number of available variables has NO relationship at all to your degree of organization. Modern coding techniques do that....
 

graynomad

Senior Member
Global variables in general and reusing them in particular is generally frowned upon and does not engender reliable code. Reliable reusability requires that the module being reused has, as far as is possible, everything encapsulated and hidden from the user. That way you can't stuff it up because you don't have access to it.

I gather local/automatic variables are not an option with the Picaxe, so maybe all this hoop jumping is trying to take it some place it shouldn't go.
 

inglewoodpete

Senior Member
Global variables in general and reusing them in particular is generally frowned upon and does not engender reliable code. Reliable reusability requires that the module being reused has, as far as is possible, everything encapsulated and hidden from the user. That way you can't stuff it up because you don't have access to it.

I gather local/automatic variables are not an option with the Picaxe, so maybe all this hoop jumping is trying to take it some place it shouldn't go.
Wow that's pretty strong Rob:eek:.

We're talking about a microcontroller with limited resources. RAM is usually counted in bytes. The user's code is interpretted at runtime, so there is a whole interpretter fitted into the available flash: the bigger the model's flash, the more commands and features available.

So the programming "rules" that we are accustomed to for PCs, minis and mainframes have to be compromised. With limited resources inside these simple "computer-in-a-chip"s, development must be done within those resources. You can't address a pin which does not exist; you can't write to RAM that does not exist either. As a professional programmer, I can see that the rules are different but that doesn't stop me from enjoying taking PICAXEs to their limits.

However, that is no excuse for poorly structured code or poorly managed RAM or EEPROM. When you run short, you have to ensure your code is sufficiently robust to run reliably and that documentation (comments) make the functions clear for future enhancements or debugging.

Peter
 

graynomad

Senior Member
Sorry, I didn't mean to sound like I'm picking on the Picaxe :)

It is fun to try and squeeze that last feature out of a chip, I remember once I had to tokenize all the strings to save EPROM eg

"This is a menu option to do that"

became something like

0x01 is a 0x03 option 0x04 0x05 0x06

That reduces the string from 32 bytes to 21 and saves 11 bytes at the expense of a table lookup. It worked well because we had a lot of recurring words so the space saved in strings was larger that the lookup table size + extra code.

I guess what I'm saying is that when you start having to do such things it's time to look at a different platform or larger version of the same one.
 

Armp

Senior Member
Global variables in general and reusing them in particular is generally frowned upon and does not engender reliable code. Reliable reusability requires that the module being reused has, as far as is possible, everything encapsulated and hidden from the user. That way you can't stuff it up because you don't have access to it.
Over several decades(!) I have collected a large number of useful algorithms.
They map over to Picaxe relatively easily, most are <50 bytes, and use only 2 or 3 'local' variables.

But now when I write a new 20 line program, and want to use sinx, cosx, atan2x, sqrtX, writeLCD etc I have to review all my variables, and try to ensure no conflict. It doesn't always work, and makes sharing code or teaching techniques difficult....

My solution so far is to hard code blocks of RAM to each subroutine with unique constant 'subptr' for each.

Assume w11 - w13 for local variables.
Then at entry: poke subptr, word w11, word w12, word w13
[ Body of Sub]
peek subptr, word w11, word w12, word w13
Return

But this can double the size of the original subroutine!

I can tweak it further by making the peek and poke lines subs and various other tricks, but you get the idea.

Many threads on this forum have been along the lines:

"My code used to work, then I changed wx to wy and now its broken" - and its caused by reusing wy somewhere else.
 

hippy

Ex-Staff (retired)
One of the first steps in avoiding variable use conflicts is to use SYMBOL to give them abstract names as that is the first step in disconnecting the code from the variables it actually uses. Then all one needs to do is put all SYMBOL definitions together, determine which need to be separate or can be reused and adjust as appropriately.

Sometimes it can get more complicated but often it's simply a matter of making sure each block of variables for the various routines follow earlier variables and don't overlap them.

The best approach is to give every variable a name and its own 'b' or 'w' variable to use and only reuse variables when it becomes necessary. With 'b' and 'w' variables throughout the code it's hard to tell which ones are used or where. With SYMBOL names they can be collated at the top of the program and conflicts will be much easier to spot and avoid in the first place.
 

Brewer

New Member
As soon as I started to learn PICAXE BASIC I ran into the problem of no native support for parameter passing in subroutines, no local variables in subroutines, and a limited number of general purpose variables. I addressed these issues by developing a template or system of coding for parameter passing and local variables. This was developed on a 08M2 chip using MacAxePad. Since then I have learned (via suggestions following my post) that the #macro directive could be used to make the code more readable, but I haven't revised it as yet. I also learned that MacAxePad doesn't support the #macro directive and the BASIC Commands Manuals included with downloads of MacAxePad and PicAxe Editor don't cover the #macro directive. You need to use the web-based manual. Sorry - my frustration is showing.

My system uses high RAM to store copies of general purpose (gp) variables while the gp variable space is used for private variables in the subroutine. The original gp variables are restored before the subroutine is ended. This system allows you to use all but two bytes of gp space in your main program and each subroutine you call, including nested subroutines, as long as you don't run out of space in high RAM. The system also handles parameter passing to and from subroutines. Maybe this would be helpful.
 
Top