Menu

Problem with word variables treated as Byte

2010-12-07
2013-05-30
  • Edward LaBudde

    Edward LaBudde - 2010-12-07

    Hi all, having a problem with GCB.  Here is a subroutine for finding phase angles.  Everything works fine for the first 3 quadrants.  The calculated phase for Img=100, Real = 100 (1st quad) is 44 degrees. For Img = -100, Real =100 (4th quad) the phase is 58 degrees not 314 as it should be (GCB adds 14 not 270).  It appears that GCB is treating Phasex as a byte not a word variable.  Here is the code and .asm snippet showing the problem.  Nothing I have tried can fix this problem!

    Can someone help me correct this problem or is there a bug in GCB?  Thanks, ED.

    [code]
    Sub Phase (Img, Real)           
        Dim Phasex as word          ‘Note word variable
        Dim Real as integer
        Dim Img as integer
        Dim ImgTemp as word
        Dim RealTemp as word
        Dim tan as word
        Dim H2 as word
        call Sign (img)             ‘Find sign
        If Img = 0 then IMG = 1*Signx       'keep from divide by zero
        Call Quad (Img,Real)            'Find quadrant
        ImgTemp = IMG*IMG           'Take Absolute value
        Call SQRT (ImgTemp)
        Img = ImgTemp
        RealTemp = Real*Real            ‘Take Absolute value
        Call SQRT (RealTemp)
        Real = RealTemp
        if img < Real then          'Keep Tan > 1
            Tan = Real/Img
        Else
            Tan = Img/Real
        End If
        H2 = 157 - 400*tan/(4*tan*tan + 1)  'Approximate Phase in degrees (+/- 2 degree accuracy)
        if Img < Real then
            Phasex = 90-H2*4/7
        else
            Phasex = H2*4/7
        end if
        If Quadx = 1 then Phasex = Phasex
        If Quadx = 2 Then Phasex = Phasex + 90
        If Quadx = 3 Then Phasex = Phasex + 180
        If Quadx = 4 Then Phasex =  [word]Phasex + [word]270 'problem here Phasex acts like a Byte not word
    Return
    Here is the .asm file at Quad 3 and 4
    movlw   3
        subwf   QUADX,W
        btfss   STATUS, Z
        goto    ENDIF6
        movlw   180 -------------------This is correct
        addwf   PHASEX,F
        movlw   0
        btfsc   STATUS,C
        addlw   1
        addwf   PHASEX_H,F
    ENDIF6
        movlw   4
        subwf   QUADX,W
        btfss   STATUS, Z
        goto    ENDIF7
        movlw   14 -------------------------Not correct! It is adding 14 to Phasex not 270  e.g. 14 = 44+270-256-44  acting like a byte overflow
        addwf   PHASEX,F
        movlw   1
        btfsc   STATUS,C
        addlw   1
        addwf   PHASEX_H,F
    ENDIF7
        return
    [/code]
    
     
  • Frank

    Frank - 2010-12-08

    Hi Ed,

    The assembly looks all right for the 4th quadrant - its adding 14 to PHASEX and then adding 1 to PHASEX_H which is the name GCBasic gives to the high byte of the word so the assembly code is adding 1 x 256 + 14 = 270 to the PHASEX word as a whole.

    Maybe the problem is later in your code - if PHASEX gets assigned to a byte variable later then you would lose the high byte and just see 58. You might also try moving the Phasex dim to the top of the program outside the sub or else make Phasex one of the subs parameters so its explicitly returned like this -

    sub Phase(Img , Real, out Phasex as word)

    and delete the dim for  Phasex in the next  line. I think GCBasic treats variables differently if they are dim'ed inside a sub - they become something like local variables. Outside the sub they often seem to be treated just like bytes regardless of what they were dim'ed as inside the sub. That may be by design though as I think it does allow certain system variables to be used as bytes or words depending on the sub using them.

    Frank

     
  • Edward LaBudde

    Edward LaBudde - 2010-12-08

    Frank thanks for your input.  When I went back today to check to see if the high Byte of Phasex was set to zero, I was shocked to find it was working correctly today!!!  I have no Idea what was wrong yesterday, as it is the identical setup.

    I did run into a new problem.  I found that if the SQRT subroutine is called more than once, it returns a value of “0” on the second pass.  I am not able to discover why.  The only way to make it work correctly is to mage a separate subroutine for each call each with a different name e.g. Sqrt, Sqrt2.    This uses up a lot more memory for all the new variables. Worst yet, Each subroutine can only be called once. 

    This is a real problem as I was intending to use this in an instrument requiring updates at a frequent rate.  If put in a loop it only gives the correct answer on the first pass.

    Try this your self-using: You will see that Vd is 5 and Vn is 0

    Any Ideas Hugh?

    [Code]
    call SQRT(25)
    Vd = SQRTx 
    call SQRT(100)
    Vn = SQRTx
    Sub SQRT (value)             
        Dim Value as word
        Dim Guess_old as word
        Dim Guess_new as word  
        Dim Delta as word
        Dim SQRTX as word
        Guess_old = 0
        Guess_new = 0
        Count = 0
        If value <= 50 then
            Guess_div = 1
        else
            Guess_div = 50
        end if
        Guess_old = value/Guess_div 
        Do until Delta = 0
            Count += 1
            Guess_new = (Guess_old + value/Guess_old)/2
            Delta = Guess_new - Guess_old
            Guess_old = Guess_new
        Loop 
        Sqrtx = Guess_new
    Return
    [/code]
    
     
  • Edward LaBudde

    Edward LaBudde - 2010-12-08

    Hi All, I found the problem with the second pass!  It was due to leaving the Variable delta = 0 after the first pass.  This requires
    Delta to be initialized at the start of the routine to a number other than 0 e.g. Delta = 1.  That fixes the problem.  How embarrassing!

    Sub SQRT (value)            'Tested time = 99 us Adding in/out will stop copy back 
        Dim Value as word
        Dim Guess_old as word
        Dim Guess_new as word  
        Dim Delta as word
        Dim SQRTX as word
        Guess_old = 0
        Guess_new = 0
        Count = 0
        Delta = 1
        If value <= 50 then
            Guess_div = 1
        else
            Guess_div = 50
        end if
        Guess_old = value/Guess_div 
        Do until Delta = 0
            Count += 1
            Guess_new = (Guess_old + value/Guess_old)/2
            Delta = Guess_new - Guess_old
            Guess_old = Guess_new
        Loop 
        Sqrtx = Guess_new
    Return
    
     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.