{ My first try for a cordic alg for spin in Propeller asm ist a lot of literature in the web about this algorithm for example a C program by Turkowski in 1999 (Apple Computer!!) http://www.worldserver.com/turk/computergraphics/FixedPointTrigonometry.pdf and http://www.gamedev.net/reference/articles/article406.asp which i have taken as blueprint (its a C programm) M.G. 2009 - 16.09.2009 Assembler version still missing - variable exchange - command interpreter Best to understand if you study the SPIN version cordic.spin. I tried a 1:1 translation but... .....this was a hard job.... Most frustrating: fetch from an array in Propasm: it is a desaster! I tried it 3 days, and found only this kind of silly solution, based on an example in the OBEX: The self modifiing code works afaik only for increments of one, so i have to fetch the values in a loop, quite frustrating, the worst construct in the Propasm architecture, they should at least encapsulate it in another construct like gvi value, pointer = get value and increment pointer or so. Generaly i would prefer an arithmetic syntax as with the ADSP from Analog Devices for exampe: xs = x xs = x+1 y = value[xs] y = y << 3 most of it may be translated to Propasm 1:1 without using an Interpreter like Spin } CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 #1, _GO1, _GO2 ' 1, 2.. ''Obj vp:"Conduit" VAR long cog, command, vectorlength OBJ ' dbg : "PASDebug" '<---- Add for Debugger PUB atan2(Xvalue, Yvalue)| angle, length, Value, Flag ' dbg.start(31, 30, @entry) ' vp.Share(@x,@Flag) ' Share memory from varA to varC with ViewPort. This lets you Flag := 1 setcommand(_GO1, @Xvalue) repeat until Flag == 0 ''Wait for Flag to clear ... data is ready vectorlength := length return angle '------------------------------------------------------------------------------------------- PUB getlength return vectorlength PUB start : okay stop okay := cog := cognew(@loop, @command)+1 PUB stop if cog cogstop(cog~ -1) command~ PRI setcommand(cmd, argptr) command := cmd << 16 + argptr repeat while command '################################################################################################################ DAT org 0 entry ' Remove the debug Kernel ' --------- Debugger Kernel for PASD add this at Entry (Addr 0) --------- { long $34FC1202,$6CE81201,$83C120B,$8BC0E0A,$E87C0E03,$8BC0E0A long $EC7C0E05,$A0BC1207,$5C7C0003,$5C7C0003,$7FFC,$7FF8 } ' -------------------------------------------------------------- '' ther first part is from http://obex.parallax.com/objects/431/ '' from SPI Engine. a 1:1 copy as message and parameter passing function '' not easy to understand ;-) - main loop ' loop rdlong t1,par wz ''wait for command if_z jmp #loop ''loop '' forher #loop movd :arg,#arg0 ''get 5 arguments ; arg0 to arg4 mov t2,t1 '' mov t3,#5 '' :arg rdlong arg0,t2 add :arg,d0 add t2,#4 djnz t3,#:arg mov address,t1 ''preserve address location for passing ''variables back to Spin language. wrlong zero,par ''zero command to signify command received ror t1,#16+2 ''lookup command address add t1,#jumps movs :table,t1 rol t1,#2 shl t1,#3 :table mov t2,0 shr t2,t1 and t2,#$FF jmp t2 ''jump to command jumps byte 0 ''0 byte GO1_ ''1 byte GO1_ ''2 not used byte NotUsed_ ''3 not used NotUsed_ jmp #loop '################################################################################################################ GO1_ nop mov x, arg0 mov y, arg1 '########################################################################################## cordic_asm mov theta, #0 cmps x, #0 wc ' c set if (x < 0) if_nc jmp #_w1 ' if (x>=0) jump to _w1 neg x,x ' x = -x HINT : neg without # neg y,y ' y = -y mov theta, quadrant shl theta, #1 ' QUARTER * 2 _w1 cmps y, #0 wc 'c set if y < 0 if_c jmp #_w2 ' if (y<0) jump to w2 neg theta, theta ' theta = -theta _w2 mov apointer,#1 ' set pointer 1 cmps y, #0 wc ' c set if y < 0 if_nc jmp #_w3 mov xs, x ' xs = x shl xs, #1 ' xs = xs << 1 mov yi, y ' yi = y adds yi, xs ' yi = yi + xs HINT: adds and subs without # mov ys, y ' ys = y shl ys, #1 ' ys = ys << 1 subs x, ys ' x = x - ys mov y, yi ' y = yi call #fetch_atan ' atanvalue = atab[apointer] add apointer, #1 ' apointer = apointer+1 subs theta, atanvalue ' theta = theta - atanvalue jmp #_w7 ' jump to the end of the block _w3 ' same as the block above but subs and abs changed mov xs, x ' xs = x shl xs, #1 ' xs = xs << 1 mov yi, y ' yi = y subs yi, xs ' yi = yi + xs mov ys, y ' ys = y shl ys, #1 ' ys = ys << 1 adds x, ys ' x = x - ys mov y, yi ' y = yi call #fetch_atan ' atanvalue = atab[apointer] add apointer, #1 ' apointer = apoitner + 1 adds theta, atanvalue ' theta = theta + atanvalue _w7 mov i, #0 ' FOR i := 0 TO 28 DO mov counter, #29 _w4 cmps y, #0 wc ' c set if y < 0 if_nc jmp #_w5 mov xs, x ' xs = x sar xs, i ' xs = xs ~> 1 HINT Arithmetic shift without # mov yi, y ' yi = y adds yi, xs ' yi = yi + xs mov ys, y ' ys = y sar ys, i ' ys = ys ~> 1 subs x, ys ' x = x - ys mov y, yi ' y = yi call #fetch_atan ' atanvalue = atab[apointer] add apointer, #1 ' apointer = apointer+1 subs theta, atanvalue ' theta = theta - atanvalue jmp #_w6 ' jump to the end of the loop _w5 ' same block as above with changed signs mov xs, x ' xs = x sar xs, i ' xs = xs ~> 1 mov yi, y ' yi = y subs yi, xs ' yi = yi - xs mov ys, y ' ys = y sar ys, i ' ys = ys ~> 1 adds x, ys ' x = x + ys mov y, yi ' y = yi call #fetch_atan ' atanvalue = atab[apointer] add apointer, #1 ' apointer = apoitner + 1 adds theta, atanvalue ' theta = theat + atanvalue _w6 add i, #1 djnz counter, #_w4 ' ### this is again from SPI_Asm ############# Update_Result mov t1, address ' Write data back to Arg4 add t1, #8 ' Arg0 = #0 ; Arg1 = #4 ; Arg2 = #8 ; Arg3 = #12 ; Arg4 = #16 wrlong theta, t1 ' angle mov t1, address ' Write data back to Arg4 add t1, #12 ' Arg0 = #0 ; Arg1 = #4 ; Arg2 = #8 ; Arg3 = #12 ; Arg4 = #16 wrlong x, t1 ' length of the vector mov t1, address ' Write data back to Arg4 add t1, #20 ' Point t1 to Flag ... Arg4 + #4 wrlong zero, t1 ' Clear Flag ... indicates SHIFTIN data is ready jmp #loop ' Go to the start and wait for next command '-------------------------------------------------------------------------- cordic_asm_ret ret fetch_atan ' add atab, #apointer movs :read1,#atab ' Point to first array element. mov ctr,apointer ' Initialize counter. mov atanvalue,#0 ' Initialize result, not necessary. :read1 mov atanvalue,0-0 ' Move array element to result. (0-0 is just a placeholder for the pointer value.) add :read1,#1 ' Increment the pointer. djnz ctr,#:read1 ' Back for another. fetch_atan_ret ret '------------------------------------------------------------------------------------------------------------------------------ '------------------------------------------------------------------- ' x := 978147 = 12 degrees ' y := 207911 x long 0 y long 0 theta long 0 xi long 0 yi long 0 ys long 0 xs long 0 atanvalue long 0 apointer long 0 i long 0 counter long 0 quadrant long 377_487_360 ' QUARTER = 90 degrees << 22 ResAddr long 0 ctr long 0 '#############variables from SPI_ASM ############################## zero long 0 ''constants d0 long $200 t1 long 0 '' temprary variables t2 long 0 '' Used for t3 long 0 '' Used to t4 long 0 '' Used to t5 long 0 '' Used for address long 0 adress long 0 arg0 long 0 ''arguments passed to/from high-level Spin arg1 long 0 arg2 long 0 arg3 long 0 arg4 long 0 '######################################### ' The tabular of atans for claculation in degrees atab long 266065460, 188743680, 111421900, 58872272, 29884485, 15000234, 7507429, 3754631, 1877430, 938729, 469366, 234683, 117342, 58671, 29335, 14668, 7334, 3667, 1833, 917, 458, 229, 115, 57, 29, 14, 7, 4, 2, 1, 0, 0 'atab res 20 FIT 496