Complex number magnitude calculation
;***********************************************
; Complex number magnitude calculation
; using CORDIC algorithm described at
; www.dspguru.com\info\faqs\cordic.htm
;
; Input:
; ReH:ReL, ImH:ImL - complex number (16 bit signed)
;
; Output:
; ReH:ReL - magnitude (16 bit unsigned)
; ImH:ImL - garbage
;
; Temporaries:
; RekH:RekL - Re multipled by k (k=2^-L, L=0,1,2,...15)
; Counter - loop counter
; Temp
;
; Instructions: 147
; Execution time(worst case including return):
; 18+18+15*(8+2+20+5+7.5*10-2)+60 ~= 1700 instruction cycles
; Notes:
; 1) Precision is 0.028%, depends on how exact
; the division by CORDIC gain is implemented:
; (0.60725293510314)
; a) 1/2+1/8-1/64-1/512 -> 0.028%
; b) 1/2+1/8-1/64-1/512-1/4096 -> 0.012384%
; c) 1/2+1/8-1/64-1/512-1/4096+1/16384 -> 0.002333%
; 2) Range of input data should be restricted so
; that M=sqrt(Re*Re+Im*Im) is less than 65536*0.60725293510314~=39760
; to prevent overflow in magnitude during calculation
; 3) To reduce execution time, the number of loops can be
; reduced to 8. The angle after rotation the initial
; vector 8 times is less then 0.22381 deg, which is good
; enough precision. Besides, the gain at 8 rotations is smaller
; and closer to the approximated gain, which is used in this code.
; Reduced execution time will be ~850 cycles!
;
; 6 Aug 2000 by Nikolai Golovchenko
;***********************************************
Magnitude16
;Find absolute value of the vector components
sb ReH.7 ;Re = abs(Re)
jmp Magnitude16a
not ReL
not ReH
inc ReL
snb Z
inc ReH
Magnitude16a
sb ImH.7 ;Im = abs(Im)
jmp Magnitude16b
not ImL
not ImH
inc ImL
snb Z
inc ImH
Magnitude16b
;Test imaginary part for zero and if yes, quit
mov W, ImL
or W, ImH
snb Z
ret ;quit if zero imaginary part
;Perform first iteration
mov W, ImL ;Imk = Im
mov ImkL, W
mov W, ImH
mov ImkH, W
mov W, ReL ;Im' = Im - Re
sub ImL, W
mov W, ReH
sb C
movsz W, ++ReH
sub ImH, W
mov W, ImkL ;Re' = Re + Im = Re + Imk
add ReL, W
mov W, ImkH
snb C
movsz W, ++ImkH
add ReH, W
;Begin loop
mov W, #1
mov Counter, W
Magnitude16loop
;load scaled values
mov W, ImL ;Imk = Im
mov ImkL, W
mov W, ImH
mov ImkH, W
mov W, ReL ;Rek = Re
mov RekL, W
mov W, ReH
mov RekH, W
;scale them (1 to 15 right shifts)
mov W, Counter ;load counter value to Temp
mov Temp, W
Magnitude16loop2
clrb C ;unsigned right shift for Rek
rr RekH
rr RekL
mov W, <<ImkH ;signed right shift for Imk
rr ImkH
rr ImkL
decsz Temp
jmp Magnitude16loop2
;update current values
mov W, ImkL
snb ImH.7 ;if Im < 0 add a phase, if Im >= 0 substract a phase
jmp Magnitude16AddPhase
;substract a phase
add ReL, W ;Re' = Re + Imk
mov W, ImkH
snb C
movsz W, ++ImkH
add ReH, W
mov W, RekL ;Im' = Im - Rek
sub ImL, W
mov W, RekH
sb C
movsz W, ++RekH
sub ImH, W
jmp Magnitude16loopend
Magnitude16AddPhase
;add a phase
snb C ;correct Imk, because shifts of negative
movsz W, ++ImkL ;values like (-1 >> 1 = -1) can
dec ImkH ;accumulate error. With this correction,
inc ImkH ;shifts of negative values will work like
;shifts of positive values (i.e. round to zero)
sub ReL, W ;Re' = Re - Imk
mov W, ImkH
sb C
movsz W, ++ImkH
sub ReH, W
mov W, RekL ;Im' = Im + Rek
add ImL, W
mov W, RekH
snb C
movsz W, ++RekH
add ImH, W
Magnitude16loopend
inc Counter
sb Counter.4 ;repeat untill counter reaches 16
;or uncomment this for better performance
; sb Counter.3 ;repeat untill counter reaches 8
jmp Magnitude16loop
;Optional:
;Divide result by 1.64676025786545 (CORDIC gain)
;or multiply by 0.60725293510314 = 1/2+1/8-1/64-1/512 - 0.028%
mov W, ReH
mov RekH, W
mov W, ReL
mov RekL, W
clrb C
rr ReH
rr ReL
clrb C
rr ReH
rr ReL
clrb C
rr ReH
rr ReL
not ReL
not ReH
inc ReL
snb Z
inc ReH
clr Temp
snb ReH.7
not Temp
sub ReL, W
mov W, RekH
sb C
movsz W, ++RekH
sub ReH, W
sb C
dec Temp
rr Temp
rr ReH
rr ReL
rr Temp
rr ReH
rr ReL
mov W, <<ReH
rr ReH
rr ReL
mov W, RekL
add ReL, W
mov W, RekH
snb C
movsz W, ++RekH
add ReH, W
clrb C
rr ReH
rr ReL
clrb C
rr ReH
rr ReL
mov W, RekL
add ReL, W
mov W, RekH
snb C
movsz W, ++RekH
add ReH, W
rr ReH
rr ReL
;Done!
ret
;***********************************************
file: /Techref/scenix/lib/math/vect/mag-ng_sx.htm, 4KB, , updated: 2004/6/10 13:40, local time: 2024/12/26 00:11,
owner: NG--944,
|
| ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://linistepper.com/techref/scenix/lib/math/vect/mag-ng_sx.htm"> SX Microcontroller Math Method </A> |
Did you find what you needed?
|