Shop OBEX P1 Docs P2 Docs Learn Events
Program slots on BS2px — Parallax Forums

Program slots on BS2px

ShmuelShmuel Posts: 14
edited 2005-12-23 08:05 in BASIC Stamp
Dear All,

I know about STORE, READ and WRITE and have read all those entries in the PBasic Manual. I still have some questions.

If my program·used all the space in Slot 0, can I continue the program in another Slot? I.e. does the program execute sequentially to the next slot?

I wrote a subroutine in Slot 1 and tried GOSUBing to it from Slot 0. This didn't work. Okay, so how do you use program slots?

Are they only meant for, say, data? Like this?
STORE 1
WRITE 0, "X"
READ 0, temp
DEBUG ? temp
STORE 0

The point is I'm writing a program that seems will be larger than a single slot. I wasn't helped by the manual. Can anyone tell me how to use this feature of the laguage?

Thanks.

P.S. It's not because my program is so large but it's definitely bulky since this is my first program on the BS2.

Comments

  • GenesisGenesis Posts: 42
    edited 2005-12-21 19:14
    You can use "RUN 1" to run a program in a different slot (in this case, slot 1)

    If you want to transfer control somewhere other than the start of that slot, you need to do so inside the slot.

    Variables and scratch-pad RAM are carried over, so one way to do this is with a SELECT in the new slot which uses a variable to determine which routine to execute.

    Its a bit tricky to code, but works well.
  • allanlane5allanlane5 Posts: 3,815
    edited 2005-12-21 19:15
    Well, you can "RUN" programs in other slots -- Jon has a tutorial on how to do it somewhere around here. But no, you can't "GOTO" or "GOSUB" another slot (unfortunately).

    This all comes from PBasic having been designed for a PIC and a 2K external EEPROM. The language itself can only figure 2K byte offesets. Having said that, it's quite remarkable they've found a nice method to allow you to continue to use that language with multiple program 'slots'.
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-12-21 19:15
    Hello,

    ·· No you cannot expand your program sequentially into another slot.· But you can transfer program control using the RUN command to run another program in another slot.· If the variables are all declared exactly the same, they will be preserved between slots.· You could also check out the following N&V article.

    http://www.parallax.com/dl/docs/cols/nv/vol3/col/nv87.pdf


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-12-21 19:18
    This is an older article, but is shows one effective technique for using multiple program slots:

    http://www.parallax.com/dl/docs/cols/nv/vol3/col/nv87.pdf

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • ShmuelShmuel Posts: 14
    edited 2005-12-21 20:10
    Okay, thanks all.

    RUN is intended to switch execution to another slot. And STORE is·used when the·other slot is needed for·data?

    How come the memory map doesn't reflect WRITEen values? Is it because the memory map only reflects tokenize-time? Not runtime?
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-12-21 20:17
    That is correct...The memory map shows the state of things at the time the code is downloaded.· At run-time, real-time values cannot be read in the memory map.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • GenesisGenesis Posts: 42
    edited 2005-12-22 05:17
    Yep.

    READ and WRITE access the slot you choose with STORE (defaults to zero) while GET and PUT access the scratch-pad RAM.

    Beware a couple of things about Read/Write though - writes go to EEPROM, and that has a finite life.· Probably not a major issue but one to be aware of - you can "wear it out."· On the other hand, what you stick in there is non-volatile.· Second, its entirely possible to scribble on top of your code - if you do its likely to cause the interpreter to freak out.

    Get/Put writes scratchpad RAM, so there's no "Wear it out" concern, but if power is lost then so is what was in there.

    In both cases you need to keep your own table of what goes where and how its referenced; that can be anything from compiler constants for simple stuff to a linked list or hash table for the more complex.

    I'm doing quite a bit of very complex branching between RUN slots using SELECT - it works· well.· The App I'm working on right now is spread over 5 partitions of the 8 available for code and is consuming roughly 75% of those in total.· You just have to be careful to keep variable declarations aligned between partitions when used this way or you will get "surprises"....

    I'm using a 2Pe, so I have the other half of the EEPROM for data logging (which I'm also using qutie effectively), reserving the last slot for non-volatile configuration data.

    So far I've run into no issues with the architecture that I can't work around.· The only "gotcha" is the lack of a real interrupt structure that makes it difficult to have the code set an output condition and then determine elapsed time (with granularity finer than one second) accurately when it comes back through on a subsequent pass.

    The speed with which I've been able to get fully-operational code running on this thing still amazes me.· I'm an old die-hard Z-80 MACRO guy, and I've done in a man-week what used to take me a man-month.· Granted, its not as "clean" nor do I have the resolution I'd have doing it the "old, hard way" but neither is there a need to write all sorts of wild support routines for various things you want to do - its pretty much all there in the language already - nor is there half the hassle doing the hardware interfacing I used to have to deal with either.· And I don't need an ICE to be able to work with reasonable speed on debugging....

    Consider the following code fragment which will do what you're after:


    ' {$STAMP BS2pe, subroutine}
    ' {$PBASIC 2.5}
    

    ' This code goes in slot 0
    choice VAR Byte
    bypass VAR Byte
    

    IF bypass = 0 THEN
        choice = 0
        RUN 1
    ENDIF
    

    IF bypass = 1 THEN
        choice = 1
        RUN 1
    ENDIF
    DEBUG "END of program", CR
    END
    

    Then stick this into the file called "subroutine"
    

    ' {$STAMP BS2pe}
    ' {$PBASIC 2.5}
    

    choice VAR Byte
    bypass VAR Byte
    SELECT choice
        CASE 0
           DEBUG "This is the first pass into Space #1", CR
        CASE 1
           DEBUG "This is the second pass into Space #1", CR
    ENDSELECT
    bypass = bypass + 1
    RUN 0
    

    When this code is run you will see the two "Debug" lines come up in turn.

    The first time through the first partition, "bypass" is not set (we just started the program, so all variables are cleared) and so choice is set to 0 and then we run the program in partition 1.

    It sees that choice is 0, prints the debug,·increments "bypass" and returns back to the first partition.

    The first partition is reentered at the top.··Bypass is non-zero, so we ignore the first statement and set choice to 1, then call the program in partition 1 again (since it matches the second condition.)

    This time since Choice is 1 we print the second debug line, again increment bypass, and return.

    Since neither condition meets in the first partition this time through execution falls through to the "END" and stops.

    (You could do this with just the one "choice" variable and a select in the top-level program, in fact, but separating it out like this makes it a bit easier to follow.)
  • kelvin jameskelvin james Posts: 531
    edited 2005-12-22 06:54
    In regards to variable structure between the program slots , I tend to think it is more of a trial and error type of issue. Obviously the pros will disagree, and i do understand the technicality of it, but personally it has not been an issue for me. I have a program using the 8 slots, each one varies with a different variable allocation, some the same, some not, and not all in the same order . A lot of this came about because at first i didn't know any better, and if i would of had to use the same variables throughout the different slots, it would of extremely restricted the amount of different ones i needed to use. I have probably run this around 500 times, and never had an issue with the memory. Maybe i just got lucky, or even just the way the code utilizes the ram, I really don't know. Anyway, i just wanted to point out if someone needs more variables across the slots, it is possible it " might " work okay. Like i said, i did some pretty extensive testing, but who knows, possibly one day a certain combination of events might prove me wrong.

    kelvin
  • GenesisGenesis Posts: 42
    edited 2005-12-22 07:04
    I handle that with aliases Kelvin.

    The problem is that if you NEED to pass data between the slots you must make sure the variables align or you're screwed, because the data DOES pass over. So if your structures don't align what you think is in one place really isn't.

    The way I've taken care of this is to have the same definitions in all partitions. That sounds restrictive, but its not - I define a base variable (e.g. "W1") as a word, then define "V1" and "V2" as W1.lowbyte and W1.highbyte, and then define the actual WORKING variables from there, as in "myvalue var v1"

    You can have any number of "aliases" to V1.

    You can do the same thing with bits, nibs, and the like.

    So long as you keep them consistent between partitions you can pass data around easily - you just have to make sure you don't scribble on something you need in the partition you're calling.

    I find that it keeps me from hosing myself if I do it this way, because alignment is guaranteed.· Done like this you can go into the memory check tool (^M) and then switch between partitions - the memory map for variable storage should stay EXACTLY the same.· If it doesn't then you've got a declaration difference between the partitions you need to go find and fix.
    ·
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-12-22 15:25
    Maybe a better way to look at the whole variable thing is not that the data is passed from one slot to another, but that there is a fixed location in RAM where the variables are stored.· When you pass program execution from one slot to another it uses that same fixed location, and all the data that was already there still remains.· Now, if your declarations are different such that different sized variables are declared in different combinations, then references to those memory locations will not be in line with what there were.· It also bears repeating that (for clarity's sake) since the variables are preserved from one slot to another you cannot count on a variable delacred differently in the target slot to be initialized to zero when this happens.·

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • GenesisGenesis Posts: 42
    edited 2005-12-22 17:19
    Good point Chris.

    I guess that some people may think of "passed" as in a language's view like "C" or Pascal where they're allocated on the stack.

    I still think in assembler though...... even after all these years [noparse]:)[/noparse]
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-12-22 17:44
    No problem...Everyone seems to have valid points here, but sometimes I need to evaluate how some information may be perceived and offer a different point of view.· Take care.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • kelvin jameskelvin james Posts: 531
    edited 2005-12-22 18:30
    Okay, i see the light, sorry about the confusion. I suppose in my program, since i am getting a value from a variable in the running slot, and then writing that data to memory and accessing it from different slots, that i am bypassing any possible changes from moving one slot to another. I copied and pasted the actual variable tables from the program, i should clean it up, but now i am afraid to!

    kelvin

    slot 0:
    pos2 VAR Word
    pos VAR Word
    step_ctr VAR Byte
    dir_ctr VAR Nib
    old VAR Nib
    new VAR Nib
    ob VAR old.BIT0
    nb VAR new.BIT1
    cnt VAR Word
    div VAR Nib
    div2 VAR Nib
    div3 VAR Nib
    key VAR Byte
    key2 VAR Byte

    slot 1:
    time VAR Byte
    pos VAR Word
    pos2 VAR Word
    speed VAR Word
    ramp VAR Byte
    key VAR Byte
    key2 VAR Byte

    slot 2:
    speed VAR Word(3)
    pos VAR Word
    pos2 VAR Word
    key VAR Word
    key2 VAR Word

    slot 3:
    pos VAR Word
    pos2 VAR Word
    old VAR Nib
    new VAR Nib
    ob VAR old.BIT0
    nb VAR new.BIT1
    cnt VAR Word
    pos3 VAR Word
    pos1 VAR Word
    div VAR Byte
    div2 VAR Byte
    div3 VAR Nib
    step_ctr VAR Byte
    key VAR Byte
    key2 VAR Byte

    slot 4:
    key VAR Byte
    key2 VAR Byte
    pos VAR Word
    pos2 VAR Word
    pos3 VAR Word
    pos4 VAR Word
    pos5 VAR Word
    pos6 VAR Word
    pos7 VAR Word
    pos8 VAR Word
    spdvalue VAR Byte

    slot 5:
    key VAR Byte
    key2 VAR Byte
    pos2 VAR Word

    pos8 VAR Word
    pos4 VAR Word
    pos5 VAR Word
    pos6 VAR Word
    pos7 VAR Word

    spd0 VAR Word
    spd1 VAR Word
    spd2 VAR Word
    spd3 VAR Word
    spd4 VAR Word
    spdmark VAR Byte

    slot6:
    speed2 VAR Word(3)
    pos VAR Word
    pos2 VAR Word
    spdvalue VAR Byte
    key VAR Byte
    key2 VAR Byte

    slot 7:
    pos8 VAR Word
    pos4 VAR Word
    pos5 VAR Word
    pos6 VAR Word
    pos7 VAR Word
    pos VAR Word
    pos2 VAR Word
    old VAR Nib
    new VAR Nib
    ob VAR old.BIT0
    nb VAR new.BIT1
    cnt VAR Word
    pos3 VAR Word
    pos1 VAR Nib
    div VAR Nib
    div2 VAR Nib
    div3 VAR Nib
    step_ctr VAR Byte
    key VAR Byte
    key2 VAR Byte
  • GenesisGenesis Posts: 42
    edited 2005-12-22 18:32
    As long as you consider the variables on entry to a slot to be un-initialized (that is, they may contain random garbage) you're fine with this approach.
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2005-12-22 22:21
    Kelvin -

    If I understand what you're doing correctly (and I'm not sure that I do), whenever you require a variable's value to be "passed" from one slot to another, you write it to EEPROM and save it initially, and then retrieve it in a subsequently run slot. From what I can gather, this is apparently done for multiple variables and multiple times, on multiple passes through the various slots. Is this correct?

    If so, I've got a couple of pieces of potentially very concerning news for you. Please let me know before you run this too many times further.

    Regards,

    Bruce Bates
  • kelvin jameskelvin james Posts: 531
    edited 2005-12-23 07:26
    Bruce I have quite a few user select parameters that are only being changed by a keypad, and that is the only time the memory gets written to in the program. I had to take this route as i wanted the presets held in memory with powerdown. So, i am not writing to memory needlessly, as not wearing out the memory location limit. I still have to gain access to the values from different slots for different operations, but just from reading the memory location. If there are any other issues that may pose a problem doing this, i would be grateful to hear about it. I actually had to dump part of the program, it was a user time select for an auto operation, just couldn't squeeze in another 4 word variables anywhere from one slot to run by itself, without anything else interfering. I don't see a lot of discussions here on efficient ram use, to me it is a fairly important part of programming.

    kelvin
  • Bruce BatesBruce Bates Posts: 3,045
    edited 2005-12-23 08:05
    Kelvin -

    I'm not sure why you can't or won't set this program up the way it should be, so that there are not potential pitfalls, but I'm not about to play the "doting parent" role here smile.gif It's not like rerranging the variables so that they're the same in every program is anything time consuming or that it's a difficult task <sigh>.

    Any way, the second, hidden problem you have is one of potential timing errors. That sounds a bit odd, so let me explain.

    If you were using the parameter passing facility the way it was intended, the very instant a variable is updated in any manner, it is available globally, to any other slot. With your EEPROM abusive method, you must remember to write any changed parameter to EEPROM, as soon as it is updated, before heading off to any other slots. You also need to remember WHICH parameters will be needed elsewhere as well. This is only 1/2 the problem though.

    Now, when you arrive in a different slot, you must remember to fetch any parameters which may have changed in another slot, and also remember WHICH parmeters you will need to fetch. Since, in the target slot, you have no idea what has changed and what hasn't, elsewhere, you must waste the time of re-fetching EVERY parameter which MIGHT have changed. I can only guess that wasted time, and programing inefficiencies are not important in this program.

    If you head for a slot before a variable representing a passed parameter has been saved - oops, when there is no need for any oops. So too, if you attempt to use it before "refreshing" it, oops again.

    For my money, all this unnecesssary "remembering" isn't worth it, since all it might give me is the ability to write code which is inherently difficult to follow. When I write a program today, I want to be able to pick it back up years from now, and between the straight forward, logical program flow, and the included documentation, I'll see exactly what I was doing with hardly any thought. I also want others who may succeed me, to be able to do the same thing. IMHO, your "scrambled parameters" method is a maintenance programmer's worst nightmare.

    At this juncture, "Have it YOUR way" begins to apply. If I were handed a program with a variable parameter list to fix or maintain, I'd just hand it back and say "No thanks, I don't need any more headaches today" smile.gif

    Regards,

    Bruce Bates
Sign In or Register to comment.