Nikolai Golovchenko says:
cblock 0x20 Temp, Counter ReH, ReL, ImH, ImL RekH, RekL, ImkH, ImkL endc #define XX 22520 #define YY 1 movlw low(XX) movwf ReL movlw high(XX) movwf ReH movlw low(YY) movwf ImL movlw high(YY) movwf ImH again call Magnitude16 stop nop incf ReL, f skpnz incf ReH, f movf ImL, f skpnz decf ImH, f decf ImL, f goto again ;*********************************************** ; 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+4+7.5*9)+60 ~= 1600 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 ~800 cycles! ; ; 6 Aug 2000 by Nikolai Golovchenko ;*********************************************** Magnitude16 ;Find absolute value of the vector components btfss ReH, 7 ;Re = abs(Re) goto Magnitude16a comf ReL, f comf ReH, f incf ReL, f skpnz incf ReH, f Magnitude16a btfss ImH, 7 ;Im = abs(Im) goto Magnitude16b comf ImL, f comf ImH, f incf ImL, f skpnz incf ImH, f Magnitude16b ;Test imaginary part for zero and if yes, quit movf ImL, w iorwf ImH, w skpnz return ;quit if zero imaginary part ;Perform first iteration movf ImL, w ;Imk = Im movwf ImkL movf ImH, w movwf ImkH movf ReL, w ;Im' = Im - Re subwf ImL, f movf ReH, w skpc incfsz ReH, w subwf ImH, f movf ImkL, w ;Re' = Re + Im = Re + Imk addwf ReL, f movf ImkH, w skpnc incfsz ImkH, w addwf ReH, f ;Begin loop movlw 1 movwf Counter Magnitude16loop ;load scaled values movf ImL, w ;Imk = Im movwf ImkL movf ImH, w movwf ImkH movf ReL, w ;Rek = Re movwf RekL movf ReH, w movwf RekH ;scale them (1 to 15 right shifts) movf Counter, w ;load counter value to Temp movwf Temp Magnitude16loop2 clrc ;unsigned right shift for Rek rrf RekH, f rrf RekL, f rlf ImkH, w ;signed right shift for Imk rrf ImkH, f rrf ImkL, f decfsz Temp, f goto Magnitude16loop2 ;update current values movf ImkL, w btfsc ImH, 7 ;if Im < 0 add a phase, if Im >= 0 substract a phase goto Magnitude16AddPhase ;substract a phase addwf ReL, f ;Re' = Re + Imk movf ImkH, w skpnc incfsz ImkH, w addwf ReH, f movf RekL, w ;Im' = Im - Rek subwf ImL, f movf RekH, w skpc incfsz RekH, w subwf ImH, f goto Magnitude16loopend Magnitude16AddPhase ;add a phase skpnc ;correct Imk, because shifts of negative incfsz ImkL, w ;values like (-1 >> 1 = -1) can decf ImkH, f ;accumulate error. With this correction, incf ImkH, f ;shifts of negative values will work like ;shifts of positive values (i.e. round to zero) subwf ReL, f ;Re' = Re - Imk movf ImkH, w skpc incfsz ImkH, w subwf ReH, f movf RekL, w ;Im' = Im + Rek addwf ImL, f movf RekH, w skpnc incfsz RekH, w addwf ImH, f Magnitude16loopend incf Counter, f btfss Counter, 4 ;repeat untill counter reaches 16 ;or uncomment this for better performance ; btfss Counter, 3 ;repeat untill counter reaches 8 goto Magnitude16loop ;Optional: ;Divide result by 1.64676025786545 (CORDIC gain) ;or multiply by 0.60725293510314 = 1/2+1/8-1/64-1/512 - 0.028% movf ReH, w movwf RekH movf ReL, w movwf RekL clrc rrf ReH, f rrf ReL, f clrc rrf ReH, f rrf ReL, f clrc rrf ReH, f rrf ReL, f comf ReL, f comf ReH, f incf ReL, f skpnz incf ReH, f clrf Temp btfsc ReH, 7 comf Temp, f subwf ReL, f movf RekH, w skpc incfsz RekH, w subwf ReH, f skpc decf Temp, f rrf Temp, f rrf ReH, f rrf ReL, f rrf Temp, f rrf ReH, f rrf ReL, f rlf ReH, w rrf ReH, f rrf ReL, f movf RekL, w addwf ReL, f movf RekH, w skpnc incfsz RekH, w addwf ReH, f clrc rrf ReH, f rrf ReL, f clrc rrf ReH, f rrf ReL, f movf RekL, w addwf ReL, f movf RekH, w skpnc incfsz RekH, w addwf ReH, f rrf ReH, f rrf ReL, f ;Done! return ;***********************************************
Comments:
file: /Techref/microchip/math/vector/mag-ng.htm, 5KB, , updated: 2007/2/13 12:43, local time: 2024/11/20 00:20,
18.223.196.123:LOG IN
|
©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/microchip/math/vector/mag-ng.htm"> PIC Microcontoller Math Method </A> |
Did you find what you needed? |