Shop OBEX P1 Docs P2 Docs Learn Events
Saving then Restoring the current BANK setting — Parallax Forums

Saving then Restoring the current BANK setting

Tony LeylandTony Leyland Posts: 71
edited 2005-03-01 19:09 in General Discussion
Hi all,

Does anyone know what is the best method of saving then restoring the current BANK setting ? I change banks within
a subroutine and would like to restore to the current bank used by the calling program, when returning from the subroutine.

I could just issue a BANK instruction in the the main code after the CALL instruction, but I'd like to treat the subroutine as a 'blackbox'
where no changes are made to important registers.

Many thanks,
Tony

Comments

  • BeanBean Posts: 8,129
    edited 2005-02-28 12:04
    Save the value in FSR when you start the routine and restore it at the end of the routine.
    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Check out· the "SX-Video Display Module"

    www.sxvm.com
    ·
  • Tony LeylandTony Leyland Posts: 71
    edited 2005-02-28 12:35
    Thanks Bean, I'll use that approach, although my global regs 8-15 are getting used up quickly :-(

    Tony
  • PJMontyPJMonty Posts: 983
    edited 2005-03-01 06:36
    Tony,

    Treat the globals like a precious resource - because they are. I'm not familiar with your level of programming experience, but the convenience of the globals is quickly outweighed by their scarcity. Most of what I'm going to mention is assembly oriented, but SX/B programmers should find useful info as well.

    One key to SX programming is grouping variables into banks. If you just toss any old variable into any old bank, you'll fgind yourself setting banks all over your code, making the code more brittle and prone to failure. Try and think about logical groups for the variables to be in, and organize them. It will mean less bank commands, and sub-routines that can simply access variables since the ones they need will usually be in the same bank.

    A helpful trick is to use an equ to set a name for the bank so your code reads in more like English. Here's some mock code setting up some variables for serial communications:

    ; I have a standard set of equates used to set the bank addresses
    ; Bank  equates
    BankGlobal  equ $08
    BankZero    equ $00
    BankOne     equ $30
    BankTwo     equ $50
    BankThree   equ $70
    BankFour     equ $90
    BankFive     equ $B0
    BankSix      equ $D0
    BankSeven equ $F0
    
        CommBank equ BankOne ; Set a "human" name to use in bank commands
        org CommBank                ; Use the human name to set the PC for defining these variables
    
    SerHead_TX      ds 1    ; Serial transmit head pointer
    SerTail_TX      ds 1    ; Serial transmit tail pointer
    SerHead_RX      ds 1  ; Serial receive head pointer
    SerTail_RX      ds 1  ; Serial receive tail pointer
    SerTxBuffer     ds 4    ; 4 byte transmit buffer
    SerRxBuffer     ds 4    ; 4 byte receive buffer
    
    ; This lets you know if you've allocated to many variables in this bank (thanks James Newton!)
    IF $ > $40
     ERROR 'Out of variable space for bank 1'
    ENDIF
    
    



    You code becomes easier to read because you can write this:
        bank CommBank        ;Get set to do communications work
    
    



    instead of this:
        bank $30                ; Get set to do something, but who can tell what it is?
    
    



    Another good trick is to use bit variables wherever possible. I often set up a global "flags" variable so that I have 8 bit flags I can use anywhere in my program without any bank switches. Set separate names for those bit flags so they are easy to read and understand in your code. For example:

    GlobalBank   EQU     $            ;Global reg bank
    byte         ds      1            ;temporary UART/I2C shift reg.
    GlobalFlags  ds      1            ;program flags register
    
    RxNewData_FLAG         EQU     GlobalFlags.5        ;Signals when byte is received
    TxEmpty_FLAG          EQU     GlobalFlags.2           ;Signals transmit buffer empty
    
    



    Globals make it quicker to write something, but usually make it a real pain to maintain or modify in the future. The time spent up front organizing banks of variables pays off as the project grows in size. Also, don't be afraid to set up banks as needed. I often create a new bank that only contains a variable or two because those vars don't really belong anywhere else. Sometimes I'll find that new vars pop up which fit with those, and sometimes I move them into other pre-existing banks; a lot depends on how the project evolves.
      Thanks, PeterM
  • Tony LeylandTony Leyland Posts: 71
    edited 2005-03-01 15:34
    Hi PeterM,

    I've been using a similar (but not as good) technique that you have described. I like the variables allocation
    checking, I'll implement it in my template.

    I was working rather "free n easy" with allocating variables to the GLOBAL range and so I will take care where
    they go in future - I now only have TempW, TempFSR and 3 memory management variables in the GLOBALS.

    I come from a Z80,68000,80486 background and so I am getting used to the RISC processor
    configuration of the SX !

    Many thanks for your help.
    Tony
  • Paul BakerPaul Baker Posts: 6,351
    edited 2005-03-01 16:17
    G
  • PJMontyPJMonty Posts: 983
    edited 2005-03-01 19:09
    Tony,

    Yeah, I came from the 6502, 68HC11, and 80806 world of assembly, so I know what you mean. Many is the time I curse the SX and the "CPU-designer-on-drugs" architecture it has, only to get the code working and marvel at how bad-*** fast it is. Programming the SX in assembly is something that takes a little bit of work to wrap your head around. Good with the bad, I guess...
      hanks, PeterM
Sign In or Register to comment.