1 \ -*- coding: utf-8 -*-
2 \ see CORDICforDummies.pdf
4 \ to see kernel options, download FastForthSpecs.f
5 \ FastForth kernel options: MSP430ASSEMBLER, CONDCOMP, FIXPOINT_INPUT
8 \ TARGET SELECTION ( = the name of \INC\target.pat file without the extension)
10 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
11 \ MSP_EXP430FR2433 CHIPSTICK_FR2433 MSP_EXP430FR2355
13 \ from scite editor : copy your target selection in (shift+F8) parameter 1:
17 \ drag and drop this file onto SendSourceFileToTarget.bat
18 \ then select your TARGET when asked.
22 \ rDODOES to rEXIT must be saved before use and restored after
23 \ scratch registers Y to S are free for use
24 \ under interrupt, IP is free for use
26 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT, rDOVAR, rDOCON, rDODOES
27 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
29 \ POPM order : rDODOES, rDOCON, rDOVAR, rEXIT, Y, X, W, T, S, IP,TOS,PSP
30 \ example : POPM #6,IP pulls Y,X,W,T,S,IP registers from return stack
32 \ FORTH conditionnals: unary{ 0= 0< 0> }, binary{ = < > U< }
34 \ ASSEMBLER conditionnal usage with IF UNTIL WHILE S< S>= U< U>= 0= 0<> 0>=
35 \ ASSEMBLER conditionnal usage with ?JMP ?GOTO S< S>= U< U>= 0= 0<> 0<
46 0<> IF MOV #0,TOS THEN \ if TOS <> 0 (FIXPOINT_INPUT), set TOS = 0
49 SUB #400,TOS \ FastForth V4.0
51 $0D EMIT \ return to column 1 without CR
52 ABORT" FastForth V4.0 please!"
53 ABORT" build FastForth with FIXPOINT_INPUT addon"
54 RST_RET \ if no abort remove this word
62 \ OPERATION | MODE | INITIALIZE x y z | DIRECTION | RESULT | post operation
63 \ --------------|-----------|-----------------------|---------------|-------------------|
64 \ sine, cosine | Rotation | x=1, y=0, z=angle | Reduce z to 0 | cos=x*Gi,sin=y*Gi | mutiply by 1/Gi
65 \ --------------|-----------|-----------------------|---------------|-------------------|
66 \ Polar to Rect | Rotation | x=magnit, y=0, Z=angle| Reduce z to 0 | X=x*Gi, Y=y*Gi | mutiply by 1/Gi
67 \ --------------|-----------|-----------------------|---------------|-------------------|
68 \ Rotation | Rotation | x=X, y=Y, z=angle | Reduce z to 0 | X'=x*Gi,Y'=y*Gi | <=== not implemented
69 \ --------------|-----------|-----------------------|---------------|-------------------|
70 \ Rect to Polar | Vector | x=X, y=Y, z=0 | Reduce y to 0 | hyp=x*Gi, angle=z | mutiply hyp by 1/Gi
71 \ --------------|-----------|-----------------------|---------------|-------------------|
72 \ Gi = CORDIC gain for i iterations; Gi < 1
74 CREATE T_ARCTAN \ ArcTan table
76 7598 , \ 286 * 26.565 = 7597,605
77 4014 , \ 286 * 14.036 = 4014,366
78 2038 , \ 286 * 7.125 = 2037,755
79 1023 , \ 286 * 3.576 = 1022,832
80 512 , \ 286 * 1.790 = 511,914
81 256 , \ 286 * 0.895 = 256,020
82 128 , \ 286 * 0.448 = 128,017
83 64 , \ 286 * 0.224 = 64,010
84 32 , \ 286 * 0.112 = 32,005
85 16 , \ 286 * 0.056 = 16,0025
86 8 , \ 286 * 0.028 = 8,00126
91 CREATE T_SCALE \ 1/Gi table
92 46340 , \ = 65536 * cos(45)
93 41448 , \ = 65536 * cos(45) * cos(26.565)
94 40211 , \ = 65536 * cos(45) * cos(26.565) * cos(14.036)
95 39900 , \ = 65536 * cos(45) * cos(26.565) * cos(14.036) * ...
108 [UNDEFINED] DABS [IF]
109 \ https://forth-standard.org/standard/double/DABS
110 \ DABS d1 -- |d1| absolute value
112 AND #-1,TOS \ clear V, set N
124 \ https://forth-standard.org/standard/core/Rfrom
125 \ R> -- x R: x -- pop from return stack ; CALL #RFROM performs DOVAR
135 \ \ https://forth-standard.org/standard/core/Equal
136 \ \ = x1 x2 -- flag test x1=x2
145 \ XOR #-1,TOS \ 1 flag Z = 1
150 \ \ https://forth-standard.org/standard/core/Uless
151 \ \ U< u1 u2 -- flag test u1<u2, unsigned
155 \ SUB @PSP+,TOS \ 2 u2-u1
159 \ AND #0,TOS \ 1 flag Z = 1
166 \ $81EF DEVICEID @ U<
167 \ DEVICEID @ $81F3 U<
170 CODE TSTBIT \ addr bit_mask -- true/flase flag
176 KERNEL_ADDON HMPY TSTBIT \ hardware MPY ?
180 [IF] ; MSP430FRxxxx with hardware_MPY
182 [UNDEFINED] HOLDS [IF]
183 \ https://forth-standard.org/standard/core/HOLDS
184 \ Adds the string represented by addr u to the pictured numeric output string
185 \ compilation use: <# S" string" HOLDS #>
186 \ free chars area in the 32+2 bytes HOLD buffer = {26,23,2} chars with a 32 bits sized {hexa,decimal,binary} number.
187 \ (2 supplementary bytes are room for sign - and decimal point)
190 MOV @PSP+,X \ 2 X=src
191 BW3 ADD TOS,X \ 1 X=src_end
202 MOV @IP+,PC \ 4 15 words
207 \ F#S Qlo Qhi u -- Qhi 0 convert fractionnal part of Q15.16 fixed point number
210 MOV 2(PSP),X \ -- Qlo Qhi u X = Qlo
211 MOV @PSP,2(PSP) \ -- Qhi Qhi u
212 MOV X,0(PSP) \ -- Qhi Qlo u
216 MOV @PSP,&MPY \ Load 1st operand
217 MOV &BASEADR,&OP2 \ Load 2nd operand
218 MOV &RES0,0(PSP) \ -- Qhi RESlo x low result on stack
219 MOV &RES1,TOS \ -- Qhi RESlo REShi high result in TOS
220 CMP #10,TOS \ digit to char
225 MOV.B TOS,HOLDS_ORG(S) \ -- Qhi RESlo char char to string
227 CMP T,S \ count=len ?
229 MOV T,TOS \ -- len RESlo len
230 MOV #0,0(PSP) \ -- Qhi 0 len
231 MOV #HOLDS_ORG,X \ -- Qhi 0 len X=HOLDS_ORG
232 GOTO BW3 \ 35~ JMP HOLDS+2
236 HDNCODE XSCALE \ X = X*Cordic_Gain
237 MOV T_SCALE(W),&MPYS32L \ 3 CORDIC Gain * 65536
239 MOV X,&OP2 \ 3 Load 1st operand
240 MOV &RES1,X \ 3 hi result
244 [ELSE] ; no hardware multiplier
246 \ https://forth-standard.org/standard/core/HOLDS
247 \ Adds the string represented by addr u to the pictured numeric output string
248 \ compilation use: <# S" string" HOLDS #>
249 \ free chars area in the 32+2 bytes HOLD buffer = {26,23,2} chars with a 32 bits sized {hexa,decimal,binary} number.
250 \ (2 supplementary bytes are room for sign - and decimal point)
255 MOV @PSP+,X \ 2 X=src
256 BW3 ADD TOS,X \ 1 X=src_end
267 MOV @IP+,PC \ 4 15 words
271 \ F#S Qlo Qhi len -- Qhi 0 convert fractional part Qlo of Q15.16 fixed point number
276 MOV @PSP,S \ -- Qlo Qhi len S = Qhi
278 PUSHM #3,IP \ R-- IP Qhi count
279 MOV 2(PSP),0(PSP) \ -- Qlo Qlo len
280 MOV TOS,2(PSP) \ -- len Qlo len
282 MOV &BASEADR,TOS \ -- len Qlo base
284 UM* \ u1 u2 -- RESlo REShi
285 HI2LO \ -- len RESlo digit
286 CMP #10,TOS \ digit to char
290 ADD #$30,TOS \ -- len RESlo char
292 MOV.B TOS,HOLDS_ORG(T) \ char to string_org(T)
295 CMP 2(PSP),T \ -- len RESlo char count=len ?
297 POPM #3,IP \ S=Qhi, T=len
298 MOV T,TOS \ -- len RESlo len
299 MOV S,2(PSP) \ -- Qhi RESlo len
300 MOV #0,0(PSP) \ -- Qhi 0 len
301 MOV #HOLDS_ORG,X \ -- Qhi 0 len X=HOLDS_ORG
302 GOTO BW3 \ 36~ JMP HOLDS
306 \ T.I. UNSIGNED MULTIPLY SUBROUTINE: U1 x U2 -> Ud
307 \ https://forth-standard.org/standard/core/UMTimes
308 \ UM* u1 u2 -- ud unsigned 16x16->32 mult.
309 HDNCODE XSCALE \ X --> X*Cordic_Gain
310 MOV T_SCALE(W),rDOCON \ rDOCON=MR, X=MDlo
314 MOV #1,W \ 1 BIT TEST REGISTER
316 BIT W,rDOCON \ 1 TEST ACTUAL BIT MRlo
318 ADD X,S \ 1 IF 1: ADD MDlo TO RES0
319 ADDC Y,T \ 1 ADDC MDhi TO RES1
321 ADD X,X \ 1 (RLA LSBs) MDlo x 2
322 ADDC Y,Y \ 1 (RLC MSBs) MDhi x 2
323 ADD W,W \ 1 (RLA) NEXT BIT TO TEST
324 U>= UNTIL \ S = RESlo, T=REShi
325 MOV T,X \ 2 IF BIT IN CARRY: FINISHED 10~ loop
326 MOV #XDOCON,rDOCON \ restore rDOCON
330 [THEN] ; endcase of hardware multiplier
332 \ input ; u = module {1000...16384}, F = angle (15Q16 number) in degrees {-89,9...89,9}
334 \ TOS = Fhi, 0(PSP) = Flo, 2(PSP) = u
335 CODE POL2REC \ u F -- X Y
336 PUSH IP \ save IP before use
337 MOV @PSP+,&MPY32L \ multiply angle by 286
341 MOV &RES1,TOS \ -- module angle*286
342 \ =====================
343 \ CORDIC 16 bits engine
344 \ =====================
345 MOV #-1,IP \ IP = i-1
348 BEGIN \ i loops with init i = -1
350 MOV X,S \ S = Xi to be right shifted
351 MOV Y,T \ T = Yi to be right shifted
358 FW1 CMP IP,W \ W = i ?
359 0= UNTIL \ loop back if W < i
360 ADD W,W \ W = 2i = T_SCALE displacement
362 0>= IF \ TOS >= 0 : Rotate clockwise
363 SUB T,X \ Xi+1 = Xi - ( Yi >> i)
364 ADD S,Y \ Yi+1 = Yi + ( Xi >> i)
366 ELSE \ TOS < 0 : Rotate counter-clockwise
367 ADD T,X \ Xi+1 = Xi + ( Yi >> i)
368 SUB S,Y \ Yi+1 = Yi - ( Xi >> i)
371 CMP #0,TOS \ if angle*256 = 0 quit loop
372 0<> WHILE \ search "Extended control-flow patterns" in https://forth-standard.org/standard/rationale
373 CMP #14,IP \ IP = size of ARC_TAN table ?
375 THEN \ search "Extended control-flow patterns" in https://forth-standard.org/standard/rationale
376 \ multiply cos by factor scale
378 MOV X,0(PSP) \ 3 hi result = cos
379 \ multiply sin by factor scale
382 MOV X,TOS \ 3 hi result = sin
384 \ endof CORDIC engine \ X = cos, Y = sin
391 \ REC2POL version with inputs scaling, to increase the accuracy of the angle:
393 \ input : X < 16384, Y < 16384
394 \ output ; u = hypothenuse, f = angle (15Q16 number) in degrees
395 \ rounded hypothenuse, 1 mn accuracy angle
396 CODE REC2POL \ X Y -- u f
399 \ normalize X Y to 16384 maxi
400 \ 1- calculate T = |Y|
407 \ 2- calculate S = |X|
414 \ 3- abort if null inputs
415 MOV #-1,TOS \ set TOS TRUE for the two ABORT" below
425 \ 4- select max of |X|,|Y|
430 \ 5- abort if |X| or |Y| >= 16384
434 ABORT" |x| or |y| >= 16384"
437 \ 6- multiply inputs by 2^n scale factor
438 MOV #1,S \ init scale factor
439 RLAM #3,T \ test bit 2^13 of max(X,Y)
444 ADD S,S \ scale factor *2
445 ADD T,T \ to test next bit 2^(n-1)
447 U>= UNTIL \ until carry set
448 \ 7- save IP and scale factor n
449 PUSHM #2,IP \ push IP,S
451 \ CORDIC 16 bits engine
453 MOV #-1,IP \ IP = i-1, X = Xi, Y = Yi
454 MOV #0,TOS \ init z=0
455 BEGIN \ i loops with init: i = -1
457 MOV X,S \ S = Xi to be right shifted
458 MOV Y,T \ T = Yi to be right shifted
459 MOV #0,W \ W = right shift loop count
465 FW1 CMP IP,W \ W = i ?
467 ADD W,W \ W = 2i = T_SCALE displacement
469 S>= IF \ Y >= 0 : Rotate counter-clockwise
470 ADD T,X \ Xi+1 = Xi + ( Yi >> i)
471 SUB S,Y \ Yi+1 = Yi - ( Xi >> i)
473 ELSE \ Y < 0 : Rotate clockwise
474 SUB T,X \ Xi+1 = Xi - ( Yi >> i)
475 ADD S,Y \ Yi+1 = Yi + ( Xi >> i)
479 0<> WHILE \ if Y = 0 quit loop ---+
482 THEN \ <---------------------+
483 \ multiply x by CORDIC gain
484 CALL #XSCALE \ 3 hi result = hypothenuse
486 \ endof CORDIC engine \ X = hypothenuse, TOS = 256*angle
488 \ divide x by scale factor
489 POPM #2,IP \ S = scale factor, restore IP
492 RRA X \ divide x by 2
493 FW1 RRA S \ shift right scale factor
494 U>= UNTIL \ until carry set
496 \ divide z by 286 to display it as a Q15.16 number
497 SUB #4,PSP \ -- X * * Zhi
498 MOV TOS,rDOCON \ -- rDOCON as sign of QUOT
504 MOV #0,2(PSP) \ -- X Zlo * Zhi
505 MOV TOS,0(PSP) \ -- X Zlo Zhi Zhi
506 MOV #286,TOS \ -- X Zlo Zhi DIV
507 CALL #MUSMOD \ -- X rem QUOTlo QUOThi
508 MOV @PSP+,0(PSP) \ remove remainder
522 CODE F. \ display a Q15.16 number with 4/5/16 digits after comma
524 MOV #4,T \ T = 4 preset 4 digits for base 16 and by default
528 ADD #1,T \ T = 5 set 5 digits
532 MOV #16,T \ T = 16 set 16 digits
535 PUSHM #3,IP \ R-- IP sign #digit
537 <# DABS \ -- uQlo uQhi R-- IP sign #digit
538 R> F#S \ -- uQhi 0 R-- IP sign
539 $2C HOLD \ $2C = char ','
541 R> SIGN #> \ -- addr len R-- IP
549 \ https://forth-standard.org/standard/core/SWAP
550 \ SWAP x1 x2 -- x2 x1 swap top two items
551 [UNDEFINED] SWAP [IF]
560 \ https://forth-standard.org/standard/core/ROT
561 \ ROT x1 x2 x3 -- x2 x3 x1
562 [UNDEFINED] ROT [IF] \
564 MOV @PSP,W \ 2 fetch x2
565 MOV TOS,0(PSP) \ 3 store x3
566 MOV 2(PSP),TOS \ 3 fetch x1
567 MOV W,2(PSP) \ 3 store x2
574 10000 89,0 POL2REC . . ; sin, cos -->
575 10000 75,0 POL2REC . . ; sin, cos -->
576 10000 60,0 POL2REC . . ; sin, cos -->
577 10000 45,0 POL2REC . . ; sin, cos -->
578 10000 30,0 POL2REC . . ; sin, cos -->
579 10000 15,0 POL2REC . . ; sin, cos -->
580 10000 1,0 POL2REC . . ; sin, cos -->
581 \ module phase -- X Y
582 16384 30,0 POL2REC SWAP . . ; x, y -->
583 16384 45,0 POL2REC SWAP . . ; x, y -->
584 16384 60,0 POL2REC SWAP . . ; x, y -->
587 10000 -89,0 POL2REC . . ; sin, cos -->
588 10000 -75,0 POL2REC . . ; sin, cos -->
589 10000 -60,0 POL2REC . . ; sin, cos -->
590 10000 -45,0 POL2REC . . ; sin, cos -->
591 10000 -30,0 POL2REC . . ; sin, cos -->
592 10000 -15,0 POL2REC . . ; sin, cos -->
593 10000 -1,0 POL2REC . . ; sin, cos -->
594 \ module phase -- X Y
595 16384 -30,0 POL2REC SWAP . . ; x, y -->
596 16384 -45,0 POL2REC SWAP . . ; x, y -->
597 16384 -60,0 POL2REC SWAP . . ; x, y -->
600 -10000 89,0 POL2REC . . ; sin, cos -->
601 -10000 75,0 POL2REC . . ; sin, cos -->
602 -10000 60,0 POL2REC . . ; sin, cos -->
603 -10000 45,0 POL2REC . . ; sin, cos -->
604 -10000 30,0 POL2REC . . ; sin, cos -->
605 -10000 15,0 POL2REC . . ; sin, cos -->
606 -10000 1,0 POL2REC . . ; sin, cos -->
607 \ module phase -- X Y
608 -16384 30,0 POL2REC SWAP . . ; x, y -->
609 -16384 45,0 POL2REC SWAP . . ; x, y -->
610 -16384 60,0 POL2REC SWAP . . ; x, y -->
613 -10000 -89,0 POL2REC . . ; sin, cos -->
614 -10000 -75,0 POL2REC . . ; sin, cos -->
615 -10000 -60,0 POL2REC . . ; sin, cos -->
616 -10000 -45,0 POL2REC . . ; sin, cos -->
617 -10000 -30,0 POL2REC . . ; sin, cos -->
618 -10000 -15,0 POL2REC . . ; sin, cos -->
619 -10000 -1,0 POL2REC . . ; sin, cos -->
620 \ module phase -- X Y
621 -16384 -30,0 POL2REC SWAP . . ; x, y -->
622 -16384 -45,0 POL2REC SWAP . . ; x, y -->
623 -16384 -60,0 POL2REC SWAP . . ; x, y -->
627 2 1 REC2POL F. . ; phase module -->
628 2 -1 REC2POL F. . ; phase module -->
629 20 10 REC2POL F. . ; phase module -->
630 20 -10 REC2POL F. . ; phase module -->
631 200 100 REC2POL F. . ; phase module -->
632 100 -100 REC2POL F. . ; phase module -->
633 2000 1000 REC2POL F. . ; phase module -->
634 1000 -1000 REC2POL F. . ; phase module -->
635 16000 8000 REC2POL F. . ; phase module -->
636 16000 -8000 REC2POL F. . ; phase module -->
637 16000 0 REC2POL F. . ; phase module -->
638 0 16000 REC2POL F. . ; phase module -->
639 \ 16384 -8192 REC2POL F. . ; --> abort
640 \ 0 0 REC2POL F. . ; --> abort
642 -2 1 REC2POL F. . ; phase module -->
643 -2 -1 REC2POL F. . ; phase module -->
644 -20 10 REC2POL F. . ; phase module -->
645 -20 -10 REC2POL F. . ; phase module -->
646 -200 100 REC2POL F. . ; phase module -->
647 -100 -100 REC2POL F. . ; phase module -->
648 -2000 1000 REC2POL F. . ; phase module -->
649 -1000 -1000 REC2POL F. . ; phase module -->
650 -16000 8000 REC2POL F. . ; phase module -->
651 -16000 -8000 REC2POL F. . ; phase module -->
652 16000 0 REC2POL F. . ; phase module -->
653 0 16000 REC2POL F. . ; phase module -->
654 \ 16384 -8192 REC2POL F. . ; --> abort
655 \ 0 0 REC2POL F. . ; --> abort
657 10000 89,0 POL2REC REC2POL ROT . F.
658 10000 75,0 POL2REC REC2POL ROT . F.
659 10000 60,0 POL2REC REC2POL ROT . F.
660 10000 45,0 POL2REC REC2POL ROT . F.
661 10000 30,0 POL2REC REC2POL ROT . F.
662 10000 26,565 POL2REC REC2POL ROT . F.
663 10000 15,0 POL2REC REC2POL ROT . F.
664 10000 14,036 POL2REC REC2POL ROT . F.
665 10000 7,125 POL2REC REC2POL ROT . F.
666 10000 1,0 POL2REC REC2POL ROT . F.