1 \ -*- coding: utf-8 -*-
3 \ ==============================================================================
4 \ routines RTC for MSP430FR5xxx
5 \ your target must have a LF_XTAL 32768Hz
6 \ ==============================================================================
8 \ to see kernel options, download FastForthSpecs.f
9 \ FastForth kernel minimal addons: MSP430ASSEMBLER, CONDCOMP
11 \ TARGET SELECTION ( = the name of \INC\target.pat file without the extension)
12 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
14 \ from scite editor : copy your target selection in (shift+F8) parameter 1:
16 \ or, from windows explorer:
17 \ drag and drop this file onto SendSourceFileToTarget.bat
18 \ then select your TARGET when asked.
20 \ ASSEMBLER REGISTERS USAGE
21 \ R4 to R7 must be saved before use and restored after
22 \ scratch registers Y to S are free for use
23 \ under interrupt, IP is free for use
25 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
26 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
28 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
30 \ POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
31 \ POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
33 \ example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
36 \ FORTH conditionnals: unary{ 0= 0< 0> }, binary{ = < > U< }
38 \ ASSEMBLER conditionnal usage with IF UNTIL WHILE S< S>= U< U>= 0= 0<> 0>=
39 \ ASSEMBLER conditionnal usage with ?JMP ?GOTO S< S>= U< U>= 0= 0<> 0<
43 ; --------------------
45 ; --------------------
47 \ to set date, type : d m y DATE!
48 \ to view date, type DATE?
49 \ to set time, type : h m [s] TIME!
50 \ to view time, type TIME?
53 \ first, we do some tests allowing the download
59 0<> IF MOV #0,TOS THEN \ if TOS <> 0 (FIXPOINT input), set TOS = 0
62 SUB #401,TOS \ FastForth V4.1
64 $0D EMIT \ return to column 1 without CR
65 ABORT" FastForth V4.1 please!"
66 ABORT" target without LF_XTAL !"
67 RST_RET \ if no abort remove this word
74 ; ------------------------------------------------------------------
75 ; first we download the set of definitions we need (from CORE_ANS.f)
76 ; ------------------------------------------------------------------
79 \ https://forth-standard.org/standard/core/OR
80 \ C OR x1 x2 -- x3 logical OR
88 \ https://forth-standard.org/standard/core/CFetch
89 \ C@ c-addr -- char fetch char from memory
97 \ https://forth-standard.org/standard/core/CStore
98 \ C! char c-addr -- store char in memory
100 MOV.B @PSP+,0(TOS) \ 4
107 [UNDEFINED] SWAP [IF]
108 \ https://forth-standard.org/standard/core/SWAP
109 \ SWAP x1 x2 -- x2 x1 swap top two items
118 [UNDEFINED] OVER [IF]
119 \ https://forth-standard.org/standard/core/OVER
120 \ OVER x1 x2 -- x1 x2 x1
122 MOV TOS,-2(PSP) \ 3 -- x1 (x2) x2
123 MOV @PSP,TOS \ 2 -- x1 (x2) x1
124 SUB #2,PSP \ 1 -- x1 x2 x1
129 [UNDEFINED] DUP [IF] \ define DUP and DUP?
130 \ https://forth-standard.org/standard/core/DUP
131 \ DUP x -- x x duplicate top of stack
133 BW1 SUB #2,PSP \ 2 push old TOS..
134 MOV TOS,0(PSP) \ 3 ..onto stack
138 \ https://forth-standard.org/standard/core/qDUP
139 \ ?DUP x -- 0 | x x DUP if nonzero
141 CMP #0,TOS \ 2 test for TOS nonzero
147 [UNDEFINED] DROP [IF]
148 \ https://forth-standard.org/standard/core/DROP
149 \ DROP x -- drop top of stack
156 [UNDEFINED] DEPTH [IF]
157 \ https://forth-standard.org/standard/core/DEPTH
158 \ DEPTH -- +n number of items on stack, must leave 0 if stack empty
162 SUB PSP,TOS \ PSP-S0--> TOS
163 RRA TOS \ TOS/2 --> TOS
164 SUB #2,PSP \ post decrement stack...
170 \ https://forth-standard.org/standard/core/toR
171 \ >R x -- R: -- x push to return stack
180 \ https://forth-standard.org/standard/core/Rfrom
181 \ R> -- x R: x -- pop from return stack ; CALL #RFROM performs DOVAR
191 \ https://forth-standard.org/standard/core/OnePlus
192 \ 1+ n1/u1 -- n2/u2 add 1 to TOS
200 \ https://forth-standard.org/standard/core/OneMinus
201 \ 1- n1/u1 -- n2/u2 subtract 1 from TOS
211 SUB @PSP+,TOS \ 2 u2-u1
215 AND #0,TOS \ 1 flag Z = 1
223 \ https://forth-standard.org/standard/core/Equal
224 \ = x1 x2 -- flag test x1=x2
231 XOR #-1,TOS \ 1 flag Z = 1
236 [UNDEFINED] IF [IF] \ define IF THEN
238 \ https://forth-standard.org/standard/core/IF
239 \ IF -- IFadr initialize conditional forward branch
243 MOV &DP,TOS \ -- HERE
244 ADD #4,&DP \ compile one word, reserve one word
245 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
246 ADD #2,TOS \ -- HERE+2=IFadr
250 \ https://forth-standard.org/standard/core/THEN
251 \ THEN IFadr -- resolve forward branch
252 CODE THEN \ immediate
253 MOV &DP,0(TOS) \ -- IFadr
259 [UNDEFINED] ELSE [IF]
260 \ https://forth-standard.org/standard/core/ELSE
261 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
262 CODE ELSE \ immediate
263 ADD #4,&DP \ make room to compile two words
266 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
268 MOV W,TOS \ -- ELSEadr
274 [UNDEFINED] DO [IF] \ define DO LOOP +LOOP
276 \ https://forth-standard.org/standard/core/DO
277 \ DO -- DOadr L: -- 0
278 HDNCODE XDO \ DO run time
279 MOV #$8000,X \ 2 compute 8000h-limit = "fudge factor"
281 MOV TOS,Y \ 1 loop ctr = index+fudge
282 ADD X,Y \ 1 Y = INDEX
283 PUSHM #2,X \ 4 PUSHM X,Y, i.e. PUSHM LIMIT, INDEX
291 ADD #2,&DP \ make room to compile xdo
292 MOV &DP,TOS \ -- HERE+2
293 MOV #XDO,-2(TOS) \ compile xdo
294 ADD #2,&LEAVEPTR \ -- HERE+2 LEAVEPTR+2
296 MOV #0,0(W) \ -- HERE+2 L-- 0
300 \ https://forth-standard.org/standard/core/LOOP
301 \ LOOP DOadr -- L-- an an-1 .. a1 0
302 HDNCODE XLOOP \ LOOP run time
303 ADD #1,0(RSP) \ 4 increment INDEX
304 BW1 BIT #$100,SR \ 2 is overflow bit set?
305 0= IF \ branch if no overflow
309 ADD #4,RSP \ 1 empties RSP
310 ADD #2,IP \ 1 overflow = loop done, skip branch ofs
311 MOV @IP+,PC \ 4 14~ taken or not taken xloop/loop
316 BW2 ADD #4,&DP \ make room to compile two words
318 MOV X,-4(W) \ xloop --> HERE
319 MOV TOS,-2(W) \ DOadr --> HERE+2
320 BEGIN \ resolve all "leave" adr
321 MOV &LEAVEPTR,TOS \ -- Adr of top LeaveStack cell
322 SUB #2,&LEAVEPTR \ --
323 MOV @TOS,TOS \ -- first LeaveStack value
324 CMP #0,TOS \ -- = value left by DO ?
326 MOV W,0(TOS) \ move adr after loop as UNLOOP adr
332 \ https://forth-standard.org/standard/core/PlusLOOP
333 \ +LOOP adrs -- L-- an an-1 .. a1 0
334 HDNCODE XPLOO \ +LOOP run time
335 ADD TOS,0(RSP) \ 4 increment INDEX by TOS value
336 MOV @PSP+,TOS \ 2 get new TOS, doesn't change flags
342 GOTO BW2 \ goto BW1 LOOP
347 [UNDEFINED] BEGIN [IF] \ define BEGIN UNTIL AGAIN WHILE REPEAT
349 \ https://forth-standard.org/standard/core/BEGIN
350 \ BEGIN -- BEGINadr initialize backward branch
355 \ https://forth-standard.org/standard/core/UNTIL
356 \ UNTIL BEGINadr -- resolve conditional backward branch
359 BW1 ADD #4,&DP \ compile two words
361 MOV X,-4(W) \ compile Bran or QFBRAN at HERE
362 MOV TOS,-2(W) \ compile bakcward adr at HERE+2
367 \ https://forth-standard.org/standard/core/AGAIN
368 \ AGAIN BEGINadr -- resolve uncondionnal backward branch
374 \ https://forth-standard.org/standard/core/WHILE
375 \ WHILE BEGINadr -- WHILEadr BEGINadr
380 \ https://forth-standard.org/standard/core/REPEAT
381 \ REPEAT WHILEadr BEGINadr -- resolve WHILE loop
383 POSTPONE AGAIN POSTPONE THEN
388 \ https://forth-standard.org/standard/core/CASE
389 [UNDEFINED] CASE [IF] \ define CASE OF ENDOF ENDCASE
392 ; IMMEDIATE \ -- #of-1
394 \ https://forth-standard.org/standard/core/OF
395 : OF \ #of-1 -- orgOF #of
397 >R \ move off the stack in case the control-flow stack is the data stack.
398 POSTPONE OVER POSTPONE = \ copy and test case value
399 POSTPONE IF \ add orig to control flow stack
400 POSTPONE DROP \ discards case value if =
401 R> \ we can bring count back now
404 \ https://forth-standard.org/standard/core/ENDOF
405 : ENDOF \ orgOF #of -- orgENDOF #of
406 >R \ move off the stack in case the control-flow stack is the data stack.
408 R> \ we can bring count back now
411 \ https://forth-standard.org/standard/core/ENDCASE
412 : ENDCASE \ orgENDOF1..orgENDOFn #of --
421 \ https://forth-standard.org/standard/core/Plus
422 \ + n1/u1 n2/u2 -- n3/u3
430 \ https://forth-standard.org/standard/core/Minus
431 \ - n1/u1 n2/u2 -- n3/u3 n3 = n1-n2
433 SUB @PSP+,TOS \ 2 -- n2-n1 ( = -n3)
435 ADD #1,TOS \ 1 -- n3 = -(n2-n1) = n1-n2
440 [UNDEFINED] MAX [IF] \define MAX and MIN
441 CODE MAX \ n1 n2 -- n3 signed maximum
448 CODE MIN \ n1 n2 -- n3 signed minimum
458 \ https://forth-standard.org/standard/core/TwoTimes
459 \ 2* x1 -- x2 arithmetic left shift
466 [UNDEFINED] UM* [IF] \ case of hardware_MPY
467 \ https://forth-standard.org/standard/core/UMTimes
468 \ UM* u1 u2 -- udlo udhi unsigned 16x16->32 mult.
470 MOV @PSP,&MPY \ Load 1st operand for unsigned multiplication
471 BW1 MOV TOS,&OP2 \ Load 2nd operand
472 MOV &RES0,0(PSP) \ low result on stack
473 MOV &RES1,TOS \ high result in TOS
477 \ https://forth-standard.org/standard/core/MTimes
478 \ M* n1 n2 -- dlo dhi signed 16*16->32 multiply
480 MOV @PSP,&MPYS \ Load 1st operand for signed multiplication
485 [UNDEFINED] UM/MOD [IF]
486 \ https://forth-standard.org/standard/core/UMDivMOD
487 \ UM/MOD udlo|udhi u1 -- ur uq unsigned 32/16->r16 q16
490 MOV #MUSMOD,PC \ execute MUSMOD then return to DROP
494 ; --------------------------
495 ; end of definitions we need
496 ; --------------------------
498 \ U*/ u1 u2 u3 -- uq u1*u2/u3
500 >R UM* R> UM/MOD SWAP DROP
503 \ U/MOD u1 u2 -- ur uq unsigned division
508 \ UMOD u1 u2 -- ur unsigned division
513 \ https://forth-standard.org/standard/core/Div
514 \ U/ u1 u2 -- uq signed quotient
519 [UNDEFINED] SPACES [IF]
520 \ https://forth-standard.org/standard/core/SPACES
521 \ SPACES n -- output n spaces
534 : U.R \ u n -- display u unsigned in n width (n >= 2)
536 R> OVER - 0 MAX SPACES TYPE
542 BIT.B #RTCRDY,&RTCCTL1
543 0<> UNTIL \ wait until RTCRDY high
545 RTCHOUR C@ 2 U.R ':' EMIT
546 RTCMIN C@ 2 U.R ':' EMIT
552 U< IF \ if 3 numbers on stack
560 CODE DATE? \ display date
562 BIT.B #RTCRDY,&RTCCTL1
563 0<> UNTIL \ wait until windows time RTC_ReaDY is high
568 \ ==============================================================================
569 \ end of RTC software|harware calendar
570 \ ==============================================================================
571 \ resume with common part of DATE? definition:
573 RTCDOW C@ \ -- weekday {0=Sat...6=Fri}
585 RTCDAY C@ \ -- year mon day
587 2 U.R '/' EMIT \ -- year mon
588 2 U.R '/' EMIT \ -- year
592 : DATE! \ year mon day --
594 U< IF \ if 3 numbers on stack
601 RTCYEAR @ \ -- day mon year
602 \ ------------------------------------------
603 \ Zeller's congruence for gregorian calendar
604 \ see https://www.rosettacode.org/wiki/Day_of_the_week#Forth
605 \ : ZELLER \ day mon year -- weekday {0=Sat, ..., 6=Fri}
607 \ IF 1- SWAP 12 + SWAP
608 \ THEN \ -- d m' y' with m' {3=March, ..., 14=february}
609 \ 100 /MOD \ -- d m' K J with K = y' in century, J = century
610 \ DUP 4 / SWAP 2* - \ -- d m' K (J/4 - 2J)
611 \ SWAP DUP 4 / + + \ -- d m' ((J/4 - 2J) + (K + K/4))
612 \ SWAP 1+ 13 5 */ + + \ -- (d + (((J/4 - 2J) + (K + K/4)) + (m+1)*13/5))
613 \ 7 MOD \ -- weekday = {0=Sat, ..., 6=Fri}
614 \ ------------------------------------------
616 IF 1 - SWAP 12 + SWAP
617 THEN \ -- d m' y' with m' {3=March, ..., 14=february}
618 100 U/MOD \ -- d m' K J with K = y' in century, J = century
619 DUP 4 U/ SWAP 2* - \ -- d m' K (J/4 - 2J)
620 SWAP DUP 4 U/ + + \ -- d m' ((J/4 - 2J) + (K + K/4))
621 SWAP 1+ 13 5 U*/ + + \ -- (d + (((J/4 - 2J) + (K + K/4)) + (m+1)*13/5))
622 7 UMOD \ -- weekday = {0=Sat, ..., 6=Fri}
623 \ ------------------------------------------
629 CODE S_ \ Squote alias with blank instead of double quote separator
633 MOV #S"+10,PC \ addr S" + 10 --> PC
640 0= IF MOV @IP+,PC \ interpret time usage disallowed
644 POSTPONE LITERAL \ compile-time code : lit $1B
645 POSTPONE EMIT \ compile-time code : EMIT
646 POSTPONE S_ \ compile-time code : S_ <escape_sequence>
647 POSTPONE TYPE \ compile-time code : TYPE
651 [UNDEFINED] >BODY [IF]
652 \ https://forth-standard.org/standard/core/toBODY
653 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
660 [UNDEFINED] EXECUTE [IF]
661 \ https://forth-standard.org/standard/core/EXECUTE
662 \ EXECUTE i*x xt -- j*x execute Forth word at 'xt'
666 MOV @RSP+,PC \ 4 xt --> PC
670 [UNDEFINED] EVALUATE [IF]
672 \ EVALUATE upside down...
673 CODENNM \ as the end of EVALUATE
675 MOV @RSP+,&SOURCE_ORG \ 4
676 MOV @RSP+,&SOURCE_LEN \ 4
679 ENDCODE \ -- end_of_EVALUATE_addr
681 \ https://forth-standard.org/standard/core/EVALUATE
682 \ EVALUATE \ i*x c-addr u -- j*x interpret string
684 MOV #SOURCE_LEN,X \ 2
685 MOV @X+,S \ 2 S = SOURCE_LEN
686 MOV @X+,T \ 2 T = SOURCE_ORG
687 MOV @X+,W \ 2 W = TOIN
688 PUSHM #4,IP \ 6 PUSHM IP,S,T,W
690 ADD #8,IP \ 1 IP = address compiled after ENDCODE
691 MOV #INTERPRET,PC \ 3 addr defined in MSP430FRxxxx.pat
692 NOP \ 1 stuffing instruction
694 , \ end_of_EVALUATE_addr -- compile the end_of_EVALUATE_addr
699 \ https://forth-standard.org/standard/core/CR
700 \ CR -- send CR+LF to the output device
702 \ DEFER CR \ DEFERed definition, by default executes that of :NONAME
703 CODE CR \ create a DEFER definition of CR
707 :NONAME \ starts at BODY address of DEFERed CR
709 ; IS CR \ CR executes :NONAME by default
713 ESC [8;42;80t \ set terminal display 42L * 80C
714 42 0 DO CR LOOP \ to avoid erasing any line of source, create 42 empty lines
715 ESC [H \ then set cursor home
718 ['] ACCEPT >BODY \ find default part of deferred ACCEPT (terminal input)
719 EXECUTE \ wait human input for D M Y
720 EVALUATE \ interpret this input
724 ['] ACCEPT >BODY \ find default part of deferred ACCEPT (terminal input)
725 EXECUTE \ wait human input for H M S
726 EVALUATE \ interpret this input