yzou_ua
Member level 5
I know nothing about assembly code, so here is what I'm doing:
I have a assembly rouine for atan(), how to make it work for my following c code:
#include "p33fj64gs610"
#include <math.h>
...
int main()
{...
x=4;
y=5;
ang = atan(x,y);
...
}
Attaching assembly code here:
; constant definitions
.equ NEG_PI_BY_2, 0xC000
.equ PI_BY_2, 0x3FFF
.equ PI, 0x7FFF
.equ NEG_PI, 0x8000
.equ ACCUM_PHASE, w7
; in this table are the values of atan scaled into the range 0 to PI
; and then converted into fractional format
.section .data
CORDIC_DATA:
.word 0x2000 ; atan(1.0) / PI
.word 0x12E4 ; atan(0.5) / PI
.word 0x09FB ; atan(0.25) / PI
.word 0x0511 ; atan(0.125) / PI
.word 0x028B ; atan(0.0625) / PI
.word 0x0146 ; etc
.word 0x00A3
.word 0x0051
.word 0x0029
.word 0x0014
.word 0x000A
.word 0x0005
.word 0x0003
.word 0x0001
.word 0x0001
.word 0x0000
.section .text
.global _atan2CORDIC
_atan2CORDIC:
lnk #0x02 ; reserve 2 bytes for storage
push w8
push w9
push CORCON
; check for values that cause errors
; due to asymptotic atan behaviour
mov #0x8000, w8
cp w0, w8 ; Q = -1.0 ?
bra NZ, checkI
mov #NEG_PI_BY_2, w0
bra exitCORDICRoutine
checkI:
cp w1, w8 ; I = -1.0
bra NZ, mainCORDICRoutine
mov #PI, w0
bra exitCORDICRoutine
mainCORDICRoutine:
; set w9 to point to the reserved 2 byte space
; this can then be used to preload w6 in the dsp MACs
mov w14, w9
; ACCUM_PHASE (w7) is the total phase angle calculated
clr ACCUM_PHASE
; adjust q and i to be in quadrant I
cp0 w1
bra NN, setupIter
mov w1, [w9] ; w2 = temporary I
cp0 w0
bra LE, quadIII
mov w0, w1
neg [w9], w0
mov #NEG_PI_BY_2, ACCUM_PHASE
bra setupIter
quadIII:
neg w0, w1
mov [w9], w0
mov #PI_BY_2, ACCUM_PHASE
setupIter:
; set ACCA and ACCB to equal I and Q
lac w0, #1, B
lac w1, #1, A
mov #CORDIC_DATA, w8 ; w8 points to CORDIC data table
mov #0x7FFF, w5 ; w5 = K = 1.0
do #9, endCORDICRoutine
sac.r a, [w9] ; put I onto local stack
sac.r b, w6 ; w6 = Q
cp0 w6 ; if Q < 0 goto rotate positive
bra N, rotate_pos
rotate_neg:
mac w5*w6, a ; I = I + Q * K, w6 = temp I
mov [w9], w6
msc w5*w6, b ; Q = Q - oldI * K
mov [w8++], w4
subbr w4, ACCUM_PHASE, ACCUM_PHASE
bra endCORDICRoutine
rotate_pos:
msc w5*w6, a ; I = I - Q * K, w6 = temp I
mov [w9], w6
mac w5*w6, b ; Q = Q + oldI * K
mov [w8++], w4
add w4, ACCUM_PHASE, ACCUM_PHASE
endCORDICRoutine:
lsr w5, w5 ; K = K / 2
neg ACCUM_PHASE, w0 ; reverse the sign
exitCORDICRoutine:
pop CORCON
pop w9
pop w8
ulnk
return
.end
I have a assembly rouine for atan(), how to make it work for my following c code:
#include "p33fj64gs610"
#include <math.h>
...
int main()
{...
x=4;
y=5;
ang = atan(x,y);
...
}
Attaching assembly code here:
; constant definitions
.equ NEG_PI_BY_2, 0xC000
.equ PI_BY_2, 0x3FFF
.equ PI, 0x7FFF
.equ NEG_PI, 0x8000
.equ ACCUM_PHASE, w7
; in this table are the values of atan scaled into the range 0 to PI
; and then converted into fractional format
.section .data
CORDIC_DATA:
.word 0x2000 ; atan(1.0) / PI
.word 0x12E4 ; atan(0.5) / PI
.word 0x09FB ; atan(0.25) / PI
.word 0x0511 ; atan(0.125) / PI
.word 0x028B ; atan(0.0625) / PI
.word 0x0146 ; etc
.word 0x00A3
.word 0x0051
.word 0x0029
.word 0x0014
.word 0x000A
.word 0x0005
.word 0x0003
.word 0x0001
.word 0x0001
.word 0x0000
.section .text
.global _atan2CORDIC
_atan2CORDIC:
lnk #0x02 ; reserve 2 bytes for storage
push w8
push w9
push CORCON
; check for values that cause errors
; due to asymptotic atan behaviour
mov #0x8000, w8
cp w0, w8 ; Q = -1.0 ?
bra NZ, checkI
mov #NEG_PI_BY_2, w0
bra exitCORDICRoutine
checkI:
cp w1, w8 ; I = -1.0
bra NZ, mainCORDICRoutine
mov #PI, w0
bra exitCORDICRoutine
mainCORDICRoutine:
; set w9 to point to the reserved 2 byte space
; this can then be used to preload w6 in the dsp MACs
mov w14, w9
; ACCUM_PHASE (w7) is the total phase angle calculated
clr ACCUM_PHASE
; adjust q and i to be in quadrant I
cp0 w1
bra NN, setupIter
mov w1, [w9] ; w2 = temporary I
cp0 w0
bra LE, quadIII
mov w0, w1
neg [w9], w0
mov #NEG_PI_BY_2, ACCUM_PHASE
bra setupIter
quadIII:
neg w0, w1
mov [w9], w0
mov #PI_BY_2, ACCUM_PHASE
setupIter:
; set ACCA and ACCB to equal I and Q
lac w0, #1, B
lac w1, #1, A
mov #CORDIC_DATA, w8 ; w8 points to CORDIC data table
mov #0x7FFF, w5 ; w5 = K = 1.0
do #9, endCORDICRoutine
sac.r a, [w9] ; put I onto local stack
sac.r b, w6 ; w6 = Q
cp0 w6 ; if Q < 0 goto rotate positive
bra N, rotate_pos
rotate_neg:
mac w5*w6, a ; I = I + Q * K, w6 = temp I
mov [w9], w6
msc w5*w6, b ; Q = Q - oldI * K
mov [w8++], w4
subbr w4, ACCUM_PHASE, ACCUM_PHASE
bra endCORDICRoutine
rotate_pos:
msc w5*w6, a ; I = I - Q * K, w6 = temp I
mov [w9], w6
mac w5*w6, b ; Q = Q + oldI * K
mov [w8++], w4
add w4, ACCUM_PHASE, ACCUM_PHASE
endCORDICRoutine:
lsr w5, w5 ; K = K / 2
neg ACCUM_PHASE, w0 ; reverse the sign
exitCORDICRoutine:
pop CORCON
pop w9
pop w8
ulnk
return
.end