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 variableDim Real as integerDim Img as integerDim ImgTemp as wordDim RealTemp as wordDim tan as wordDim H2 as wordcall Sign (img) ‘Find signIf 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 wordReturnHere is the .asm file at Quad 3 and 4movlw 3subwf QUADX,Wbtfss STATUS, Zgoto ENDIF6movlw 180 -------------------This is correctaddwf PHASEX,Fmovlw 0btfsc STATUS,Caddlw 1addwf PHASEX_H,FENDIF6movlw 4subwf QUADX,Wbtfss STATUS, Zgoto ENDIF7movlw 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,FENDIF7return[/code]
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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=SQRTxSub SQRT (value) Dim Value as wordDim Guess_old as wordDim Guess_new as word Dim Delta as wordDim SQRTX as wordGuess_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_newReturn[/code]
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
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.
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
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?
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!