Shop OBEX P1 Docs P2 Docs Learn Events
BS2SX Programming Theory? — Parallax Forums

BS2SX Programming Theory?

ArchiverArchiver Posts: 46,084
edited 2000-07-18 04:23 in General Discussion
Hello,

I'm having some conceptual problems with using the full program space of the Basic Stamp 2SX. I have an existing application that runs on a BS2 and now I need a little bit more memory. So I bought a BS2SX. I think what I need to do now is break up my program, which·was made up of several subroutines, into several different programs. One subroutine becomes one program. But my problem is that I can't "call" a seperate program as a subroutine and have it return to the place where it was called from. You can't "call" a program, you can only "run" it.

As I see it, the way the BS2SX is configured is that you get 8 seperate program spaces each of which must be self contained. The only way to "call" a different program as though it were a subroutine is to set up some pass variables in·RAM or scratch-pad and then "run" the desired subroutine, letting it use the variables you've set up. Then, the only way to "return" from the call is for the·subroutine to set up some kind of return vector (via yet another RAM variable) and then "run" the original program back again, letting the original program, at its beginning, decode the return vector to jump back into the place where it called the subroutine from.

Sound complicated? It is.·Therefore, it must be wrong. So here's the question:

Does anyone have any experience with setting up clusters of intercommunicating subroutines in a BS2SX? What is the best way to utilize the BS2SX's memory to its fullest and still make the overall program readable and maintainable? Was the BS2SX designed to be used in this way?

I'm at the brink of coming up with my own software scheme but I really want to see what everybody else knows about this so I don't go down the wrong path too far. It seems like it could become a pretty complex issue and decisions now may affect further strategies later.

If nothing else, it's food for thought.

Regards,
John Schulz

Comments

  • ArchiverArchiver Posts: 46,084
    edited 2000-07-12 06:48
    Hi John,

    It sounds complicated, and it is :-(
    I can't think of another way of doing what you want than to use 'address'
    variables in scratch pad RAM to direct program entry point to the subroutine
    that applies.

    Cheers,

    Mike

    Mensaje original
    De: John Schulz [noparse]/noparse]mailto:[url=http://forums.parallaxinc.com/group/basicstamps/post?postID=LTYxd3UmjB8bpg-ULfWgJkSdDc48cRTBFnIgQ8ASGJwTpwRKRwHwamOrVJhp4CzWdPiCY-tBm3Y0D-HE]jschulz@c...[/url
    Enviado el: mi
  • ArchiverArchiver Posts: 46,084
    edited 2000-07-12 09:17
    At 08:52 PM 7/11/00, you wrote:
    Hello,

    I'm having some conceptual problems with usingthe full program space of the Basic Stamp 2SX. I have an existingapplication that runs on a BS2 and now I need a little bit more memory.So I bought a BS2SX. I think what I need to do now is break up myprogram, which was made up of several subroutines, into several differentprograms. One subroutine becomes one program. But my problem is that Ican't "call" a seperate program as a subroutine and have itreturn to the place where it was called from. You can't "call"a program, you can only "run" it.

    As I see it, the way the BS2SX is configured isthat you get 8 seperate program spaces each of which must be selfcontained. The only way to "call" a different program as thoughit were a subroutine is to set up some pass variables in RAM orscratch-pad and then "run" the desired subroutine, letting ituse the variables you've set up. Then, the only way to "return"from the call is for the subroutine to set up some kind of return vector(via yet another RAM variable) and then "run" the originalprogram back again, letting the original program, at its beginning,decode the return vector to jump back into the place where it called thesubroutine from.
    ·


    You may find this a helpful reference for BS-2 hints and tips. There is aseparate section for the BS-2SX within this URL:

    ········[noparse]/noparse][url=http://www.emesystems.com/BS2index.htm]http://www.emesystems.com/BS2index.htm[/url

    You are correct in your analysis of one way to use the program control facility on the BS-2SX. Said differently:

    ········RUN = CALL without inline parameter passing, and
    ··························· with no "next instruction" return point.

    Thus, the return point must be pre-established as you suggest. The "gain" is in the 8X factor of program space availablity, NOT in program length. There is no Parallax facility for increasing an individual program space beyond 2K (at the moment). The advent of the BS-2X was expected (by the user community) to address this hardware restriction. There is no practical reason why it CAN NOT be done, just that it has not been done by Parallax to date. I suspect the next hardware revision of the BS-2SX might do two things - increase the program space, and increase the horsepower (in excess of 50 MHz). This is purely my opinion, however, and is only based on my past experience (4+ years) watching the Parallax Stamps as they develop. Time will tell what happens.

    Sidenote:

    On some operating systems this is the equivalent of the XCTL (transfer control) supervisor call. XCTL routines in many operating systems are used for fetch/xeq of sequential or non-sequential subroutines or overlays, when there is a pre-established parameter block, and a cadence of software flow. Load/Go at the system level (so to speak). The Load function (NOT the mere load hardware instruction) in many systems may operate similarly

    Often it is used in Open/Close/End Of Volume routines, since there is an expectation of events based on a set of rules and procedures. So too during high level error recovery.

    Hope that helps
    Sound complicated? It is. Therefore, it must be wrong. So here's the question:


    <snip>

    I'm at the brink of coming up with my own software scheme but I really want to see what everybody else knows about this so I don't go down the wrong path too far. It seems like it could become a pretty complex issue and decisions now may affect further strategies later.
    ·


    That it is !

    If nothing else, it's food for thought.

    Regards,
    John Schulz

    Regards,

    Bruce Bates
  • ArchiverArchiver Posts: 46,084
    edited 2000-07-12 13:21
    At 20:52 11.07.2000 -0700, John Schulz wrote:
    >Hello,
    >
    >I'm having some conceptual problems with using the full program space of the
    >Basic Stamp 2SX. I have an existing application that runs on a BS2 and now I
    >need a little bit more memory. So I bought a BS2SX. I think what I need to
    >do now is break up my program, which was made up of several subroutines,
    >into several different programs. One subroutine becomes one program. But my
    >problem is that I can't "call" a seperate program as a subroutine and have
    >it return to the place where it was called from. You can't "call" a program,
    >you can only "run" it.
    >
    >As I see it, the way the BS2SX is configured is that you get 8 seperate
    >program spaces each of which must be self contained. The only way to "call"
    >a different program as though it were a subroutine is to set up some pass
    >variables in RAM or scratch-pad and then "run" the desired subroutine,
    >letting it use the variables you've set up. Then, the only way to "return"
    >from the call is for the subroutine to set up some kind of return vector
    >(via yet another RAM variable) and then "run" the original program back
    >again, letting the original program, at its beginning, decode the return
    >vector to jump back into the place where it called the subroutine from.
    >
    >Sound complicated? It is. Therefore, it must be wrong. So here's the
    >question:
    >
    >Does anyone have any experience with setting up clusters of
    >intercommunicating subroutines in a BS2SX? What is the best way to utilize
    >the BS2SX's memory to its fullest and still make the overall program
    >readable and maintainable? Was the BS2SX designed to be used in this way?
    >
    >I'm at the brink of coming up with my own software scheme but I really want
    >to see what everybody else knows about this so I don't go down the wrong
    >path too far. It seems like it could become a pretty complex issue and
    >decisions now may affect further strategies later.
    >
    >If nothing else, it's food for thought.
    >
    >Regards,
    >John Schulz
    >
    >Attachment Converted: "c:\internet\eudora\attach\basicst2.htm"
    >

    John,
    to enhance memory with 8 banks to 2 K by using BS2SX is a successful way.
    The CALL-statement (not in PBASIC !) is common used for calling
    subroutines, as You wrote,- and missed !. Last statement of called
    subroutine must be a RETURN ( or END SUB for Visual Basic) for correct
    working.

    With programming PBASIC "RUN.." for BS2SX You have the same effect. Load
    Your parts of program in different banks (with directives ) according to
    subroutines.Set RUN <destinBankNr> to "call"
    Instead of RETURN set RUN <sourceBankNr> to return to the bank, You are
    started
    from. So all parts of Your program are running in different banks in chain
    as You like.
    Added from declaration RUN: " The I/O pins retain their current
    state....and all Variable and Scratch Pad RAM locations retain their
    current data..."

    Just my little contribution.- Best Regards Klaus Zahnert
  • ArchiverArchiver Posts: 46,084
    edited 2000-07-12 19:36
    "John Schulz" <jschulz@c...> wrote:
    >I'm having some conceptual problems with using the full program space of
    >the Basic Stamp 2SX. I have an existing application that runs on a BS2 and

    >now I need a little bit more memory. So I bought a BS2SX. I think what I
    >need to do now is break up my program, which was made up of several
    >subroutines, into several different programs. One subroutine becomes one
    >program. But my problem is that I can't "call" a seperate program as a
    >subroutine and have it return to the place where it was called from. You
    >can't "call" a program, you can only "run" it.
    >
    >As I see it, the way the BS2SX is configured is that you get 8 seperate
    >program spaces each of which must be self contained. The only way to
    >"call" a different program as though it were a subroutine is to set up
    >some pass variables in RAM or scratch-pad and then "run" the desired
    >subroutine, letting it use the variables you've set up. Then, the only way

    >to "return" from the call is for the subroutine to set up some kind of
    >return vector (via yet another RAM variable) and then "run" the original
    >program back again, letting the original program, at its beginning, decode

    >the return vector to jump back into the place where it called the
    >subroutine from.

    Hi John,

    Your understanding of the problem and the workaround are right on.

    I always define a byte in scratchram that I use as a one-level "stack".
    stack con 62 ' will hold the return vector
    And I always define the first word variable in RAM as an active vector that
    works in conjuction with the "stack"

    sxw var word ' put this variable first in ram
    sxgo var sxw.byte0 ' alias, first byte in memory
    sxgo2 var sxgo.nib0 ' alias, first nib in memory
    sxbank var sxgo.nib1 ' alias, second nib in memory
    sxdat var sxw.byte1 ' alias, second byte in memory

    At the top of the program code in each bank I have a branch instruction,
    which keys in on the contents of the nibble "sxgo2". For example:

    branch sxgo2,[noparse][[/noparse]initialize,setup1,setup2,setup3]

    Since sxgo2 is a nib variable, this allows for an immediate branch to up to
    16 different locations in the bank. When the BS2 is powered up or reset,
    the contents of variable sxgo2 is always a zero and the execution starts in
    bank 0, so the first branch in bank 0 vectors to the initialization
    routine. When a program in one bank needs to call a subroutine in another
    bank, it pushes an index for its own return address onto the "stack", The
    return vectorincludes both a bank number (nib1) and an index (nib0):

    put stack,$03 ' return here
    '^---- to bank 0
    '^----setup3 is the third label ref'ed in the BRANCH
    ' for bank 0
    sxgo=$32 ' run bank 3, the label with index 2 in that bank.
    ' that bank starts with
    ' branch sxgo2,[noparse][[/noparse]routine0,routine1,routine2,...]
    ' we will end up here^^^^^^^^
    run sxbank ' RUN 3 in this case
    ' transfers to bank 3, then to routine2.
    setup3: ' will return here later
    ' continue here upon return from the other bank

    In bank 3, the branch instruction at the top takes the program execution to
    the label that has been set up as index 2. When the routine finishes, it
    pops the return vector off the stack:

    branch sxgo2,[noparse][[/noparse]routine0,routine1,routine2,...]
    ' we go here^^^^^^^^

    ' .... other stuff
    routine2: ' here we are
    ' do something
    get stack,sxgo ' get the active return vector
    run sxbank ' this is the nibble that holds the return bank
    ' the nibble "sxgo2" holds the return index
    ' that is used by the BRANCH in the return bank
    ' sxgo=$03 in the example

    At this point the program transfers back to bank 0.

    branch sxgo2,[noparse][[/noparse]initialize,setup1,setup2,setup3]
    ' we go here^^^^^^

    Some pointers: The Stamp interpreter does not allow jumps from the middle
    of a subroutine in one bank into another bank, with return to the same
    spot--The local return stack is trashed by the RUN command. Similarly, it
    does not allow jumps from bank to bank as part of a for-next loop, because
    the for-next logic too is trashed. You have to create your own loop
    structures at the main level of the program. The mechanism I have outlined
    has only a one-level stack. I know of people who have gone way beyond that
    to create stack pointer and a deeper stack. But... your milage may vary...
    I like to keep it as KISS as possible. It is complicated enough already.
    You get used to it?

    In working with the BS2sx, usually several variable definitions to be
    consistent across all the banks. Call these "global". Some of them will
    be words, but others will be bytes, nibbles and bits. The Stamp software
    allocates RAM for all the words first, then bytes, then nibs, then bits.
    So if you have a one-bit flag you want to be global, you should _not_
    define it in this manner:
    flag0 var bit
    flag1 var bit
    --unless you plan meticulously to keep all of the variable definitions in
    all the banks exactly the same. Otherwise, a new variable introduced in
    one bank will throw off the alignment in the other banks. Unfortunately,
    the STAMP2W.EXE program does not have any kind of "include" directive, so
    keeping the variables consistent from bank to bank as a program develops
    can be a tremendous headache. I have found it much more effective and
    foolproof (that's me!) to define several global word variables at the top
    of my programs, and then define "global" bytes, nibs and bits as aliases
    inside those words. The variable "sxw" for bank switching mentioned above
    is one example. Here is another

    status var word 'near top of definitions in all banks.
    flag0 var status.bit0 ' global flag bit will not move
    flag1 var status.bit1
    nag var status.nib1 ' global nib
    bag var status.byte1 ' byte

    By defining the chucks as aliases inside words, the interpreter keeps the
    globals in consistent positions from bank to bank, and allows leftover RAM
    to be used indiscriminately for "local" variables.

    I always set aside several global words as a buffer to transfer data from
    bank to bank. I give those variables a generic name, and several alias
    names to indicate different functions, for time values here, for memory
    transfers there, for temporary process variables in another place, etc.
    That is the usual BS2 variable aliasing problem. I also make intensive use
    of the scratchRAM as a data buffer. Say you are logging data--it is easier
    to accumulate a string of 50 bytes in scratchRAM and then call another bank
    to transfer it all at once to external memory, than it is to call a memory
    routine in another bank 50 separate times. That is because of all the
    overhead involved in transferring from bank to bank. This may take some
    reorganization of a program originally written for a BS2. The subroutines
    for RUN should be "bigger". Smaller, frequently called subroutines may
    have to be duplicated in several banks to avoid the overhead.


    I hope that helps,

    -- Tracy Allen
    Electronically Monitored Ecosystems
    http://www.emesystems.com <-- there is some more 'sx info here
  • ArchiverArchiver Posts: 46,084
    edited 2000-07-18 04:13
    At 08:23 PM 7/17/00, you wrote:

    >Tracy,
    >
    >In a recent posting, you mentioned a "STAMP2W.EXE" program. Is this an
    >(overdue) non-beta version of the BS2SX editor? If so, where can I get it?
    >I couldn't find it on the Parallax web site. I can only find stampw.exe, the
    >BASIC Stamp II, IISX Windows 95/98/NT4.0 editor, v. 1.096 beta.
    >
    >Rob Richmond

    Rob -

    Too many twos <g>. The BS 2 and BS II (Roman numeral 2) are the same.
    The program name which you mention is the latest version - to my knowledge.

    Bruce Bates
  • ArchiverArchiver Posts: 46,084
    edited 2000-07-18 04:23
    Tracy,

    In a recent posting, you mentioned a "STAMP2W.EXE" program. Is this an
    (overdue) non-beta version of the BS2SX editor? If so, where can I get it?
    I couldn't find it on the Parallax web site. I can only find stampw.exe, the
    BASIC Stamp II, IISX Windows 95/98/NT4.0 editor, v. 1.096 beta.

    Rob Richmond
Sign In or Register to comment.