Shop OBEX P1 Docs P2 Docs Learn Events
Temp Varable with SXB — Parallax Forums

Temp Varable with SXB

RS_JimRS_Jim Posts: 1,771
edited 2008-08-24 07:48 in General Discussion
Good Morning,

Jonny Mac recently posted a neat series of routines that printed out bin hex and Dec results from Byte parameters.· I thought that was really cool but needed a Decimal printout of a Word Varable.· So I edited his routine and came up with the following:

'
' Use: TX_DEC5 value
' -- transmit word in (fixed-width) DEC5 format
'
SUB TX_DEC5
·dvalW· VAR TmpW1
·divisorW VAR tmpW2
·dDigit· Var tmpB1
·dChar· Var tmpB2

· dValW = __wPARAM12······················ ·' copy output value
· divisorW = 10000···························· ··' set initial divisor
· FOR dDigit = 4 TO 0 STEP -1············ · ·' show three digits
··· __wparam34 = dValW / divisorW·········· ' get a digit
··· dValW = __wREMAINDER··············· ··· ·' save remainder
·· dChar = __param3··························· ·' it going to be <10
·· dChar = dChar + "0"·························· ' convert to ASCII
··· TX_BYTE dChar
··· divisorW = divisorW / 10··············· ···· ' update divisor
· NEXT
·
ENDSUB
if I declare tmpW1 = 23456· or any 5 digit number short of 65,535:
·· TX_DEC5 tmpW1

my results always come out 00000.
I wonder if I have one temp varable stepping on another.· When I look at .lst file I do find some VAR with the same address.· I am I missing something?· It is hard to step through the Devide by 10,000 to see what is happening.· I tried setting dChar = dValw / divisorW but it is expecting a word param not a byte and wont compile.

Comments

  • ZootZoot Posts: 2,227
    edited 2008-08-23 15:27
    Does the TX_BYTE sub use one of the tmps? Can you post the whole program?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-23 18:37
    Jim,

    You can't use __WPARAM34 as the result of a division because those bytes (__PARAM3 and __PARAM4) are actually used to hold the divisor during the division -- your code is clobbering the divisor as it runs. I've been "looking under the hood" a lot and finding areas where internal variables can be used; here are some examples.

    SUB DELAY_MS
      \ SB   __PARAMCNT.1
      \ CLR  __WPARAM12_MSB
      PAUSE __WPARAM12
      ENDSUB
    
    ' -------------------------------------------------------------------------
    
    SUB TX_BYTE
      SEROUT TX, Baud, __PARAM1
      ENDSUB
    
    ' -------------------------------------------------------------------------
    
    SUB TX_STR
      strAddr       VAR     __WPARAM34
      sChar         VAR     __PARAM1
    
      strAddr = __WPARAM12
    
      DO
        READINC strAddr, sChar
        IF sChar = 0 THEN EXIT
        TX_BYTE sChar
      LOOP
      ENDSUB
    
    ' -------------------------------------------------------------------------
    
    SUB TX_DEC5
      wResult       VAR     tmpW1
      wDivisor      VAR     tmpW2
      wIdx          VAR     tmpB1
      wChar         VAR     __PARAM3
    
      \ SB   __PARAMCNT.1
      \ CLR  __WPARAM12_MSB
      wResult = __WPARAM12
      wDivisor = 10_000
    
      FOR wIdx = 4 TO 0 STEP -1
        wResult = wResult / wDivisor
        wChar = wResult_LSB + "0"
        wResult = __WREMAINDER
        TX_BYTE wChar    
        wDivisor = wDivisor / 10
      NEXT
      ENDSUB
    


    As you can see there are very limited opportunities to use internal variables with TX_DEC5 -- sometimes it just works that way.

    Post Edited (JonnyMac) : 8/23/2008 9:49:23 PM GMT
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-23 19:52
    If you want to generalize that routine so that it will print only the characters needed you can do it like this:

    SUB TX_DEC 
      wResult       VAR     tmpW1
      wDivisor      VAR     tmpW2
      wIdx          VAR     tmpB1
      wChar         VAR     __PARAM3
    
      \ SB  __PARAMCNT.1
      \ CLR __WPARAM12_MSB
      wResult = __WPARAM12
      
      IF wResult > 9999 THEN
        wDivisor = 10_000
        wIdx = 5
      ELSEIF wResult > 999 THEN
        wDivisor = 1_000
        wIdx = 4
      ELSEIF wResult > 99 THEN
        wDivisor = 100
        wIdx = 3
      ELSEIF wResult > 9 THEN
        wDivisor = 10
        wIdx = 2
      ELSE
        wChar = __WPARAM12_LSB + "0"
        TX_BYTE wChar
        widx = 0
      ENDIF
    
      DO WHILE wIdx > 0
        wResult = wResult / wDivisor
        wChar = wResult_LSB + "0"
        wResult = __WREMAINDER
        TX_BYTE wChar    
        wDivisor = wDivisor / 10    
        DEC wIdx
      LOOP
      ENDSUB
    

    Post Edited (JonnyMac) : 8/23/2008 9:46:21 PM GMT
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-23 21:06
    How about one more version before I head across the hill to Hollywood for a big party. This one lets you pass a value and the number of digits you want to print.

    ' Use: TX_FDEC value, digits
    ' -- formatted decimal
    
    SUB TX_FDEC
      wResult       VAR     tmpW1
      wDivisor      VAR     tmpW2
      wIdx          VAR     tmpB1
      wChar         VAR     __PARAM3
    
      IF __PARAMCNT = 2 THEN
        wResult = __PARAM1
        wIdx = __PARAM2
      ELSE
        wResult = __WPARAM12
        wIdx = __PARAM3
      ENDIF
    
      wIdx = wIdx MIN 1
      wIdx = wIdx MAX 5
    
      IF wIdx = 5 THEN
        wDivisor = 10_000
      ELSE
        INC wIdx                                    ' point to next divisor
        wIdx = wIdx << 1                            ' wIdx*2 for WDATA
        READ D_Table+wIdx, wDivisor                 ' get divisor
        wResult = wResult // wDivisor               ' truncate unused digits
        wIdx = wIdx - 2                             ' readjust for value
        READ D_Table+wIdx, wDivisor                 ' get divisor for print loop
        wIdx = wIdx >> 1                            ' wIdx/2 for print loop
      ENDIF
    
      DO WHILE wIdx > 0
        wResult = wResult / wDivisor
        wChar = wResult_LSB + "0"
        wResult = __WREMAINDER
        TX_BYTE wChar
        wDivisor = wDivisor / 10
        DEC wIdx
      LOOP
      ENDSUB
    
    
    ' -------------------------------------------------------------------------
    ' User Data
    ' -------------------------------------------------------------------------
    
    D_Table:
      WDATA 1, 1, 10, 100, 1_000, 10_000
    



    [noparse][[/noparse]Edit] After having a bit of lunch I was able to trim all thre TX_DEC type routines. Note that the order of instructions is important due to the use of internal variables where possible.

    Post Edited (JonnyMac) : 8/23/2008 9:48:35 PM GMT
  • RS_JimRS_Jim Posts: 1,771
    edited 2008-08-24 05:12
    Thanks Jonny,

    I suspected that I was stepping on one of the temp variables.· Is there anywhere that their addresses are listed so that we can determine ahead of time when not to use a particular temp variable?· Or do I have to print out the variable section of the .lst file and go through it with a fine tooth comb?· I really appreciate the code as it should help what I am doing a lot.

    JIm
  • JonnyMacJonnyMac Posts: 9,215
    edited 2008-08-24 07:48
    Yep, you've got to take the fine-tooth comb approach. I use Ctrl-L all the time to look at the list file to see where I can sneak in the use of an internal variable.
Sign In or Register to comment.