1 \ -*- coding: utf-8 -*-
3 ; -----------------------------------
4 ; PROG100k.f = 76 x RC5toLCD.f
5 ; -----------------------------------
6 ; download source file sized to compile 100 kbytes
7 ; -----------------------------------
10 \ MSP_EXP430FR5739 MSP_EXP430FR5969 MSP_EXP430FR5994 MSP_EXP430FR6989
13 \ MY_MSP430FR5738 MY_MSP430FR5738_1 MY_MSP430FR5738_2
14 \ MY_MSP430FR5948 MY_MSP430FR5948_1
17 \ Copyright (C) <2016> <J.M. THOORENS>
19 \ This program is free software: you can redistribute it and/or modify
20 \ it under the terms of the GNU General Public License as published by
21 \ the Free Software Foundation, either version 3 of the License, or
22 \ (at your option) any later version.
24 \ This program is distributed in the hope that it will be useful,
25 \ but WITHOUT ANY WARRANTY\ without even the implied warranty of
26 \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 \ GNU General Public License for more details.
29 \ You should have received a copy of the GNU General Public License
30 \ along with this program. If not, see <http://www.gnu.org/licenses/>.
33 \ ===========================================================================
34 \ remember: for good downloading to target, all lines must be ended with CR+LF !
35 \ ===========================================================================
39 \ R4 to R7 must be saved before use and restored after
40 \ scratch registers Y to S are free for use
41 \ under interrupt, IP is free for use
42 \ interrupts reset SR register !
44 \ PUSHM order : PSP,TOS, IP, S, T, W, X, Y, rEXIT,rDOVAR,rDOCON, rDODOES, R3, SR,RSP, PC
45 \ PUSHM order : R15,R14,R13,R12,R11,R10, R9, R8, R7 , R6 , R5 , R4 , R3, R2, R1, R0
47 \ example : PUSHM #6,IP pushes IP,S,T,W,X,Y registers to return stack
49 \ POPM order : PC,RSP, SR, R3, rDODOES,rDOCON,rDOVAR,rEXIT, Y, X, W, T, S, IP,TOS,PSP
50 \ POPM order : R0, R1, R2, R3, R4 , R5 , R6 , R7 , R8, R9,R10,R11,R12,R13,R14,R15
52 \ example : POPM #6,IP pop Y,X,W,T,S,IP registers from return stack
54 \ ASSEMBLER conditionnal usage after IF UNTIL WHILE : S< S>= U< U>= 0= 0<> 0>=
55 \ ASSEMBLER conditionnal usage before ?JMP ?GOTO : S< S>= U< U>= 0= 0<> 0<
57 \ FORTH conditionnal : 0= 0< = < > U<
59 \ display on a LCD 2x20 CHAR the code sent by an IR remote under philips RC5 protocol
60 \ target : any TI MSP-EXP430FRxxxx launchpad (FRAM)
61 \ LPM_MODE = LPM0 because use SMCLK for LCDVo
63 \ DEMO : driver for IR remote compatible with the PHILIPS RC5 protocol
64 \ plus : driver for 5V LCD 2x20 characters display with 4 bits data interface
65 \ without usage of an auxiliary 5V to feed the LCD_Vo
66 \ and without potentiometer to adjust the LCD contrast :
67 \ to adjust LCD contrast, just press S1 (-) or S2 (+)
68 \ LCDVo current consumption ~ 500 uA.
70 \ ===================================================================================
71 \ notice : adjust WDT_TIM_EX0,LCD_TIM_CTL,LCD_TIM_EX0 and 20_us to the target frequency if <> 8MHz !
72 \ ===================================================================================
75 \ layout : I/O are defined in the launchpad.pat file (don't work with ChipStick_FR2433)
77 \ GND <-------+---0V0----------> 1 LCD_Vss
78 \ VCC >------ | --3V6-----+----> 2 LCD_Vdd
85 \ LCD_TIM_.2 >---||--+--^/\/\/v--+----> 3 LCD_Vo (= 0V6 without modulation)
86 \ -------------------------> 4 LCD_RW
87 \ -------------------------> 5 LCD_RW
88 \ -------------------------> 6 LCD_EN
89 \ <------------------------> 11 LCD_DB4
90 \ <------------------------> 12 LCD_DB5
91 \ <------------------------> 13 LCD_DB5
92 \ <------------------------> 14 LCD_DB7
94 \ <----- LCD contrast + <--- Sw1 <--- (finger) :-)
95 \ <----- LCD contrast - <--- Sw2 <--- (finger) :-)
97 \ rc5 <--- OUT IR_Receiver (1 TSOP32236)
101 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
103 [UNDEFINED] MARKER [IF]
104 \ https://forth-standard.org/standard/core/MARKER
106 \ ( "<spaces>name" -- )
107 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
108 \ with the execution semantics defined below.
110 \ name Execution: ( -- )
111 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
112 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
113 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
114 \ not necessarily provided. No other contextual information such as numeric base is affected
119 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
121 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
122 ADD #4,&DP \ 3 add 2 cells
126 MOV @RSP+,IP \ -- PFA
127 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
128 MOV @TOS,&INIDP \ set DP value for RST_STATE
130 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
137 \ https://forth-standard.org/standard/core/Fetch
138 \ @ c-addr -- char fetch char from memory
145 [UNDEFINED] CONSTANT [IF]
146 \ https://forth-standard.org/standard/core/CONSTANT
147 \ CONSTANT <name> n -- define a Forth CONSTANT
151 MOV TOS,-2(W) \ PFA = n
158 [UNDEFINED] STATE [IF]
159 \ https://forth-standard.org/standard/core/STATE
160 \ STATE -- a-addr holds compiler state
161 STATEADR CONSTANT STATE
165 \ https://forth-standard.org/standard/core/Equal
166 \ = x1 x2 -- flag test x1=x2
173 XOR #-1,TOS \ 1 flag Z = 1
179 \ https://forth-standard.org/standard/core/IF
180 \ IF -- IFadr initialize conditional forward branch
184 MOV &DP,TOS \ -- HERE
185 ADD #4,&DP \ compile one word, reserve one word
186 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
187 ADD #2,TOS \ -- HERE+2=IFadr
192 [UNDEFINED] THEN [IF]
193 \ https://forth-standard.org/standard/core/THEN
194 \ THEN IFadr -- resolve forward branch
195 CODE THEN \ immediate
196 MOV &DP,0(TOS) \ -- IFadr
202 [UNDEFINED] ELSE [IF]
203 \ https://forth-standard.org/standard/core/ELSE
204 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
205 CODE ELSE \ immediate
206 ADD #4,&DP \ make room to compile two words
209 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
211 MOV W,TOS \ -- ELSEadr
216 [UNDEFINED] DEFER [IF]
217 \ https://forth-standard.org/standard/core/DEFER
218 \ DEFER "<spaces>name" --
219 \ Skip leading space delimiters. Parse name delimited by a space.
220 \ Create a definition for name with the execution semantics defined below.
223 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
224 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
228 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
229 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
235 [UNDEFINED] DEFER! [IF]
236 \ https://forth-standard.org/standard/core/DEFERStore
237 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
238 CODE DEFER! \ xt2 xt1 --
239 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
246 \ https://forth-standard.org/standard/core/IS
249 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
250 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
251 \ or in a definition : ... ['] U. IS DISPLAY ...
252 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
254 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
257 IF POSTPONE ['] POSTPONE DEFER!
263 [UNDEFINED] >BODY [IF]
264 \ https://forth-standard.org/standard/core/toBODY
265 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
272 \ CODE 20uS \ n -- 8MHz version
273 \ BEGIN \ 4 + 16 ~ loop
274 \ MOV #39,rDOCON \ 39
281 \ MOV #XDOCON,rDOCON \ 2
286 CODE 20_US \ n -- n * 20 us
287 BEGIN \ here we presume that LCD_TIM_IFG = 1...
289 BIT #1,&LCD_TIM_CTL \ 3
290 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
291 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
293 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
298 CODE TOP_LCD \ LCD Sample
299 \ \ if write : %xxxx_WWWW --
300 \ \ if read : -- %0000_RRRR
301 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
302 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
303 0= IF \ write LCD bits pattern
305 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
306 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
309 THEN \ read LCD bits pattern
312 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
313 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
318 CODE LCD_WRC \ char -- Write Char
319 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
321 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
322 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
323 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
324 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
325 COLON \ high level word starts here
326 TOP_LCD 2 20_US \ write high nibble first
330 CODE LCD_WRF \ func -- Write Fonction
331 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
335 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
336 : LCD_HOME $02 LCD_WRF 100 20_us ;
338 \ [UNDEFINED] OR [IF]
340 \ \ https://forth-standard.org/standard/core/OR
341 \ \ C OR x1 x2 -- x3 logical OR
349 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
350 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
351 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
352 \ : LCD_FN_SET $20 OR LCD_WrF ;
353 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
354 \ : LCD_GOTO $80 OR LCD_WrF ;
357 \ CODE LCD_RDS \ -- status Read Status
358 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
359 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
360 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
361 \ COLON \ starts a FORTH word
362 \ TOP_LCD 2 20_us \ -- %0000_HHHH
363 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
364 \ HI2LO \ switch from FORTH to assembler
365 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
366 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
367 \ MOV @RSP+,IP \ restore IP saved by COLON
371 \ CODE LCD_RDC \ -- char Read Char
372 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
377 \ ******************************\
378 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
379 \ ******************************\
380 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
381 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
382 BIT.B #SW2,&SW2_IN \ test switch S2
383 0= IF \ case of switch S2 pressed
384 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
386 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
389 BIT.B #SW1,&SW1_IN \ test switch S1 input
390 0= IF \ case of Switch S1 pressed
391 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
393 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
397 BW1 \ from quit on truncated RC5 message, repeated RC5 command
401 \ ******************************\
402 ASM RC5_INT \ wake up on Px.RC5 change interrupt
403 \ ******************************\
404 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
405 \ ******************************\
406 \ \ in : SR(9)=old Toggle bit memory (ADD on)
407 \ \ SMclock = 8|16|24 MHz
408 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
409 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
410 \ \ SR(9)=new Toggle bit memory (ADD on)
411 \ ******************************\
412 \ RC5_FirstStartBitHalfCycle: \
413 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
414 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
415 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
416 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
418 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
419 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
421 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
422 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
424 MOV #1778,X \ RC5_Period * 1us
425 MOV #14,W \ count of loop
427 \ ******************************\
428 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
429 \ ******************************\ |
430 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
431 \ RC5_Compute_3/4_Period: \ |
432 RRUM #1,X \ X=1/2 cycle |
435 ADD X,Y \ Y=3/4 cycle
436 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
438 \ ******************************\
439 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
440 \ ******************************\
441 BIT.B #RC5,&IR_IN \ C_flag = IR bit
442 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
443 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
444 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
445 SUB #1,W \ decrement count loop
446 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
447 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
448 0<> WHILE \ ----> out of loop ----+
449 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
451 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
452 CMP Y,X \ 1 | cycle time out of bound ?
454 BIC #$30,&RC5_TIM_CTL \ | | stop timer
455 GOTO BW1 \ | | quit on truncated RC5 message
457 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
459 REPEAT \ ----> loop back --+ | with X = new RC5_period value
460 \ ******************************\ |
461 \ RC5_SampleEndOf: \ <---------------------+
462 \ ******************************\
463 BIC #$30,&RC5_TIM_CTL \ stop timer
464 \ ******************************\
465 \ RC5_ComputeNewRC5word \
466 \ ******************************\
467 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
468 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
469 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
470 \ ******************************\
472 \ ******************************\
473 BIT #BIT14,T \ test /C6 bit in T
474 0= IF BIS #BIT6,X \ set C6 bit in X
475 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
476 \ ******************************\
477 \ RC5_CommandByteIsDone \ -- BASE RC5_code
478 \ ******************************\
479 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
480 \ ******************************\
481 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
482 XOR @RSP,T \ (new XOR old) Toggle bits
483 BIT #UF10,T \ repeated RC5_command ?
484 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
485 XOR #UF10,0(RSP) \ 5 toggle bit memory
486 \ ******************************\
487 \ Display IR_RC5 code \
488 \ ******************************\
489 SUB #8,PSP \ TOS -- x x x x TOS
490 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
491 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
492 MOV #$10,&BASEADR \ set hexadecimal base
493 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
494 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
495 LO2HI \ switch from assembler to FORTH
496 LCD_CLEAR \ set LCD cursor at home
497 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
498 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
499 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
500 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
501 HI2LO \ -- switch from FORTH to assembler
502 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
503 MOV @PSP+,TOS \ -- TOS
507 \ ******************************\
509 \ ******************************\
511 \ ... \ insert here your background task
514 CALL &RXON \ comment this line to disable TERMINAL_INPUT
516 \ ******************************\
517 \ here start all interrupts \
518 \ ******************************\
519 \ here return all interrupts \
520 \ ******************************\
523 \ ******************************\
525 \ ------------------------------\
526 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
527 \ ------------------------------\
528 \ ... \ init specific I/O sys as you want
529 \ ... \ before executing default WARM
530 MOV #WARM,X \ ['] WARM
532 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
534 \ ------------------------------\
536 \ ------------------------------\
537 CODE STOP \ stops multitasking, must to be used before downloading app
538 \ ------------------------------\
539 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
540 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
541 MOV X,-2(X) \ restore the default background: SLEEP
543 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
544 BIC.B #RC5,&IR_IE \ clear RC5_Int
545 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
546 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
547 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
548 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
549 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
550 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
552 ." RC5toLCD is removed,"
553 ." type START to restart"
554 WARM \ performs reset to reset all interrupt vectors.
556 \ ------------------------------\
558 \ ------------------------------\
559 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
560 \ ------------------------------\
561 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
562 \ - - \CNTL Counter lentgh \ 00 = 16 bits
563 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
564 \ -- \ID input divider \ 10 = /4
565 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
566 \ - \TBCLR TimerB Clear
569 \ -------------------------------\
570 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
571 \ -- \CM Capture Mode
576 \ --- \OUTMOD \ 011 = set/reset
582 \ -------------------------------\
584 \ -------------------------------\
586 \ ------------------------------\
587 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
588 \ ------------------------------\
589 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
590 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
591 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
592 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
594 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
595 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
597 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
598 \ ------------------------------\
599 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
600 \ ------------------------------\
601 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
602 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
603 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
604 \ ------------------------------\
605 BIS.B #LCDVo,&LCDVo_DIR \
606 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
607 \ ------------------------------\
608 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
609 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
610 \ ------------------------------\
611 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
612 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
613 \ ******************************\
615 \ ******************************\
616 BIS.B #RC5,&IR_IE \ enable RC5_Int
617 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
618 MOV #RC5_INT,&IR_Vec \ init interrupt vector
619 \ ******************************\
620 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
621 \ ******************************\
622 \ %01 0001 0100 \ TAxCTL
623 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
624 \ -- \ ID divided by 1
625 \ -- \ MC MODE = up to TAxCCRn
626 \ - \ TACLR clear timer count
629 \ ------------------------------\
630 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
631 \ ------------------------------\
633 \ --- \ TAIDEX pre divisor
634 \ ------------------------------\
635 \ %0000 0000 0000 0101 \ TAxCCR0
636 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
637 \ ------------------------------\
638 \ %0000 0000 0001 0000 \ TAxCCTL0
639 \ - \ CAP capture/compare mode = compare
642 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
643 \ ------------------------------\
644 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
645 \ ------------------------------\
646 \ define LPM mode for ACCEPT \
647 \ ------------------------------\
648 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
649 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
650 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
651 \ ------------------------------\
653 \ ------------------------------\
654 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
655 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
656 \ ------------------------------\
657 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
658 \ ------------------------------\
659 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
660 \ CMP #2,Y \ Power_ON event
661 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
663 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
665 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
667 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
669 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
670 \ ------------------------------\
672 \ ------------------------------\
674 \ ------------------------------\
675 #1000 20_US \ 1- wait 20 ms
676 %011 TOP_LCD \ 2- send DB5=DB4=1
677 #205 20_US \ 3- wait 4,1 ms
678 %011 TOP_LCD \ 4- send again DB5=DB4=1
679 #5 20_US \ 5- wait 0,1 ms
680 %011 TOP_LCD \ 6- send again again DB5=DB4=1
681 #2 20_US \ wait 40 us = LCD cycle
682 %010 TOP_LCD \ 7- send DB5=1 DB4=0
683 #2 20_US \ wait 40 us = LCD cycle
684 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
685 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
686 LCD_CLEAR \ 10- "LCD_Clear"
687 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
688 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
689 LCD_CLEAR \ 10- "LCD_Clear"
690 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
691 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
692 CR ." I love you" \ display message on LCD
693 ['] CR >BODY IS CR \ CR executes its default value
694 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
695 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
696 PWR_STATE ABORT \ init DP and continues with ABORT
698 \ ------------------------------\
700 \ ------------------------------\
701 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
702 \ ------------------------------\
703 MOV #SLEEP,X \ replace default background process SLEEP
704 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
705 MOV #WARM,X \ replace default WARM
706 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
707 MOV X,PC \ then execute new WARM
709 \ ------------------------------\
712 ; downloading RC5toLCD.4th is done
713 RST_HERE ; this app is protected against <reset>
718 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
720 [UNDEFINED] MARKER [IF]
721 \ https://forth-standard.org/standard/core/MARKER
723 \ ( "<spaces>name" -- )
724 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
725 \ with the execution semantics defined below.
727 \ name Execution: ( -- )
728 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
729 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
730 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
731 \ not necessarily provided. No other contextual information such as numeric base is affected
736 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
738 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
739 ADD #4,&DP \ 3 add 2 cells
743 MOV @RSP+,IP \ -- PFA
744 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
745 MOV @TOS,&INIDP \ set DP value for RST_STATE
747 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
754 \ https://forth-standard.org/standard/core/Fetch
755 \ @ c-addr -- char fetch char from memory
762 [UNDEFINED] CONSTANT [IF]
763 \ https://forth-standard.org/standard/core/CONSTANT
764 \ CONSTANT <name> n -- define a Forth CONSTANT
768 MOV TOS,-2(W) \ PFA = n
775 [UNDEFINED] STATE [IF]
776 \ https://forth-standard.org/standard/core/STATE
777 \ STATE -- a-addr holds compiler state
778 STATEADR CONSTANT STATE
782 \ https://forth-standard.org/standard/core/Equal
783 \ = x1 x2 -- flag test x1=x2
790 XOR #-1,TOS \ 1 flag Z = 1
796 \ https://forth-standard.org/standard/core/IF
797 \ IF -- IFadr initialize conditional forward branch
801 MOV &DP,TOS \ -- HERE
802 ADD #4,&DP \ compile one word, reserve one word
803 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
804 ADD #2,TOS \ -- HERE+2=IFadr
809 [UNDEFINED] THEN [IF]
810 \ https://forth-standard.org/standard/core/THEN
811 \ THEN IFadr -- resolve forward branch
812 CODE THEN \ immediate
813 MOV &DP,0(TOS) \ -- IFadr
819 [UNDEFINED] ELSE [IF]
820 \ https://forth-standard.org/standard/core/ELSE
821 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
822 CODE ELSE \ immediate
823 ADD #4,&DP \ make room to compile two words
826 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
828 MOV W,TOS \ -- ELSEadr
833 [UNDEFINED] DEFER [IF]
834 \ https://forth-standard.org/standard/core/DEFER
835 \ DEFER "<spaces>name" --
836 \ Skip leading space delimiters. Parse name delimited by a space.
837 \ Create a definition for name with the execution semantics defined below.
840 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
841 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
845 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
846 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
852 [UNDEFINED] DEFER! [IF]
853 \ https://forth-standard.org/standard/core/DEFERStore
854 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
855 CODE DEFER! \ xt2 xt1 --
856 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
863 \ https://forth-standard.org/standard/core/IS
866 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
867 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
868 \ or in a definition : ... ['] U. IS DISPLAY ...
869 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
871 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
874 IF POSTPONE ['] POSTPONE DEFER!
880 [UNDEFINED] >BODY [IF]
881 \ https://forth-standard.org/standard/core/toBODY
882 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
889 \ CODE 20uS \ n -- 8MHz version
890 \ BEGIN \ 4 + 16 ~ loop
891 \ MOV #39,rDOCON \ 39
898 \ MOV #XDOCON,rDOCON \ 2
903 CODE 20_US \ n -- n * 20 us
904 BEGIN \ here we presume that LCD_TIM_IFG = 1...
906 BIT #1,&LCD_TIM_CTL \ 3
907 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
908 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
910 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
915 CODE TOP_LCD \ LCD Sample
916 \ \ if write : %xxxx_WWWW --
917 \ \ if read : -- %0000_RRRR
918 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
919 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
920 0= IF \ write LCD bits pattern
922 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
923 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
926 THEN \ read LCD bits pattern
929 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
930 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
935 CODE LCD_WRC \ char -- Write Char
936 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
938 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
939 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
940 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
941 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
942 COLON \ high level word starts here
943 TOP_LCD 2 20_US \ write high nibble first
947 CODE LCD_WRF \ func -- Write Fonction
948 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
952 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
953 : LCD_HOME $02 LCD_WRF 100 20_us ;
955 \ [UNDEFINED] OR [IF]
957 \ \ https://forth-standard.org/standard/core/OR
958 \ \ C OR x1 x2 -- x3 logical OR
966 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
967 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
968 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
969 \ : LCD_FN_SET $20 OR LCD_WrF ;
970 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
971 \ : LCD_GOTO $80 OR LCD_WrF ;
974 \ CODE LCD_RDS \ -- status Read Status
975 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
976 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
977 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
978 \ COLON \ starts a FORTH word
979 \ TOP_LCD 2 20_us \ -- %0000_HHHH
980 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
981 \ HI2LO \ switch from FORTH to assembler
982 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
983 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
984 \ MOV @RSP+,IP \ restore IP saved by COLON
988 \ CODE LCD_RDC \ -- char Read Char
989 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
994 \ ******************************\
995 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
996 \ ******************************\
997 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
998 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
999 BIT.B #SW2,&SW2_IN \ test switch S2
1000 0= IF \ case of switch S2 pressed
1001 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1003 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
1006 BIT.B #SW1,&SW1_IN \ test switch S1 input
1007 0= IF \ case of Switch S1 pressed
1008 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1010 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1014 BW1 \ from quit on truncated RC5 message, repeated RC5 command
1018 \ ******************************\
1019 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1020 \ ******************************\
1021 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1022 \ ******************************\
1023 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1024 \ \ SMclock = 8|16|24 MHz
1025 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1026 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1027 \ \ SR(9)=new Toggle bit memory (ADD on)
1028 \ ******************************\
1029 \ RC5_FirstStartBitHalfCycle: \
1030 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1031 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1032 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
1033 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1035 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
1036 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1038 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
1039 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
1041 MOV #1778,X \ RC5_Period * 1us
1042 MOV #14,W \ count of loop
1044 \ ******************************\
1045 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
1046 \ ******************************\ |
1047 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1048 \ RC5_Compute_3/4_Period: \ |
1049 RRUM #1,X \ X=1/2 cycle |
1052 ADD X,Y \ Y=3/4 cycle
1053 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
1055 \ ******************************\
1056 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1057 \ ******************************\
1058 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1059 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
1060 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1061 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1062 SUB #1,W \ decrement count loop
1063 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
1064 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1065 0<> WHILE \ ----> out of loop ----+
1066 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1068 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
1069 CMP Y,X \ 1 | cycle time out of bound ?
1071 BIC #$30,&RC5_TIM_CTL \ | | stop timer
1072 GOTO BW1 \ | | quit on truncated RC5 message
1074 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
1076 REPEAT \ ----> loop back --+ | with X = new RC5_period value
1077 \ ******************************\ |
1078 \ RC5_SampleEndOf: \ <---------------------+
1079 \ ******************************\
1080 BIC #$30,&RC5_TIM_CTL \ stop timer
1081 \ ******************************\
1082 \ RC5_ComputeNewRC5word \
1083 \ ******************************\
1084 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
1085 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
1086 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
1087 \ ******************************\
1088 \ RC5_ComputeC6bit \
1089 \ ******************************\
1090 BIT #BIT14,T \ test /C6 bit in T
1091 0= IF BIS #BIT6,X \ set C6 bit in X
1092 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
1093 \ ******************************\
1094 \ RC5_CommandByteIsDone \ -- BASE RC5_code
1095 \ ******************************\
1096 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1097 \ ******************************\
1098 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
1099 XOR @RSP,T \ (new XOR old) Toggle bits
1100 BIT #UF10,T \ repeated RC5_command ?
1101 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
1102 XOR #UF10,0(RSP) \ 5 toggle bit memory
1103 \ ******************************\
1104 \ Display IR_RC5 code \
1105 \ ******************************\
1106 SUB #8,PSP \ TOS -- x x x x TOS
1107 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
1108 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
1109 MOV #$10,&BASEADR \ set hexadecimal base
1110 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
1111 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
1112 LO2HI \ switch from assembler to FORTH
1113 LCD_CLEAR \ set LCD cursor at home
1114 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
1115 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
1116 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
1117 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
1118 HI2LO \ -- switch from FORTH to assembler
1119 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
1120 MOV @PSP+,TOS \ -- TOS
1124 \ ******************************\
1126 \ ******************************\
1128 \ ... \ insert here your background task
1131 CALL &RXON \ comment this line to disable TERMINAL_INPUT
1133 \ ******************************\
1134 \ here start all interrupts \
1135 \ ******************************\
1136 \ here return all interrupts \
1137 \ ******************************\
1140 \ ******************************\
1142 \ ------------------------------\
1143 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
1144 \ ------------------------------\
1145 \ ... \ init specific I/O sys as you want
1146 \ ... \ before executing default WARM
1147 MOV #WARM,X \ ['] WARM
1149 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
1151 \ ------------------------------\
1153 \ ------------------------------\
1154 CODE STOP \ stops multitasking, must to be used before downloading app
1155 \ ------------------------------\
1156 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
1157 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
1158 MOV X,-2(X) \ restore the default background: SLEEP
1160 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
1161 BIC.B #RC5,&IR_IE \ clear RC5_Int
1162 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
1163 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
1164 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
1165 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
1166 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
1167 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
1169 ." RC5toLCD is removed,"
1170 ." type START to restart"
1171 WARM \ performs reset to reset all interrupt vectors.
1173 \ ------------------------------\
1175 \ ------------------------------\
1176 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
1177 \ ------------------------------\
1178 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1179 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1180 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1181 \ -- \ID input divider \ 10 = /4
1182 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1183 \ - \TBCLR TimerB Clear
1186 \ -------------------------------\
1187 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1188 \ -- \CM Capture Mode
1193 \ --- \OUTMOD \ 011 = set/reset
1199 \ -------------------------------\
1201 \ -------------------------------\
1203 \ ------------------------------\
1204 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1205 \ ------------------------------\
1206 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
1207 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1208 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
1209 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1211 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
1212 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1214 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
1215 \ ------------------------------\
1216 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1217 \ ------------------------------\
1218 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
1219 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1220 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1221 \ ------------------------------\
1222 BIS.B #LCDVo,&LCDVo_DIR \
1223 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
1224 \ ------------------------------\
1225 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1226 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1227 \ ------------------------------\
1228 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1229 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1230 \ ******************************\
1232 \ ******************************\
1233 BIS.B #RC5,&IR_IE \ enable RC5_Int
1234 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1235 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1236 \ ******************************\
1237 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1238 \ ******************************\
1239 \ %01 0001 0100 \ TAxCTL
1240 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
1241 \ -- \ ID divided by 1
1242 \ -- \ MC MODE = up to TAxCCRn
1243 \ - \ TACLR clear timer count
1246 \ ------------------------------\
1247 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1248 \ ------------------------------\
1250 \ --- \ TAIDEX pre divisor
1251 \ ------------------------------\
1252 \ %0000 0000 0000 0101 \ TAxCCR0
1253 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1254 \ ------------------------------\
1255 \ %0000 0000 0001 0000 \ TAxCCTL0
1256 \ - \ CAP capture/compare mode = compare
1259 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
1260 \ ------------------------------\
1261 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1262 \ ------------------------------\
1263 \ define LPM mode for ACCEPT \
1264 \ ------------------------------\
1265 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1266 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1267 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1268 \ ------------------------------\
1270 \ ------------------------------\
1271 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
1272 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
1273 \ ------------------------------\
1274 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
1275 \ ------------------------------\
1276 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
1277 \ CMP #2,Y \ Power_ON event
1278 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
1280 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
1282 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
1284 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
1286 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
1287 \ ------------------------------\
1289 \ ------------------------------\
1291 \ ------------------------------\
1292 #1000 20_US \ 1- wait 20 ms
1293 %011 TOP_LCD \ 2- send DB5=DB4=1
1294 #205 20_US \ 3- wait 4,1 ms
1295 %011 TOP_LCD \ 4- send again DB5=DB4=1
1296 #5 20_US \ 5- wait 0,1 ms
1297 %011 TOP_LCD \ 6- send again again DB5=DB4=1
1298 #2 20_US \ wait 40 us = LCD cycle
1299 %010 TOP_LCD \ 7- send DB5=1 DB4=0
1300 #2 20_US \ wait 40 us = LCD cycle
1301 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1302 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1303 LCD_CLEAR \ 10- "LCD_Clear"
1304 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1305 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1306 LCD_CLEAR \ 10- "LCD_Clear"
1307 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1308 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1309 CR ." I love you" \ display message on LCD
1310 ['] CR >BODY IS CR \ CR executes its default value
1311 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
1312 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
1313 PWR_STATE ABORT \ init DP and continues with ABORT
1315 \ ------------------------------\
1317 \ ------------------------------\
1318 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
1319 \ ------------------------------\
1320 MOV #SLEEP,X \ replace default background process SLEEP
1321 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
1322 MOV #WARM,X \ replace default WARM
1323 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
1324 MOV X,PC \ then execute new WARM
1326 \ ------------------------------\
1329 ; downloading RC5toLCD.4th is done
1330 RST_HERE ; this app is protected against <reset>
1335 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
1337 [UNDEFINED] MARKER [IF]
1338 \ https://forth-standard.org/standard/core/MARKER
1340 \ ( "<spaces>name" -- )
1341 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
1342 \ with the execution semantics defined below.
1344 \ name Execution: ( -- )
1345 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
1346 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
1347 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
1348 \ not necessarily provided. No other contextual information such as numeric base is affected
1353 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
1354 SUB #2,Y \ 1 Y = LFA
1355 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
1356 ADD #4,&DP \ 3 add 2 cells
1360 MOV @RSP+,IP \ -- PFA
1361 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
1362 MOV @TOS,&INIDP \ set DP value for RST_STATE
1364 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
1371 \ https://forth-standard.org/standard/core/Fetch
1372 \ @ c-addr -- char fetch char from memory
1379 [UNDEFINED] CONSTANT [IF]
1380 \ https://forth-standard.org/standard/core/CONSTANT
1381 \ CONSTANT <name> n -- define a Forth CONSTANT
1385 MOV TOS,-2(W) \ PFA = n
1392 [UNDEFINED] STATE [IF]
1393 \ https://forth-standard.org/standard/core/STATE
1394 \ STATE -- a-addr holds compiler state
1395 STATEADR CONSTANT STATE
1399 \ https://forth-standard.org/standard/core/Equal
1400 \ = x1 x2 -- flag test x1=x2
1407 XOR #-1,TOS \ 1 flag Z = 1
1413 \ https://forth-standard.org/standard/core/IF
1414 \ IF -- IFadr initialize conditional forward branch
1418 MOV &DP,TOS \ -- HERE
1419 ADD #4,&DP \ compile one word, reserve one word
1420 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
1421 ADD #2,TOS \ -- HERE+2=IFadr
1426 [UNDEFINED] THEN [IF]
1427 \ https://forth-standard.org/standard/core/THEN
1428 \ THEN IFadr -- resolve forward branch
1429 CODE THEN \ immediate
1430 MOV &DP,0(TOS) \ -- IFadr
1436 [UNDEFINED] ELSE [IF]
1437 \ https://forth-standard.org/standard/core/ELSE
1438 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
1439 CODE ELSE \ immediate
1440 ADD #4,&DP \ make room to compile two words
1441 MOV &DP,W \ W=HERE+4
1443 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
1445 MOV W,TOS \ -- ELSEadr
1450 [UNDEFINED] DEFER [IF]
1451 \ https://forth-standard.org/standard/core/DEFER
1452 \ DEFER "<spaces>name" --
1453 \ Skip leading space delimiters. Parse name delimited by a space.
1454 \ Create a definition for name with the execution semantics defined below.
1456 \ name Execution: --
1457 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
1458 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
1462 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
1463 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
1469 [UNDEFINED] DEFER! [IF]
1470 \ https://forth-standard.org/standard/core/DEFERStore
1471 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
1472 CODE DEFER! \ xt2 xt1 --
1473 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
1480 \ https://forth-standard.org/standard/core/IS
1483 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
1484 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
1485 \ or in a definition : ... ['] U. IS DISPLAY ...
1486 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
1488 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
1491 IF POSTPONE ['] POSTPONE DEFER!
1497 [UNDEFINED] >BODY [IF]
1498 \ https://forth-standard.org/standard/core/toBODY
1499 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
1506 \ CODE 20uS \ n -- 8MHz version
1507 \ BEGIN \ 4 + 16 ~ loop
1508 \ MOV #39,rDOCON \ 39
1515 \ MOV #XDOCON,rDOCON \ 2
1520 CODE 20_US \ n -- n * 20 us
1521 BEGIN \ here we presume that LCD_TIM_IFG = 1...
1523 BIT #1,&LCD_TIM_CTL \ 3
1524 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
1525 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
1527 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
1532 CODE TOP_LCD \ LCD Sample
1533 \ \ if write : %xxxx_WWWW --
1534 \ \ if read : -- %0000_RRRR
1535 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
1536 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
1537 0= IF \ write LCD bits pattern
1539 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
1540 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1543 THEN \ read LCD bits pattern
1546 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
1547 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
1552 CODE LCD_WRC \ char -- Write Char
1553 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1555 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
1556 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
1557 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
1558 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
1559 COLON \ high level word starts here
1560 TOP_LCD 2 20_US \ write high nibble first
1564 CODE LCD_WRF \ func -- Write Fonction
1565 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1569 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
1570 : LCD_HOME $02 LCD_WRF 100 20_us ;
1572 \ [UNDEFINED] OR [IF]
1574 \ \ https://forth-standard.org/standard/core/OR
1575 \ \ C OR x1 x2 -- x3 logical OR
1583 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
1584 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
1585 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
1586 \ : LCD_FN_SET $20 OR LCD_WrF ;
1587 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
1588 \ : LCD_GOTO $80 OR LCD_WrF ;
1591 \ CODE LCD_RDS \ -- status Read Status
1592 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
1593 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
1594 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
1595 \ COLON \ starts a FORTH word
1596 \ TOP_LCD 2 20_us \ -- %0000_HHHH
1597 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
1598 \ HI2LO \ switch from FORTH to assembler
1599 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
1600 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
1601 \ MOV @RSP+,IP \ restore IP saved by COLON
1605 \ CODE LCD_RDC \ -- char Read Char
1606 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
1611 \ ******************************\
1612 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
1613 \ ******************************\
1614 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1615 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
1616 BIT.B #SW2,&SW2_IN \ test switch S2
1617 0= IF \ case of switch S2 pressed
1618 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
1620 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
1623 BIT.B #SW1,&SW1_IN \ test switch S1 input
1624 0= IF \ case of Switch S1 pressed
1625 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
1627 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
1631 BW1 \ from quit on truncated RC5 message, repeated RC5 command
1635 \ ******************************\
1636 ASM RC5_INT \ wake up on Px.RC5 change interrupt
1637 \ ******************************\
1638 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
1639 \ ******************************\
1640 \ \ in : SR(9)=old Toggle bit memory (ADD on)
1641 \ \ SMclock = 8|16|24 MHz
1642 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
1643 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
1644 \ \ SR(9)=new Toggle bit memory (ADD on)
1645 \ ******************************\
1646 \ RC5_FirstStartBitHalfCycle: \
1647 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
1648 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
1649 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
1650 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
1652 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
1653 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
1655 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
1656 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
1658 MOV #1778,X \ RC5_Period * 1us
1659 MOV #14,W \ count of loop
1661 \ ******************************\
1662 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
1663 \ ******************************\ |
1664 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
1665 \ RC5_Compute_3/4_Period: \ |
1666 RRUM #1,X \ X=1/2 cycle |
1669 ADD X,Y \ Y=3/4 cycle
1670 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
1672 \ ******************************\
1673 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
1674 \ ******************************\
1675 BIT.B #RC5,&IR_IN \ C_flag = IR bit
1676 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
1677 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
1678 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
1679 SUB #1,W \ decrement count loop
1680 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
1681 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
1682 0<> WHILE \ ----> out of loop ----+
1683 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
1685 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
1686 CMP Y,X \ 1 | cycle time out of bound ?
1688 BIC #$30,&RC5_TIM_CTL \ | | stop timer
1689 GOTO BW1 \ | | quit on truncated RC5 message
1691 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
1693 REPEAT \ ----> loop back --+ | with X = new RC5_period value
1694 \ ******************************\ |
1695 \ RC5_SampleEndOf: \ <---------------------+
1696 \ ******************************\
1697 BIC #$30,&RC5_TIM_CTL \ stop timer
1698 \ ******************************\
1699 \ RC5_ComputeNewRC5word \
1700 \ ******************************\
1701 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
1702 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
1703 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
1704 \ ******************************\
1705 \ RC5_ComputeC6bit \
1706 \ ******************************\
1707 BIT #BIT14,T \ test /C6 bit in T
1708 0= IF BIS #BIT6,X \ set C6 bit in X
1709 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
1710 \ ******************************\
1711 \ RC5_CommandByteIsDone \ -- BASE RC5_code
1712 \ ******************************\
1713 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
1714 \ ******************************\
1715 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
1716 XOR @RSP,T \ (new XOR old) Toggle bits
1717 BIT #UF10,T \ repeated RC5_command ?
1718 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
1719 XOR #UF10,0(RSP) \ 5 toggle bit memory
1720 \ ******************************\
1721 \ Display IR_RC5 code \
1722 \ ******************************\
1723 SUB #8,PSP \ TOS -- x x x x TOS
1724 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
1725 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
1726 MOV #$10,&BASEADR \ set hexadecimal base
1727 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
1728 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
1729 LO2HI \ switch from assembler to FORTH
1730 LCD_CLEAR \ set LCD cursor at home
1731 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
1732 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
1733 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
1734 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
1735 HI2LO \ -- switch from FORTH to assembler
1736 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
1737 MOV @PSP+,TOS \ -- TOS
1741 \ ******************************\
1743 \ ******************************\
1745 \ ... \ insert here your background task
1748 CALL &RXON \ comment this line to disable TERMINAL_INPUT
1750 \ ******************************\
1751 \ here start all interrupts \
1752 \ ******************************\
1753 \ here return all interrupts \
1754 \ ******************************\
1757 \ ******************************\
1759 \ ------------------------------\
1760 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
1761 \ ------------------------------\
1762 \ ... \ init specific I/O sys as you want
1763 \ ... \ before executing default WARM
1764 MOV #WARM,X \ ['] WARM
1766 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
1768 \ ------------------------------\
1770 \ ------------------------------\
1771 CODE STOP \ stops multitasking, must to be used before downloading app
1772 \ ------------------------------\
1773 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
1774 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
1775 MOV X,-2(X) \ restore the default background: SLEEP
1777 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
1778 BIC.B #RC5,&IR_IE \ clear RC5_Int
1779 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
1780 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
1781 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
1782 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
1783 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
1784 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
1786 ." RC5toLCD is removed,"
1787 ." type START to restart"
1788 WARM \ performs reset to reset all interrupt vectors.
1790 \ ------------------------------\
1792 \ ------------------------------\
1793 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
1794 \ ------------------------------\
1795 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
1796 \ - - \CNTL Counter lentgh \ 00 = 16 bits
1797 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
1798 \ -- \ID input divider \ 10 = /4
1799 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
1800 \ - \TBCLR TimerB Clear
1803 \ -------------------------------\
1804 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
1805 \ -- \CM Capture Mode
1810 \ --- \OUTMOD \ 011 = set/reset
1816 \ -------------------------------\
1818 \ -------------------------------\
1820 \ ------------------------------\
1821 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
1822 \ ------------------------------\
1823 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
1824 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
1825 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
1826 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
1828 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
1829 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
1831 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
1832 \ ------------------------------\
1833 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
1834 \ ------------------------------\
1835 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
1836 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
1837 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
1838 \ ------------------------------\
1839 BIS.B #LCDVo,&LCDVo_DIR \
1840 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
1841 \ ------------------------------\
1842 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
1843 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
1844 \ ------------------------------\
1845 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
1846 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
1847 \ ******************************\
1849 \ ******************************\
1850 BIS.B #RC5,&IR_IE \ enable RC5_Int
1851 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
1852 MOV #RC5_INT,&IR_Vec \ init interrupt vector
1853 \ ******************************\
1854 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
1855 \ ******************************\
1856 \ %01 0001 0100 \ TAxCTL
1857 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
1858 \ -- \ ID divided by 1
1859 \ -- \ MC MODE = up to TAxCCRn
1860 \ - \ TACLR clear timer count
1863 \ ------------------------------\
1864 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
1865 \ ------------------------------\
1867 \ --- \ TAIDEX pre divisor
1868 \ ------------------------------\
1869 \ %0000 0000 0000 0101 \ TAxCCR0
1870 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
1871 \ ------------------------------\
1872 \ %0000 0000 0001 0000 \ TAxCCTL0
1873 \ - \ CAP capture/compare mode = compare
1876 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
1877 \ ------------------------------\
1878 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
1879 \ ------------------------------\
1880 \ define LPM mode for ACCEPT \
1881 \ ------------------------------\
1882 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
1883 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
1884 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
1885 \ ------------------------------\
1887 \ ------------------------------\
1888 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
1889 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
1890 \ ------------------------------\
1891 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
1892 \ ------------------------------\
1893 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
1894 \ CMP #2,Y \ Power_ON event
1895 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
1897 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
1899 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
1901 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
1903 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
1904 \ ------------------------------\
1906 \ ------------------------------\
1908 \ ------------------------------\
1909 #1000 20_US \ 1- wait 20 ms
1910 %011 TOP_LCD \ 2- send DB5=DB4=1
1911 #205 20_US \ 3- wait 4,1 ms
1912 %011 TOP_LCD \ 4- send again DB5=DB4=1
1913 #5 20_US \ 5- wait 0,1 ms
1914 %011 TOP_LCD \ 6- send again again DB5=DB4=1
1915 #2 20_US \ wait 40 us = LCD cycle
1916 %010 TOP_LCD \ 7- send DB5=1 DB4=0
1917 #2 20_US \ wait 40 us = LCD cycle
1918 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
1919 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
1920 LCD_CLEAR \ 10- "LCD_Clear"
1921 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
1922 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
1923 LCD_CLEAR \ 10- "LCD_Clear"
1924 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
1925 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
1926 CR ." I love you" \ display message on LCD
1927 ['] CR >BODY IS CR \ CR executes its default value
1928 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
1929 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
1930 PWR_STATE ABORT \ init DP and continues with ABORT
1932 \ ------------------------------\
1934 \ ------------------------------\
1935 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
1936 \ ------------------------------\
1937 MOV #SLEEP,X \ replace default background process SLEEP
1938 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
1939 MOV #WARM,X \ replace default WARM
1940 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
1941 MOV X,PC \ then execute new WARM
1943 \ ------------------------------\
1946 ; downloading RC5toLCD.4th is done
1947 RST_HERE ; this app is protected against <reset>
1952 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
1954 [UNDEFINED] MARKER [IF]
1955 \ https://forth-standard.org/standard/core/MARKER
1957 \ ( "<spaces>name" -- )
1958 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
1959 \ with the execution semantics defined below.
1961 \ name Execution: ( -- )
1962 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
1963 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
1964 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
1965 \ not necessarily provided. No other contextual information such as numeric base is affected
1970 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
1971 SUB #2,Y \ 1 Y = LFA
1972 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
1973 ADD #4,&DP \ 3 add 2 cells
1977 MOV @RSP+,IP \ -- PFA
1978 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
1979 MOV @TOS,&INIDP \ set DP value for RST_STATE
1981 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
1988 \ https://forth-standard.org/standard/core/Fetch
1989 \ @ c-addr -- char fetch char from memory
1996 [UNDEFINED] CONSTANT [IF]
1997 \ https://forth-standard.org/standard/core/CONSTANT
1998 \ CONSTANT <name> n -- define a Forth CONSTANT
2002 MOV TOS,-2(W) \ PFA = n
2009 [UNDEFINED] STATE [IF]
2010 \ https://forth-standard.org/standard/core/STATE
2011 \ STATE -- a-addr holds compiler state
2012 STATEADR CONSTANT STATE
2016 \ https://forth-standard.org/standard/core/Equal
2017 \ = x1 x2 -- flag test x1=x2
2024 XOR #-1,TOS \ 1 flag Z = 1
2030 \ https://forth-standard.org/standard/core/IF
2031 \ IF -- IFadr initialize conditional forward branch
2035 MOV &DP,TOS \ -- HERE
2036 ADD #4,&DP \ compile one word, reserve one word
2037 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
2038 ADD #2,TOS \ -- HERE+2=IFadr
2043 [UNDEFINED] THEN [IF]
2044 \ https://forth-standard.org/standard/core/THEN
2045 \ THEN IFadr -- resolve forward branch
2046 CODE THEN \ immediate
2047 MOV &DP,0(TOS) \ -- IFadr
2053 [UNDEFINED] ELSE [IF]
2054 \ https://forth-standard.org/standard/core/ELSE
2055 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
2056 CODE ELSE \ immediate
2057 ADD #4,&DP \ make room to compile two words
2058 MOV &DP,W \ W=HERE+4
2060 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
2062 MOV W,TOS \ -- ELSEadr
2067 [UNDEFINED] DEFER [IF]
2068 \ https://forth-standard.org/standard/core/DEFER
2069 \ DEFER "<spaces>name" --
2070 \ Skip leading space delimiters. Parse name delimited by a space.
2071 \ Create a definition for name with the execution semantics defined below.
2073 \ name Execution: --
2074 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
2075 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
2079 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
2080 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
2086 [UNDEFINED] DEFER! [IF]
2087 \ https://forth-standard.org/standard/core/DEFERStore
2088 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
2089 CODE DEFER! \ xt2 xt1 --
2090 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
2097 \ https://forth-standard.org/standard/core/IS
2100 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
2101 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
2102 \ or in a definition : ... ['] U. IS DISPLAY ...
2103 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
2105 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
2108 IF POSTPONE ['] POSTPONE DEFER!
2114 [UNDEFINED] >BODY [IF]
2115 \ https://forth-standard.org/standard/core/toBODY
2116 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
2123 \ CODE 20uS \ n -- 8MHz version
2124 \ BEGIN \ 4 + 16 ~ loop
2125 \ MOV #39,rDOCON \ 39
2132 \ MOV #XDOCON,rDOCON \ 2
2137 CODE 20_US \ n -- n * 20 us
2138 BEGIN \ here we presume that LCD_TIM_IFG = 1...
2140 BIT #1,&LCD_TIM_CTL \ 3
2141 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
2142 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
2144 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
2149 CODE TOP_LCD \ LCD Sample
2150 \ \ if write : %xxxx_WWWW --
2151 \ \ if read : -- %0000_RRRR
2152 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2153 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2154 0= IF \ write LCD bits pattern
2156 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2157 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2160 THEN \ read LCD bits pattern
2163 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2164 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2169 CODE LCD_WRC \ char -- Write Char
2170 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2172 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
2173 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
2174 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2175 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2176 COLON \ high level word starts here
2177 TOP_LCD 2 20_US \ write high nibble first
2181 CODE LCD_WRF \ func -- Write Fonction
2182 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2186 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
2187 : LCD_HOME $02 LCD_WRF 100 20_us ;
2189 \ [UNDEFINED] OR [IF]
2191 \ \ https://forth-standard.org/standard/core/OR
2192 \ \ C OR x1 x2 -- x3 logical OR
2200 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
2201 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
2202 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
2203 \ : LCD_FN_SET $20 OR LCD_WrF ;
2204 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
2205 \ : LCD_GOTO $80 OR LCD_WrF ;
2208 \ CODE LCD_RDS \ -- status Read Status
2209 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2210 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2211 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2212 \ COLON \ starts a FORTH word
2213 \ TOP_LCD 2 20_us \ -- %0000_HHHH
2214 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
2215 \ HI2LO \ switch from FORTH to assembler
2216 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
2217 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
2218 \ MOV @RSP+,IP \ restore IP saved by COLON
2222 \ CODE LCD_RDC \ -- char Read Char
2223 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2228 \ ******************************\
2229 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2230 \ ******************************\
2231 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
2232 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
2233 BIT.B #SW2,&SW2_IN \ test switch S2
2234 0= IF \ case of switch S2 pressed
2235 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2237 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
2240 BIT.B #SW1,&SW1_IN \ test switch S1 input
2241 0= IF \ case of Switch S1 pressed
2242 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2244 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2248 BW1 \ from quit on truncated RC5 message, repeated RC5 command
2252 \ ******************************\
2253 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2254 \ ******************************\
2255 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2256 \ ******************************\
2257 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2258 \ \ SMclock = 8|16|24 MHz
2259 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2260 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2261 \ \ SR(9)=new Toggle bit memory (ADD on)
2262 \ ******************************\
2263 \ RC5_FirstStartBitHalfCycle: \
2264 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
2265 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
2266 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
2267 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
2269 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
2270 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
2272 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
2273 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
2275 MOV #1778,X \ RC5_Period * 1us
2276 MOV #14,W \ count of loop
2278 \ ******************************\
2279 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
2280 \ ******************************\ |
2281 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2282 \ RC5_Compute_3/4_Period: \ |
2283 RRUM #1,X \ X=1/2 cycle |
2286 ADD X,Y \ Y=3/4 cycle
2287 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2289 \ ******************************\
2290 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2291 \ ******************************\
2292 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2293 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
2294 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2295 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2296 SUB #1,W \ decrement count loop
2297 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
2298 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2299 0<> WHILE \ ----> out of loop ----+
2300 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2302 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
2303 CMP Y,X \ 1 | cycle time out of bound ?
2305 BIC #$30,&RC5_TIM_CTL \ | | stop timer
2306 GOTO BW1 \ | | quit on truncated RC5 message
2308 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
2310 REPEAT \ ----> loop back --+ | with X = new RC5_period value
2311 \ ******************************\ |
2312 \ RC5_SampleEndOf: \ <---------------------+
2313 \ ******************************\
2314 BIC #$30,&RC5_TIM_CTL \ stop timer
2315 \ ******************************\
2316 \ RC5_ComputeNewRC5word \
2317 \ ******************************\
2318 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
2319 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
2320 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
2321 \ ******************************\
2322 \ RC5_ComputeC6bit \
2323 \ ******************************\
2324 BIT #BIT14,T \ test /C6 bit in T
2325 0= IF BIS #BIT6,X \ set C6 bit in X
2326 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
2327 \ ******************************\
2328 \ RC5_CommandByteIsDone \ -- BASE RC5_code
2329 \ ******************************\
2330 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2331 \ ******************************\
2332 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
2333 XOR @RSP,T \ (new XOR old) Toggle bits
2334 BIT #UF10,T \ repeated RC5_command ?
2335 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
2336 XOR #UF10,0(RSP) \ 5 toggle bit memory
2337 \ ******************************\
2338 \ Display IR_RC5 code \
2339 \ ******************************\
2340 SUB #8,PSP \ TOS -- x x x x TOS
2341 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
2342 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
2343 MOV #$10,&BASEADR \ set hexadecimal base
2344 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
2345 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
2346 LO2HI \ switch from assembler to FORTH
2347 LCD_CLEAR \ set LCD cursor at home
2348 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
2349 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
2350 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
2351 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
2352 HI2LO \ -- switch from FORTH to assembler
2353 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
2354 MOV @PSP+,TOS \ -- TOS
2358 \ ******************************\
2360 \ ******************************\
2362 \ ... \ insert here your background task
2365 CALL &RXON \ comment this line to disable TERMINAL_INPUT
2367 \ ******************************\
2368 \ here start all interrupts \
2369 \ ******************************\
2370 \ here return all interrupts \
2371 \ ******************************\
2374 \ ******************************\
2376 \ ------------------------------\
2377 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
2378 \ ------------------------------\
2379 \ ... \ init specific I/O sys as you want
2380 \ ... \ before executing default WARM
2381 MOV #WARM,X \ ['] WARM
2383 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
2385 \ ------------------------------\
2387 \ ------------------------------\
2388 CODE STOP \ stops multitasking, must to be used before downloading app
2389 \ ------------------------------\
2390 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
2391 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
2392 MOV X,-2(X) \ restore the default background: SLEEP
2394 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
2395 BIC.B #RC5,&IR_IE \ clear RC5_Int
2396 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
2397 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
2398 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
2399 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
2400 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
2401 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
2403 ." RC5toLCD is removed,"
2404 ." type START to restart"
2405 WARM \ performs reset to reset all interrupt vectors.
2407 \ ------------------------------\
2409 \ ------------------------------\
2410 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
2411 \ ------------------------------\
2412 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
2413 \ - - \CNTL Counter lentgh \ 00 = 16 bits
2414 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
2415 \ -- \ID input divider \ 10 = /4
2416 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
2417 \ - \TBCLR TimerB Clear
2420 \ -------------------------------\
2421 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
2422 \ -- \CM Capture Mode
2427 \ --- \OUTMOD \ 011 = set/reset
2433 \ -------------------------------\
2435 \ -------------------------------\
2437 \ ------------------------------\
2438 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
2439 \ ------------------------------\
2440 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
2441 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
2442 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
2443 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
2445 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
2446 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
2448 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
2449 \ ------------------------------\
2450 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
2451 \ ------------------------------\
2452 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
2453 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
2454 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
2455 \ ------------------------------\
2456 BIS.B #LCDVo,&LCDVo_DIR \
2457 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
2458 \ ------------------------------\
2459 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
2460 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
2461 \ ------------------------------\
2462 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
2463 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
2464 \ ******************************\
2466 \ ******************************\
2467 BIS.B #RC5,&IR_IE \ enable RC5_Int
2468 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
2469 MOV #RC5_INT,&IR_Vec \ init interrupt vector
2470 \ ******************************\
2471 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
2472 \ ******************************\
2473 \ %01 0001 0100 \ TAxCTL
2474 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
2475 \ -- \ ID divided by 1
2476 \ -- \ MC MODE = up to TAxCCRn
2477 \ - \ TACLR clear timer count
2480 \ ------------------------------\
2481 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
2482 \ ------------------------------\
2484 \ --- \ TAIDEX pre divisor
2485 \ ------------------------------\
2486 \ %0000 0000 0000 0101 \ TAxCCR0
2487 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
2488 \ ------------------------------\
2489 \ %0000 0000 0001 0000 \ TAxCCTL0
2490 \ - \ CAP capture/compare mode = compare
2493 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
2494 \ ------------------------------\
2495 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
2496 \ ------------------------------\
2497 \ define LPM mode for ACCEPT \
2498 \ ------------------------------\
2499 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
2500 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
2501 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
2502 \ ------------------------------\
2504 \ ------------------------------\
2505 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
2506 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
2507 \ ------------------------------\
2508 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
2509 \ ------------------------------\
2510 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
2511 \ CMP #2,Y \ Power_ON event
2512 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
2514 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
2516 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
2518 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
2520 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
2521 \ ------------------------------\
2523 \ ------------------------------\
2525 \ ------------------------------\
2526 #1000 20_US \ 1- wait 20 ms
2527 %011 TOP_LCD \ 2- send DB5=DB4=1
2528 #205 20_US \ 3- wait 4,1 ms
2529 %011 TOP_LCD \ 4- send again DB5=DB4=1
2530 #5 20_US \ 5- wait 0,1 ms
2531 %011 TOP_LCD \ 6- send again again DB5=DB4=1
2532 #2 20_US \ wait 40 us = LCD cycle
2533 %010 TOP_LCD \ 7- send DB5=1 DB4=0
2534 #2 20_US \ wait 40 us = LCD cycle
2535 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
2536 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
2537 LCD_CLEAR \ 10- "LCD_Clear"
2538 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
2539 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
2540 LCD_CLEAR \ 10- "LCD_Clear"
2541 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
2542 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
2543 CR ." I love you" \ display message on LCD
2544 ['] CR >BODY IS CR \ CR executes its default value
2545 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
2546 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
2547 PWR_STATE ABORT \ init DP and continues with ABORT
2549 \ ------------------------------\
2551 \ ------------------------------\
2552 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
2553 \ ------------------------------\
2554 MOV #SLEEP,X \ replace default background process SLEEP
2555 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
2556 MOV #WARM,X \ replace default WARM
2557 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
2558 MOV X,PC \ then execute new WARM
2560 \ ------------------------------\
2563 ; downloading RC5toLCD.4th is done
2564 RST_HERE ; this app is protected against <reset>
2569 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
2571 [UNDEFINED] MARKER [IF]
2572 \ https://forth-standard.org/standard/core/MARKER
2574 \ ( "<spaces>name" -- )
2575 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
2576 \ with the execution semantics defined below.
2578 \ name Execution: ( -- )
2579 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
2580 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
2581 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
2582 \ not necessarily provided. No other contextual information such as numeric base is affected
2587 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
2588 SUB #2,Y \ 1 Y = LFA
2589 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
2590 ADD #4,&DP \ 3 add 2 cells
2594 MOV @RSP+,IP \ -- PFA
2595 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
2596 MOV @TOS,&INIDP \ set DP value for RST_STATE
2598 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
2605 \ https://forth-standard.org/standard/core/Fetch
2606 \ @ c-addr -- char fetch char from memory
2613 [UNDEFINED] CONSTANT [IF]
2614 \ https://forth-standard.org/standard/core/CONSTANT
2615 \ CONSTANT <name> n -- define a Forth CONSTANT
2619 MOV TOS,-2(W) \ PFA = n
2626 [UNDEFINED] STATE [IF]
2627 \ https://forth-standard.org/standard/core/STATE
2628 \ STATE -- a-addr holds compiler state
2629 STATEADR CONSTANT STATE
2633 \ https://forth-standard.org/standard/core/Equal
2634 \ = x1 x2 -- flag test x1=x2
2641 XOR #-1,TOS \ 1 flag Z = 1
2647 \ https://forth-standard.org/standard/core/IF
2648 \ IF -- IFadr initialize conditional forward branch
2652 MOV &DP,TOS \ -- HERE
2653 ADD #4,&DP \ compile one word, reserve one word
2654 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
2655 ADD #2,TOS \ -- HERE+2=IFadr
2660 [UNDEFINED] THEN [IF]
2661 \ https://forth-standard.org/standard/core/THEN
2662 \ THEN IFadr -- resolve forward branch
2663 CODE THEN \ immediate
2664 MOV &DP,0(TOS) \ -- IFadr
2670 [UNDEFINED] ELSE [IF]
2671 \ https://forth-standard.org/standard/core/ELSE
2672 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
2673 CODE ELSE \ immediate
2674 ADD #4,&DP \ make room to compile two words
2675 MOV &DP,W \ W=HERE+4
2677 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
2679 MOV W,TOS \ -- ELSEadr
2684 [UNDEFINED] DEFER [IF]
2685 \ https://forth-standard.org/standard/core/DEFER
2686 \ DEFER "<spaces>name" --
2687 \ Skip leading space delimiters. Parse name delimited by a space.
2688 \ Create a definition for name with the execution semantics defined below.
2690 \ name Execution: --
2691 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
2692 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
2696 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
2697 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
2703 [UNDEFINED] DEFER! [IF]
2704 \ https://forth-standard.org/standard/core/DEFERStore
2705 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
2706 CODE DEFER! \ xt2 xt1 --
2707 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
2714 \ https://forth-standard.org/standard/core/IS
2717 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
2718 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
2719 \ or in a definition : ... ['] U. IS DISPLAY ...
2720 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
2722 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
2725 IF POSTPONE ['] POSTPONE DEFER!
2731 [UNDEFINED] >BODY [IF]
2732 \ https://forth-standard.org/standard/core/toBODY
2733 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
2740 \ CODE 20uS \ n -- 8MHz version
2741 \ BEGIN \ 4 + 16 ~ loop
2742 \ MOV #39,rDOCON \ 39
2749 \ MOV #XDOCON,rDOCON \ 2
2754 CODE 20_US \ n -- n * 20 us
2755 BEGIN \ here we presume that LCD_TIM_IFG = 1...
2757 BIT #1,&LCD_TIM_CTL \ 3
2758 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
2759 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
2761 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
2766 CODE TOP_LCD \ LCD Sample
2767 \ \ if write : %xxxx_WWWW --
2768 \ \ if read : -- %0000_RRRR
2769 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
2770 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
2771 0= IF \ write LCD bits pattern
2773 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
2774 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2777 THEN \ read LCD bits pattern
2780 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
2781 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
2786 CODE LCD_WRC \ char -- Write Char
2787 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2789 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
2790 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
2791 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
2792 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
2793 COLON \ high level word starts here
2794 TOP_LCD 2 20_US \ write high nibble first
2798 CODE LCD_WRF \ func -- Write Fonction
2799 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2803 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
2804 : LCD_HOME $02 LCD_WRF 100 20_us ;
2806 \ [UNDEFINED] OR [IF]
2808 \ \ https://forth-standard.org/standard/core/OR
2809 \ \ C OR x1 x2 -- x3 logical OR
2817 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
2818 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
2819 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
2820 \ : LCD_FN_SET $20 OR LCD_WrF ;
2821 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
2822 \ : LCD_GOTO $80 OR LCD_WrF ;
2825 \ CODE LCD_RDS \ -- status Read Status
2826 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
2827 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
2828 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
2829 \ COLON \ starts a FORTH word
2830 \ TOP_LCD 2 20_us \ -- %0000_HHHH
2831 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
2832 \ HI2LO \ switch from FORTH to assembler
2833 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
2834 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
2835 \ MOV @RSP+,IP \ restore IP saved by COLON
2839 \ CODE LCD_RDC \ -- char Read Char
2840 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
2845 \ ******************************\
2846 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
2847 \ ******************************\
2848 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
2849 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
2850 BIT.B #SW2,&SW2_IN \ test switch S2
2851 0= IF \ case of switch S2 pressed
2852 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
2854 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
2857 BIT.B #SW1,&SW1_IN \ test switch S1 input
2858 0= IF \ case of Switch S1 pressed
2859 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
2861 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
2865 BW1 \ from quit on truncated RC5 message, repeated RC5 command
2869 \ ******************************\
2870 ASM RC5_INT \ wake up on Px.RC5 change interrupt
2871 \ ******************************\
2872 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
2873 \ ******************************\
2874 \ \ in : SR(9)=old Toggle bit memory (ADD on)
2875 \ \ SMclock = 8|16|24 MHz
2876 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
2877 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
2878 \ \ SR(9)=new Toggle bit memory (ADD on)
2879 \ ******************************\
2880 \ RC5_FirstStartBitHalfCycle: \
2881 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
2882 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
2883 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
2884 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
2886 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
2887 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
2889 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
2890 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
2892 MOV #1778,X \ RC5_Period * 1us
2893 MOV #14,W \ count of loop
2895 \ ******************************\
2896 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
2897 \ ******************************\ |
2898 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
2899 \ RC5_Compute_3/4_Period: \ |
2900 RRUM #1,X \ X=1/2 cycle |
2903 ADD X,Y \ Y=3/4 cycle
2904 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
2906 \ ******************************\
2907 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
2908 \ ******************************\
2909 BIT.B #RC5,&IR_IN \ C_flag = IR bit
2910 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
2911 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
2912 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
2913 SUB #1,W \ decrement count loop
2914 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
2915 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
2916 0<> WHILE \ ----> out of loop ----+
2917 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
2919 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
2920 CMP Y,X \ 1 | cycle time out of bound ?
2922 BIC #$30,&RC5_TIM_CTL \ | | stop timer
2923 GOTO BW1 \ | | quit on truncated RC5 message
2925 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
2927 REPEAT \ ----> loop back --+ | with X = new RC5_period value
2928 \ ******************************\ |
2929 \ RC5_SampleEndOf: \ <---------------------+
2930 \ ******************************\
2931 BIC #$30,&RC5_TIM_CTL \ stop timer
2932 \ ******************************\
2933 \ RC5_ComputeNewRC5word \
2934 \ ******************************\
2935 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
2936 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
2937 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
2938 \ ******************************\
2939 \ RC5_ComputeC6bit \
2940 \ ******************************\
2941 BIT #BIT14,T \ test /C6 bit in T
2942 0= IF BIS #BIT6,X \ set C6 bit in X
2943 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
2944 \ ******************************\
2945 \ RC5_CommandByteIsDone \ -- BASE RC5_code
2946 \ ******************************\
2947 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
2948 \ ******************************\
2949 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
2950 XOR @RSP,T \ (new XOR old) Toggle bits
2951 BIT #UF10,T \ repeated RC5_command ?
2952 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
2953 XOR #UF10,0(RSP) \ 5 toggle bit memory
2954 \ ******************************\
2955 \ Display IR_RC5 code \
2956 \ ******************************\
2957 SUB #8,PSP \ TOS -- x x x x TOS
2958 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
2959 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
2960 MOV #$10,&BASEADR \ set hexadecimal base
2961 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
2962 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
2963 LO2HI \ switch from assembler to FORTH
2964 LCD_CLEAR \ set LCD cursor at home
2965 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
2966 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
2967 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
2968 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
2969 HI2LO \ -- switch from FORTH to assembler
2970 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
2971 MOV @PSP+,TOS \ -- TOS
2975 \ ******************************\
2977 \ ******************************\
2979 \ ... \ insert here your background task
2982 CALL &RXON \ comment this line to disable TERMINAL_INPUT
2984 \ ******************************\
2985 \ here start all interrupts \
2986 \ ******************************\
2987 \ here return all interrupts \
2988 \ ******************************\
2991 \ ******************************\
2993 \ ------------------------------\
2994 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
2995 \ ------------------------------\
2996 \ ... \ init specific I/O sys as you want
2997 \ ... \ before executing default WARM
2998 MOV #WARM,X \ ['] WARM
3000 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
3002 \ ------------------------------\
3004 \ ------------------------------\
3005 CODE STOP \ stops multitasking, must to be used before downloading app
3006 \ ------------------------------\
3007 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
3008 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
3009 MOV X,-2(X) \ restore the default background: SLEEP
3011 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
3012 BIC.B #RC5,&IR_IE \ clear RC5_Int
3013 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
3014 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
3015 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
3016 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
3017 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
3018 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
3020 ." RC5toLCD is removed,"
3021 ." type START to restart"
3022 WARM \ performs reset to reset all interrupt vectors.
3024 \ ------------------------------\
3026 \ ------------------------------\
3027 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
3028 \ ------------------------------\
3029 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
3030 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3031 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3032 \ -- \ID input divider \ 10 = /4
3033 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3034 \ - \TBCLR TimerB Clear
3037 \ -------------------------------\
3038 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3039 \ -- \CM Capture Mode
3044 \ --- \OUTMOD \ 011 = set/reset
3050 \ -------------------------------\
3052 \ -------------------------------\
3054 \ ------------------------------\
3055 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3056 \ ------------------------------\
3057 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
3058 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3059 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
3060 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3062 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
3063 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3065 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
3066 \ ------------------------------\
3067 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3068 \ ------------------------------\
3069 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
3070 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3071 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3072 \ ------------------------------\
3073 BIS.B #LCDVo,&LCDVo_DIR \
3074 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
3075 \ ------------------------------\
3076 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3077 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3078 \ ------------------------------\
3079 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3080 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3081 \ ******************************\
3083 \ ******************************\
3084 BIS.B #RC5,&IR_IE \ enable RC5_Int
3085 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3086 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3087 \ ******************************\
3088 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3089 \ ******************************\
3090 \ %01 0001 0100 \ TAxCTL
3091 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
3092 \ -- \ ID divided by 1
3093 \ -- \ MC MODE = up to TAxCCRn
3094 \ - \ TACLR clear timer count
3097 \ ------------------------------\
3098 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3099 \ ------------------------------\
3101 \ --- \ TAIDEX pre divisor
3102 \ ------------------------------\
3103 \ %0000 0000 0000 0101 \ TAxCCR0
3104 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3105 \ ------------------------------\
3106 \ %0000 0000 0001 0000 \ TAxCCTL0
3107 \ - \ CAP capture/compare mode = compare
3110 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
3111 \ ------------------------------\
3112 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3113 \ ------------------------------\
3114 \ define LPM mode for ACCEPT \
3115 \ ------------------------------\
3116 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3117 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3118 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3119 \ ------------------------------\
3121 \ ------------------------------\
3122 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
3123 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
3124 \ ------------------------------\
3125 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
3126 \ ------------------------------\
3127 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
3128 \ CMP #2,Y \ Power_ON event
3129 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
3131 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
3133 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
3135 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
3137 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
3138 \ ------------------------------\
3140 \ ------------------------------\
3142 \ ------------------------------\
3143 #1000 20_US \ 1- wait 20 ms
3144 %011 TOP_LCD \ 2- send DB5=DB4=1
3145 #205 20_US \ 3- wait 4,1 ms
3146 %011 TOP_LCD \ 4- send again DB5=DB4=1
3147 #5 20_US \ 5- wait 0,1 ms
3148 %011 TOP_LCD \ 6- send again again DB5=DB4=1
3149 #2 20_US \ wait 40 us = LCD cycle
3150 %010 TOP_LCD \ 7- send DB5=1 DB4=0
3151 #2 20_US \ wait 40 us = LCD cycle
3152 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3153 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3154 LCD_CLEAR \ 10- "LCD_Clear"
3155 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3156 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3157 LCD_CLEAR \ 10- "LCD_Clear"
3158 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3159 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3160 CR ." I love you" \ display message on LCD
3161 ['] CR >BODY IS CR \ CR executes its default value
3162 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
3163 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
3164 PWR_STATE ABORT \ init DP and continues with ABORT
3166 \ ------------------------------\
3168 \ ------------------------------\
3169 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
3170 \ ------------------------------\
3171 MOV #SLEEP,X \ replace default background process SLEEP
3172 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
3173 MOV #WARM,X \ replace default WARM
3174 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
3175 MOV X,PC \ then execute new WARM
3177 \ ------------------------------\
3180 ; downloading RC5toLCD.4th is done
3181 RST_HERE ; this app is protected against <reset>
3186 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
3188 [UNDEFINED] MARKER [IF]
3189 \ https://forth-standard.org/standard/core/MARKER
3191 \ ( "<spaces>name" -- )
3192 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
3193 \ with the execution semantics defined below.
3195 \ name Execution: ( -- )
3196 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
3197 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
3198 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
3199 \ not necessarily provided. No other contextual information such as numeric base is affected
3204 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
3205 SUB #2,Y \ 1 Y = LFA
3206 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
3207 ADD #4,&DP \ 3 add 2 cells
3211 MOV @RSP+,IP \ -- PFA
3212 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
3213 MOV @TOS,&INIDP \ set DP value for RST_STATE
3215 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
3222 \ https://forth-standard.org/standard/core/Fetch
3223 \ @ c-addr -- char fetch char from memory
3230 [UNDEFINED] CONSTANT [IF]
3231 \ https://forth-standard.org/standard/core/CONSTANT
3232 \ CONSTANT <name> n -- define a Forth CONSTANT
3236 MOV TOS,-2(W) \ PFA = n
3243 [UNDEFINED] STATE [IF]
3244 \ https://forth-standard.org/standard/core/STATE
3245 \ STATE -- a-addr holds compiler state
3246 STATEADR CONSTANT STATE
3250 \ https://forth-standard.org/standard/core/Equal
3251 \ = x1 x2 -- flag test x1=x2
3258 XOR #-1,TOS \ 1 flag Z = 1
3264 \ https://forth-standard.org/standard/core/IF
3265 \ IF -- IFadr initialize conditional forward branch
3269 MOV &DP,TOS \ -- HERE
3270 ADD #4,&DP \ compile one word, reserve one word
3271 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
3272 ADD #2,TOS \ -- HERE+2=IFadr
3277 [UNDEFINED] THEN [IF]
3278 \ https://forth-standard.org/standard/core/THEN
3279 \ THEN IFadr -- resolve forward branch
3280 CODE THEN \ immediate
3281 MOV &DP,0(TOS) \ -- IFadr
3287 [UNDEFINED] ELSE [IF]
3288 \ https://forth-standard.org/standard/core/ELSE
3289 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
3290 CODE ELSE \ immediate
3291 ADD #4,&DP \ make room to compile two words
3292 MOV &DP,W \ W=HERE+4
3294 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
3296 MOV W,TOS \ -- ELSEadr
3301 [UNDEFINED] DEFER [IF]
3302 \ https://forth-standard.org/standard/core/DEFER
3303 \ DEFER "<spaces>name" --
3304 \ Skip leading space delimiters. Parse name delimited by a space.
3305 \ Create a definition for name with the execution semantics defined below.
3307 \ name Execution: --
3308 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
3309 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
3313 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
3314 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
3320 [UNDEFINED] DEFER! [IF]
3321 \ https://forth-standard.org/standard/core/DEFERStore
3322 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3323 CODE DEFER! \ xt2 xt1 --
3324 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
3331 \ https://forth-standard.org/standard/core/IS
3334 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
3335 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
3336 \ or in a definition : ... ['] U. IS DISPLAY ...
3337 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3339 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3342 IF POSTPONE ['] POSTPONE DEFER!
3348 [UNDEFINED] >BODY [IF]
3349 \ https://forth-standard.org/standard/core/toBODY
3350 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3357 \ CODE 20uS \ n -- 8MHz version
3358 \ BEGIN \ 4 + 16 ~ loop
3359 \ MOV #39,rDOCON \ 39
3366 \ MOV #XDOCON,rDOCON \ 2
3371 CODE 20_US \ n -- n * 20 us
3372 BEGIN \ here we presume that LCD_TIM_IFG = 1...
3374 BIT #1,&LCD_TIM_CTL \ 3
3375 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
3376 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
3378 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
3383 CODE TOP_LCD \ LCD Sample
3384 \ \ if write : %xxxx_WWWW --
3385 \ \ if read : -- %0000_RRRR
3386 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
3387 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
3388 0= IF \ write LCD bits pattern
3390 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
3391 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3394 THEN \ read LCD bits pattern
3397 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
3398 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
3403 CODE LCD_WRC \ char -- Write Char
3404 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3406 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
3407 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
3408 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
3409 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
3410 COLON \ high level word starts here
3411 TOP_LCD 2 20_US \ write high nibble first
3415 CODE LCD_WRF \ func -- Write Fonction
3416 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3420 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
3421 : LCD_HOME $02 LCD_WRF 100 20_us ;
3423 \ [UNDEFINED] OR [IF]
3425 \ \ https://forth-standard.org/standard/core/OR
3426 \ \ C OR x1 x2 -- x3 logical OR
3434 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
3435 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
3436 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
3437 \ : LCD_FN_SET $20 OR LCD_WrF ;
3438 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
3439 \ : LCD_GOTO $80 OR LCD_WrF ;
3442 \ CODE LCD_RDS \ -- status Read Status
3443 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
3444 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
3445 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
3446 \ COLON \ starts a FORTH word
3447 \ TOP_LCD 2 20_us \ -- %0000_HHHH
3448 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
3449 \ HI2LO \ switch from FORTH to assembler
3450 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
3451 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
3452 \ MOV @RSP+,IP \ restore IP saved by COLON
3456 \ CODE LCD_RDC \ -- char Read Char
3457 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
3462 \ ******************************\
3463 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
3464 \ ******************************\
3465 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
3466 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
3467 BIT.B #SW2,&SW2_IN \ test switch S2
3468 0= IF \ case of switch S2 pressed
3469 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
3471 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
3474 BIT.B #SW1,&SW1_IN \ test switch S1 input
3475 0= IF \ case of Switch S1 pressed
3476 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
3478 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
3482 BW1 \ from quit on truncated RC5 message, repeated RC5 command
3486 \ ******************************\
3487 ASM RC5_INT \ wake up on Px.RC5 change interrupt
3488 \ ******************************\
3489 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
3490 \ ******************************\
3491 \ \ in : SR(9)=old Toggle bit memory (ADD on)
3492 \ \ SMclock = 8|16|24 MHz
3493 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
3494 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
3495 \ \ SR(9)=new Toggle bit memory (ADD on)
3496 \ ******************************\
3497 \ RC5_FirstStartBitHalfCycle: \
3498 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
3499 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
3500 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
3501 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
3503 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
3504 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
3506 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
3507 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
3509 MOV #1778,X \ RC5_Period * 1us
3510 MOV #14,W \ count of loop
3512 \ ******************************\
3513 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
3514 \ ******************************\ |
3515 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
3516 \ RC5_Compute_3/4_Period: \ |
3517 RRUM #1,X \ X=1/2 cycle |
3520 ADD X,Y \ Y=3/4 cycle
3521 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
3523 \ ******************************\
3524 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
3525 \ ******************************\
3526 BIT.B #RC5,&IR_IN \ C_flag = IR bit
3527 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
3528 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
3529 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
3530 SUB #1,W \ decrement count loop
3531 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
3532 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
3533 0<> WHILE \ ----> out of loop ----+
3534 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
3536 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
3537 CMP Y,X \ 1 | cycle time out of bound ?
3539 BIC #$30,&RC5_TIM_CTL \ | | stop timer
3540 GOTO BW1 \ | | quit on truncated RC5 message
3542 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
3544 REPEAT \ ----> loop back --+ | with X = new RC5_period value
3545 \ ******************************\ |
3546 \ RC5_SampleEndOf: \ <---------------------+
3547 \ ******************************\
3548 BIC #$30,&RC5_TIM_CTL \ stop timer
3549 \ ******************************\
3550 \ RC5_ComputeNewRC5word \
3551 \ ******************************\
3552 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
3553 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
3554 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
3555 \ ******************************\
3556 \ RC5_ComputeC6bit \
3557 \ ******************************\
3558 BIT #BIT14,T \ test /C6 bit in T
3559 0= IF BIS #BIT6,X \ set C6 bit in X
3560 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
3561 \ ******************************\
3562 \ RC5_CommandByteIsDone \ -- BASE RC5_code
3563 \ ******************************\
3564 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
3565 \ ******************************\
3566 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
3567 XOR @RSP,T \ (new XOR old) Toggle bits
3568 BIT #UF10,T \ repeated RC5_command ?
3569 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
3570 XOR #UF10,0(RSP) \ 5 toggle bit memory
3571 \ ******************************\
3572 \ Display IR_RC5 code \
3573 \ ******************************\
3574 SUB #8,PSP \ TOS -- x x x x TOS
3575 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
3576 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
3577 MOV #$10,&BASEADR \ set hexadecimal base
3578 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
3579 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
3580 LO2HI \ switch from assembler to FORTH
3581 LCD_CLEAR \ set LCD cursor at home
3582 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
3583 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
3584 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
3585 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
3586 HI2LO \ -- switch from FORTH to assembler
3587 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
3588 MOV @PSP+,TOS \ -- TOS
3592 \ ******************************\
3594 \ ******************************\
3596 \ ... \ insert here your background task
3599 CALL &RXON \ comment this line to disable TERMINAL_INPUT
3601 \ ******************************\
3602 \ here start all interrupts \
3603 \ ******************************\
3604 \ here return all interrupts \
3605 \ ******************************\
3608 \ ******************************\
3610 \ ------------------------------\
3611 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
3612 \ ------------------------------\
3613 \ ... \ init specific I/O sys as you want
3614 \ ... \ before executing default WARM
3615 MOV #WARM,X \ ['] WARM
3617 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
3619 \ ------------------------------\
3621 \ ------------------------------\
3622 CODE STOP \ stops multitasking, must to be used before downloading app
3623 \ ------------------------------\
3624 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
3625 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
3626 MOV X,-2(X) \ restore the default background: SLEEP
3628 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
3629 BIC.B #RC5,&IR_IE \ clear RC5_Int
3630 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
3631 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
3632 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
3633 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
3634 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
3635 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
3637 ." RC5toLCD is removed,"
3638 ." type START to restart"
3639 WARM \ performs reset to reset all interrupt vectors.
3641 \ ------------------------------\
3643 \ ------------------------------\
3644 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
3645 \ ------------------------------\
3646 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
3647 \ - - \CNTL Counter lentgh \ 00 = 16 bits
3648 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
3649 \ -- \ID input divider \ 10 = /4
3650 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
3651 \ - \TBCLR TimerB Clear
3654 \ -------------------------------\
3655 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
3656 \ -- \CM Capture Mode
3661 \ --- \OUTMOD \ 011 = set/reset
3667 \ -------------------------------\
3669 \ -------------------------------\
3671 \ ------------------------------\
3672 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
3673 \ ------------------------------\
3674 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
3675 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
3676 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
3677 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
3679 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
3680 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
3682 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
3683 \ ------------------------------\
3684 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
3685 \ ------------------------------\
3686 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
3687 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
3688 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
3689 \ ------------------------------\
3690 BIS.B #LCDVo,&LCDVo_DIR \
3691 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
3692 \ ------------------------------\
3693 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
3694 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
3695 \ ------------------------------\
3696 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
3697 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
3698 \ ******************************\
3700 \ ******************************\
3701 BIS.B #RC5,&IR_IE \ enable RC5_Int
3702 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
3703 MOV #RC5_INT,&IR_Vec \ init interrupt vector
3704 \ ******************************\
3705 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
3706 \ ******************************\
3707 \ %01 0001 0100 \ TAxCTL
3708 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
3709 \ -- \ ID divided by 1
3710 \ -- \ MC MODE = up to TAxCCRn
3711 \ - \ TACLR clear timer count
3714 \ ------------------------------\
3715 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
3716 \ ------------------------------\
3718 \ --- \ TAIDEX pre divisor
3719 \ ------------------------------\
3720 \ %0000 0000 0000 0101 \ TAxCCR0
3721 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
3722 \ ------------------------------\
3723 \ %0000 0000 0001 0000 \ TAxCCTL0
3724 \ - \ CAP capture/compare mode = compare
3727 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
3728 \ ------------------------------\
3729 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
3730 \ ------------------------------\
3731 \ define LPM mode for ACCEPT \
3732 \ ------------------------------\
3733 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
3734 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
3735 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
3736 \ ------------------------------\
3738 \ ------------------------------\
3739 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
3740 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
3741 \ ------------------------------\
3742 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
3743 \ ------------------------------\
3744 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
3745 \ CMP #2,Y \ Power_ON event
3746 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
3748 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
3750 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
3752 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
3754 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
3755 \ ------------------------------\
3757 \ ------------------------------\
3759 \ ------------------------------\
3760 #1000 20_US \ 1- wait 20 ms
3761 %011 TOP_LCD \ 2- send DB5=DB4=1
3762 #205 20_US \ 3- wait 4,1 ms
3763 %011 TOP_LCD \ 4- send again DB5=DB4=1
3764 #5 20_US \ 5- wait 0,1 ms
3765 %011 TOP_LCD \ 6- send again again DB5=DB4=1
3766 #2 20_US \ wait 40 us = LCD cycle
3767 %010 TOP_LCD \ 7- send DB5=1 DB4=0
3768 #2 20_US \ wait 40 us = LCD cycle
3769 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
3770 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
3771 LCD_CLEAR \ 10- "LCD_Clear"
3772 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
3773 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
3774 LCD_CLEAR \ 10- "LCD_Clear"
3775 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
3776 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
3777 CR ." I love you" \ display message on LCD
3778 ['] CR >BODY IS CR \ CR executes its default value
3779 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
3780 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
3781 PWR_STATE ABORT \ init DP and continues with ABORT
3783 \ ------------------------------\
3785 \ ------------------------------\
3786 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
3787 \ ------------------------------\
3788 MOV #SLEEP,X \ replace default background process SLEEP
3789 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
3790 MOV #WARM,X \ replace default WARM
3791 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
3792 MOV X,PC \ then execute new WARM
3794 \ ------------------------------\
3797 ; downloading RC5toLCD.4th is done
3798 RST_HERE ; this app is protected against <reset>
3803 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
3805 [UNDEFINED] MARKER [IF]
3806 \ https://forth-standard.org/standard/core/MARKER
3808 \ ( "<spaces>name" -- )
3809 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
3810 \ with the execution semantics defined below.
3812 \ name Execution: ( -- )
3813 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
3814 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
3815 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
3816 \ not necessarily provided. No other contextual information such as numeric base is affected
3821 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
3822 SUB #2,Y \ 1 Y = LFA
3823 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
3824 ADD #4,&DP \ 3 add 2 cells
3828 MOV @RSP+,IP \ -- PFA
3829 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
3830 MOV @TOS,&INIDP \ set DP value for RST_STATE
3832 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
3839 \ https://forth-standard.org/standard/core/Fetch
3840 \ @ c-addr -- char fetch char from memory
3847 [UNDEFINED] CONSTANT [IF]
3848 \ https://forth-standard.org/standard/core/CONSTANT
3849 \ CONSTANT <name> n -- define a Forth CONSTANT
3853 MOV TOS,-2(W) \ PFA = n
3860 [UNDEFINED] STATE [IF]
3861 \ https://forth-standard.org/standard/core/STATE
3862 \ STATE -- a-addr holds compiler state
3863 STATEADR CONSTANT STATE
3867 \ https://forth-standard.org/standard/core/Equal
3868 \ = x1 x2 -- flag test x1=x2
3875 XOR #-1,TOS \ 1 flag Z = 1
3881 \ https://forth-standard.org/standard/core/IF
3882 \ IF -- IFadr initialize conditional forward branch
3886 MOV &DP,TOS \ -- HERE
3887 ADD #4,&DP \ compile one word, reserve one word
3888 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
3889 ADD #2,TOS \ -- HERE+2=IFadr
3894 [UNDEFINED] THEN [IF]
3895 \ https://forth-standard.org/standard/core/THEN
3896 \ THEN IFadr -- resolve forward branch
3897 CODE THEN \ immediate
3898 MOV &DP,0(TOS) \ -- IFadr
3904 [UNDEFINED] ELSE [IF]
3905 \ https://forth-standard.org/standard/core/ELSE
3906 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
3907 CODE ELSE \ immediate
3908 ADD #4,&DP \ make room to compile two words
3909 MOV &DP,W \ W=HERE+4
3911 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
3913 MOV W,TOS \ -- ELSEadr
3918 [UNDEFINED] DEFER [IF]
3919 \ https://forth-standard.org/standard/core/DEFER
3920 \ DEFER "<spaces>name" --
3921 \ Skip leading space delimiters. Parse name delimited by a space.
3922 \ Create a definition for name with the execution semantics defined below.
3924 \ name Execution: --
3925 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
3926 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
3930 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
3931 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
3937 [UNDEFINED] DEFER! [IF]
3938 \ https://forth-standard.org/standard/core/DEFERStore
3939 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
3940 CODE DEFER! \ xt2 xt1 --
3941 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
3948 \ https://forth-standard.org/standard/core/IS
3951 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
3952 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
3953 \ or in a definition : ... ['] U. IS DISPLAY ...
3954 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
3956 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
3959 IF POSTPONE ['] POSTPONE DEFER!
3965 [UNDEFINED] >BODY [IF]
3966 \ https://forth-standard.org/standard/core/toBODY
3967 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
3974 \ CODE 20uS \ n -- 8MHz version
3975 \ BEGIN \ 4 + 16 ~ loop
3976 \ MOV #39,rDOCON \ 39
3983 \ MOV #XDOCON,rDOCON \ 2
3988 CODE 20_US \ n -- n * 20 us
3989 BEGIN \ here we presume that LCD_TIM_IFG = 1...
3991 BIT #1,&LCD_TIM_CTL \ 3
3992 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
3993 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
3995 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
4000 CODE TOP_LCD \ LCD Sample
4001 \ \ if write : %xxxx_WWWW --
4002 \ \ if read : -- %0000_RRRR
4003 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4004 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4005 0= IF \ write LCD bits pattern
4007 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4008 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4011 THEN \ read LCD bits pattern
4014 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4015 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4020 CODE LCD_WRC \ char -- Write Char
4021 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4023 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
4024 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
4025 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4026 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4027 COLON \ high level word starts here
4028 TOP_LCD 2 20_US \ write high nibble first
4032 CODE LCD_WRF \ func -- Write Fonction
4033 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4037 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
4038 : LCD_HOME $02 LCD_WRF 100 20_us ;
4040 \ [UNDEFINED] OR [IF]
4042 \ \ https://forth-standard.org/standard/core/OR
4043 \ \ C OR x1 x2 -- x3 logical OR
4051 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
4052 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
4053 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
4054 \ : LCD_FN_SET $20 OR LCD_WrF ;
4055 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
4056 \ : LCD_GOTO $80 OR LCD_WrF ;
4059 \ CODE LCD_RDS \ -- status Read Status
4060 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4061 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4062 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4063 \ COLON \ starts a FORTH word
4064 \ TOP_LCD 2 20_us \ -- %0000_HHHH
4065 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
4066 \ HI2LO \ switch from FORTH to assembler
4067 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
4068 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
4069 \ MOV @RSP+,IP \ restore IP saved by COLON
4073 \ CODE LCD_RDC \ -- char Read Char
4074 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4079 \ ******************************\
4080 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4081 \ ******************************\
4082 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
4083 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
4084 BIT.B #SW2,&SW2_IN \ test switch S2
4085 0= IF \ case of switch S2 pressed
4086 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4088 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
4091 BIT.B #SW1,&SW1_IN \ test switch S1 input
4092 0= IF \ case of Switch S1 pressed
4093 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4095 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4099 BW1 \ from quit on truncated RC5 message, repeated RC5 command
4103 \ ******************************\
4104 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4105 \ ******************************\
4106 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4107 \ ******************************\
4108 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4109 \ \ SMclock = 8|16|24 MHz
4110 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4111 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4112 \ \ SR(9)=new Toggle bit memory (ADD on)
4113 \ ******************************\
4114 \ RC5_FirstStartBitHalfCycle: \
4115 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
4116 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
4117 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
4118 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
4120 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
4121 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
4123 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
4124 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
4126 MOV #1778,X \ RC5_Period * 1us
4127 MOV #14,W \ count of loop
4129 \ ******************************\
4130 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
4131 \ ******************************\ |
4132 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4133 \ RC5_Compute_3/4_Period: \ |
4134 RRUM #1,X \ X=1/2 cycle |
4137 ADD X,Y \ Y=3/4 cycle
4138 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
4140 \ ******************************\
4141 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4142 \ ******************************\
4143 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4144 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
4145 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4146 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4147 SUB #1,W \ decrement count loop
4148 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
4149 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4150 0<> WHILE \ ----> out of loop ----+
4151 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4153 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
4154 CMP Y,X \ 1 | cycle time out of bound ?
4156 BIC #$30,&RC5_TIM_CTL \ | | stop timer
4157 GOTO BW1 \ | | quit on truncated RC5 message
4159 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
4161 REPEAT \ ----> loop back --+ | with X = new RC5_period value
4162 \ ******************************\ |
4163 \ RC5_SampleEndOf: \ <---------------------+
4164 \ ******************************\
4165 BIC #$30,&RC5_TIM_CTL \ stop timer
4166 \ ******************************\
4167 \ RC5_ComputeNewRC5word \
4168 \ ******************************\
4169 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
4170 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
4171 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
4172 \ ******************************\
4173 \ RC5_ComputeC6bit \
4174 \ ******************************\
4175 BIT #BIT14,T \ test /C6 bit in T
4176 0= IF BIS #BIT6,X \ set C6 bit in X
4177 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
4178 \ ******************************\
4179 \ RC5_CommandByteIsDone \ -- BASE RC5_code
4180 \ ******************************\
4181 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4182 \ ******************************\
4183 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
4184 XOR @RSP,T \ (new XOR old) Toggle bits
4185 BIT #UF10,T \ repeated RC5_command ?
4186 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
4187 XOR #UF10,0(RSP) \ 5 toggle bit memory
4188 \ ******************************\
4189 \ Display IR_RC5 code \
4190 \ ******************************\
4191 SUB #8,PSP \ TOS -- x x x x TOS
4192 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
4193 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
4194 MOV #$10,&BASEADR \ set hexadecimal base
4195 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
4196 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
4197 LO2HI \ switch from assembler to FORTH
4198 LCD_CLEAR \ set LCD cursor at home
4199 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
4200 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
4201 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
4202 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
4203 HI2LO \ -- switch from FORTH to assembler
4204 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
4205 MOV @PSP+,TOS \ -- TOS
4209 \ ******************************\
4211 \ ******************************\
4213 \ ... \ insert here your background task
4216 CALL &RXON \ comment this line to disable TERMINAL_INPUT
4218 \ ******************************\
4219 \ here start all interrupts \
4220 \ ******************************\
4221 \ here return all interrupts \
4222 \ ******************************\
4225 \ ******************************\
4227 \ ------------------------------\
4228 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
4229 \ ------------------------------\
4230 \ ... \ init specific I/O sys as you want
4231 \ ... \ before executing default WARM
4232 MOV #WARM,X \ ['] WARM
4234 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
4236 \ ------------------------------\
4238 \ ------------------------------\
4239 CODE STOP \ stops multitasking, must to be used before downloading app
4240 \ ------------------------------\
4241 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
4242 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
4243 MOV X,-2(X) \ restore the default background: SLEEP
4245 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
4246 BIC.B #RC5,&IR_IE \ clear RC5_Int
4247 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
4248 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
4249 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
4250 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
4251 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
4252 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
4254 ." RC5toLCD is removed,"
4255 ." type START to restart"
4256 WARM \ performs reset to reset all interrupt vectors.
4258 \ ------------------------------\
4260 \ ------------------------------\
4261 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
4262 \ ------------------------------\
4263 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
4264 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4265 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4266 \ -- \ID input divider \ 10 = /4
4267 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4268 \ - \TBCLR TimerB Clear
4271 \ -------------------------------\
4272 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4273 \ -- \CM Capture Mode
4278 \ --- \OUTMOD \ 011 = set/reset
4284 \ -------------------------------\
4286 \ -------------------------------\
4288 \ ------------------------------\
4289 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4290 \ ------------------------------\
4291 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4292 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4293 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
4294 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4296 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
4297 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4299 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
4300 \ ------------------------------\
4301 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4302 \ ------------------------------\
4303 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
4304 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4305 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4306 \ ------------------------------\
4307 BIS.B #LCDVo,&LCDVo_DIR \
4308 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
4309 \ ------------------------------\
4310 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4311 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4312 \ ------------------------------\
4313 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4314 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4315 \ ******************************\
4317 \ ******************************\
4318 BIS.B #RC5,&IR_IE \ enable RC5_Int
4319 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4320 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4321 \ ******************************\
4322 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4323 \ ******************************\
4324 \ %01 0001 0100 \ TAxCTL
4325 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
4326 \ -- \ ID divided by 1
4327 \ -- \ MC MODE = up to TAxCCRn
4328 \ - \ TACLR clear timer count
4331 \ ------------------------------\
4332 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4333 \ ------------------------------\
4335 \ --- \ TAIDEX pre divisor
4336 \ ------------------------------\
4337 \ %0000 0000 0000 0101 \ TAxCCR0
4338 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4339 \ ------------------------------\
4340 \ %0000 0000 0001 0000 \ TAxCCTL0
4341 \ - \ CAP capture/compare mode = compare
4344 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
4345 \ ------------------------------\
4346 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4347 \ ------------------------------\
4348 \ define LPM mode for ACCEPT \
4349 \ ------------------------------\
4350 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4351 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4352 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4353 \ ------------------------------\
4355 \ ------------------------------\
4356 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
4357 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
4358 \ ------------------------------\
4359 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
4360 \ ------------------------------\
4361 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
4362 \ CMP #2,Y \ Power_ON event
4363 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
4365 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
4367 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
4369 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
4371 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
4372 \ ------------------------------\
4374 \ ------------------------------\
4376 \ ------------------------------\
4377 #1000 20_US \ 1- wait 20 ms
4378 %011 TOP_LCD \ 2- send DB5=DB4=1
4379 #205 20_US \ 3- wait 4,1 ms
4380 %011 TOP_LCD \ 4- send again DB5=DB4=1
4381 #5 20_US \ 5- wait 0,1 ms
4382 %011 TOP_LCD \ 6- send again again DB5=DB4=1
4383 #2 20_US \ wait 40 us = LCD cycle
4384 %010 TOP_LCD \ 7- send DB5=1 DB4=0
4385 #2 20_US \ wait 40 us = LCD cycle
4386 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
4387 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
4388 LCD_CLEAR \ 10- "LCD_Clear"
4389 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
4390 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
4391 LCD_CLEAR \ 10- "LCD_Clear"
4392 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
4393 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
4394 CR ." I love you" \ display message on LCD
4395 ['] CR >BODY IS CR \ CR executes its default value
4396 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
4397 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
4398 PWR_STATE ABORT \ init DP and continues with ABORT
4400 \ ------------------------------\
4402 \ ------------------------------\
4403 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
4404 \ ------------------------------\
4405 MOV #SLEEP,X \ replace default background process SLEEP
4406 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
4407 MOV #WARM,X \ replace default WARM
4408 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
4409 MOV X,PC \ then execute new WARM
4411 \ ------------------------------\
4414 ; downloading RC5toLCD.4th is done
4415 RST_HERE ; this app is protected against <reset>
4420 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
4422 [UNDEFINED] MARKER [IF]
4423 \ https://forth-standard.org/standard/core/MARKER
4425 \ ( "<spaces>name" -- )
4426 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
4427 \ with the execution semantics defined below.
4429 \ name Execution: ( -- )
4430 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
4431 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
4432 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
4433 \ not necessarily provided. No other contextual information such as numeric base is affected
4438 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
4439 SUB #2,Y \ 1 Y = LFA
4440 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
4441 ADD #4,&DP \ 3 add 2 cells
4445 MOV @RSP+,IP \ -- PFA
4446 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
4447 MOV @TOS,&INIDP \ set DP value for RST_STATE
4449 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
4456 \ https://forth-standard.org/standard/core/Fetch
4457 \ @ c-addr -- char fetch char from memory
4464 [UNDEFINED] CONSTANT [IF]
4465 \ https://forth-standard.org/standard/core/CONSTANT
4466 \ CONSTANT <name> n -- define a Forth CONSTANT
4470 MOV TOS,-2(W) \ PFA = n
4477 [UNDEFINED] STATE [IF]
4478 \ https://forth-standard.org/standard/core/STATE
4479 \ STATE -- a-addr holds compiler state
4480 STATEADR CONSTANT STATE
4484 \ https://forth-standard.org/standard/core/Equal
4485 \ = x1 x2 -- flag test x1=x2
4492 XOR #-1,TOS \ 1 flag Z = 1
4498 \ https://forth-standard.org/standard/core/IF
4499 \ IF -- IFadr initialize conditional forward branch
4503 MOV &DP,TOS \ -- HERE
4504 ADD #4,&DP \ compile one word, reserve one word
4505 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
4506 ADD #2,TOS \ -- HERE+2=IFadr
4511 [UNDEFINED] THEN [IF]
4512 \ https://forth-standard.org/standard/core/THEN
4513 \ THEN IFadr -- resolve forward branch
4514 CODE THEN \ immediate
4515 MOV &DP,0(TOS) \ -- IFadr
4521 [UNDEFINED] ELSE [IF]
4522 \ https://forth-standard.org/standard/core/ELSE
4523 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
4524 CODE ELSE \ immediate
4525 ADD #4,&DP \ make room to compile two words
4526 MOV &DP,W \ W=HERE+4
4528 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
4530 MOV W,TOS \ -- ELSEadr
4535 [UNDEFINED] DEFER [IF]
4536 \ https://forth-standard.org/standard/core/DEFER
4537 \ DEFER "<spaces>name" --
4538 \ Skip leading space delimiters. Parse name delimited by a space.
4539 \ Create a definition for name with the execution semantics defined below.
4541 \ name Execution: --
4542 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
4543 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
4547 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
4548 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
4554 [UNDEFINED] DEFER! [IF]
4555 \ https://forth-standard.org/standard/core/DEFERStore
4556 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
4557 CODE DEFER! \ xt2 xt1 --
4558 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
4565 \ https://forth-standard.org/standard/core/IS
4568 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
4569 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
4570 \ or in a definition : ... ['] U. IS DISPLAY ...
4571 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
4573 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
4576 IF POSTPONE ['] POSTPONE DEFER!
4582 [UNDEFINED] >BODY [IF]
4583 \ https://forth-standard.org/standard/core/toBODY
4584 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
4591 \ CODE 20uS \ n -- 8MHz version
4592 \ BEGIN \ 4 + 16 ~ loop
4593 \ MOV #39,rDOCON \ 39
4600 \ MOV #XDOCON,rDOCON \ 2
4605 CODE 20_US \ n -- n * 20 us
4606 BEGIN \ here we presume that LCD_TIM_IFG = 1...
4608 BIT #1,&LCD_TIM_CTL \ 3
4609 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
4610 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
4612 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
4617 CODE TOP_LCD \ LCD Sample
4618 \ \ if write : %xxxx_WWWW --
4619 \ \ if read : -- %0000_RRRR
4620 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
4621 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
4622 0= IF \ write LCD bits pattern
4624 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
4625 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4628 THEN \ read LCD bits pattern
4631 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
4632 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
4637 CODE LCD_WRC \ char -- Write Char
4638 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4640 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
4641 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
4642 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
4643 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
4644 COLON \ high level word starts here
4645 TOP_LCD 2 20_US \ write high nibble first
4649 CODE LCD_WRF \ func -- Write Fonction
4650 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4654 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
4655 : LCD_HOME $02 LCD_WRF 100 20_us ;
4657 \ [UNDEFINED] OR [IF]
4659 \ \ https://forth-standard.org/standard/core/OR
4660 \ \ C OR x1 x2 -- x3 logical OR
4668 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
4669 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
4670 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
4671 \ : LCD_FN_SET $20 OR LCD_WrF ;
4672 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
4673 \ : LCD_GOTO $80 OR LCD_WrF ;
4676 \ CODE LCD_RDS \ -- status Read Status
4677 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
4678 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
4679 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
4680 \ COLON \ starts a FORTH word
4681 \ TOP_LCD 2 20_us \ -- %0000_HHHH
4682 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
4683 \ HI2LO \ switch from FORTH to assembler
4684 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
4685 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
4686 \ MOV @RSP+,IP \ restore IP saved by COLON
4690 \ CODE LCD_RDC \ -- char Read Char
4691 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
4696 \ ******************************\
4697 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
4698 \ ******************************\
4699 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
4700 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
4701 BIT.B #SW2,&SW2_IN \ test switch S2
4702 0= IF \ case of switch S2 pressed
4703 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
4705 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
4708 BIT.B #SW1,&SW1_IN \ test switch S1 input
4709 0= IF \ case of Switch S1 pressed
4710 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
4712 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
4716 BW1 \ from quit on truncated RC5 message, repeated RC5 command
4720 \ ******************************\
4721 ASM RC5_INT \ wake up on Px.RC5 change interrupt
4722 \ ******************************\
4723 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
4724 \ ******************************\
4725 \ \ in : SR(9)=old Toggle bit memory (ADD on)
4726 \ \ SMclock = 8|16|24 MHz
4727 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
4728 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
4729 \ \ SR(9)=new Toggle bit memory (ADD on)
4730 \ ******************************\
4731 \ RC5_FirstStartBitHalfCycle: \
4732 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
4733 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
4734 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
4735 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
4737 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
4738 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
4740 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
4741 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
4743 MOV #1778,X \ RC5_Period * 1us
4744 MOV #14,W \ count of loop
4746 \ ******************************\
4747 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
4748 \ ******************************\ |
4749 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
4750 \ RC5_Compute_3/4_Period: \ |
4751 RRUM #1,X \ X=1/2 cycle |
4754 ADD X,Y \ Y=3/4 cycle
4755 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
4757 \ ******************************\
4758 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
4759 \ ******************************\
4760 BIT.B #RC5,&IR_IN \ C_flag = IR bit
4761 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
4762 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
4763 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
4764 SUB #1,W \ decrement count loop
4765 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
4766 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
4767 0<> WHILE \ ----> out of loop ----+
4768 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
4770 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
4771 CMP Y,X \ 1 | cycle time out of bound ?
4773 BIC #$30,&RC5_TIM_CTL \ | | stop timer
4774 GOTO BW1 \ | | quit on truncated RC5 message
4776 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
4778 REPEAT \ ----> loop back --+ | with X = new RC5_period value
4779 \ ******************************\ |
4780 \ RC5_SampleEndOf: \ <---------------------+
4781 \ ******************************\
4782 BIC #$30,&RC5_TIM_CTL \ stop timer
4783 \ ******************************\
4784 \ RC5_ComputeNewRC5word \
4785 \ ******************************\
4786 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
4787 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
4788 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
4789 \ ******************************\
4790 \ RC5_ComputeC6bit \
4791 \ ******************************\
4792 BIT #BIT14,T \ test /C6 bit in T
4793 0= IF BIS #BIT6,X \ set C6 bit in X
4794 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
4795 \ ******************************\
4796 \ RC5_CommandByteIsDone \ -- BASE RC5_code
4797 \ ******************************\
4798 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
4799 \ ******************************\
4800 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
4801 XOR @RSP,T \ (new XOR old) Toggle bits
4802 BIT #UF10,T \ repeated RC5_command ?
4803 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
4804 XOR #UF10,0(RSP) \ 5 toggle bit memory
4805 \ ******************************\
4806 \ Display IR_RC5 code \
4807 \ ******************************\
4808 SUB #8,PSP \ TOS -- x x x x TOS
4809 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
4810 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
4811 MOV #$10,&BASEADR \ set hexadecimal base
4812 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
4813 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
4814 LO2HI \ switch from assembler to FORTH
4815 LCD_CLEAR \ set LCD cursor at home
4816 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
4817 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
4818 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
4819 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
4820 HI2LO \ -- switch from FORTH to assembler
4821 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
4822 MOV @PSP+,TOS \ -- TOS
4826 \ ******************************\
4828 \ ******************************\
4830 \ ... \ insert here your background task
4833 CALL &RXON \ comment this line to disable TERMINAL_INPUT
4835 \ ******************************\
4836 \ here start all interrupts \
4837 \ ******************************\
4838 \ here return all interrupts \
4839 \ ******************************\
4842 \ ******************************\
4844 \ ------------------------------\
4845 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
4846 \ ------------------------------\
4847 \ ... \ init specific I/O sys as you want
4848 \ ... \ before executing default WARM
4849 MOV #WARM,X \ ['] WARM
4851 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
4853 \ ------------------------------\
4855 \ ------------------------------\
4856 CODE STOP \ stops multitasking, must to be used before downloading app
4857 \ ------------------------------\
4858 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
4859 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
4860 MOV X,-2(X) \ restore the default background: SLEEP
4862 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
4863 BIC.B #RC5,&IR_IE \ clear RC5_Int
4864 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
4865 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
4866 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
4867 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
4868 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
4869 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
4871 ." RC5toLCD is removed,"
4872 ." type START to restart"
4873 WARM \ performs reset to reset all interrupt vectors.
4875 \ ------------------------------\
4877 \ ------------------------------\
4878 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
4879 \ ------------------------------\
4880 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
4881 \ - - \CNTL Counter lentgh \ 00 = 16 bits
4882 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
4883 \ -- \ID input divider \ 10 = /4
4884 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
4885 \ - \TBCLR TimerB Clear
4888 \ -------------------------------\
4889 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
4890 \ -- \CM Capture Mode
4895 \ --- \OUTMOD \ 011 = set/reset
4901 \ -------------------------------\
4903 \ -------------------------------\
4905 \ ------------------------------\
4906 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
4907 \ ------------------------------\
4908 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
4909 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
4910 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
4911 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
4913 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
4914 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
4916 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
4917 \ ------------------------------\
4918 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
4919 \ ------------------------------\
4920 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
4921 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
4922 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
4923 \ ------------------------------\
4924 BIS.B #LCDVo,&LCDVo_DIR \
4925 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
4926 \ ------------------------------\
4927 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
4928 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
4929 \ ------------------------------\
4930 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
4931 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
4932 \ ******************************\
4934 \ ******************************\
4935 BIS.B #RC5,&IR_IE \ enable RC5_Int
4936 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
4937 MOV #RC5_INT,&IR_Vec \ init interrupt vector
4938 \ ******************************\
4939 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
4940 \ ******************************\
4941 \ %01 0001 0100 \ TAxCTL
4942 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
4943 \ -- \ ID divided by 1
4944 \ -- \ MC MODE = up to TAxCCRn
4945 \ - \ TACLR clear timer count
4948 \ ------------------------------\
4949 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
4950 \ ------------------------------\
4952 \ --- \ TAIDEX pre divisor
4953 \ ------------------------------\
4954 \ %0000 0000 0000 0101 \ TAxCCR0
4955 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
4956 \ ------------------------------\
4957 \ %0000 0000 0001 0000 \ TAxCCTL0
4958 \ - \ CAP capture/compare mode = compare
4961 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
4962 \ ------------------------------\
4963 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
4964 \ ------------------------------\
4965 \ define LPM mode for ACCEPT \
4966 \ ------------------------------\
4967 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
4968 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
4969 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
4970 \ ------------------------------\
4972 \ ------------------------------\
4973 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
4974 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
4975 \ ------------------------------\
4976 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
4977 \ ------------------------------\
4978 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
4979 \ CMP #2,Y \ Power_ON event
4980 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
4982 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
4984 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
4986 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
4988 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
4989 \ ------------------------------\
4991 \ ------------------------------\
4993 \ ------------------------------\
4994 #1000 20_US \ 1- wait 20 ms
4995 %011 TOP_LCD \ 2- send DB5=DB4=1
4996 #205 20_US \ 3- wait 4,1 ms
4997 %011 TOP_LCD \ 4- send again DB5=DB4=1
4998 #5 20_US \ 5- wait 0,1 ms
4999 %011 TOP_LCD \ 6- send again again DB5=DB4=1
5000 #2 20_US \ wait 40 us = LCD cycle
5001 %010 TOP_LCD \ 7- send DB5=1 DB4=0
5002 #2 20_US \ wait 40 us = LCD cycle
5003 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5004 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5005 LCD_CLEAR \ 10- "LCD_Clear"
5006 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5007 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5008 LCD_CLEAR \ 10- "LCD_Clear"
5009 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5010 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5011 CR ." I love you" \ display message on LCD
5012 ['] CR >BODY IS CR \ CR executes its default value
5013 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
5014 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
5015 PWR_STATE ABORT \ init DP and continues with ABORT
5017 \ ------------------------------\
5019 \ ------------------------------\
5020 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
5021 \ ------------------------------\
5022 MOV #SLEEP,X \ replace default background process SLEEP
5023 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
5024 MOV #WARM,X \ replace default WARM
5025 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
5026 MOV X,PC \ then execute new WARM
5028 \ ------------------------------\
5031 ; downloading RC5toLCD.4th is done
5032 RST_HERE ; this app is protected against <reset>
5037 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
5039 [UNDEFINED] MARKER [IF]
5040 \ https://forth-standard.org/standard/core/MARKER
5042 \ ( "<spaces>name" -- )
5043 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
5044 \ with the execution semantics defined below.
5046 \ name Execution: ( -- )
5047 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
5048 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
5049 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
5050 \ not necessarily provided. No other contextual information such as numeric base is affected
5055 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
5056 SUB #2,Y \ 1 Y = LFA
5057 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
5058 ADD #4,&DP \ 3 add 2 cells
5062 MOV @RSP+,IP \ -- PFA
5063 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
5064 MOV @TOS,&INIDP \ set DP value for RST_STATE
5066 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
5073 \ https://forth-standard.org/standard/core/Fetch
5074 \ @ c-addr -- char fetch char from memory
5081 [UNDEFINED] CONSTANT [IF]
5082 \ https://forth-standard.org/standard/core/CONSTANT
5083 \ CONSTANT <name> n -- define a Forth CONSTANT
5087 MOV TOS,-2(W) \ PFA = n
5094 [UNDEFINED] STATE [IF]
5095 \ https://forth-standard.org/standard/core/STATE
5096 \ STATE -- a-addr holds compiler state
5097 STATEADR CONSTANT STATE
5101 \ https://forth-standard.org/standard/core/Equal
5102 \ = x1 x2 -- flag test x1=x2
5109 XOR #-1,TOS \ 1 flag Z = 1
5115 \ https://forth-standard.org/standard/core/IF
5116 \ IF -- IFadr initialize conditional forward branch
5120 MOV &DP,TOS \ -- HERE
5121 ADD #4,&DP \ compile one word, reserve one word
5122 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
5123 ADD #2,TOS \ -- HERE+2=IFadr
5128 [UNDEFINED] THEN [IF]
5129 \ https://forth-standard.org/standard/core/THEN
5130 \ THEN IFadr -- resolve forward branch
5131 CODE THEN \ immediate
5132 MOV &DP,0(TOS) \ -- IFadr
5138 [UNDEFINED] ELSE [IF]
5139 \ https://forth-standard.org/standard/core/ELSE
5140 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
5141 CODE ELSE \ immediate
5142 ADD #4,&DP \ make room to compile two words
5143 MOV &DP,W \ W=HERE+4
5145 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
5147 MOV W,TOS \ -- ELSEadr
5152 [UNDEFINED] DEFER [IF]
5153 \ https://forth-standard.org/standard/core/DEFER
5154 \ DEFER "<spaces>name" --
5155 \ Skip leading space delimiters. Parse name delimited by a space.
5156 \ Create a definition for name with the execution semantics defined below.
5158 \ name Execution: --
5159 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
5160 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
5164 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
5165 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
5171 [UNDEFINED] DEFER! [IF]
5172 \ https://forth-standard.org/standard/core/DEFERStore
5173 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
5174 CODE DEFER! \ xt2 xt1 --
5175 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
5182 \ https://forth-standard.org/standard/core/IS
5185 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
5186 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
5187 \ or in a definition : ... ['] U. IS DISPLAY ...
5188 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
5190 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
5193 IF POSTPONE ['] POSTPONE DEFER!
5199 [UNDEFINED] >BODY [IF]
5200 \ https://forth-standard.org/standard/core/toBODY
5201 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
5208 \ CODE 20uS \ n -- 8MHz version
5209 \ BEGIN \ 4 + 16 ~ loop
5210 \ MOV #39,rDOCON \ 39
5217 \ MOV #XDOCON,rDOCON \ 2
5222 CODE 20_US \ n -- n * 20 us
5223 BEGIN \ here we presume that LCD_TIM_IFG = 1...
5225 BIT #1,&LCD_TIM_CTL \ 3
5226 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
5227 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
5229 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
5234 CODE TOP_LCD \ LCD Sample
5235 \ \ if write : %xxxx_WWWW --
5236 \ \ if read : -- %0000_RRRR
5237 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5238 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5239 0= IF \ write LCD bits pattern
5241 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5242 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5245 THEN \ read LCD bits pattern
5248 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5249 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5254 CODE LCD_WRC \ char -- Write Char
5255 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5257 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
5258 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
5259 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5260 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5261 COLON \ high level word starts here
5262 TOP_LCD 2 20_US \ write high nibble first
5266 CODE LCD_WRF \ func -- Write Fonction
5267 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5271 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
5272 : LCD_HOME $02 LCD_WRF 100 20_us ;
5274 \ [UNDEFINED] OR [IF]
5276 \ \ https://forth-standard.org/standard/core/OR
5277 \ \ C OR x1 x2 -- x3 logical OR
5285 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
5286 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
5287 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
5288 \ : LCD_FN_SET $20 OR LCD_WrF ;
5289 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
5290 \ : LCD_GOTO $80 OR LCD_WrF ;
5293 \ CODE LCD_RDS \ -- status Read Status
5294 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5295 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5296 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5297 \ COLON \ starts a FORTH word
5298 \ TOP_LCD 2 20_us \ -- %0000_HHHH
5299 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
5300 \ HI2LO \ switch from FORTH to assembler
5301 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
5302 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
5303 \ MOV @RSP+,IP \ restore IP saved by COLON
5307 \ CODE LCD_RDC \ -- char Read Char
5308 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5313 \ ******************************\
5314 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5315 \ ******************************\
5316 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5317 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
5318 BIT.B #SW2,&SW2_IN \ test switch S2
5319 0= IF \ case of switch S2 pressed
5320 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5322 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
5325 BIT.B #SW1,&SW1_IN \ test switch S1 input
5326 0= IF \ case of Switch S1 pressed
5327 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5329 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5333 BW1 \ from quit on truncated RC5 message, repeated RC5 command
5337 \ ******************************\
5338 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5339 \ ******************************\
5340 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5341 \ ******************************\
5342 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5343 \ \ SMclock = 8|16|24 MHz
5344 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5345 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5346 \ \ SR(9)=new Toggle bit memory (ADD on)
5347 \ ******************************\
5348 \ RC5_FirstStartBitHalfCycle: \
5349 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5350 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5351 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
5352 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
5354 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
5355 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
5357 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
5358 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
5360 MOV #1778,X \ RC5_Period * 1us
5361 MOV #14,W \ count of loop
5363 \ ******************************\
5364 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
5365 \ ******************************\ |
5366 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5367 \ RC5_Compute_3/4_Period: \ |
5368 RRUM #1,X \ X=1/2 cycle |
5371 ADD X,Y \ Y=3/4 cycle
5372 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
5374 \ ******************************\
5375 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5376 \ ******************************\
5377 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5378 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
5379 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5380 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5381 SUB #1,W \ decrement count loop
5382 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
5383 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
5384 0<> WHILE \ ----> out of loop ----+
5385 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
5387 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
5388 CMP Y,X \ 1 | cycle time out of bound ?
5390 BIC #$30,&RC5_TIM_CTL \ | | stop timer
5391 GOTO BW1 \ | | quit on truncated RC5 message
5393 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
5395 REPEAT \ ----> loop back --+ | with X = new RC5_period value
5396 \ ******************************\ |
5397 \ RC5_SampleEndOf: \ <---------------------+
5398 \ ******************************\
5399 BIC #$30,&RC5_TIM_CTL \ stop timer
5400 \ ******************************\
5401 \ RC5_ComputeNewRC5word \
5402 \ ******************************\
5403 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
5404 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
5405 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
5406 \ ******************************\
5407 \ RC5_ComputeC6bit \
5408 \ ******************************\
5409 BIT #BIT14,T \ test /C6 bit in T
5410 0= IF BIS #BIT6,X \ set C6 bit in X
5411 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
5412 \ ******************************\
5413 \ RC5_CommandByteIsDone \ -- BASE RC5_code
5414 \ ******************************\
5415 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
5416 \ ******************************\
5417 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
5418 XOR @RSP,T \ (new XOR old) Toggle bits
5419 BIT #UF10,T \ repeated RC5_command ?
5420 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
5421 XOR #UF10,0(RSP) \ 5 toggle bit memory
5422 \ ******************************\
5423 \ Display IR_RC5 code \
5424 \ ******************************\
5425 SUB #8,PSP \ TOS -- x x x x TOS
5426 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
5427 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
5428 MOV #$10,&BASEADR \ set hexadecimal base
5429 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
5430 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
5431 LO2HI \ switch from assembler to FORTH
5432 LCD_CLEAR \ set LCD cursor at home
5433 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
5434 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
5435 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
5436 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
5437 HI2LO \ -- switch from FORTH to assembler
5438 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
5439 MOV @PSP+,TOS \ -- TOS
5443 \ ******************************\
5445 \ ******************************\
5447 \ ... \ insert here your background task
5450 CALL &RXON \ comment this line to disable TERMINAL_INPUT
5452 \ ******************************\
5453 \ here start all interrupts \
5454 \ ******************************\
5455 \ here return all interrupts \
5456 \ ******************************\
5459 \ ******************************\
5461 \ ------------------------------\
5462 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
5463 \ ------------------------------\
5464 \ ... \ init specific I/O sys as you want
5465 \ ... \ before executing default WARM
5466 MOV #WARM,X \ ['] WARM
5468 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
5470 \ ------------------------------\
5472 \ ------------------------------\
5473 CODE STOP \ stops multitasking, must to be used before downloading app
5474 \ ------------------------------\
5475 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
5476 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
5477 MOV X,-2(X) \ restore the default background: SLEEP
5479 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
5480 BIC.B #RC5,&IR_IE \ clear RC5_Int
5481 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
5482 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
5483 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
5484 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
5485 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
5486 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
5488 ." RC5toLCD is removed,"
5489 ." type START to restart"
5490 WARM \ performs reset to reset all interrupt vectors.
5492 \ ------------------------------\
5494 \ ------------------------------\
5495 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
5496 \ ------------------------------\
5497 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
5498 \ - - \CNTL Counter lentgh \ 00 = 16 bits
5499 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
5500 \ -- \ID input divider \ 10 = /4
5501 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
5502 \ - \TBCLR TimerB Clear
5505 \ -------------------------------\
5506 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
5507 \ -- \CM Capture Mode
5512 \ --- \OUTMOD \ 011 = set/reset
5518 \ -------------------------------\
5520 \ -------------------------------\
5522 \ ------------------------------\
5523 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
5524 \ ------------------------------\
5525 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
5526 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
5527 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
5528 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
5530 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
5531 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
5533 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
5534 \ ------------------------------\
5535 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
5536 \ ------------------------------\
5537 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
5538 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
5539 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
5540 \ ------------------------------\
5541 BIS.B #LCDVo,&LCDVo_DIR \
5542 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
5543 \ ------------------------------\
5544 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
5545 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
5546 \ ------------------------------\
5547 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
5548 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
5549 \ ******************************\
5551 \ ******************************\
5552 BIS.B #RC5,&IR_IE \ enable RC5_Int
5553 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
5554 MOV #RC5_INT,&IR_Vec \ init interrupt vector
5555 \ ******************************\
5556 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
5557 \ ******************************\
5558 \ %01 0001 0100 \ TAxCTL
5559 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
5560 \ -- \ ID divided by 1
5561 \ -- \ MC MODE = up to TAxCCRn
5562 \ - \ TACLR clear timer count
5565 \ ------------------------------\
5566 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
5567 \ ------------------------------\
5569 \ --- \ TAIDEX pre divisor
5570 \ ------------------------------\
5571 \ %0000 0000 0000 0101 \ TAxCCR0
5572 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
5573 \ ------------------------------\
5574 \ %0000 0000 0001 0000 \ TAxCCTL0
5575 \ - \ CAP capture/compare mode = compare
5578 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
5579 \ ------------------------------\
5580 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
5581 \ ------------------------------\
5582 \ define LPM mode for ACCEPT \
5583 \ ------------------------------\
5584 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
5585 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
5586 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
5587 \ ------------------------------\
5589 \ ------------------------------\
5590 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
5591 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
5592 \ ------------------------------\
5593 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
5594 \ ------------------------------\
5595 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
5596 \ CMP #2,Y \ Power_ON event
5597 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
5599 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
5601 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
5603 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
5605 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
5606 \ ------------------------------\
5608 \ ------------------------------\
5610 \ ------------------------------\
5611 #1000 20_US \ 1- wait 20 ms
5612 %011 TOP_LCD \ 2- send DB5=DB4=1
5613 #205 20_US \ 3- wait 4,1 ms
5614 %011 TOP_LCD \ 4- send again DB5=DB4=1
5615 #5 20_US \ 5- wait 0,1 ms
5616 %011 TOP_LCD \ 6- send again again DB5=DB4=1
5617 #2 20_US \ wait 40 us = LCD cycle
5618 %010 TOP_LCD \ 7- send DB5=1 DB4=0
5619 #2 20_US \ wait 40 us = LCD cycle
5620 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
5621 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
5622 LCD_CLEAR \ 10- "LCD_Clear"
5623 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
5624 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
5625 LCD_CLEAR \ 10- "LCD_Clear"
5626 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
5627 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
5628 CR ." I love you" \ display message on LCD
5629 ['] CR >BODY IS CR \ CR executes its default value
5630 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
5631 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
5632 PWR_STATE ABORT \ init DP and continues with ABORT
5634 \ ------------------------------\
5636 \ ------------------------------\
5637 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
5638 \ ------------------------------\
5639 MOV #SLEEP,X \ replace default background process SLEEP
5640 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
5641 MOV #WARM,X \ replace default WARM
5642 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
5643 MOV X,PC \ then execute new WARM
5645 \ ------------------------------\
5648 ; downloading RC5toLCD.4th is done
5649 RST_HERE ; this app is protected against <reset>
5654 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
5656 [UNDEFINED] MARKER [IF]
5657 \ https://forth-standard.org/standard/core/MARKER
5659 \ ( "<spaces>name" -- )
5660 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
5661 \ with the execution semantics defined below.
5663 \ name Execution: ( -- )
5664 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
5665 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
5666 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
5667 \ not necessarily provided. No other contextual information such as numeric base is affected
5672 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
5673 SUB #2,Y \ 1 Y = LFA
5674 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
5675 ADD #4,&DP \ 3 add 2 cells
5679 MOV @RSP+,IP \ -- PFA
5680 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
5681 MOV @TOS,&INIDP \ set DP value for RST_STATE
5683 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
5690 \ https://forth-standard.org/standard/core/Fetch
5691 \ @ c-addr -- char fetch char from memory
5698 [UNDEFINED] CONSTANT [IF]
5699 \ https://forth-standard.org/standard/core/CONSTANT
5700 \ CONSTANT <name> n -- define a Forth CONSTANT
5704 MOV TOS,-2(W) \ PFA = n
5711 [UNDEFINED] STATE [IF]
5712 \ https://forth-standard.org/standard/core/STATE
5713 \ STATE -- a-addr holds compiler state
5714 STATEADR CONSTANT STATE
5718 \ https://forth-standard.org/standard/core/Equal
5719 \ = x1 x2 -- flag test x1=x2
5726 XOR #-1,TOS \ 1 flag Z = 1
5732 \ https://forth-standard.org/standard/core/IF
5733 \ IF -- IFadr initialize conditional forward branch
5737 MOV &DP,TOS \ -- HERE
5738 ADD #4,&DP \ compile one word, reserve one word
5739 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
5740 ADD #2,TOS \ -- HERE+2=IFadr
5745 [UNDEFINED] THEN [IF]
5746 \ https://forth-standard.org/standard/core/THEN
5747 \ THEN IFadr -- resolve forward branch
5748 CODE THEN \ immediate
5749 MOV &DP,0(TOS) \ -- IFadr
5755 [UNDEFINED] ELSE [IF]
5756 \ https://forth-standard.org/standard/core/ELSE
5757 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
5758 CODE ELSE \ immediate
5759 ADD #4,&DP \ make room to compile two words
5760 MOV &DP,W \ W=HERE+4
5762 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
5764 MOV W,TOS \ -- ELSEadr
5769 [UNDEFINED] DEFER [IF]
5770 \ https://forth-standard.org/standard/core/DEFER
5771 \ DEFER "<spaces>name" --
5772 \ Skip leading space delimiters. Parse name delimited by a space.
5773 \ Create a definition for name with the execution semantics defined below.
5775 \ name Execution: --
5776 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
5777 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
5781 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
5782 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
5788 [UNDEFINED] DEFER! [IF]
5789 \ https://forth-standard.org/standard/core/DEFERStore
5790 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
5791 CODE DEFER! \ xt2 xt1 --
5792 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
5799 \ https://forth-standard.org/standard/core/IS
5802 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
5803 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
5804 \ or in a definition : ... ['] U. IS DISPLAY ...
5805 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
5807 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
5810 IF POSTPONE ['] POSTPONE DEFER!
5816 [UNDEFINED] >BODY [IF]
5817 \ https://forth-standard.org/standard/core/toBODY
5818 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
5825 \ CODE 20uS \ n -- 8MHz version
5826 \ BEGIN \ 4 + 16 ~ loop
5827 \ MOV #39,rDOCON \ 39
5834 \ MOV #XDOCON,rDOCON \ 2
5839 CODE 20_US \ n -- n * 20 us
5840 BEGIN \ here we presume that LCD_TIM_IFG = 1...
5842 BIT #1,&LCD_TIM_CTL \ 3
5843 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
5844 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
5846 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
5851 CODE TOP_LCD \ LCD Sample
5852 \ \ if write : %xxxx_WWWW --
5853 \ \ if read : -- %0000_RRRR
5854 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
5855 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
5856 0= IF \ write LCD bits pattern
5858 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
5859 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5862 THEN \ read LCD bits pattern
5865 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
5866 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
5871 CODE LCD_WRC \ char -- Write Char
5872 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5874 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
5875 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
5876 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
5877 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
5878 COLON \ high level word starts here
5879 TOP_LCD 2 20_US \ write high nibble first
5883 CODE LCD_WRF \ func -- Write Fonction
5884 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5888 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
5889 : LCD_HOME $02 LCD_WRF 100 20_us ;
5891 \ [UNDEFINED] OR [IF]
5893 \ \ https://forth-standard.org/standard/core/OR
5894 \ \ C OR x1 x2 -- x3 logical OR
5902 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
5903 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
5904 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
5905 \ : LCD_FN_SET $20 OR LCD_WrF ;
5906 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
5907 \ : LCD_GOTO $80 OR LCD_WrF ;
5910 \ CODE LCD_RDS \ -- status Read Status
5911 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
5912 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
5913 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
5914 \ COLON \ starts a FORTH word
5915 \ TOP_LCD 2 20_us \ -- %0000_HHHH
5916 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
5917 \ HI2LO \ switch from FORTH to assembler
5918 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
5919 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
5920 \ MOV @RSP+,IP \ restore IP saved by COLON
5924 \ CODE LCD_RDC \ -- char Read Char
5925 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
5930 \ ******************************\
5931 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
5932 \ ******************************\
5933 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5934 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
5935 BIT.B #SW2,&SW2_IN \ test switch S2
5936 0= IF \ case of switch S2 pressed
5937 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
5939 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
5942 BIT.B #SW1,&SW1_IN \ test switch S1 input
5943 0= IF \ case of Switch S1 pressed
5944 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
5946 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
5950 BW1 \ from quit on truncated RC5 message, repeated RC5 command
5954 \ ******************************\
5955 ASM RC5_INT \ wake up on Px.RC5 change interrupt
5956 \ ******************************\
5957 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
5958 \ ******************************\
5959 \ \ in : SR(9)=old Toggle bit memory (ADD on)
5960 \ \ SMclock = 8|16|24 MHz
5961 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
5962 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
5963 \ \ SR(9)=new Toggle bit memory (ADD on)
5964 \ ******************************\
5965 \ RC5_FirstStartBitHalfCycle: \
5966 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
5967 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
5968 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
5969 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
5971 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
5972 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
5974 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
5975 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
5977 MOV #1778,X \ RC5_Period * 1us
5978 MOV #14,W \ count of loop
5980 \ ******************************\
5981 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
5982 \ ******************************\ |
5983 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
5984 \ RC5_Compute_3/4_Period: \ |
5985 RRUM #1,X \ X=1/2 cycle |
5988 ADD X,Y \ Y=3/4 cycle
5989 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
5991 \ ******************************\
5992 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
5993 \ ******************************\
5994 BIT.B #RC5,&IR_IN \ C_flag = IR bit
5995 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
5996 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
5997 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
5998 SUB #1,W \ decrement count loop
5999 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
6000 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6001 0<> WHILE \ ----> out of loop ----+
6002 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
6004 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
6005 CMP Y,X \ 1 | cycle time out of bound ?
6007 BIC #$30,&RC5_TIM_CTL \ | | stop timer
6008 GOTO BW1 \ | | quit on truncated RC5 message
6010 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
6012 REPEAT \ ----> loop back --+ | with X = new RC5_period value
6013 \ ******************************\ |
6014 \ RC5_SampleEndOf: \ <---------------------+
6015 \ ******************************\
6016 BIC #$30,&RC5_TIM_CTL \ stop timer
6017 \ ******************************\
6018 \ RC5_ComputeNewRC5word \
6019 \ ******************************\
6020 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
6021 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
6022 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
6023 \ ******************************\
6024 \ RC5_ComputeC6bit \
6025 \ ******************************\
6026 BIT #BIT14,T \ test /C6 bit in T
6027 0= IF BIS #BIT6,X \ set C6 bit in X
6028 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
6029 \ ******************************\
6030 \ RC5_CommandByteIsDone \ -- BASE RC5_code
6031 \ ******************************\
6032 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
6033 \ ******************************\
6034 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
6035 XOR @RSP,T \ (new XOR old) Toggle bits
6036 BIT #UF10,T \ repeated RC5_command ?
6037 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
6038 XOR #UF10,0(RSP) \ 5 toggle bit memory
6039 \ ******************************\
6040 \ Display IR_RC5 code \
6041 \ ******************************\
6042 SUB #8,PSP \ TOS -- x x x x TOS
6043 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
6044 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
6045 MOV #$10,&BASEADR \ set hexadecimal base
6046 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
6047 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
6048 LO2HI \ switch from assembler to FORTH
6049 LCD_CLEAR \ set LCD cursor at home
6050 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
6051 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
6052 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
6053 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
6054 HI2LO \ -- switch from FORTH to assembler
6055 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
6056 MOV @PSP+,TOS \ -- TOS
6060 \ ******************************\
6062 \ ******************************\
6064 \ ... \ insert here your background task
6067 CALL &RXON \ comment this line to disable TERMINAL_INPUT
6069 \ ******************************\
6070 \ here start all interrupts \
6071 \ ******************************\
6072 \ here return all interrupts \
6073 \ ******************************\
6076 \ ******************************\
6078 \ ------------------------------\
6079 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
6080 \ ------------------------------\
6081 \ ... \ init specific I/O sys as you want
6082 \ ... \ before executing default WARM
6083 MOV #WARM,X \ ['] WARM
6085 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
6087 \ ------------------------------\
6089 \ ------------------------------\
6090 CODE STOP \ stops multitasking, must to be used before downloading app
6091 \ ------------------------------\
6092 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
6093 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
6094 MOV X,-2(X) \ restore the default background: SLEEP
6096 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
6097 BIC.B #RC5,&IR_IE \ clear RC5_Int
6098 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
6099 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
6100 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
6101 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
6102 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
6103 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
6105 ." RC5toLCD is removed,"
6106 ." type START to restart"
6107 WARM \ performs reset to reset all interrupt vectors.
6109 \ ------------------------------\
6111 \ ------------------------------\
6112 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
6113 \ ------------------------------\
6114 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
6115 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6116 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6117 \ -- \ID input divider \ 10 = /4
6118 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
6119 \ - \TBCLR TimerB Clear
6122 \ -------------------------------\
6123 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6124 \ -- \CM Capture Mode
6129 \ --- \OUTMOD \ 011 = set/reset
6135 \ -------------------------------\
6137 \ -------------------------------\
6139 \ ------------------------------\
6140 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6141 \ ------------------------------\
6142 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6143 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6144 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
6145 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6147 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
6148 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6150 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
6151 \ ------------------------------\
6152 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6153 \ ------------------------------\
6154 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
6155 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6156 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6157 \ ------------------------------\
6158 BIS.B #LCDVo,&LCDVo_DIR \
6159 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
6160 \ ------------------------------\
6161 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6162 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6163 \ ------------------------------\
6164 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6165 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6166 \ ******************************\
6168 \ ******************************\
6169 BIS.B #RC5,&IR_IE \ enable RC5_Int
6170 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6171 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6172 \ ******************************\
6173 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6174 \ ******************************\
6175 \ %01 0001 0100 \ TAxCTL
6176 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
6177 \ -- \ ID divided by 1
6178 \ -- \ MC MODE = up to TAxCCRn
6179 \ - \ TACLR clear timer count
6182 \ ------------------------------\
6183 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
6184 \ ------------------------------\
6186 \ --- \ TAIDEX pre divisor
6187 \ ------------------------------\
6188 \ %0000 0000 0000 0101 \ TAxCCR0
6189 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6190 \ ------------------------------\
6191 \ %0000 0000 0001 0000 \ TAxCCTL0
6192 \ - \ CAP capture/compare mode = compare
6195 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
6196 \ ------------------------------\
6197 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6198 \ ------------------------------\
6199 \ define LPM mode for ACCEPT \
6200 \ ------------------------------\
6201 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6202 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6203 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6204 \ ------------------------------\
6206 \ ------------------------------\
6207 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
6208 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
6209 \ ------------------------------\
6210 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
6211 \ ------------------------------\
6212 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
6213 \ CMP #2,Y \ Power_ON event
6214 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
6216 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
6218 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
6220 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
6222 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
6223 \ ------------------------------\
6225 \ ------------------------------\
6227 \ ------------------------------\
6228 #1000 20_US \ 1- wait 20 ms
6229 %011 TOP_LCD \ 2- send DB5=DB4=1
6230 #205 20_US \ 3- wait 4,1 ms
6231 %011 TOP_LCD \ 4- send again DB5=DB4=1
6232 #5 20_US \ 5- wait 0,1 ms
6233 %011 TOP_LCD \ 6- send again again DB5=DB4=1
6234 #2 20_US \ wait 40 us = LCD cycle
6235 %010 TOP_LCD \ 7- send DB5=1 DB4=0
6236 #2 20_US \ wait 40 us = LCD cycle
6237 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6238 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6239 LCD_CLEAR \ 10- "LCD_Clear"
6240 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6241 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6242 LCD_CLEAR \ 10- "LCD_Clear"
6243 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6244 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6245 CR ." I love you" \ display message on LCD
6246 ['] CR >BODY IS CR \ CR executes its default value
6247 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
6248 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
6249 PWR_STATE ABORT \ init DP and continues with ABORT
6251 \ ------------------------------\
6253 \ ------------------------------\
6254 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
6255 \ ------------------------------\
6256 MOV #SLEEP,X \ replace default background process SLEEP
6257 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
6258 MOV #WARM,X \ replace default WARM
6259 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
6260 MOV X,PC \ then execute new WARM
6262 \ ------------------------------\
6265 ; downloading RC5toLCD.4th is done
6266 RST_HERE ; this app is protected against <reset>
6271 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
6273 [UNDEFINED] MARKER [IF]
6274 \ https://forth-standard.org/standard/core/MARKER
6276 \ ( "<spaces>name" -- )
6277 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
6278 \ with the execution semantics defined below.
6280 \ name Execution: ( -- )
6281 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
6282 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
6283 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
6284 \ not necessarily provided. No other contextual information such as numeric base is affected
6289 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
6290 SUB #2,Y \ 1 Y = LFA
6291 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
6292 ADD #4,&DP \ 3 add 2 cells
6296 MOV @RSP+,IP \ -- PFA
6297 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
6298 MOV @TOS,&INIDP \ set DP value for RST_STATE
6300 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
6307 \ https://forth-standard.org/standard/core/Fetch
6308 \ @ c-addr -- char fetch char from memory
6315 [UNDEFINED] CONSTANT [IF]
6316 \ https://forth-standard.org/standard/core/CONSTANT
6317 \ CONSTANT <name> n -- define a Forth CONSTANT
6321 MOV TOS,-2(W) \ PFA = n
6328 [UNDEFINED] STATE [IF]
6329 \ https://forth-standard.org/standard/core/STATE
6330 \ STATE -- a-addr holds compiler state
6331 STATEADR CONSTANT STATE
6335 \ https://forth-standard.org/standard/core/Equal
6336 \ = x1 x2 -- flag test x1=x2
6343 XOR #-1,TOS \ 1 flag Z = 1
6349 \ https://forth-standard.org/standard/core/IF
6350 \ IF -- IFadr initialize conditional forward branch
6354 MOV &DP,TOS \ -- HERE
6355 ADD #4,&DP \ compile one word, reserve one word
6356 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
6357 ADD #2,TOS \ -- HERE+2=IFadr
6362 [UNDEFINED] THEN [IF]
6363 \ https://forth-standard.org/standard/core/THEN
6364 \ THEN IFadr -- resolve forward branch
6365 CODE THEN \ immediate
6366 MOV &DP,0(TOS) \ -- IFadr
6372 [UNDEFINED] ELSE [IF]
6373 \ https://forth-standard.org/standard/core/ELSE
6374 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
6375 CODE ELSE \ immediate
6376 ADD #4,&DP \ make room to compile two words
6377 MOV &DP,W \ W=HERE+4
6379 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
6381 MOV W,TOS \ -- ELSEadr
6386 [UNDEFINED] DEFER [IF]
6387 \ https://forth-standard.org/standard/core/DEFER
6388 \ DEFER "<spaces>name" --
6389 \ Skip leading space delimiters. Parse name delimited by a space.
6390 \ Create a definition for name with the execution semantics defined below.
6392 \ name Execution: --
6393 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
6394 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
6398 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
6399 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
6405 [UNDEFINED] DEFER! [IF]
6406 \ https://forth-standard.org/standard/core/DEFERStore
6407 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
6408 CODE DEFER! \ xt2 xt1 --
6409 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
6416 \ https://forth-standard.org/standard/core/IS
6419 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
6420 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
6421 \ or in a definition : ... ['] U. IS DISPLAY ...
6422 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
6424 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
6427 IF POSTPONE ['] POSTPONE DEFER!
6433 [UNDEFINED] >BODY [IF]
6434 \ https://forth-standard.org/standard/core/toBODY
6435 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
6442 \ CODE 20uS \ n -- 8MHz version
6443 \ BEGIN \ 4 + 16 ~ loop
6444 \ MOV #39,rDOCON \ 39
6451 \ MOV #XDOCON,rDOCON \ 2
6456 CODE 20_US \ n -- n * 20 us
6457 BEGIN \ here we presume that LCD_TIM_IFG = 1...
6459 BIT #1,&LCD_TIM_CTL \ 3
6460 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
6461 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
6463 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
6468 CODE TOP_LCD \ LCD Sample
6469 \ \ if write : %xxxx_WWWW --
6470 \ \ if read : -- %0000_RRRR
6471 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
6472 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
6473 0= IF \ write LCD bits pattern
6475 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
6476 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6479 THEN \ read LCD bits pattern
6482 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
6483 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
6488 CODE LCD_WRC \ char -- Write Char
6489 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6491 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
6492 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
6493 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
6494 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
6495 COLON \ high level word starts here
6496 TOP_LCD 2 20_US \ write high nibble first
6500 CODE LCD_WRF \ func -- Write Fonction
6501 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6505 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
6506 : LCD_HOME $02 LCD_WRF 100 20_us ;
6508 \ [UNDEFINED] OR [IF]
6510 \ \ https://forth-standard.org/standard/core/OR
6511 \ \ C OR x1 x2 -- x3 logical OR
6519 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
6520 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
6521 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
6522 \ : LCD_FN_SET $20 OR LCD_WrF ;
6523 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
6524 \ : LCD_GOTO $80 OR LCD_WrF ;
6527 \ CODE LCD_RDS \ -- status Read Status
6528 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
6529 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
6530 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
6531 \ COLON \ starts a FORTH word
6532 \ TOP_LCD 2 20_us \ -- %0000_HHHH
6533 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
6534 \ HI2LO \ switch from FORTH to assembler
6535 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
6536 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
6537 \ MOV @RSP+,IP \ restore IP saved by COLON
6541 \ CODE LCD_RDC \ -- char Read Char
6542 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
6547 \ ******************************\
6548 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
6549 \ ******************************\
6550 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
6551 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
6552 BIT.B #SW2,&SW2_IN \ test switch S2
6553 0= IF \ case of switch S2 pressed
6554 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
6556 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
6559 BIT.B #SW1,&SW1_IN \ test switch S1 input
6560 0= IF \ case of Switch S1 pressed
6561 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
6563 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
6567 BW1 \ from quit on truncated RC5 message, repeated RC5 command
6571 \ ******************************\
6572 ASM RC5_INT \ wake up on Px.RC5 change interrupt
6573 \ ******************************\
6574 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
6575 \ ******************************\
6576 \ \ in : SR(9)=old Toggle bit memory (ADD on)
6577 \ \ SMclock = 8|16|24 MHz
6578 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
6579 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
6580 \ \ SR(9)=new Toggle bit memory (ADD on)
6581 \ ******************************\
6582 \ RC5_FirstStartBitHalfCycle: \
6583 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
6584 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
6585 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
6586 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
6588 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
6589 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
6591 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
6592 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
6594 MOV #1778,X \ RC5_Period * 1us
6595 MOV #14,W \ count of loop
6597 \ ******************************\
6598 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
6599 \ ******************************\ |
6600 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
6601 \ RC5_Compute_3/4_Period: \ |
6602 RRUM #1,X \ X=1/2 cycle |
6605 ADD X,Y \ Y=3/4 cycle
6606 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
6608 \ ******************************\
6609 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
6610 \ ******************************\
6611 BIT.B #RC5,&IR_IN \ C_flag = IR bit
6612 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
6613 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
6614 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
6615 SUB #1,W \ decrement count loop
6616 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
6617 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
6618 0<> WHILE \ ----> out of loop ----+
6619 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
6621 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
6622 CMP Y,X \ 1 | cycle time out of bound ?
6624 BIC #$30,&RC5_TIM_CTL \ | | stop timer
6625 GOTO BW1 \ | | quit on truncated RC5 message
6627 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
6629 REPEAT \ ----> loop back --+ | with X = new RC5_period value
6630 \ ******************************\ |
6631 \ RC5_SampleEndOf: \ <---------------------+
6632 \ ******************************\
6633 BIC #$30,&RC5_TIM_CTL \ stop timer
6634 \ ******************************\
6635 \ RC5_ComputeNewRC5word \
6636 \ ******************************\
6637 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
6638 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
6639 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
6640 \ ******************************\
6641 \ RC5_ComputeC6bit \
6642 \ ******************************\
6643 BIT #BIT14,T \ test /C6 bit in T
6644 0= IF BIS #BIT6,X \ set C6 bit in X
6645 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
6646 \ ******************************\
6647 \ RC5_CommandByteIsDone \ -- BASE RC5_code
6648 \ ******************************\
6649 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
6650 \ ******************************\
6651 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
6652 XOR @RSP,T \ (new XOR old) Toggle bits
6653 BIT #UF10,T \ repeated RC5_command ?
6654 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
6655 XOR #UF10,0(RSP) \ 5 toggle bit memory
6656 \ ******************************\
6657 \ Display IR_RC5 code \
6658 \ ******************************\
6659 SUB #8,PSP \ TOS -- x x x x TOS
6660 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
6661 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
6662 MOV #$10,&BASEADR \ set hexadecimal base
6663 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
6664 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
6665 LO2HI \ switch from assembler to FORTH
6666 LCD_CLEAR \ set LCD cursor at home
6667 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
6668 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
6669 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
6670 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
6671 HI2LO \ -- switch from FORTH to assembler
6672 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
6673 MOV @PSP+,TOS \ -- TOS
6677 \ ******************************\
6679 \ ******************************\
6681 \ ... \ insert here your background task
6684 CALL &RXON \ comment this line to disable TERMINAL_INPUT
6686 \ ******************************\
6687 \ here start all interrupts \
6688 \ ******************************\
6689 \ here return all interrupts \
6690 \ ******************************\
6693 \ ******************************\
6695 \ ------------------------------\
6696 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
6697 \ ------------------------------\
6698 \ ... \ init specific I/O sys as you want
6699 \ ... \ before executing default WARM
6700 MOV #WARM,X \ ['] WARM
6702 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
6704 \ ------------------------------\
6706 \ ------------------------------\
6707 CODE STOP \ stops multitasking, must to be used before downloading app
6708 \ ------------------------------\
6709 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
6710 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
6711 MOV X,-2(X) \ restore the default background: SLEEP
6713 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
6714 BIC.B #RC5,&IR_IE \ clear RC5_Int
6715 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
6716 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
6717 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
6718 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
6719 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
6720 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
6722 ." RC5toLCD is removed,"
6723 ." type START to restart"
6724 WARM \ performs reset to reset all interrupt vectors.
6726 \ ------------------------------\
6728 \ ------------------------------\
6729 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
6730 \ ------------------------------\
6731 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
6732 \ - - \CNTL Counter lentgh \ 00 = 16 bits
6733 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
6734 \ -- \ID input divider \ 10 = /4
6735 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
6736 \ - \TBCLR TimerB Clear
6739 \ -------------------------------\
6740 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
6741 \ -- \CM Capture Mode
6746 \ --- \OUTMOD \ 011 = set/reset
6752 \ -------------------------------\
6754 \ -------------------------------\
6756 \ ------------------------------\
6757 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
6758 \ ------------------------------\
6759 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
6760 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
6761 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
6762 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
6764 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
6765 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
6767 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
6768 \ ------------------------------\
6769 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
6770 \ ------------------------------\
6771 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
6772 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
6773 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
6774 \ ------------------------------\
6775 BIS.B #LCDVo,&LCDVo_DIR \
6776 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
6777 \ ------------------------------\
6778 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
6779 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
6780 \ ------------------------------\
6781 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
6782 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
6783 \ ******************************\
6785 \ ******************************\
6786 BIS.B #RC5,&IR_IE \ enable RC5_Int
6787 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
6788 MOV #RC5_INT,&IR_Vec \ init interrupt vector
6789 \ ******************************\
6790 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
6791 \ ******************************\
6792 \ %01 0001 0100 \ TAxCTL
6793 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
6794 \ -- \ ID divided by 1
6795 \ -- \ MC MODE = up to TAxCCRn
6796 \ - \ TACLR clear timer count
6799 \ ------------------------------\
6800 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
6801 \ ------------------------------\
6803 \ --- \ TAIDEX pre divisor
6804 \ ------------------------------\
6805 \ %0000 0000 0000 0101 \ TAxCCR0
6806 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
6807 \ ------------------------------\
6808 \ %0000 0000 0001 0000 \ TAxCCTL0
6809 \ - \ CAP capture/compare mode = compare
6812 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
6813 \ ------------------------------\
6814 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
6815 \ ------------------------------\
6816 \ define LPM mode for ACCEPT \
6817 \ ------------------------------\
6818 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
6819 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
6820 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
6821 \ ------------------------------\
6823 \ ------------------------------\
6824 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
6825 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
6826 \ ------------------------------\
6827 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
6828 \ ------------------------------\
6829 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
6830 \ CMP #2,Y \ Power_ON event
6831 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
6833 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
6835 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
6837 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
6839 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
6840 \ ------------------------------\
6842 \ ------------------------------\
6844 \ ------------------------------\
6845 #1000 20_US \ 1- wait 20 ms
6846 %011 TOP_LCD \ 2- send DB5=DB4=1
6847 #205 20_US \ 3- wait 4,1 ms
6848 %011 TOP_LCD \ 4- send again DB5=DB4=1
6849 #5 20_US \ 5- wait 0,1 ms
6850 %011 TOP_LCD \ 6- send again again DB5=DB4=1
6851 #2 20_US \ wait 40 us = LCD cycle
6852 %010 TOP_LCD \ 7- send DB5=1 DB4=0
6853 #2 20_US \ wait 40 us = LCD cycle
6854 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
6855 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
6856 LCD_CLEAR \ 10- "LCD_Clear"
6857 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
6858 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
6859 LCD_CLEAR \ 10- "LCD_Clear"
6860 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
6861 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
6862 CR ." I love you" \ display message on LCD
6863 ['] CR >BODY IS CR \ CR executes its default value
6864 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
6865 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
6866 PWR_STATE ABORT \ init DP and continues with ABORT
6868 \ ------------------------------\
6870 \ ------------------------------\
6871 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
6872 \ ------------------------------\
6873 MOV #SLEEP,X \ replace default background process SLEEP
6874 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
6875 MOV #WARM,X \ replace default WARM
6876 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
6877 MOV X,PC \ then execute new WARM
6879 \ ------------------------------\
6882 ; downloading RC5toLCD.4th is done
6883 RST_HERE ; this app is protected against <reset>
6888 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
6890 [UNDEFINED] MARKER [IF]
6891 \ https://forth-standard.org/standard/core/MARKER
6893 \ ( "<spaces>name" -- )
6894 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
6895 \ with the execution semantics defined below.
6897 \ name Execution: ( -- )
6898 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
6899 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
6900 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
6901 \ not necessarily provided. No other contextual information such as numeric base is affected
6906 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
6907 SUB #2,Y \ 1 Y = LFA
6908 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
6909 ADD #4,&DP \ 3 add 2 cells
6913 MOV @RSP+,IP \ -- PFA
6914 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
6915 MOV @TOS,&INIDP \ set DP value for RST_STATE
6917 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
6924 \ https://forth-standard.org/standard/core/Fetch
6925 \ @ c-addr -- char fetch char from memory
6932 [UNDEFINED] CONSTANT [IF]
6933 \ https://forth-standard.org/standard/core/CONSTANT
6934 \ CONSTANT <name> n -- define a Forth CONSTANT
6938 MOV TOS,-2(W) \ PFA = n
6945 [UNDEFINED] STATE [IF]
6946 \ https://forth-standard.org/standard/core/STATE
6947 \ STATE -- a-addr holds compiler state
6948 STATEADR CONSTANT STATE
6952 \ https://forth-standard.org/standard/core/Equal
6953 \ = x1 x2 -- flag test x1=x2
6960 XOR #-1,TOS \ 1 flag Z = 1
6966 \ https://forth-standard.org/standard/core/IF
6967 \ IF -- IFadr initialize conditional forward branch
6971 MOV &DP,TOS \ -- HERE
6972 ADD #4,&DP \ compile one word, reserve one word
6973 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
6974 ADD #2,TOS \ -- HERE+2=IFadr
6979 [UNDEFINED] THEN [IF]
6980 \ https://forth-standard.org/standard/core/THEN
6981 \ THEN IFadr -- resolve forward branch
6982 CODE THEN \ immediate
6983 MOV &DP,0(TOS) \ -- IFadr
6989 [UNDEFINED] ELSE [IF]
6990 \ https://forth-standard.org/standard/core/ELSE
6991 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
6992 CODE ELSE \ immediate
6993 ADD #4,&DP \ make room to compile two words
6994 MOV &DP,W \ W=HERE+4
6996 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
6998 MOV W,TOS \ -- ELSEadr
7003 [UNDEFINED] DEFER [IF]
7004 \ https://forth-standard.org/standard/core/DEFER
7005 \ DEFER "<spaces>name" --
7006 \ Skip leading space delimiters. Parse name delimited by a space.
7007 \ Create a definition for name with the execution semantics defined below.
7009 \ name Execution: --
7010 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
7011 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
7015 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
7016 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
7022 [UNDEFINED] DEFER! [IF]
7023 \ https://forth-standard.org/standard/core/DEFERStore
7024 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
7025 CODE DEFER! \ xt2 xt1 --
7026 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
7033 \ https://forth-standard.org/standard/core/IS
7036 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
7037 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
7038 \ or in a definition : ... ['] U. IS DISPLAY ...
7039 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
7041 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
7044 IF POSTPONE ['] POSTPONE DEFER!
7050 [UNDEFINED] >BODY [IF]
7051 \ https://forth-standard.org/standard/core/toBODY
7052 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
7059 \ CODE 20uS \ n -- 8MHz version
7060 \ BEGIN \ 4 + 16 ~ loop
7061 \ MOV #39,rDOCON \ 39
7068 \ MOV #XDOCON,rDOCON \ 2
7073 CODE 20_US \ n -- n * 20 us
7074 BEGIN \ here we presume that LCD_TIM_IFG = 1...
7076 BIT #1,&LCD_TIM_CTL \ 3
7077 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
7078 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
7080 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
7085 CODE TOP_LCD \ LCD Sample
7086 \ \ if write : %xxxx_WWWW --
7087 \ \ if read : -- %0000_RRRR
7088 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7089 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7090 0= IF \ write LCD bits pattern
7092 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7093 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7096 THEN \ read LCD bits pattern
7099 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7100 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7105 CODE LCD_WRC \ char -- Write Char
7106 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7108 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
7109 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
7110 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7111 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7112 COLON \ high level word starts here
7113 TOP_LCD 2 20_US \ write high nibble first
7117 CODE LCD_WRF \ func -- Write Fonction
7118 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7122 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
7123 : LCD_HOME $02 LCD_WRF 100 20_us ;
7125 \ [UNDEFINED] OR [IF]
7127 \ \ https://forth-standard.org/standard/core/OR
7128 \ \ C OR x1 x2 -- x3 logical OR
7136 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
7137 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
7138 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
7139 \ : LCD_FN_SET $20 OR LCD_WrF ;
7140 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
7141 \ : LCD_GOTO $80 OR LCD_WrF ;
7144 \ CODE LCD_RDS \ -- status Read Status
7145 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7146 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7147 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7148 \ COLON \ starts a FORTH word
7149 \ TOP_LCD 2 20_us \ -- %0000_HHHH
7150 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
7151 \ HI2LO \ switch from FORTH to assembler
7152 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
7153 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
7154 \ MOV @RSP+,IP \ restore IP saved by COLON
7158 \ CODE LCD_RDC \ -- char Read Char
7159 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7164 \ ******************************\
7165 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7166 \ ******************************\
7167 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7168 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
7169 BIT.B #SW2,&SW2_IN \ test switch S2
7170 0= IF \ case of switch S2 pressed
7171 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7173 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
7176 BIT.B #SW1,&SW1_IN \ test switch S1 input
7177 0= IF \ case of Switch S1 pressed
7178 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7180 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7184 BW1 \ from quit on truncated RC5 message, repeated RC5 command
7188 \ ******************************\
7189 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7190 \ ******************************\
7191 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7192 \ ******************************\
7193 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7194 \ \ SMclock = 8|16|24 MHz
7195 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
7196 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
7197 \ \ SR(9)=new Toggle bit memory (ADD on)
7198 \ ******************************\
7199 \ RC5_FirstStartBitHalfCycle: \
7200 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
7201 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7202 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
7203 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
7205 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
7206 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
7208 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
7209 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
7211 MOV #1778,X \ RC5_Period * 1us
7212 MOV #14,W \ count of loop
7214 \ ******************************\
7215 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
7216 \ ******************************\ |
7217 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
7218 \ RC5_Compute_3/4_Period: \ |
7219 RRUM #1,X \ X=1/2 cycle |
7222 ADD X,Y \ Y=3/4 cycle
7223 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
7225 \ ******************************\
7226 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
7227 \ ******************************\
7228 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7229 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
7230 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7231 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7232 SUB #1,W \ decrement count loop
7233 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
7234 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7235 0<> WHILE \ ----> out of loop ----+
7236 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
7238 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
7239 CMP Y,X \ 1 | cycle time out of bound ?
7241 BIC #$30,&RC5_TIM_CTL \ | | stop timer
7242 GOTO BW1 \ | | quit on truncated RC5 message
7244 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
7246 REPEAT \ ----> loop back --+ | with X = new RC5_period value
7247 \ ******************************\ |
7248 \ RC5_SampleEndOf: \ <---------------------+
7249 \ ******************************\
7250 BIC #$30,&RC5_TIM_CTL \ stop timer
7251 \ ******************************\
7252 \ RC5_ComputeNewRC5word \
7253 \ ******************************\
7254 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
7255 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
7256 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
7257 \ ******************************\
7258 \ RC5_ComputeC6bit \
7259 \ ******************************\
7260 BIT #BIT14,T \ test /C6 bit in T
7261 0= IF BIS #BIT6,X \ set C6 bit in X
7262 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
7263 \ ******************************\
7264 \ RC5_CommandByteIsDone \ -- BASE RC5_code
7265 \ ******************************\
7266 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7267 \ ******************************\
7268 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
7269 XOR @RSP,T \ (new XOR old) Toggle bits
7270 BIT #UF10,T \ repeated RC5_command ?
7271 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
7272 XOR #UF10,0(RSP) \ 5 toggle bit memory
7273 \ ******************************\
7274 \ Display IR_RC5 code \
7275 \ ******************************\
7276 SUB #8,PSP \ TOS -- x x x x TOS
7277 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
7278 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
7279 MOV #$10,&BASEADR \ set hexadecimal base
7280 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
7281 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
7282 LO2HI \ switch from assembler to FORTH
7283 LCD_CLEAR \ set LCD cursor at home
7284 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
7285 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
7286 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
7287 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
7288 HI2LO \ -- switch from FORTH to assembler
7289 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
7290 MOV @PSP+,TOS \ -- TOS
7294 \ ******************************\
7296 \ ******************************\
7298 \ ... \ insert here your background task
7301 CALL &RXON \ comment this line to disable TERMINAL_INPUT
7303 \ ******************************\
7304 \ here start all interrupts \
7305 \ ******************************\
7306 \ here return all interrupts \
7307 \ ******************************\
7310 \ ******************************\
7312 \ ------------------------------\
7313 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
7314 \ ------------------------------\
7315 \ ... \ init specific I/O sys as you want
7316 \ ... \ before executing default WARM
7317 MOV #WARM,X \ ['] WARM
7319 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
7321 \ ------------------------------\
7323 \ ------------------------------\
7324 CODE STOP \ stops multitasking, must to be used before downloading app
7325 \ ------------------------------\
7326 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
7327 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
7328 MOV X,-2(X) \ restore the default background: SLEEP
7330 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
7331 BIC.B #RC5,&IR_IE \ clear RC5_Int
7332 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
7333 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
7334 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
7335 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
7336 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
7337 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
7339 ." RC5toLCD is removed,"
7340 ." type START to restart"
7341 WARM \ performs reset to reset all interrupt vectors.
7343 \ ------------------------------\
7345 \ ------------------------------\
7346 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
7347 \ ------------------------------\
7348 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
7349 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7350 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7351 \ -- \ID input divider \ 10 = /4
7352 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
7353 \ - \TBCLR TimerB Clear
7356 \ -------------------------------\
7357 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7358 \ -- \CM Capture Mode
7363 \ --- \OUTMOD \ 011 = set/reset
7369 \ -------------------------------\
7371 \ -------------------------------\
7373 \ ------------------------------\
7374 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
7375 \ ------------------------------\
7376 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
7377 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
7378 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
7379 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
7381 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
7382 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
7384 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
7385 \ ------------------------------\
7386 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
7387 \ ------------------------------\
7388 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
7389 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
7390 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
7391 \ ------------------------------\
7392 BIS.B #LCDVo,&LCDVo_DIR \
7393 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
7394 \ ------------------------------\
7395 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
7396 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
7397 \ ------------------------------\
7398 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
7399 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
7400 \ ******************************\
7402 \ ******************************\
7403 BIS.B #RC5,&IR_IE \ enable RC5_Int
7404 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
7405 MOV #RC5_INT,&IR_Vec \ init interrupt vector
7406 \ ******************************\
7407 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
7408 \ ******************************\
7409 \ %01 0001 0100 \ TAxCTL
7410 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
7411 \ -- \ ID divided by 1
7412 \ -- \ MC MODE = up to TAxCCRn
7413 \ - \ TACLR clear timer count
7416 \ ------------------------------\
7417 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
7418 \ ------------------------------\
7420 \ --- \ TAIDEX pre divisor
7421 \ ------------------------------\
7422 \ %0000 0000 0000 0101 \ TAxCCR0
7423 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
7424 \ ------------------------------\
7425 \ %0000 0000 0001 0000 \ TAxCCTL0
7426 \ - \ CAP capture/compare mode = compare
7429 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
7430 \ ------------------------------\
7431 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
7432 \ ------------------------------\
7433 \ define LPM mode for ACCEPT \
7434 \ ------------------------------\
7435 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
7436 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
7437 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
7438 \ ------------------------------\
7440 \ ------------------------------\
7441 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
7442 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
7443 \ ------------------------------\
7444 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
7445 \ ------------------------------\
7446 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
7447 \ CMP #2,Y \ Power_ON event
7448 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
7450 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
7452 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
7454 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
7456 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
7457 \ ------------------------------\
7459 \ ------------------------------\
7461 \ ------------------------------\
7462 #1000 20_US \ 1- wait 20 ms
7463 %011 TOP_LCD \ 2- send DB5=DB4=1
7464 #205 20_US \ 3- wait 4,1 ms
7465 %011 TOP_LCD \ 4- send again DB5=DB4=1
7466 #5 20_US \ 5- wait 0,1 ms
7467 %011 TOP_LCD \ 6- send again again DB5=DB4=1
7468 #2 20_US \ wait 40 us = LCD cycle
7469 %010 TOP_LCD \ 7- send DB5=1 DB4=0
7470 #2 20_US \ wait 40 us = LCD cycle
7471 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
7472 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
7473 LCD_CLEAR \ 10- "LCD_Clear"
7474 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
7475 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
7476 LCD_CLEAR \ 10- "LCD_Clear"
7477 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
7478 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
7479 CR ." I love you" \ display message on LCD
7480 ['] CR >BODY IS CR \ CR executes its default value
7481 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
7482 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
7483 PWR_STATE ABORT \ init DP and continues with ABORT
7485 \ ------------------------------\
7487 \ ------------------------------\
7488 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
7489 \ ------------------------------\
7490 MOV #SLEEP,X \ replace default background process SLEEP
7491 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
7492 MOV #WARM,X \ replace default WARM
7493 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
7494 MOV X,PC \ then execute new WARM
7496 \ ------------------------------\
7499 ; downloading RC5toLCD.4th is done
7500 RST_HERE ; this app is protected against <reset>
7505 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
7507 [UNDEFINED] MARKER [IF]
7508 \ https://forth-standard.org/standard/core/MARKER
7510 \ ( "<spaces>name" -- )
7511 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
7512 \ with the execution semantics defined below.
7514 \ name Execution: ( -- )
7515 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
7516 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
7517 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
7518 \ not necessarily provided. No other contextual information such as numeric base is affected
7523 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
7524 SUB #2,Y \ 1 Y = LFA
7525 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
7526 ADD #4,&DP \ 3 add 2 cells
7530 MOV @RSP+,IP \ -- PFA
7531 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
7532 MOV @TOS,&INIDP \ set DP value for RST_STATE
7534 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
7541 \ https://forth-standard.org/standard/core/Fetch
7542 \ @ c-addr -- char fetch char from memory
7549 [UNDEFINED] CONSTANT [IF]
7550 \ https://forth-standard.org/standard/core/CONSTANT
7551 \ CONSTANT <name> n -- define a Forth CONSTANT
7555 MOV TOS,-2(W) \ PFA = n
7562 [UNDEFINED] STATE [IF]
7563 \ https://forth-standard.org/standard/core/STATE
7564 \ STATE -- a-addr holds compiler state
7565 STATEADR CONSTANT STATE
7569 \ https://forth-standard.org/standard/core/Equal
7570 \ = x1 x2 -- flag test x1=x2
7577 XOR #-1,TOS \ 1 flag Z = 1
7583 \ https://forth-standard.org/standard/core/IF
7584 \ IF -- IFadr initialize conditional forward branch
7588 MOV &DP,TOS \ -- HERE
7589 ADD #4,&DP \ compile one word, reserve one word
7590 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
7591 ADD #2,TOS \ -- HERE+2=IFadr
7596 [UNDEFINED] THEN [IF]
7597 \ https://forth-standard.org/standard/core/THEN
7598 \ THEN IFadr -- resolve forward branch
7599 CODE THEN \ immediate
7600 MOV &DP,0(TOS) \ -- IFadr
7606 [UNDEFINED] ELSE [IF]
7607 \ https://forth-standard.org/standard/core/ELSE
7608 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
7609 CODE ELSE \ immediate
7610 ADD #4,&DP \ make room to compile two words
7611 MOV &DP,W \ W=HERE+4
7613 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
7615 MOV W,TOS \ -- ELSEadr
7620 [UNDEFINED] DEFER [IF]
7621 \ https://forth-standard.org/standard/core/DEFER
7622 \ DEFER "<spaces>name" --
7623 \ Skip leading space delimiters. Parse name delimited by a space.
7624 \ Create a definition for name with the execution semantics defined below.
7626 \ name Execution: --
7627 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
7628 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
7632 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
7633 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
7639 [UNDEFINED] DEFER! [IF]
7640 \ https://forth-standard.org/standard/core/DEFERStore
7641 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
7642 CODE DEFER! \ xt2 xt1 --
7643 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
7650 \ https://forth-standard.org/standard/core/IS
7653 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
7654 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
7655 \ or in a definition : ... ['] U. IS DISPLAY ...
7656 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
7658 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
7661 IF POSTPONE ['] POSTPONE DEFER!
7667 [UNDEFINED] >BODY [IF]
7668 \ https://forth-standard.org/standard/core/toBODY
7669 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
7676 \ CODE 20uS \ n -- 8MHz version
7677 \ BEGIN \ 4 + 16 ~ loop
7678 \ MOV #39,rDOCON \ 39
7685 \ MOV #XDOCON,rDOCON \ 2
7690 CODE 20_US \ n -- n * 20 us
7691 BEGIN \ here we presume that LCD_TIM_IFG = 1...
7693 BIT #1,&LCD_TIM_CTL \ 3
7694 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
7695 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
7697 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
7702 CODE TOP_LCD \ LCD Sample
7703 \ \ if write : %xxxx_WWWW --
7704 \ \ if read : -- %0000_RRRR
7705 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
7706 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
7707 0= IF \ write LCD bits pattern
7709 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
7710 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7713 THEN \ read LCD bits pattern
7716 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
7717 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
7722 CODE LCD_WRC \ char -- Write Char
7723 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7725 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
7726 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
7727 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
7728 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
7729 COLON \ high level word starts here
7730 TOP_LCD 2 20_US \ write high nibble first
7734 CODE LCD_WRF \ func -- Write Fonction
7735 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7739 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
7740 : LCD_HOME $02 LCD_WRF 100 20_us ;
7742 \ [UNDEFINED] OR [IF]
7744 \ \ https://forth-standard.org/standard/core/OR
7745 \ \ C OR x1 x2 -- x3 logical OR
7753 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
7754 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
7755 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
7756 \ : LCD_FN_SET $20 OR LCD_WrF ;
7757 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
7758 \ : LCD_GOTO $80 OR LCD_WrF ;
7761 \ CODE LCD_RDS \ -- status Read Status
7762 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
7763 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
7764 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
7765 \ COLON \ starts a FORTH word
7766 \ TOP_LCD 2 20_us \ -- %0000_HHHH
7767 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
7768 \ HI2LO \ switch from FORTH to assembler
7769 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
7770 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
7771 \ MOV @RSP+,IP \ restore IP saved by COLON
7775 \ CODE LCD_RDC \ -- char Read Char
7776 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
7781 \ ******************************\
7782 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
7783 \ ******************************\
7784 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7785 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
7786 BIT.B #SW2,&SW2_IN \ test switch S2
7787 0= IF \ case of switch S2 pressed
7788 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
7790 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
7793 BIT.B #SW1,&SW1_IN \ test switch S1 input
7794 0= IF \ case of Switch S1 pressed
7795 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
7797 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
7801 BW1 \ from quit on truncated RC5 message, repeated RC5 command
7805 \ ******************************\
7806 ASM RC5_INT \ wake up on Px.RC5 change interrupt
7807 \ ******************************\
7808 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
7809 \ ******************************\
7810 \ \ in : SR(9)=old Toggle bit memory (ADD on)
7811 \ \ SMclock = 8|16|24 MHz
7812 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
7813 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
7814 \ \ SR(9)=new Toggle bit memory (ADD on)
7815 \ ******************************\
7816 \ RC5_FirstStartBitHalfCycle: \
7817 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
7818 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
7819 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
7820 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
7822 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
7823 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
7825 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
7826 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
7828 MOV #1778,X \ RC5_Period * 1us
7829 MOV #14,W \ count of loop
7831 \ ******************************\
7832 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
7833 \ ******************************\ |
7834 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
7835 \ RC5_Compute_3/4_Period: \ |
7836 RRUM #1,X \ X=1/2 cycle |
7839 ADD X,Y \ Y=3/4 cycle
7840 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
7842 \ ******************************\
7843 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
7844 \ ******************************\
7845 BIT.B #RC5,&IR_IN \ C_flag = IR bit
7846 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
7847 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
7848 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
7849 SUB #1,W \ decrement count loop
7850 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
7851 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
7852 0<> WHILE \ ----> out of loop ----+
7853 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
7855 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
7856 CMP Y,X \ 1 | cycle time out of bound ?
7858 BIC #$30,&RC5_TIM_CTL \ | | stop timer
7859 GOTO BW1 \ | | quit on truncated RC5 message
7861 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
7863 REPEAT \ ----> loop back --+ | with X = new RC5_period value
7864 \ ******************************\ |
7865 \ RC5_SampleEndOf: \ <---------------------+
7866 \ ******************************\
7867 BIC #$30,&RC5_TIM_CTL \ stop timer
7868 \ ******************************\
7869 \ RC5_ComputeNewRC5word \
7870 \ ******************************\
7871 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
7872 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
7873 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
7874 \ ******************************\
7875 \ RC5_ComputeC6bit \
7876 \ ******************************\
7877 BIT #BIT14,T \ test /C6 bit in T
7878 0= IF BIS #BIT6,X \ set C6 bit in X
7879 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
7880 \ ******************************\
7881 \ RC5_CommandByteIsDone \ -- BASE RC5_code
7882 \ ******************************\
7883 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
7884 \ ******************************\
7885 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
7886 XOR @RSP,T \ (new XOR old) Toggle bits
7887 BIT #UF10,T \ repeated RC5_command ?
7888 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
7889 XOR #UF10,0(RSP) \ 5 toggle bit memory
7890 \ ******************************\
7891 \ Display IR_RC5 code \
7892 \ ******************************\
7893 SUB #8,PSP \ TOS -- x x x x TOS
7894 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
7895 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
7896 MOV #$10,&BASEADR \ set hexadecimal base
7897 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
7898 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
7899 LO2HI \ switch from assembler to FORTH
7900 LCD_CLEAR \ set LCD cursor at home
7901 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
7902 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
7903 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
7904 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
7905 HI2LO \ -- switch from FORTH to assembler
7906 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
7907 MOV @PSP+,TOS \ -- TOS
7911 \ ******************************\
7913 \ ******************************\
7915 \ ... \ insert here your background task
7918 CALL &RXON \ comment this line to disable TERMINAL_INPUT
7920 \ ******************************\
7921 \ here start all interrupts \
7922 \ ******************************\
7923 \ here return all interrupts \
7924 \ ******************************\
7927 \ ******************************\
7929 \ ------------------------------\
7930 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
7931 \ ------------------------------\
7932 \ ... \ init specific I/O sys as you want
7933 \ ... \ before executing default WARM
7934 MOV #WARM,X \ ['] WARM
7936 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
7938 \ ------------------------------\
7940 \ ------------------------------\
7941 CODE STOP \ stops multitasking, must to be used before downloading app
7942 \ ------------------------------\
7943 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
7944 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
7945 MOV X,-2(X) \ restore the default background: SLEEP
7947 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
7948 BIC.B #RC5,&IR_IE \ clear RC5_Int
7949 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
7950 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
7951 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
7952 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
7953 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
7954 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
7956 ." RC5toLCD is removed,"
7957 ." type START to restart"
7958 WARM \ performs reset to reset all interrupt vectors.
7960 \ ------------------------------\
7962 \ ------------------------------\
7963 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
7964 \ ------------------------------\
7965 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
7966 \ - - \CNTL Counter lentgh \ 00 = 16 bits
7967 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
7968 \ -- \ID input divider \ 10 = /4
7969 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
7970 \ - \TBCLR TimerB Clear
7973 \ -------------------------------\
7974 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
7975 \ -- \CM Capture Mode
7980 \ --- \OUTMOD \ 011 = set/reset
7986 \ -------------------------------\
7988 \ -------------------------------\
7990 \ ------------------------------\
7991 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
7992 \ ------------------------------\
7993 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
7994 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
7995 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
7996 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
7998 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
7999 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8001 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
8002 \ ------------------------------\
8003 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8004 \ ------------------------------\
8005 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
8006 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8007 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8008 \ ------------------------------\
8009 BIS.B #LCDVo,&LCDVo_DIR \
8010 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
8011 \ ------------------------------\
8012 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8013 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8014 \ ------------------------------\
8015 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8016 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8017 \ ******************************\
8019 \ ******************************\
8020 BIS.B #RC5,&IR_IE \ enable RC5_Int
8021 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8022 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8023 \ ******************************\
8024 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8025 \ ******************************\
8026 \ %01 0001 0100 \ TAxCTL
8027 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
8028 \ -- \ ID divided by 1
8029 \ -- \ MC MODE = up to TAxCCRn
8030 \ - \ TACLR clear timer count
8033 \ ------------------------------\
8034 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
8035 \ ------------------------------\
8037 \ --- \ TAIDEX pre divisor
8038 \ ------------------------------\
8039 \ %0000 0000 0000 0101 \ TAxCCR0
8040 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8041 \ ------------------------------\
8042 \ %0000 0000 0001 0000 \ TAxCCTL0
8043 \ - \ CAP capture/compare mode = compare
8046 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
8047 \ ------------------------------\
8048 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8049 \ ------------------------------\
8050 \ define LPM mode for ACCEPT \
8051 \ ------------------------------\
8052 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8053 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8054 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8055 \ ------------------------------\
8057 \ ------------------------------\
8058 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
8059 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
8060 \ ------------------------------\
8061 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
8062 \ ------------------------------\
8063 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
8064 \ CMP #2,Y \ Power_ON event
8065 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
8067 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
8069 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
8071 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
8073 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
8074 \ ------------------------------\
8076 \ ------------------------------\
8078 \ ------------------------------\
8079 #1000 20_US \ 1- wait 20 ms
8080 %011 TOP_LCD \ 2- send DB5=DB4=1
8081 #205 20_US \ 3- wait 4,1 ms
8082 %011 TOP_LCD \ 4- send again DB5=DB4=1
8083 #5 20_US \ 5- wait 0,1 ms
8084 %011 TOP_LCD \ 6- send again again DB5=DB4=1
8085 #2 20_US \ wait 40 us = LCD cycle
8086 %010 TOP_LCD \ 7- send DB5=1 DB4=0
8087 #2 20_US \ wait 40 us = LCD cycle
8088 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8089 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8090 LCD_CLEAR \ 10- "LCD_Clear"
8091 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8092 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8093 LCD_CLEAR \ 10- "LCD_Clear"
8094 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8095 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8096 CR ." I love you" \ display message on LCD
8097 ['] CR >BODY IS CR \ CR executes its default value
8098 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
8099 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
8100 PWR_STATE ABORT \ init DP and continues with ABORT
8102 \ ------------------------------\
8104 \ ------------------------------\
8105 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
8106 \ ------------------------------\
8107 MOV #SLEEP,X \ replace default background process SLEEP
8108 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
8109 MOV #WARM,X \ replace default WARM
8110 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
8111 MOV X,PC \ then execute new WARM
8113 \ ------------------------------\
8116 ; downloading RC5toLCD.4th is done
8117 RST_HERE ; this app is protected against <reset>
8122 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
8124 [UNDEFINED] MARKER [IF]
8125 \ https://forth-standard.org/standard/core/MARKER
8127 \ ( "<spaces>name" -- )
8128 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
8129 \ with the execution semantics defined below.
8131 \ name Execution: ( -- )
8132 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
8133 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
8134 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
8135 \ not necessarily provided. No other contextual information such as numeric base is affected
8140 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
8141 SUB #2,Y \ 1 Y = LFA
8142 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
8143 ADD #4,&DP \ 3 add 2 cells
8147 MOV @RSP+,IP \ -- PFA
8148 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
8149 MOV @TOS,&INIDP \ set DP value for RST_STATE
8151 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
8158 \ https://forth-standard.org/standard/core/Fetch
8159 \ @ c-addr -- char fetch char from memory
8166 [UNDEFINED] CONSTANT [IF]
8167 \ https://forth-standard.org/standard/core/CONSTANT
8168 \ CONSTANT <name> n -- define a Forth CONSTANT
8172 MOV TOS,-2(W) \ PFA = n
8179 [UNDEFINED] STATE [IF]
8180 \ https://forth-standard.org/standard/core/STATE
8181 \ STATE -- a-addr holds compiler state
8182 STATEADR CONSTANT STATE
8186 \ https://forth-standard.org/standard/core/Equal
8187 \ = x1 x2 -- flag test x1=x2
8194 XOR #-1,TOS \ 1 flag Z = 1
8200 \ https://forth-standard.org/standard/core/IF
8201 \ IF -- IFadr initialize conditional forward branch
8205 MOV &DP,TOS \ -- HERE
8206 ADD #4,&DP \ compile one word, reserve one word
8207 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
8208 ADD #2,TOS \ -- HERE+2=IFadr
8213 [UNDEFINED] THEN [IF]
8214 \ https://forth-standard.org/standard/core/THEN
8215 \ THEN IFadr -- resolve forward branch
8216 CODE THEN \ immediate
8217 MOV &DP,0(TOS) \ -- IFadr
8223 [UNDEFINED] ELSE [IF]
8224 \ https://forth-standard.org/standard/core/ELSE
8225 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
8226 CODE ELSE \ immediate
8227 ADD #4,&DP \ make room to compile two words
8228 MOV &DP,W \ W=HERE+4
8230 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
8232 MOV W,TOS \ -- ELSEadr
8237 [UNDEFINED] DEFER [IF]
8238 \ https://forth-standard.org/standard/core/DEFER
8239 \ DEFER "<spaces>name" --
8240 \ Skip leading space delimiters. Parse name delimited by a space.
8241 \ Create a definition for name with the execution semantics defined below.
8243 \ name Execution: --
8244 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
8245 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
8249 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
8250 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
8256 [UNDEFINED] DEFER! [IF]
8257 \ https://forth-standard.org/standard/core/DEFERStore
8258 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
8259 CODE DEFER! \ xt2 xt1 --
8260 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
8267 \ https://forth-standard.org/standard/core/IS
8270 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
8271 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
8272 \ or in a definition : ... ['] U. IS DISPLAY ...
8273 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
8275 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
8278 IF POSTPONE ['] POSTPONE DEFER!
8284 [UNDEFINED] >BODY [IF]
8285 \ https://forth-standard.org/standard/core/toBODY
8286 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
8293 \ CODE 20uS \ n -- 8MHz version
8294 \ BEGIN \ 4 + 16 ~ loop
8295 \ MOV #39,rDOCON \ 39
8302 \ MOV #XDOCON,rDOCON \ 2
8307 CODE 20_US \ n -- n * 20 us
8308 BEGIN \ here we presume that LCD_TIM_IFG = 1...
8310 BIT #1,&LCD_TIM_CTL \ 3
8311 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
8312 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
8314 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
8319 CODE TOP_LCD \ LCD Sample
8320 \ \ if write : %xxxx_WWWW --
8321 \ \ if read : -- %0000_RRRR
8322 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8323 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8324 0= IF \ write LCD bits pattern
8326 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8327 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8330 THEN \ read LCD bits pattern
8333 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8334 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8339 CODE LCD_WRC \ char -- Write Char
8340 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8342 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
8343 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
8344 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8345 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8346 COLON \ high level word starts here
8347 TOP_LCD 2 20_US \ write high nibble first
8351 CODE LCD_WRF \ func -- Write Fonction
8352 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8356 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
8357 : LCD_HOME $02 LCD_WRF 100 20_us ;
8359 \ [UNDEFINED] OR [IF]
8361 \ \ https://forth-standard.org/standard/core/OR
8362 \ \ C OR x1 x2 -- x3 logical OR
8370 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
8371 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
8372 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
8373 \ : LCD_FN_SET $20 OR LCD_WrF ;
8374 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
8375 \ : LCD_GOTO $80 OR LCD_WrF ;
8378 \ CODE LCD_RDS \ -- status Read Status
8379 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8380 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8381 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8382 \ COLON \ starts a FORTH word
8383 \ TOP_LCD 2 20_us \ -- %0000_HHHH
8384 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
8385 \ HI2LO \ switch from FORTH to assembler
8386 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
8387 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
8388 \ MOV @RSP+,IP \ restore IP saved by COLON
8392 \ CODE LCD_RDC \ -- char Read Char
8393 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8398 \ ******************************\
8399 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
8400 \ ******************************\
8401 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
8402 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
8403 BIT.B #SW2,&SW2_IN \ test switch S2
8404 0= IF \ case of switch S2 pressed
8405 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
8407 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
8410 BIT.B #SW1,&SW1_IN \ test switch S1 input
8411 0= IF \ case of Switch S1 pressed
8412 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
8414 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
8418 BW1 \ from quit on truncated RC5 message, repeated RC5 command
8422 \ ******************************\
8423 ASM RC5_INT \ wake up on Px.RC5 change interrupt
8424 \ ******************************\
8425 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
8426 \ ******************************\
8427 \ \ in : SR(9)=old Toggle bit memory (ADD on)
8428 \ \ SMclock = 8|16|24 MHz
8429 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
8430 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
8431 \ \ SR(9)=new Toggle bit memory (ADD on)
8432 \ ******************************\
8433 \ RC5_FirstStartBitHalfCycle: \
8434 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
8435 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
8436 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
8437 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
8439 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
8440 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
8442 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
8443 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
8445 MOV #1778,X \ RC5_Period * 1us
8446 MOV #14,W \ count of loop
8448 \ ******************************\
8449 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
8450 \ ******************************\ |
8451 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
8452 \ RC5_Compute_3/4_Period: \ |
8453 RRUM #1,X \ X=1/2 cycle |
8456 ADD X,Y \ Y=3/4 cycle
8457 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
8459 \ ******************************\
8460 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
8461 \ ******************************\
8462 BIT.B #RC5,&IR_IN \ C_flag = IR bit
8463 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
8464 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
8465 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
8466 SUB #1,W \ decrement count loop
8467 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
8468 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
8469 0<> WHILE \ ----> out of loop ----+
8470 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
8472 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
8473 CMP Y,X \ 1 | cycle time out of bound ?
8475 BIC #$30,&RC5_TIM_CTL \ | | stop timer
8476 GOTO BW1 \ | | quit on truncated RC5 message
8478 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
8480 REPEAT \ ----> loop back --+ | with X = new RC5_period value
8481 \ ******************************\ |
8482 \ RC5_SampleEndOf: \ <---------------------+
8483 \ ******************************\
8484 BIC #$30,&RC5_TIM_CTL \ stop timer
8485 \ ******************************\
8486 \ RC5_ComputeNewRC5word \
8487 \ ******************************\
8488 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
8489 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
8490 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
8491 \ ******************************\
8492 \ RC5_ComputeC6bit \
8493 \ ******************************\
8494 BIT #BIT14,T \ test /C6 bit in T
8495 0= IF BIS #BIT6,X \ set C6 bit in X
8496 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
8497 \ ******************************\
8498 \ RC5_CommandByteIsDone \ -- BASE RC5_code
8499 \ ******************************\
8500 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
8501 \ ******************************\
8502 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
8503 XOR @RSP,T \ (new XOR old) Toggle bits
8504 BIT #UF10,T \ repeated RC5_command ?
8505 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
8506 XOR #UF10,0(RSP) \ 5 toggle bit memory
8507 \ ******************************\
8508 \ Display IR_RC5 code \
8509 \ ******************************\
8510 SUB #8,PSP \ TOS -- x x x x TOS
8511 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
8512 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
8513 MOV #$10,&BASEADR \ set hexadecimal base
8514 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
8515 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
8516 LO2HI \ switch from assembler to FORTH
8517 LCD_CLEAR \ set LCD cursor at home
8518 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
8519 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
8520 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
8521 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
8522 HI2LO \ -- switch from FORTH to assembler
8523 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
8524 MOV @PSP+,TOS \ -- TOS
8528 \ ******************************\
8530 \ ******************************\
8532 \ ... \ insert here your background task
8535 CALL &RXON \ comment this line to disable TERMINAL_INPUT
8537 \ ******************************\
8538 \ here start all interrupts \
8539 \ ******************************\
8540 \ here return all interrupts \
8541 \ ******************************\
8544 \ ******************************\
8546 \ ------------------------------\
8547 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
8548 \ ------------------------------\
8549 \ ... \ init specific I/O sys as you want
8550 \ ... \ before executing default WARM
8551 MOV #WARM,X \ ['] WARM
8553 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
8555 \ ------------------------------\
8557 \ ------------------------------\
8558 CODE STOP \ stops multitasking, must to be used before downloading app
8559 \ ------------------------------\
8560 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
8561 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
8562 MOV X,-2(X) \ restore the default background: SLEEP
8564 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
8565 BIC.B #RC5,&IR_IE \ clear RC5_Int
8566 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
8567 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
8568 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
8569 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
8570 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
8571 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
8573 ." RC5toLCD is removed,"
8574 ." type START to restart"
8575 WARM \ performs reset to reset all interrupt vectors.
8577 \ ------------------------------\
8579 \ ------------------------------\
8580 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
8581 \ ------------------------------\
8582 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
8583 \ - - \CNTL Counter lentgh \ 00 = 16 bits
8584 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
8585 \ -- \ID input divider \ 10 = /4
8586 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
8587 \ - \TBCLR TimerB Clear
8590 \ -------------------------------\
8591 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
8592 \ -- \CM Capture Mode
8597 \ --- \OUTMOD \ 011 = set/reset
8603 \ -------------------------------\
8605 \ -------------------------------\
8607 \ ------------------------------\
8608 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
8609 \ ------------------------------\
8610 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
8611 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
8612 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
8613 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
8615 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
8616 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
8618 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
8619 \ ------------------------------\
8620 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
8621 \ ------------------------------\
8622 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
8623 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
8624 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
8625 \ ------------------------------\
8626 BIS.B #LCDVo,&LCDVo_DIR \
8627 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
8628 \ ------------------------------\
8629 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
8630 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
8631 \ ------------------------------\
8632 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
8633 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
8634 \ ******************************\
8636 \ ******************************\
8637 BIS.B #RC5,&IR_IE \ enable RC5_Int
8638 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
8639 MOV #RC5_INT,&IR_Vec \ init interrupt vector
8640 \ ******************************\
8641 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
8642 \ ******************************\
8643 \ %01 0001 0100 \ TAxCTL
8644 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
8645 \ -- \ ID divided by 1
8646 \ -- \ MC MODE = up to TAxCCRn
8647 \ - \ TACLR clear timer count
8650 \ ------------------------------\
8651 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
8652 \ ------------------------------\
8654 \ --- \ TAIDEX pre divisor
8655 \ ------------------------------\
8656 \ %0000 0000 0000 0101 \ TAxCCR0
8657 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
8658 \ ------------------------------\
8659 \ %0000 0000 0001 0000 \ TAxCCTL0
8660 \ - \ CAP capture/compare mode = compare
8663 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
8664 \ ------------------------------\
8665 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
8666 \ ------------------------------\
8667 \ define LPM mode for ACCEPT \
8668 \ ------------------------------\
8669 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
8670 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
8671 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
8672 \ ------------------------------\
8674 \ ------------------------------\
8675 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
8676 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
8677 \ ------------------------------\
8678 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
8679 \ ------------------------------\
8680 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
8681 \ CMP #2,Y \ Power_ON event
8682 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
8684 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
8686 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
8688 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
8690 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
8691 \ ------------------------------\
8693 \ ------------------------------\
8695 \ ------------------------------\
8696 #1000 20_US \ 1- wait 20 ms
8697 %011 TOP_LCD \ 2- send DB5=DB4=1
8698 #205 20_US \ 3- wait 4,1 ms
8699 %011 TOP_LCD \ 4- send again DB5=DB4=1
8700 #5 20_US \ 5- wait 0,1 ms
8701 %011 TOP_LCD \ 6- send again again DB5=DB4=1
8702 #2 20_US \ wait 40 us = LCD cycle
8703 %010 TOP_LCD \ 7- send DB5=1 DB4=0
8704 #2 20_US \ wait 40 us = LCD cycle
8705 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
8706 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
8707 LCD_CLEAR \ 10- "LCD_Clear"
8708 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
8709 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
8710 LCD_CLEAR \ 10- "LCD_Clear"
8711 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
8712 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
8713 CR ." I love you" \ display message on LCD
8714 ['] CR >BODY IS CR \ CR executes its default value
8715 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
8716 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
8717 PWR_STATE ABORT \ init DP and continues with ABORT
8719 \ ------------------------------\
8721 \ ------------------------------\
8722 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
8723 \ ------------------------------\
8724 MOV #SLEEP,X \ replace default background process SLEEP
8725 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
8726 MOV #WARM,X \ replace default WARM
8727 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
8728 MOV X,PC \ then execute new WARM
8730 \ ------------------------------\
8733 ; downloading RC5toLCD.4th is done
8734 RST_HERE ; this app is protected against <reset>
8739 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
8741 [UNDEFINED] MARKER [IF]
8742 \ https://forth-standard.org/standard/core/MARKER
8744 \ ( "<spaces>name" -- )
8745 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
8746 \ with the execution semantics defined below.
8748 \ name Execution: ( -- )
8749 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
8750 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
8751 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
8752 \ not necessarily provided. No other contextual information such as numeric base is affected
8757 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
8758 SUB #2,Y \ 1 Y = LFA
8759 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
8760 ADD #4,&DP \ 3 add 2 cells
8764 MOV @RSP+,IP \ -- PFA
8765 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
8766 MOV @TOS,&INIDP \ set DP value for RST_STATE
8768 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
8775 \ https://forth-standard.org/standard/core/Fetch
8776 \ @ c-addr -- char fetch char from memory
8783 [UNDEFINED] CONSTANT [IF]
8784 \ https://forth-standard.org/standard/core/CONSTANT
8785 \ CONSTANT <name> n -- define a Forth CONSTANT
8789 MOV TOS,-2(W) \ PFA = n
8796 [UNDEFINED] STATE [IF]
8797 \ https://forth-standard.org/standard/core/STATE
8798 \ STATE -- a-addr holds compiler state
8799 STATEADR CONSTANT STATE
8803 \ https://forth-standard.org/standard/core/Equal
8804 \ = x1 x2 -- flag test x1=x2
8811 XOR #-1,TOS \ 1 flag Z = 1
8817 \ https://forth-standard.org/standard/core/IF
8818 \ IF -- IFadr initialize conditional forward branch
8822 MOV &DP,TOS \ -- HERE
8823 ADD #4,&DP \ compile one word, reserve one word
8824 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
8825 ADD #2,TOS \ -- HERE+2=IFadr
8830 [UNDEFINED] THEN [IF]
8831 \ https://forth-standard.org/standard/core/THEN
8832 \ THEN IFadr -- resolve forward branch
8833 CODE THEN \ immediate
8834 MOV &DP,0(TOS) \ -- IFadr
8840 [UNDEFINED] ELSE [IF]
8841 \ https://forth-standard.org/standard/core/ELSE
8842 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
8843 CODE ELSE \ immediate
8844 ADD #4,&DP \ make room to compile two words
8845 MOV &DP,W \ W=HERE+4
8847 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
8849 MOV W,TOS \ -- ELSEadr
8854 [UNDEFINED] DEFER [IF]
8855 \ https://forth-standard.org/standard/core/DEFER
8856 \ DEFER "<spaces>name" --
8857 \ Skip leading space delimiters. Parse name delimited by a space.
8858 \ Create a definition for name with the execution semantics defined below.
8860 \ name Execution: --
8861 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
8862 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
8866 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
8867 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
8873 [UNDEFINED] DEFER! [IF]
8874 \ https://forth-standard.org/standard/core/DEFERStore
8875 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
8876 CODE DEFER! \ xt2 xt1 --
8877 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
8884 \ https://forth-standard.org/standard/core/IS
8887 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
8888 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
8889 \ or in a definition : ... ['] U. IS DISPLAY ...
8890 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
8892 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
8895 IF POSTPONE ['] POSTPONE DEFER!
8901 [UNDEFINED] >BODY [IF]
8902 \ https://forth-standard.org/standard/core/toBODY
8903 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
8910 \ CODE 20uS \ n -- 8MHz version
8911 \ BEGIN \ 4 + 16 ~ loop
8912 \ MOV #39,rDOCON \ 39
8919 \ MOV #XDOCON,rDOCON \ 2
8924 CODE 20_US \ n -- n * 20 us
8925 BEGIN \ here we presume that LCD_TIM_IFG = 1...
8927 BIT #1,&LCD_TIM_CTL \ 3
8928 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
8929 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
8931 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
8936 CODE TOP_LCD \ LCD Sample
8937 \ \ if write : %xxxx_WWWW --
8938 \ \ if read : -- %0000_RRRR
8939 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
8940 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
8941 0= IF \ write LCD bits pattern
8943 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
8944 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8947 THEN \ read LCD bits pattern
8950 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
8951 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
8956 CODE LCD_WRC \ char -- Write Char
8957 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
8959 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
8960 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
8961 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
8962 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
8963 COLON \ high level word starts here
8964 TOP_LCD 2 20_US \ write high nibble first
8968 CODE LCD_WRF \ func -- Write Fonction
8969 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8973 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
8974 : LCD_HOME $02 LCD_WRF 100 20_us ;
8976 \ [UNDEFINED] OR [IF]
8978 \ \ https://forth-standard.org/standard/core/OR
8979 \ \ C OR x1 x2 -- x3 logical OR
8987 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
8988 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
8989 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
8990 \ : LCD_FN_SET $20 OR LCD_WrF ;
8991 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
8992 \ : LCD_GOTO $80 OR LCD_WrF ;
8995 \ CODE LCD_RDS \ -- status Read Status
8996 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
8997 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
8998 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
8999 \ COLON \ starts a FORTH word
9000 \ TOP_LCD 2 20_us \ -- %0000_HHHH
9001 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
9002 \ HI2LO \ switch from FORTH to assembler
9003 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
9004 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
9005 \ MOV @RSP+,IP \ restore IP saved by COLON
9009 \ CODE LCD_RDC \ -- char Read Char
9010 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9015 \ ******************************\
9016 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9017 \ ******************************\
9018 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9019 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
9020 BIT.B #SW2,&SW2_IN \ test switch S2
9021 0= IF \ case of switch S2 pressed
9022 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9024 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
9027 BIT.B #SW1,&SW1_IN \ test switch S1 input
9028 0= IF \ case of Switch S1 pressed
9029 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9031 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9035 BW1 \ from quit on truncated RC5 message, repeated RC5 command
9039 \ ******************************\
9040 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9041 \ ******************************\
9042 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9043 \ ******************************\
9044 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9045 \ \ SMclock = 8|16|24 MHz
9046 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9047 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9048 \ \ SR(9)=new Toggle bit memory (ADD on)
9049 \ ******************************\
9050 \ RC5_FirstStartBitHalfCycle: \
9051 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9052 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9053 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
9054 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
9056 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
9057 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
9059 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
9060 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
9062 MOV #1778,X \ RC5_Period * 1us
9063 MOV #14,W \ count of loop
9065 \ ******************************\
9066 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
9067 \ ******************************\ |
9068 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
9069 \ RC5_Compute_3/4_Period: \ |
9070 RRUM #1,X \ X=1/2 cycle |
9073 ADD X,Y \ Y=3/4 cycle
9074 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
9076 \ ******************************\
9077 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
9078 \ ******************************\
9079 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9080 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
9081 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9082 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9083 SUB #1,W \ decrement count loop
9084 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
9085 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9086 0<> WHILE \ ----> out of loop ----+
9087 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
9089 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
9090 CMP Y,X \ 1 | cycle time out of bound ?
9092 BIC #$30,&RC5_TIM_CTL \ | | stop timer
9093 GOTO BW1 \ | | quit on truncated RC5 message
9095 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
9097 REPEAT \ ----> loop back --+ | with X = new RC5_period value
9098 \ ******************************\ |
9099 \ RC5_SampleEndOf: \ <---------------------+
9100 \ ******************************\
9101 BIC #$30,&RC5_TIM_CTL \ stop timer
9102 \ ******************************\
9103 \ RC5_ComputeNewRC5word \
9104 \ ******************************\
9105 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
9106 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
9107 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
9108 \ ******************************\
9109 \ RC5_ComputeC6bit \
9110 \ ******************************\
9111 BIT #BIT14,T \ test /C6 bit in T
9112 0= IF BIS #BIT6,X \ set C6 bit in X
9113 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
9114 \ ******************************\
9115 \ RC5_CommandByteIsDone \ -- BASE RC5_code
9116 \ ******************************\
9117 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9118 \ ******************************\
9119 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
9120 XOR @RSP,T \ (new XOR old) Toggle bits
9121 BIT #UF10,T \ repeated RC5_command ?
9122 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
9123 XOR #UF10,0(RSP) \ 5 toggle bit memory
9124 \ ******************************\
9125 \ Display IR_RC5 code \
9126 \ ******************************\
9127 SUB #8,PSP \ TOS -- x x x x TOS
9128 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
9129 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
9130 MOV #$10,&BASEADR \ set hexadecimal base
9131 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
9132 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
9133 LO2HI \ switch from assembler to FORTH
9134 LCD_CLEAR \ set LCD cursor at home
9135 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
9136 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
9137 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
9138 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
9139 HI2LO \ -- switch from FORTH to assembler
9140 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
9141 MOV @PSP+,TOS \ -- TOS
9145 \ ******************************\
9147 \ ******************************\
9149 \ ... \ insert here your background task
9152 CALL &RXON \ comment this line to disable TERMINAL_INPUT
9154 \ ******************************\
9155 \ here start all interrupts \
9156 \ ******************************\
9157 \ here return all interrupts \
9158 \ ******************************\
9161 \ ******************************\
9163 \ ------------------------------\
9164 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
9165 \ ------------------------------\
9166 \ ... \ init specific I/O sys as you want
9167 \ ... \ before executing default WARM
9168 MOV #WARM,X \ ['] WARM
9170 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
9172 \ ------------------------------\
9174 \ ------------------------------\
9175 CODE STOP \ stops multitasking, must to be used before downloading app
9176 \ ------------------------------\
9177 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
9178 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
9179 MOV X,-2(X) \ restore the default background: SLEEP
9181 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
9182 BIC.B #RC5,&IR_IE \ clear RC5_Int
9183 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
9184 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
9185 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
9186 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
9187 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
9188 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
9190 ." RC5toLCD is removed,"
9191 ." type START to restart"
9192 WARM \ performs reset to reset all interrupt vectors.
9194 \ ------------------------------\
9196 \ ------------------------------\
9197 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
9198 \ ------------------------------\
9199 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
9200 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9201 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9202 \ -- \ID input divider \ 10 = /4
9203 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
9204 \ - \TBCLR TimerB Clear
9207 \ -------------------------------\
9208 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9209 \ -- \CM Capture Mode
9214 \ --- \OUTMOD \ 011 = set/reset
9220 \ -------------------------------\
9222 \ -------------------------------\
9224 \ ------------------------------\
9225 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
9226 \ ------------------------------\
9227 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
9228 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
9229 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
9230 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
9232 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
9233 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
9235 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
9236 \ ------------------------------\
9237 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
9238 \ ------------------------------\
9239 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
9240 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
9241 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9242 \ ------------------------------\
9243 BIS.B #LCDVo,&LCDVo_DIR \
9244 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
9245 \ ------------------------------\
9246 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9247 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9248 \ ------------------------------\
9249 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9250 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9251 \ ******************************\
9253 \ ******************************\
9254 BIS.B #RC5,&IR_IE \ enable RC5_Int
9255 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9256 MOV #RC5_INT,&IR_Vec \ init interrupt vector
9257 \ ******************************\
9258 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
9259 \ ******************************\
9260 \ %01 0001 0100 \ TAxCTL
9261 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
9262 \ -- \ ID divided by 1
9263 \ -- \ MC MODE = up to TAxCCRn
9264 \ - \ TACLR clear timer count
9267 \ ------------------------------\
9268 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
9269 \ ------------------------------\
9271 \ --- \ TAIDEX pre divisor
9272 \ ------------------------------\
9273 \ %0000 0000 0000 0101 \ TAxCCR0
9274 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
9275 \ ------------------------------\
9276 \ %0000 0000 0001 0000 \ TAxCCTL0
9277 \ - \ CAP capture/compare mode = compare
9280 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
9281 \ ------------------------------\
9282 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
9283 \ ------------------------------\
9284 \ define LPM mode for ACCEPT \
9285 \ ------------------------------\
9286 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9287 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9288 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9289 \ ------------------------------\
9291 \ ------------------------------\
9292 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
9293 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
9294 \ ------------------------------\
9295 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
9296 \ ------------------------------\
9297 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
9298 \ CMP #2,Y \ Power_ON event
9299 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
9301 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
9303 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
9305 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
9307 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
9308 \ ------------------------------\
9310 \ ------------------------------\
9312 \ ------------------------------\
9313 #1000 20_US \ 1- wait 20 ms
9314 %011 TOP_LCD \ 2- send DB5=DB4=1
9315 #205 20_US \ 3- wait 4,1 ms
9316 %011 TOP_LCD \ 4- send again DB5=DB4=1
9317 #5 20_US \ 5- wait 0,1 ms
9318 %011 TOP_LCD \ 6- send again again DB5=DB4=1
9319 #2 20_US \ wait 40 us = LCD cycle
9320 %010 TOP_LCD \ 7- send DB5=1 DB4=0
9321 #2 20_US \ wait 40 us = LCD cycle
9322 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9323 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9324 LCD_CLEAR \ 10- "LCD_Clear"
9325 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9326 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9327 LCD_CLEAR \ 10- "LCD_Clear"
9328 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9329 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9330 CR ." I love you" \ display message on LCD
9331 ['] CR >BODY IS CR \ CR executes its default value
9332 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
9333 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9334 PWR_STATE ABORT \ init DP and continues with ABORT
9336 \ ------------------------------\
9338 \ ------------------------------\
9339 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
9340 \ ------------------------------\
9341 MOV #SLEEP,X \ replace default background process SLEEP
9342 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
9343 MOV #WARM,X \ replace default WARM
9344 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
9345 MOV X,PC \ then execute new WARM
9347 \ ------------------------------\
9350 ; downloading RC5toLCD.4th is done
9351 RST_HERE ; this app is protected against <reset>
9356 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
9358 [UNDEFINED] MARKER [IF]
9359 \ https://forth-standard.org/standard/core/MARKER
9361 \ ( "<spaces>name" -- )
9362 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
9363 \ with the execution semantics defined below.
9365 \ name Execution: ( -- )
9366 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
9367 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
9368 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
9369 \ not necessarily provided. No other contextual information such as numeric base is affected
9374 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
9375 SUB #2,Y \ 1 Y = LFA
9376 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
9377 ADD #4,&DP \ 3 add 2 cells
9381 MOV @RSP+,IP \ -- PFA
9382 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
9383 MOV @TOS,&INIDP \ set DP value for RST_STATE
9385 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
9392 \ https://forth-standard.org/standard/core/Fetch
9393 \ @ c-addr -- char fetch char from memory
9400 [UNDEFINED] CONSTANT [IF]
9401 \ https://forth-standard.org/standard/core/CONSTANT
9402 \ CONSTANT <name> n -- define a Forth CONSTANT
9406 MOV TOS,-2(W) \ PFA = n
9413 [UNDEFINED] STATE [IF]
9414 \ https://forth-standard.org/standard/core/STATE
9415 \ STATE -- a-addr holds compiler state
9416 STATEADR CONSTANT STATE
9420 \ https://forth-standard.org/standard/core/Equal
9421 \ = x1 x2 -- flag test x1=x2
9428 XOR #-1,TOS \ 1 flag Z = 1
9434 \ https://forth-standard.org/standard/core/IF
9435 \ IF -- IFadr initialize conditional forward branch
9439 MOV &DP,TOS \ -- HERE
9440 ADD #4,&DP \ compile one word, reserve one word
9441 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
9442 ADD #2,TOS \ -- HERE+2=IFadr
9447 [UNDEFINED] THEN [IF]
9448 \ https://forth-standard.org/standard/core/THEN
9449 \ THEN IFadr -- resolve forward branch
9450 CODE THEN \ immediate
9451 MOV &DP,0(TOS) \ -- IFadr
9457 [UNDEFINED] ELSE [IF]
9458 \ https://forth-standard.org/standard/core/ELSE
9459 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
9460 CODE ELSE \ immediate
9461 ADD #4,&DP \ make room to compile two words
9462 MOV &DP,W \ W=HERE+4
9464 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
9466 MOV W,TOS \ -- ELSEadr
9471 [UNDEFINED] DEFER [IF]
9472 \ https://forth-standard.org/standard/core/DEFER
9473 \ DEFER "<spaces>name" --
9474 \ Skip leading space delimiters. Parse name delimited by a space.
9475 \ Create a definition for name with the execution semantics defined below.
9477 \ name Execution: --
9478 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
9479 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
9483 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
9484 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
9490 [UNDEFINED] DEFER! [IF]
9491 \ https://forth-standard.org/standard/core/DEFERStore
9492 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
9493 CODE DEFER! \ xt2 xt1 --
9494 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
9501 \ https://forth-standard.org/standard/core/IS
9504 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
9505 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
9506 \ or in a definition : ... ['] U. IS DISPLAY ...
9507 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
9509 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
9512 IF POSTPONE ['] POSTPONE DEFER!
9518 [UNDEFINED] >BODY [IF]
9519 \ https://forth-standard.org/standard/core/toBODY
9520 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
9527 \ CODE 20uS \ n -- 8MHz version
9528 \ BEGIN \ 4 + 16 ~ loop
9529 \ MOV #39,rDOCON \ 39
9536 \ MOV #XDOCON,rDOCON \ 2
9541 CODE 20_US \ n -- n * 20 us
9542 BEGIN \ here we presume that LCD_TIM_IFG = 1...
9544 BIT #1,&LCD_TIM_CTL \ 3
9545 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
9546 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
9548 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
9553 CODE TOP_LCD \ LCD Sample
9554 \ \ if write : %xxxx_WWWW --
9555 \ \ if read : -- %0000_RRRR
9556 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
9557 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
9558 0= IF \ write LCD bits pattern
9560 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
9561 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9564 THEN \ read LCD bits pattern
9567 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
9568 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
9573 CODE LCD_WRC \ char -- Write Char
9574 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9576 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
9577 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
9578 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
9579 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
9580 COLON \ high level word starts here
9581 TOP_LCD 2 20_US \ write high nibble first
9585 CODE LCD_WRF \ func -- Write Fonction
9586 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9590 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
9591 : LCD_HOME $02 LCD_WRF 100 20_us ;
9593 \ [UNDEFINED] OR [IF]
9595 \ \ https://forth-standard.org/standard/core/OR
9596 \ \ C OR x1 x2 -- x3 logical OR
9604 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
9605 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
9606 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
9607 \ : LCD_FN_SET $20 OR LCD_WrF ;
9608 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
9609 \ : LCD_GOTO $80 OR LCD_WrF ;
9612 \ CODE LCD_RDS \ -- status Read Status
9613 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
9614 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
9615 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
9616 \ COLON \ starts a FORTH word
9617 \ TOP_LCD 2 20_us \ -- %0000_HHHH
9618 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
9619 \ HI2LO \ switch from FORTH to assembler
9620 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
9621 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
9622 \ MOV @RSP+,IP \ restore IP saved by COLON
9626 \ CODE LCD_RDC \ -- char Read Char
9627 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
9632 \ ******************************\
9633 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
9634 \ ******************************\
9635 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9636 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
9637 BIT.B #SW2,&SW2_IN \ test switch S2
9638 0= IF \ case of switch S2 pressed
9639 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
9641 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
9644 BIT.B #SW1,&SW1_IN \ test switch S1 input
9645 0= IF \ case of Switch S1 pressed
9646 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
9648 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
9652 BW1 \ from quit on truncated RC5 message, repeated RC5 command
9656 \ ******************************\
9657 ASM RC5_INT \ wake up on Px.RC5 change interrupt
9658 \ ******************************\
9659 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
9660 \ ******************************\
9661 \ \ in : SR(9)=old Toggle bit memory (ADD on)
9662 \ \ SMclock = 8|16|24 MHz
9663 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
9664 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
9665 \ \ SR(9)=new Toggle bit memory (ADD on)
9666 \ ******************************\
9667 \ RC5_FirstStartBitHalfCycle: \
9668 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
9669 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
9670 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
9671 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
9673 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
9674 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
9676 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
9677 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
9679 MOV #1778,X \ RC5_Period * 1us
9680 MOV #14,W \ count of loop
9682 \ ******************************\
9683 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
9684 \ ******************************\ |
9685 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
9686 \ RC5_Compute_3/4_Period: \ |
9687 RRUM #1,X \ X=1/2 cycle |
9690 ADD X,Y \ Y=3/4 cycle
9691 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
9693 \ ******************************\
9694 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
9695 \ ******************************\
9696 BIT.B #RC5,&IR_IN \ C_flag = IR bit
9697 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
9698 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
9699 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
9700 SUB #1,W \ decrement count loop
9701 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
9702 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
9703 0<> WHILE \ ----> out of loop ----+
9704 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
9706 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
9707 CMP Y,X \ 1 | cycle time out of bound ?
9709 BIC #$30,&RC5_TIM_CTL \ | | stop timer
9710 GOTO BW1 \ | | quit on truncated RC5 message
9712 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
9714 REPEAT \ ----> loop back --+ | with X = new RC5_period value
9715 \ ******************************\ |
9716 \ RC5_SampleEndOf: \ <---------------------+
9717 \ ******************************\
9718 BIC #$30,&RC5_TIM_CTL \ stop timer
9719 \ ******************************\
9720 \ RC5_ComputeNewRC5word \
9721 \ ******************************\
9722 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
9723 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
9724 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
9725 \ ******************************\
9726 \ RC5_ComputeC6bit \
9727 \ ******************************\
9728 BIT #BIT14,T \ test /C6 bit in T
9729 0= IF BIS #BIT6,X \ set C6 bit in X
9730 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
9731 \ ******************************\
9732 \ RC5_CommandByteIsDone \ -- BASE RC5_code
9733 \ ******************************\
9734 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
9735 \ ******************************\
9736 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
9737 XOR @RSP,T \ (new XOR old) Toggle bits
9738 BIT #UF10,T \ repeated RC5_command ?
9739 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
9740 XOR #UF10,0(RSP) \ 5 toggle bit memory
9741 \ ******************************\
9742 \ Display IR_RC5 code \
9743 \ ******************************\
9744 SUB #8,PSP \ TOS -- x x x x TOS
9745 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
9746 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
9747 MOV #$10,&BASEADR \ set hexadecimal base
9748 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
9749 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
9750 LO2HI \ switch from assembler to FORTH
9751 LCD_CLEAR \ set LCD cursor at home
9752 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
9753 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
9754 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
9755 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
9756 HI2LO \ -- switch from FORTH to assembler
9757 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
9758 MOV @PSP+,TOS \ -- TOS
9762 \ ******************************\
9764 \ ******************************\
9766 \ ... \ insert here your background task
9769 CALL &RXON \ comment this line to disable TERMINAL_INPUT
9771 \ ******************************\
9772 \ here start all interrupts \
9773 \ ******************************\
9774 \ here return all interrupts \
9775 \ ******************************\
9778 \ ******************************\
9780 \ ------------------------------\
9781 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
9782 \ ------------------------------\
9783 \ ... \ init specific I/O sys as you want
9784 \ ... \ before executing default WARM
9785 MOV #WARM,X \ ['] WARM
9787 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
9789 \ ------------------------------\
9791 \ ------------------------------\
9792 CODE STOP \ stops multitasking, must to be used before downloading app
9793 \ ------------------------------\
9794 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
9795 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
9796 MOV X,-2(X) \ restore the default background: SLEEP
9798 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
9799 BIC.B #RC5,&IR_IE \ clear RC5_Int
9800 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
9801 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
9802 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
9803 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
9804 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
9805 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
9807 ." RC5toLCD is removed,"
9808 ." type START to restart"
9809 WARM \ performs reset to reset all interrupt vectors.
9811 \ ------------------------------\
9813 \ ------------------------------\
9814 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
9815 \ ------------------------------\
9816 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
9817 \ - - \CNTL Counter lentgh \ 00 = 16 bits
9818 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
9819 \ -- \ID input divider \ 10 = /4
9820 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
9821 \ - \TBCLR TimerB Clear
9824 \ -------------------------------\
9825 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
9826 \ -- \CM Capture Mode
9831 \ --- \OUTMOD \ 011 = set/reset
9837 \ -------------------------------\
9839 \ -------------------------------\
9841 \ ------------------------------\
9842 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
9843 \ ------------------------------\
9844 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
9845 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
9846 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
9847 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
9849 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
9850 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
9852 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
9853 \ ------------------------------\
9854 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
9855 \ ------------------------------\
9856 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
9857 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
9858 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
9859 \ ------------------------------\
9860 BIS.B #LCDVo,&LCDVo_DIR \
9861 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
9862 \ ------------------------------\
9863 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
9864 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
9865 \ ------------------------------\
9866 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
9867 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
9868 \ ******************************\
9870 \ ******************************\
9871 BIS.B #RC5,&IR_IE \ enable RC5_Int
9872 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
9873 MOV #RC5_INT,&IR_Vec \ init interrupt vector
9874 \ ******************************\
9875 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
9876 \ ******************************\
9877 \ %01 0001 0100 \ TAxCTL
9878 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
9879 \ -- \ ID divided by 1
9880 \ -- \ MC MODE = up to TAxCCRn
9881 \ - \ TACLR clear timer count
9884 \ ------------------------------\
9885 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
9886 \ ------------------------------\
9888 \ --- \ TAIDEX pre divisor
9889 \ ------------------------------\
9890 \ %0000 0000 0000 0101 \ TAxCCR0
9891 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
9892 \ ------------------------------\
9893 \ %0000 0000 0001 0000 \ TAxCCTL0
9894 \ - \ CAP capture/compare mode = compare
9897 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
9898 \ ------------------------------\
9899 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
9900 \ ------------------------------\
9901 \ define LPM mode for ACCEPT \
9902 \ ------------------------------\
9903 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
9904 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
9905 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
9906 \ ------------------------------\
9908 \ ------------------------------\
9909 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
9910 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
9911 \ ------------------------------\
9912 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
9913 \ ------------------------------\
9914 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
9915 \ CMP #2,Y \ Power_ON event
9916 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
9918 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
9920 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
9922 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
9924 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
9925 \ ------------------------------\
9927 \ ------------------------------\
9929 \ ------------------------------\
9930 #1000 20_US \ 1- wait 20 ms
9931 %011 TOP_LCD \ 2- send DB5=DB4=1
9932 #205 20_US \ 3- wait 4,1 ms
9933 %011 TOP_LCD \ 4- send again DB5=DB4=1
9934 #5 20_US \ 5- wait 0,1 ms
9935 %011 TOP_LCD \ 6- send again again DB5=DB4=1
9936 #2 20_US \ wait 40 us = LCD cycle
9937 %010 TOP_LCD \ 7- send DB5=1 DB4=0
9938 #2 20_US \ wait 40 us = LCD cycle
9939 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
9940 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
9941 LCD_CLEAR \ 10- "LCD_Clear"
9942 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
9943 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
9944 LCD_CLEAR \ 10- "LCD_Clear"
9945 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
9946 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
9947 CR ." I love you" \ display message on LCD
9948 ['] CR >BODY IS CR \ CR executes its default value
9949 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
9950 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
9951 PWR_STATE ABORT \ init DP and continues with ABORT
9953 \ ------------------------------\
9955 \ ------------------------------\
9956 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
9957 \ ------------------------------\
9958 MOV #SLEEP,X \ replace default background process SLEEP
9959 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
9960 MOV #WARM,X \ replace default WARM
9961 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
9962 MOV X,PC \ then execute new WARM
9964 \ ------------------------------\
9967 ; downloading RC5toLCD.4th is done
9968 RST_HERE ; this app is protected against <reset>
9973 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
9975 [UNDEFINED] MARKER [IF]
9976 \ https://forth-standard.org/standard/core/MARKER
9978 \ ( "<spaces>name" -- )
9979 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
9980 \ with the execution semantics defined below.
9982 \ name Execution: ( -- )
9983 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
9984 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
9985 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
9986 \ not necessarily provided. No other contextual information such as numeric base is affected
9991 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
9992 SUB #2,Y \ 1 Y = LFA
9993 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
9994 ADD #4,&DP \ 3 add 2 cells
9998 MOV @RSP+,IP \ -- PFA
9999 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
10000 MOV @TOS,&INIDP \ set DP value for RST_STATE
10002 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
10009 \ https://forth-standard.org/standard/core/Fetch
10010 \ @ c-addr -- char fetch char from memory
10017 [UNDEFINED] CONSTANT [IF]
10018 \ https://forth-standard.org/standard/core/CONSTANT
10019 \ CONSTANT <name> n -- define a Forth CONSTANT
10023 MOV TOS,-2(W) \ PFA = n
10030 [UNDEFINED] STATE [IF]
10031 \ https://forth-standard.org/standard/core/STATE
10032 \ STATE -- a-addr holds compiler state
10033 STATEADR CONSTANT STATE
10037 \ https://forth-standard.org/standard/core/Equal
10038 \ = x1 x2 -- flag test x1=x2
10045 XOR #-1,TOS \ 1 flag Z = 1
10050 [UNDEFINED] IF [IF]
10051 \ https://forth-standard.org/standard/core/IF
10052 \ IF -- IFadr initialize conditional forward branch
10053 CODE IF \ immediate
10056 MOV &DP,TOS \ -- HERE
10057 ADD #4,&DP \ compile one word, reserve one word
10058 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
10059 ADD #2,TOS \ -- HERE+2=IFadr
10064 [UNDEFINED] THEN [IF]
10065 \ https://forth-standard.org/standard/core/THEN
10066 \ THEN IFadr -- resolve forward branch
10067 CODE THEN \ immediate
10068 MOV &DP,0(TOS) \ -- IFadr
10074 [UNDEFINED] ELSE [IF]
10075 \ https://forth-standard.org/standard/core/ELSE
10076 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
10077 CODE ELSE \ immediate
10078 ADD #4,&DP \ make room to compile two words
10079 MOV &DP,W \ W=HERE+4
10081 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
10083 MOV W,TOS \ -- ELSEadr
10088 [UNDEFINED] DEFER [IF]
10089 \ https://forth-standard.org/standard/core/DEFER
10090 \ DEFER "<spaces>name" --
10091 \ Skip leading space delimiters. Parse name delimited by a space.
10092 \ Create a definition for name with the execution semantics defined below.
10094 \ name Execution: --
10095 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
10096 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
10100 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
10101 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
10107 [UNDEFINED] DEFER! [IF]
10108 \ https://forth-standard.org/standard/core/DEFERStore
10109 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
10110 CODE DEFER! \ xt2 xt1 --
10111 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
10117 [UNDEFINED] IS [IF]
10118 \ https://forth-standard.org/standard/core/IS
10121 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
10122 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
10123 \ or in a definition : ... ['] U. IS DISPLAY ...
10124 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
10126 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
10129 IF POSTPONE ['] POSTPONE DEFER!
10135 [UNDEFINED] >BODY [IF]
10136 \ https://forth-standard.org/standard/core/toBODY
10137 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
10144 \ CODE 20uS \ n -- 8MHz version
10145 \ BEGIN \ 4 + 16 ~ loop
10146 \ MOV #39,rDOCON \ 39
10153 \ MOV #XDOCON,rDOCON \ 2
10158 CODE 20_US \ n -- n * 20 us
10159 BEGIN \ here we presume that LCD_TIM_IFG = 1...
10161 BIT #1,&LCD_TIM_CTL \ 3
10162 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
10163 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
10165 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
10170 CODE TOP_LCD \ LCD Sample
10171 \ \ if write : %xxxx_WWWW --
10172 \ \ if read : -- %0000_RRRR
10173 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10174 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10175 0= IF \ write LCD bits pattern
10176 AND.B #LCD_DB,TOS \
10177 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10178 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10181 THEN \ read LCD bits pattern
10184 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10185 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10186 AND.B #LCD_DB,TOS \
10190 CODE LCD_WRC \ char -- Write Char
10191 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10193 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
10194 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
10195 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10196 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10197 COLON \ high level word starts here
10198 TOP_LCD 2 20_US \ write high nibble first
10202 CODE LCD_WRF \ func -- Write Fonction
10203 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10207 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
10208 : LCD_HOME $02 LCD_WRF 100 20_us ;
10210 \ [UNDEFINED] OR [IF]
10212 \ \ https://forth-standard.org/standard/core/OR
10213 \ \ C OR x1 x2 -- x3 logical OR
10221 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
10222 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
10223 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
10224 \ : LCD_FN_SET $20 OR LCD_WrF ;
10225 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
10226 \ : LCD_GOTO $80 OR LCD_WrF ;
10229 \ CODE LCD_RDS \ -- status Read Status
10230 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10231 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10232 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10233 \ COLON \ starts a FORTH word
10234 \ TOP_LCD 2 20_us \ -- %0000_HHHH
10235 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
10236 \ HI2LO \ switch from FORTH to assembler
10237 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
10238 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
10239 \ MOV @RSP+,IP \ restore IP saved by COLON
10243 \ CODE LCD_RDC \ -- char Read Char
10244 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10249 \ ******************************\
10250 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10251 \ ******************************\
10252 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10253 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
10254 BIT.B #SW2,&SW2_IN \ test switch S2
10255 0= IF \ case of switch S2 pressed
10256 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
10258 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
10261 BIT.B #SW1,&SW1_IN \ test switch S1 input
10262 0= IF \ case of Switch S1 pressed
10263 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
10265 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
10269 BW1 \ from quit on truncated RC5 message, repeated RC5 command
10273 \ ******************************\
10274 ASM RC5_INT \ wake up on Px.RC5 change interrupt
10275 \ ******************************\
10276 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10277 \ ******************************\
10278 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10279 \ \ SMclock = 8|16|24 MHz
10280 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
10281 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
10282 \ \ SR(9)=new Toggle bit memory (ADD on)
10283 \ ******************************\
10284 \ RC5_FirstStartBitHalfCycle: \
10285 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
10286 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10287 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
10288 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
10290 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
10291 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
10293 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
10294 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
10296 MOV #1778,X \ RC5_Period * 1us
10297 MOV #14,W \ count of loop
10299 \ ******************************\
10300 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
10301 \ ******************************\ |
10302 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10303 \ RC5_Compute_3/4_Period: \ |
10304 RRUM #1,X \ X=1/2 cycle |
10307 ADD X,Y \ Y=3/4 cycle
10308 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
10310 \ ******************************\
10311 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10312 \ ******************************\
10313 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10314 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
10315 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10316 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10317 SUB #1,W \ decrement count loop
10318 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
10319 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10320 0<> WHILE \ ----> out of loop ----+
10321 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10323 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
10324 CMP Y,X \ 1 | cycle time out of bound ?
10325 U>= IF \ 2 ^ | yes:
10326 BIC #$30,&RC5_TIM_CTL \ | | stop timer
10327 GOTO BW1 \ | | quit on truncated RC5 message
10329 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
10331 REPEAT \ ----> loop back --+ | with X = new RC5_period value
10332 \ ******************************\ |
10333 \ RC5_SampleEndOf: \ <---------------------+
10334 \ ******************************\
10335 BIC #$30,&RC5_TIM_CTL \ stop timer
10336 \ ******************************\
10337 \ RC5_ComputeNewRC5word \
10338 \ ******************************\
10339 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
10340 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
10341 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
10342 \ ******************************\
10343 \ RC5_ComputeC6bit \
10344 \ ******************************\
10345 BIT #BIT14,T \ test /C6 bit in T
10346 0= IF BIS #BIT6,X \ set C6 bit in X
10347 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
10348 \ ******************************\
10349 \ RC5_CommandByteIsDone \ -- BASE RC5_code
10350 \ ******************************\
10351 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10352 \ ******************************\
10353 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
10354 XOR @RSP,T \ (new XOR old) Toggle bits
10355 BIT #UF10,T \ repeated RC5_command ?
10356 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
10357 XOR #UF10,0(RSP) \ 5 toggle bit memory
10358 \ ******************************\
10359 \ Display IR_RC5 code \
10360 \ ******************************\
10361 SUB #8,PSP \ TOS -- x x x x TOS
10362 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
10363 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
10364 MOV #$10,&BASEADR \ set hexadecimal base
10365 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
10366 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
10367 LO2HI \ switch from assembler to FORTH
10368 LCD_CLEAR \ set LCD cursor at home
10369 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
10370 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
10371 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
10372 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
10373 HI2LO \ -- switch from FORTH to assembler
10374 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
10375 MOV @PSP+,TOS \ -- TOS
10379 \ ******************************\
10381 \ ******************************\
10383 \ ... \ insert here your background task
10386 CALL &RXON \ comment this line to disable TERMINAL_INPUT
10388 \ ******************************\
10389 \ here start all interrupts \
10390 \ ******************************\
10391 \ here return all interrupts \
10392 \ ******************************\
10395 \ ******************************\
10397 \ ------------------------------\
10398 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
10399 \ ------------------------------\
10400 \ ... \ init specific I/O sys as you want
10401 \ ... \ before executing default WARM
10402 MOV #WARM,X \ ['] WARM
10404 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
10406 \ ------------------------------\
10408 \ ------------------------------\
10409 CODE STOP \ stops multitasking, must to be used before downloading app
10410 \ ------------------------------\
10411 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
10412 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
10413 MOV X,-2(X) \ restore the default background: SLEEP
10415 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
10416 BIC.B #RC5,&IR_IE \ clear RC5_Int
10417 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
10418 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
10419 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
10420 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
10421 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
10422 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
10424 ." RC5toLCD is removed,"
10425 ." type START to restart"
10426 WARM \ performs reset to reset all interrupt vectors.
10428 \ ------------------------------\
10430 \ ------------------------------\
10431 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
10432 \ ------------------------------\
10433 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
10434 \ - - \CNTL Counter lentgh \ 00 = 16 bits
10435 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
10436 \ -- \ID input divider \ 10 = /4
10437 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
10438 \ - \TBCLR TimerB Clear
10441 \ -------------------------------\
10442 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
10443 \ -- \CM Capture Mode
10448 \ --- \OUTMOD \ 011 = set/reset
10454 \ -------------------------------\
10456 \ -------------------------------\
10458 \ ------------------------------\
10459 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
10460 \ ------------------------------\
10461 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
10462 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
10463 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
10464 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
10466 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
10467 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
10469 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
10470 \ ------------------------------\
10471 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
10472 \ ------------------------------\
10473 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
10474 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
10475 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
10476 \ ------------------------------\
10477 BIS.B #LCDVo,&LCDVo_DIR \
10478 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
10479 \ ------------------------------\
10480 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
10481 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
10482 \ ------------------------------\
10483 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
10484 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
10485 \ ******************************\
10487 \ ******************************\
10488 BIS.B #RC5,&IR_IE \ enable RC5_Int
10489 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
10490 MOV #RC5_INT,&IR_Vec \ init interrupt vector
10491 \ ******************************\
10492 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
10493 \ ******************************\
10494 \ %01 0001 0100 \ TAxCTL
10495 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
10496 \ -- \ ID divided by 1
10497 \ -- \ MC MODE = up to TAxCCRn
10498 \ - \ TACLR clear timer count
10501 \ ------------------------------\
10502 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
10503 \ ------------------------------\
10505 \ --- \ TAIDEX pre divisor
10506 \ ------------------------------\
10507 \ %0000 0000 0000 0101 \ TAxCCR0
10508 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
10509 \ ------------------------------\
10510 \ %0000 0000 0001 0000 \ TAxCCTL0
10511 \ - \ CAP capture/compare mode = compare
10514 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
10515 \ ------------------------------\
10516 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
10517 \ ------------------------------\
10518 \ define LPM mode for ACCEPT \
10519 \ ------------------------------\
10520 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
10521 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
10522 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
10523 \ ------------------------------\
10525 \ ------------------------------\
10526 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
10527 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
10528 \ ------------------------------\
10529 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
10530 \ ------------------------------\
10531 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
10532 \ CMP #2,Y \ Power_ON event
10533 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
10535 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
10537 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
10539 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
10541 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
10542 \ ------------------------------\
10544 \ ------------------------------\
10546 \ ------------------------------\
10547 #1000 20_US \ 1- wait 20 ms
10548 %011 TOP_LCD \ 2- send DB5=DB4=1
10549 #205 20_US \ 3- wait 4,1 ms
10550 %011 TOP_LCD \ 4- send again DB5=DB4=1
10551 #5 20_US \ 5- wait 0,1 ms
10552 %011 TOP_LCD \ 6- send again again DB5=DB4=1
10553 #2 20_US \ wait 40 us = LCD cycle
10554 %010 TOP_LCD \ 7- send DB5=1 DB4=0
10555 #2 20_US \ wait 40 us = LCD cycle
10556 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
10557 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
10558 LCD_CLEAR \ 10- "LCD_Clear"
10559 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
10560 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
10561 LCD_CLEAR \ 10- "LCD_Clear"
10562 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
10563 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
10564 CR ." I love you" \ display message on LCD
10565 ['] CR >BODY IS CR \ CR executes its default value
10566 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
10567 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
10568 PWR_STATE ABORT \ init DP and continues with ABORT
10570 \ ------------------------------\
10572 \ ------------------------------\
10573 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
10574 \ ------------------------------\
10575 MOV #SLEEP,X \ replace default background process SLEEP
10576 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
10577 MOV #WARM,X \ replace default WARM
10578 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
10579 MOV X,PC \ then execute new WARM
10581 \ ------------------------------\
10584 ; downloading RC5toLCD.4th is done
10585 RST_HERE ; this app is protected against <reset>
10590 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
10592 [UNDEFINED] MARKER [IF]
10593 \ https://forth-standard.org/standard/core/MARKER
10595 \ ( "<spaces>name" -- )
10596 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
10597 \ with the execution semantics defined below.
10599 \ name Execution: ( -- )
10600 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
10601 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
10602 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
10603 \ not necessarily provided. No other contextual information such as numeric base is affected
10608 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
10609 SUB #2,Y \ 1 Y = LFA
10610 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
10611 ADD #4,&DP \ 3 add 2 cells
10615 MOV @RSP+,IP \ -- PFA
10616 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
10617 MOV @TOS,&INIDP \ set DP value for RST_STATE
10619 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
10626 \ https://forth-standard.org/standard/core/Fetch
10627 \ @ c-addr -- char fetch char from memory
10634 [UNDEFINED] CONSTANT [IF]
10635 \ https://forth-standard.org/standard/core/CONSTANT
10636 \ CONSTANT <name> n -- define a Forth CONSTANT
10640 MOV TOS,-2(W) \ PFA = n
10647 [UNDEFINED] STATE [IF]
10648 \ https://forth-standard.org/standard/core/STATE
10649 \ STATE -- a-addr holds compiler state
10650 STATEADR CONSTANT STATE
10654 \ https://forth-standard.org/standard/core/Equal
10655 \ = x1 x2 -- flag test x1=x2
10662 XOR #-1,TOS \ 1 flag Z = 1
10667 [UNDEFINED] IF [IF]
10668 \ https://forth-standard.org/standard/core/IF
10669 \ IF -- IFadr initialize conditional forward branch
10670 CODE IF \ immediate
10673 MOV &DP,TOS \ -- HERE
10674 ADD #4,&DP \ compile one word, reserve one word
10675 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
10676 ADD #2,TOS \ -- HERE+2=IFadr
10681 [UNDEFINED] THEN [IF]
10682 \ https://forth-standard.org/standard/core/THEN
10683 \ THEN IFadr -- resolve forward branch
10684 CODE THEN \ immediate
10685 MOV &DP,0(TOS) \ -- IFadr
10691 [UNDEFINED] ELSE [IF]
10692 \ https://forth-standard.org/standard/core/ELSE
10693 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
10694 CODE ELSE \ immediate
10695 ADD #4,&DP \ make room to compile two words
10696 MOV &DP,W \ W=HERE+4
10698 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
10700 MOV W,TOS \ -- ELSEadr
10705 [UNDEFINED] DEFER [IF]
10706 \ https://forth-standard.org/standard/core/DEFER
10707 \ DEFER "<spaces>name" --
10708 \ Skip leading space delimiters. Parse name delimited by a space.
10709 \ Create a definition for name with the execution semantics defined below.
10711 \ name Execution: --
10712 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
10713 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
10717 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
10718 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
10724 [UNDEFINED] DEFER! [IF]
10725 \ https://forth-standard.org/standard/core/DEFERStore
10726 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
10727 CODE DEFER! \ xt2 xt1 --
10728 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
10734 [UNDEFINED] IS [IF]
10735 \ https://forth-standard.org/standard/core/IS
10738 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
10739 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
10740 \ or in a definition : ... ['] U. IS DISPLAY ...
10741 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
10743 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
10746 IF POSTPONE ['] POSTPONE DEFER!
10752 [UNDEFINED] >BODY [IF]
10753 \ https://forth-standard.org/standard/core/toBODY
10754 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
10761 \ CODE 20uS \ n -- 8MHz version
10762 \ BEGIN \ 4 + 16 ~ loop
10763 \ MOV #39,rDOCON \ 39
10770 \ MOV #XDOCON,rDOCON \ 2
10775 CODE 20_US \ n -- n * 20 us
10776 BEGIN \ here we presume that LCD_TIM_IFG = 1...
10778 BIT #1,&LCD_TIM_CTL \ 3
10779 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
10780 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
10782 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
10787 CODE TOP_LCD \ LCD Sample
10788 \ \ if write : %xxxx_WWWW --
10789 \ \ if read : -- %0000_RRRR
10790 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
10791 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
10792 0= IF \ write LCD bits pattern
10793 AND.B #LCD_DB,TOS \
10794 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
10795 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10798 THEN \ read LCD bits pattern
10801 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
10802 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
10803 AND.B #LCD_DB,TOS \
10807 CODE LCD_WRC \ char -- Write Char
10808 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10810 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
10811 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
10812 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
10813 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
10814 COLON \ high level word starts here
10815 TOP_LCD 2 20_US \ write high nibble first
10819 CODE LCD_WRF \ func -- Write Fonction
10820 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10824 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
10825 : LCD_HOME $02 LCD_WRF 100 20_us ;
10827 \ [UNDEFINED] OR [IF]
10829 \ \ https://forth-standard.org/standard/core/OR
10830 \ \ C OR x1 x2 -- x3 logical OR
10838 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
10839 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
10840 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
10841 \ : LCD_FN_SET $20 OR LCD_WrF ;
10842 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
10843 \ : LCD_GOTO $80 OR LCD_WrF ;
10846 \ CODE LCD_RDS \ -- status Read Status
10847 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
10848 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
10849 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
10850 \ COLON \ starts a FORTH word
10851 \ TOP_LCD 2 20_us \ -- %0000_HHHH
10852 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
10853 \ HI2LO \ switch from FORTH to assembler
10854 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
10855 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
10856 \ MOV @RSP+,IP \ restore IP saved by COLON
10860 \ CODE LCD_RDC \ -- char Read Char
10861 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
10866 \ ******************************\
10867 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
10868 \ ******************************\
10869 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10870 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
10871 BIT.B #SW2,&SW2_IN \ test switch S2
10872 0= IF \ case of switch S2 pressed
10873 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
10875 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
10878 BIT.B #SW1,&SW1_IN \ test switch S1 input
10879 0= IF \ case of Switch S1 pressed
10880 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
10882 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
10886 BW1 \ from quit on truncated RC5 message, repeated RC5 command
10890 \ ******************************\
10891 ASM RC5_INT \ wake up on Px.RC5 change interrupt
10892 \ ******************************\
10893 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
10894 \ ******************************\
10895 \ \ in : SR(9)=old Toggle bit memory (ADD on)
10896 \ \ SMclock = 8|16|24 MHz
10897 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
10898 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
10899 \ \ SR(9)=new Toggle bit memory (ADD on)
10900 \ ******************************\
10901 \ RC5_FirstStartBitHalfCycle: \
10902 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
10903 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
10904 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
10905 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
10907 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
10908 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
10910 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
10911 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
10913 MOV #1778,X \ RC5_Period * 1us
10914 MOV #14,W \ count of loop
10916 \ ******************************\
10917 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
10918 \ ******************************\ |
10919 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
10920 \ RC5_Compute_3/4_Period: \ |
10921 RRUM #1,X \ X=1/2 cycle |
10924 ADD X,Y \ Y=3/4 cycle
10925 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
10927 \ ******************************\
10928 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
10929 \ ******************************\
10930 BIT.B #RC5,&IR_IN \ C_flag = IR bit
10931 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
10932 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
10933 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
10934 SUB #1,W \ decrement count loop
10935 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
10936 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
10937 0<> WHILE \ ----> out of loop ----+
10938 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
10940 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
10941 CMP Y,X \ 1 | cycle time out of bound ?
10942 U>= IF \ 2 ^ | yes:
10943 BIC #$30,&RC5_TIM_CTL \ | | stop timer
10944 GOTO BW1 \ | | quit on truncated RC5 message
10946 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
10948 REPEAT \ ----> loop back --+ | with X = new RC5_period value
10949 \ ******************************\ |
10950 \ RC5_SampleEndOf: \ <---------------------+
10951 \ ******************************\
10952 BIC #$30,&RC5_TIM_CTL \ stop timer
10953 \ ******************************\
10954 \ RC5_ComputeNewRC5word \
10955 \ ******************************\
10956 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
10957 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
10958 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
10959 \ ******************************\
10960 \ RC5_ComputeC6bit \
10961 \ ******************************\
10962 BIT #BIT14,T \ test /C6 bit in T
10963 0= IF BIS #BIT6,X \ set C6 bit in X
10964 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
10965 \ ******************************\
10966 \ RC5_CommandByteIsDone \ -- BASE RC5_code
10967 \ ******************************\
10968 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
10969 \ ******************************\
10970 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
10971 XOR @RSP,T \ (new XOR old) Toggle bits
10972 BIT #UF10,T \ repeated RC5_command ?
10973 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
10974 XOR #UF10,0(RSP) \ 5 toggle bit memory
10975 \ ******************************\
10976 \ Display IR_RC5 code \
10977 \ ******************************\
10978 SUB #8,PSP \ TOS -- x x x x TOS
10979 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
10980 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
10981 MOV #$10,&BASEADR \ set hexadecimal base
10982 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
10983 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
10984 LO2HI \ switch from assembler to FORTH
10985 LCD_CLEAR \ set LCD cursor at home
10986 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
10987 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
10988 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
10989 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
10990 HI2LO \ -- switch from FORTH to assembler
10991 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
10992 MOV @PSP+,TOS \ -- TOS
10996 \ ******************************\
10998 \ ******************************\
11000 \ ... \ insert here your background task
11003 CALL &RXON \ comment this line to disable TERMINAL_INPUT
11005 \ ******************************\
11006 \ here start all interrupts \
11007 \ ******************************\
11008 \ here return all interrupts \
11009 \ ******************************\
11012 \ ******************************\
11014 \ ------------------------------\
11015 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
11016 \ ------------------------------\
11017 \ ... \ init specific I/O sys as you want
11018 \ ... \ before executing default WARM
11019 MOV #WARM,X \ ['] WARM
11021 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
11023 \ ------------------------------\
11025 \ ------------------------------\
11026 CODE STOP \ stops multitasking, must to be used before downloading app
11027 \ ------------------------------\
11028 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
11029 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
11030 MOV X,-2(X) \ restore the default background: SLEEP
11032 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
11033 BIC.B #RC5,&IR_IE \ clear RC5_Int
11034 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
11035 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
11036 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
11037 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
11038 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
11039 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
11041 ." RC5toLCD is removed,"
11042 ." type START to restart"
11043 WARM \ performs reset to reset all interrupt vectors.
11045 \ ------------------------------\
11047 \ ------------------------------\
11048 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
11049 \ ------------------------------\
11050 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
11051 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11052 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11053 \ -- \ID input divider \ 10 = /4
11054 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
11055 \ - \TBCLR TimerB Clear
11058 \ -------------------------------\
11059 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11060 \ -- \CM Capture Mode
11065 \ --- \OUTMOD \ 011 = set/reset
11071 \ -------------------------------\
11073 \ -------------------------------\
11075 \ ------------------------------\
11076 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
11077 \ ------------------------------\
11078 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
11079 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
11080 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
11081 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
11083 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
11084 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
11086 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
11087 \ ------------------------------\
11088 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
11089 \ ------------------------------\
11090 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
11091 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
11092 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11093 \ ------------------------------\
11094 BIS.B #LCDVo,&LCDVo_DIR \
11095 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
11096 \ ------------------------------\
11097 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11098 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11099 \ ------------------------------\
11100 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11101 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11102 \ ******************************\
11104 \ ******************************\
11105 BIS.B #RC5,&IR_IE \ enable RC5_Int
11106 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11107 MOV #RC5_INT,&IR_Vec \ init interrupt vector
11108 \ ******************************\
11109 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
11110 \ ******************************\
11111 \ %01 0001 0100 \ TAxCTL
11112 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
11113 \ -- \ ID divided by 1
11114 \ -- \ MC MODE = up to TAxCCRn
11115 \ - \ TACLR clear timer count
11118 \ ------------------------------\
11119 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
11120 \ ------------------------------\
11122 \ --- \ TAIDEX pre divisor
11123 \ ------------------------------\
11124 \ %0000 0000 0000 0101 \ TAxCCR0
11125 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
11126 \ ------------------------------\
11127 \ %0000 0000 0001 0000 \ TAxCCTL0
11128 \ - \ CAP capture/compare mode = compare
11131 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
11132 \ ------------------------------\
11133 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11134 \ ------------------------------\
11135 \ define LPM mode for ACCEPT \
11136 \ ------------------------------\
11137 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11138 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11139 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11140 \ ------------------------------\
11142 \ ------------------------------\
11143 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
11144 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
11145 \ ------------------------------\
11146 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
11147 \ ------------------------------\
11148 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
11149 \ CMP #2,Y \ Power_ON event
11150 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
11152 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
11154 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
11156 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
11158 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
11159 \ ------------------------------\
11161 \ ------------------------------\
11163 \ ------------------------------\
11164 #1000 20_US \ 1- wait 20 ms
11165 %011 TOP_LCD \ 2- send DB5=DB4=1
11166 #205 20_US \ 3- wait 4,1 ms
11167 %011 TOP_LCD \ 4- send again DB5=DB4=1
11168 #5 20_US \ 5- wait 0,1 ms
11169 %011 TOP_LCD \ 6- send again again DB5=DB4=1
11170 #2 20_US \ wait 40 us = LCD cycle
11171 %010 TOP_LCD \ 7- send DB5=1 DB4=0
11172 #2 20_US \ wait 40 us = LCD cycle
11173 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11174 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11175 LCD_CLEAR \ 10- "LCD_Clear"
11176 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11177 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11178 LCD_CLEAR \ 10- "LCD_Clear"
11179 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11180 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11181 CR ." I love you" \ display message on LCD
11182 ['] CR >BODY IS CR \ CR executes its default value
11183 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
11184 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11185 PWR_STATE ABORT \ init DP and continues with ABORT
11187 \ ------------------------------\
11189 \ ------------------------------\
11190 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
11191 \ ------------------------------\
11192 MOV #SLEEP,X \ replace default background process SLEEP
11193 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
11194 MOV #WARM,X \ replace default WARM
11195 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
11196 MOV X,PC \ then execute new WARM
11198 \ ------------------------------\
11201 ; downloading RC5toLCD.4th is done
11202 RST_HERE ; this app is protected against <reset>
11207 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
11209 [UNDEFINED] MARKER [IF]
11210 \ https://forth-standard.org/standard/core/MARKER
11212 \ ( "<spaces>name" -- )
11213 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
11214 \ with the execution semantics defined below.
11216 \ name Execution: ( -- )
11217 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
11218 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
11219 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
11220 \ not necessarily provided. No other contextual information such as numeric base is affected
11225 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
11226 SUB #2,Y \ 1 Y = LFA
11227 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
11228 ADD #4,&DP \ 3 add 2 cells
11232 MOV @RSP+,IP \ -- PFA
11233 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
11234 MOV @TOS,&INIDP \ set DP value for RST_STATE
11236 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
11243 \ https://forth-standard.org/standard/core/Fetch
11244 \ @ c-addr -- char fetch char from memory
11251 [UNDEFINED] CONSTANT [IF]
11252 \ https://forth-standard.org/standard/core/CONSTANT
11253 \ CONSTANT <name> n -- define a Forth CONSTANT
11257 MOV TOS,-2(W) \ PFA = n
11264 [UNDEFINED] STATE [IF]
11265 \ https://forth-standard.org/standard/core/STATE
11266 \ STATE -- a-addr holds compiler state
11267 STATEADR CONSTANT STATE
11271 \ https://forth-standard.org/standard/core/Equal
11272 \ = x1 x2 -- flag test x1=x2
11279 XOR #-1,TOS \ 1 flag Z = 1
11284 [UNDEFINED] IF [IF]
11285 \ https://forth-standard.org/standard/core/IF
11286 \ IF -- IFadr initialize conditional forward branch
11287 CODE IF \ immediate
11290 MOV &DP,TOS \ -- HERE
11291 ADD #4,&DP \ compile one word, reserve one word
11292 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
11293 ADD #2,TOS \ -- HERE+2=IFadr
11298 [UNDEFINED] THEN [IF]
11299 \ https://forth-standard.org/standard/core/THEN
11300 \ THEN IFadr -- resolve forward branch
11301 CODE THEN \ immediate
11302 MOV &DP,0(TOS) \ -- IFadr
11308 [UNDEFINED] ELSE [IF]
11309 \ https://forth-standard.org/standard/core/ELSE
11310 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
11311 CODE ELSE \ immediate
11312 ADD #4,&DP \ make room to compile two words
11313 MOV &DP,W \ W=HERE+4
11315 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
11317 MOV W,TOS \ -- ELSEadr
11322 [UNDEFINED] DEFER [IF]
11323 \ https://forth-standard.org/standard/core/DEFER
11324 \ DEFER "<spaces>name" --
11325 \ Skip leading space delimiters. Parse name delimited by a space.
11326 \ Create a definition for name with the execution semantics defined below.
11328 \ name Execution: --
11329 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
11330 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
11334 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
11335 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
11341 [UNDEFINED] DEFER! [IF]
11342 \ https://forth-standard.org/standard/core/DEFERStore
11343 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
11344 CODE DEFER! \ xt2 xt1 --
11345 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
11351 [UNDEFINED] IS [IF]
11352 \ https://forth-standard.org/standard/core/IS
11355 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
11356 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
11357 \ or in a definition : ... ['] U. IS DISPLAY ...
11358 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
11360 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
11363 IF POSTPONE ['] POSTPONE DEFER!
11369 [UNDEFINED] >BODY [IF]
11370 \ https://forth-standard.org/standard/core/toBODY
11371 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
11378 \ CODE 20uS \ n -- 8MHz version
11379 \ BEGIN \ 4 + 16 ~ loop
11380 \ MOV #39,rDOCON \ 39
11387 \ MOV #XDOCON,rDOCON \ 2
11392 CODE 20_US \ n -- n * 20 us
11393 BEGIN \ here we presume that LCD_TIM_IFG = 1...
11395 BIT #1,&LCD_TIM_CTL \ 3
11396 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
11397 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
11399 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
11404 CODE TOP_LCD \ LCD Sample
11405 \ \ if write : %xxxx_WWWW --
11406 \ \ if read : -- %0000_RRRR
11407 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
11408 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
11409 0= IF \ write LCD bits pattern
11410 AND.B #LCD_DB,TOS \
11411 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
11412 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11415 THEN \ read LCD bits pattern
11418 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
11419 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
11420 AND.B #LCD_DB,TOS \
11424 CODE LCD_WRC \ char -- Write Char
11425 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11427 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
11428 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
11429 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
11430 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
11431 COLON \ high level word starts here
11432 TOP_LCD 2 20_US \ write high nibble first
11436 CODE LCD_WRF \ func -- Write Fonction
11437 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11441 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
11442 : LCD_HOME $02 LCD_WRF 100 20_us ;
11444 \ [UNDEFINED] OR [IF]
11446 \ \ https://forth-standard.org/standard/core/OR
11447 \ \ C OR x1 x2 -- x3 logical OR
11455 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
11456 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
11457 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
11458 \ : LCD_FN_SET $20 OR LCD_WrF ;
11459 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
11460 \ : LCD_GOTO $80 OR LCD_WrF ;
11463 \ CODE LCD_RDS \ -- status Read Status
11464 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
11465 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
11466 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
11467 \ COLON \ starts a FORTH word
11468 \ TOP_LCD 2 20_us \ -- %0000_HHHH
11469 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
11470 \ HI2LO \ switch from FORTH to assembler
11471 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
11472 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
11473 \ MOV @RSP+,IP \ restore IP saved by COLON
11477 \ CODE LCD_RDC \ -- char Read Char
11478 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
11483 \ ******************************\
11484 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
11485 \ ******************************\
11486 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
11487 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
11488 BIT.B #SW2,&SW2_IN \ test switch S2
11489 0= IF \ case of switch S2 pressed
11490 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
11492 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
11495 BIT.B #SW1,&SW1_IN \ test switch S1 input
11496 0= IF \ case of Switch S1 pressed
11497 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
11499 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
11503 BW1 \ from quit on truncated RC5 message, repeated RC5 command
11507 \ ******************************\
11508 ASM RC5_INT \ wake up on Px.RC5 change interrupt
11509 \ ******************************\
11510 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
11511 \ ******************************\
11512 \ \ in : SR(9)=old Toggle bit memory (ADD on)
11513 \ \ SMclock = 8|16|24 MHz
11514 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
11515 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
11516 \ \ SR(9)=new Toggle bit memory (ADD on)
11517 \ ******************************\
11518 \ RC5_FirstStartBitHalfCycle: \
11519 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
11520 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
11521 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
11522 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
11524 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
11525 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
11527 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
11528 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
11530 MOV #1778,X \ RC5_Period * 1us
11531 MOV #14,W \ count of loop
11533 \ ******************************\
11534 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
11535 \ ******************************\ |
11536 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
11537 \ RC5_Compute_3/4_Period: \ |
11538 RRUM #1,X \ X=1/2 cycle |
11541 ADD X,Y \ Y=3/4 cycle
11542 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
11544 \ ******************************\
11545 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
11546 \ ******************************\
11547 BIT.B #RC5,&IR_IN \ C_flag = IR bit
11548 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
11549 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
11550 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
11551 SUB #1,W \ decrement count loop
11552 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
11553 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
11554 0<> WHILE \ ----> out of loop ----+
11555 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
11557 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
11558 CMP Y,X \ 1 | cycle time out of bound ?
11559 U>= IF \ 2 ^ | yes:
11560 BIC #$30,&RC5_TIM_CTL \ | | stop timer
11561 GOTO BW1 \ | | quit on truncated RC5 message
11563 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
11565 REPEAT \ ----> loop back --+ | with X = new RC5_period value
11566 \ ******************************\ |
11567 \ RC5_SampleEndOf: \ <---------------------+
11568 \ ******************************\
11569 BIC #$30,&RC5_TIM_CTL \ stop timer
11570 \ ******************************\
11571 \ RC5_ComputeNewRC5word \
11572 \ ******************************\
11573 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
11574 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
11575 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
11576 \ ******************************\
11577 \ RC5_ComputeC6bit \
11578 \ ******************************\
11579 BIT #BIT14,T \ test /C6 bit in T
11580 0= IF BIS #BIT6,X \ set C6 bit in X
11581 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
11582 \ ******************************\
11583 \ RC5_CommandByteIsDone \ -- BASE RC5_code
11584 \ ******************************\
11585 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
11586 \ ******************************\
11587 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
11588 XOR @RSP,T \ (new XOR old) Toggle bits
11589 BIT #UF10,T \ repeated RC5_command ?
11590 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
11591 XOR #UF10,0(RSP) \ 5 toggle bit memory
11592 \ ******************************\
11593 \ Display IR_RC5 code \
11594 \ ******************************\
11595 SUB #8,PSP \ TOS -- x x x x TOS
11596 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
11597 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
11598 MOV #$10,&BASEADR \ set hexadecimal base
11599 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
11600 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
11601 LO2HI \ switch from assembler to FORTH
11602 LCD_CLEAR \ set LCD cursor at home
11603 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
11604 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
11605 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
11606 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
11607 HI2LO \ -- switch from FORTH to assembler
11608 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
11609 MOV @PSP+,TOS \ -- TOS
11613 \ ******************************\
11615 \ ******************************\
11617 \ ... \ insert here your background task
11620 CALL &RXON \ comment this line to disable TERMINAL_INPUT
11622 \ ******************************\
11623 \ here start all interrupts \
11624 \ ******************************\
11625 \ here return all interrupts \
11626 \ ******************************\
11629 \ ******************************\
11631 \ ------------------------------\
11632 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
11633 \ ------------------------------\
11634 \ ... \ init specific I/O sys as you want
11635 \ ... \ before executing default WARM
11636 MOV #WARM,X \ ['] WARM
11638 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
11640 \ ------------------------------\
11642 \ ------------------------------\
11643 CODE STOP \ stops multitasking, must to be used before downloading app
11644 \ ------------------------------\
11645 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
11646 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
11647 MOV X,-2(X) \ restore the default background: SLEEP
11649 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
11650 BIC.B #RC5,&IR_IE \ clear RC5_Int
11651 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
11652 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
11653 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
11654 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
11655 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
11656 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
11658 ." RC5toLCD is removed,"
11659 ." type START to restart"
11660 WARM \ performs reset to reset all interrupt vectors.
11662 \ ------------------------------\
11664 \ ------------------------------\
11665 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
11666 \ ------------------------------\
11667 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
11668 \ - - \CNTL Counter lentgh \ 00 = 16 bits
11669 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
11670 \ -- \ID input divider \ 10 = /4
11671 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
11672 \ - \TBCLR TimerB Clear
11675 \ -------------------------------\
11676 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
11677 \ -- \CM Capture Mode
11682 \ --- \OUTMOD \ 011 = set/reset
11688 \ -------------------------------\
11690 \ -------------------------------\
11692 \ ------------------------------\
11693 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
11694 \ ------------------------------\
11695 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
11696 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
11697 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
11698 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
11700 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
11701 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
11703 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
11704 \ ------------------------------\
11705 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
11706 \ ------------------------------\
11707 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
11708 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
11709 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
11710 \ ------------------------------\
11711 BIS.B #LCDVo,&LCDVo_DIR \
11712 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
11713 \ ------------------------------\
11714 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
11715 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
11716 \ ------------------------------\
11717 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
11718 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
11719 \ ******************************\
11721 \ ******************************\
11722 BIS.B #RC5,&IR_IE \ enable RC5_Int
11723 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
11724 MOV #RC5_INT,&IR_Vec \ init interrupt vector
11725 \ ******************************\
11726 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
11727 \ ******************************\
11728 \ %01 0001 0100 \ TAxCTL
11729 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
11730 \ -- \ ID divided by 1
11731 \ -- \ MC MODE = up to TAxCCRn
11732 \ - \ TACLR clear timer count
11735 \ ------------------------------\
11736 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
11737 \ ------------------------------\
11739 \ --- \ TAIDEX pre divisor
11740 \ ------------------------------\
11741 \ %0000 0000 0000 0101 \ TAxCCR0
11742 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
11743 \ ------------------------------\
11744 \ %0000 0000 0001 0000 \ TAxCCTL0
11745 \ - \ CAP capture/compare mode = compare
11748 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
11749 \ ------------------------------\
11750 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
11751 \ ------------------------------\
11752 \ define LPM mode for ACCEPT \
11753 \ ------------------------------\
11754 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
11755 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
11756 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
11757 \ ------------------------------\
11759 \ ------------------------------\
11760 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
11761 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
11762 \ ------------------------------\
11763 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
11764 \ ------------------------------\
11765 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
11766 \ CMP #2,Y \ Power_ON event
11767 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
11769 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
11771 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
11773 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
11775 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
11776 \ ------------------------------\
11778 \ ------------------------------\
11780 \ ------------------------------\
11781 #1000 20_US \ 1- wait 20 ms
11782 %011 TOP_LCD \ 2- send DB5=DB4=1
11783 #205 20_US \ 3- wait 4,1 ms
11784 %011 TOP_LCD \ 4- send again DB5=DB4=1
11785 #5 20_US \ 5- wait 0,1 ms
11786 %011 TOP_LCD \ 6- send again again DB5=DB4=1
11787 #2 20_US \ wait 40 us = LCD cycle
11788 %010 TOP_LCD \ 7- send DB5=1 DB4=0
11789 #2 20_US \ wait 40 us = LCD cycle
11790 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
11791 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
11792 LCD_CLEAR \ 10- "LCD_Clear"
11793 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
11794 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
11795 LCD_CLEAR \ 10- "LCD_Clear"
11796 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
11797 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
11798 CR ." I love you" \ display message on LCD
11799 ['] CR >BODY IS CR \ CR executes its default value
11800 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
11801 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
11802 PWR_STATE ABORT \ init DP and continues with ABORT
11804 \ ------------------------------\
11806 \ ------------------------------\
11807 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
11808 \ ------------------------------\
11809 MOV #SLEEP,X \ replace default background process SLEEP
11810 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
11811 MOV #WARM,X \ replace default WARM
11812 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
11813 MOV X,PC \ then execute new WARM
11815 \ ------------------------------\
11818 ; downloading RC5toLCD.4th is done
11819 RST_HERE ; this app is protected against <reset>
11824 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
11826 [UNDEFINED] MARKER [IF]
11827 \ https://forth-standard.org/standard/core/MARKER
11829 \ ( "<spaces>name" -- )
11830 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
11831 \ with the execution semantics defined below.
11833 \ name Execution: ( -- )
11834 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
11835 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
11836 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
11837 \ not necessarily provided. No other contextual information such as numeric base is affected
11842 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
11843 SUB #2,Y \ 1 Y = LFA
11844 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
11845 ADD #4,&DP \ 3 add 2 cells
11849 MOV @RSP+,IP \ -- PFA
11850 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
11851 MOV @TOS,&INIDP \ set DP value for RST_STATE
11853 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
11860 \ https://forth-standard.org/standard/core/Fetch
11861 \ @ c-addr -- char fetch char from memory
11868 [UNDEFINED] CONSTANT [IF]
11869 \ https://forth-standard.org/standard/core/CONSTANT
11870 \ CONSTANT <name> n -- define a Forth CONSTANT
11874 MOV TOS,-2(W) \ PFA = n
11881 [UNDEFINED] STATE [IF]
11882 \ https://forth-standard.org/standard/core/STATE
11883 \ STATE -- a-addr holds compiler state
11884 STATEADR CONSTANT STATE
11888 \ https://forth-standard.org/standard/core/Equal
11889 \ = x1 x2 -- flag test x1=x2
11896 XOR #-1,TOS \ 1 flag Z = 1
11901 [UNDEFINED] IF [IF]
11902 \ https://forth-standard.org/standard/core/IF
11903 \ IF -- IFadr initialize conditional forward branch
11904 CODE IF \ immediate
11907 MOV &DP,TOS \ -- HERE
11908 ADD #4,&DP \ compile one word, reserve one word
11909 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
11910 ADD #2,TOS \ -- HERE+2=IFadr
11915 [UNDEFINED] THEN [IF]
11916 \ https://forth-standard.org/standard/core/THEN
11917 \ THEN IFadr -- resolve forward branch
11918 CODE THEN \ immediate
11919 MOV &DP,0(TOS) \ -- IFadr
11925 [UNDEFINED] ELSE [IF]
11926 \ https://forth-standard.org/standard/core/ELSE
11927 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
11928 CODE ELSE \ immediate
11929 ADD #4,&DP \ make room to compile two words
11930 MOV &DP,W \ W=HERE+4
11932 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
11934 MOV W,TOS \ -- ELSEadr
11939 [UNDEFINED] DEFER [IF]
11940 \ https://forth-standard.org/standard/core/DEFER
11941 \ DEFER "<spaces>name" --
11942 \ Skip leading space delimiters. Parse name delimited by a space.
11943 \ Create a definition for name with the execution semantics defined below.
11945 \ name Execution: --
11946 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
11947 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
11951 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
11952 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
11958 [UNDEFINED] DEFER! [IF]
11959 \ https://forth-standard.org/standard/core/DEFERStore
11960 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
11961 CODE DEFER! \ xt2 xt1 --
11962 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
11968 [UNDEFINED] IS [IF]
11969 \ https://forth-standard.org/standard/core/IS
11972 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
11973 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
11974 \ or in a definition : ... ['] U. IS DISPLAY ...
11975 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
11977 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
11980 IF POSTPONE ['] POSTPONE DEFER!
11986 [UNDEFINED] >BODY [IF]
11987 \ https://forth-standard.org/standard/core/toBODY
11988 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
11995 \ CODE 20uS \ n -- 8MHz version
11996 \ BEGIN \ 4 + 16 ~ loop
11997 \ MOV #39,rDOCON \ 39
12004 \ MOV #XDOCON,rDOCON \ 2
12009 CODE 20_US \ n -- n * 20 us
12010 BEGIN \ here we presume that LCD_TIM_IFG = 1...
12012 BIT #1,&LCD_TIM_CTL \ 3
12013 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
12014 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
12016 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
12021 CODE TOP_LCD \ LCD Sample
12022 \ \ if write : %xxxx_WWWW --
12023 \ \ if read : -- %0000_RRRR
12024 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12025 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12026 0= IF \ write LCD bits pattern
12027 AND.B #LCD_DB,TOS \
12028 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12029 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12032 THEN \ read LCD bits pattern
12035 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12036 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12037 AND.B #LCD_DB,TOS \
12041 CODE LCD_WRC \ char -- Write Char
12042 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12044 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
12045 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
12046 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12047 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12048 COLON \ high level word starts here
12049 TOP_LCD 2 20_US \ write high nibble first
12053 CODE LCD_WRF \ func -- Write Fonction
12054 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12058 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
12059 : LCD_HOME $02 LCD_WRF 100 20_us ;
12061 \ [UNDEFINED] OR [IF]
12063 \ \ https://forth-standard.org/standard/core/OR
12064 \ \ C OR x1 x2 -- x3 logical OR
12072 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
12073 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
12074 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
12075 \ : LCD_FN_SET $20 OR LCD_WrF ;
12076 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
12077 \ : LCD_GOTO $80 OR LCD_WrF ;
12080 \ CODE LCD_RDS \ -- status Read Status
12081 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12082 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12083 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12084 \ COLON \ starts a FORTH word
12085 \ TOP_LCD 2 20_us \ -- %0000_HHHH
12086 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
12087 \ HI2LO \ switch from FORTH to assembler
12088 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
12089 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
12090 \ MOV @RSP+,IP \ restore IP saved by COLON
12094 \ CODE LCD_RDC \ -- char Read Char
12095 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12100 \ ******************************\
12101 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12102 \ ******************************\
12103 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12104 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
12105 BIT.B #SW2,&SW2_IN \ test switch S2
12106 0= IF \ case of switch S2 pressed
12107 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12109 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
12112 BIT.B #SW1,&SW1_IN \ test switch S1 input
12113 0= IF \ case of Switch S1 pressed
12114 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12116 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12120 BW1 \ from quit on truncated RC5 message, repeated RC5 command
12124 \ ******************************\
12125 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12126 \ ******************************\
12127 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12128 \ ******************************\
12129 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12130 \ \ SMclock = 8|16|24 MHz
12131 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12132 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12133 \ \ SR(9)=new Toggle bit memory (ADD on)
12134 \ ******************************\
12135 \ RC5_FirstStartBitHalfCycle: \
12136 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12137 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12138 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
12139 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
12141 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
12142 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
12144 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
12145 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
12147 MOV #1778,X \ RC5_Period * 1us
12148 MOV #14,W \ count of loop
12150 \ ******************************\
12151 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
12152 \ ******************************\ |
12153 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12154 \ RC5_Compute_3/4_Period: \ |
12155 RRUM #1,X \ X=1/2 cycle |
12158 ADD X,Y \ Y=3/4 cycle
12159 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
12161 \ ******************************\
12162 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12163 \ ******************************\
12164 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12165 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
12166 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12167 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12168 SUB #1,W \ decrement count loop
12169 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
12170 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12171 0<> WHILE \ ----> out of loop ----+
12172 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12174 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
12175 CMP Y,X \ 1 | cycle time out of bound ?
12176 U>= IF \ 2 ^ | yes:
12177 BIC #$30,&RC5_TIM_CTL \ | | stop timer
12178 GOTO BW1 \ | | quit on truncated RC5 message
12180 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
12182 REPEAT \ ----> loop back --+ | with X = new RC5_period value
12183 \ ******************************\ |
12184 \ RC5_SampleEndOf: \ <---------------------+
12185 \ ******************************\
12186 BIC #$30,&RC5_TIM_CTL \ stop timer
12187 \ ******************************\
12188 \ RC5_ComputeNewRC5word \
12189 \ ******************************\
12190 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
12191 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
12192 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
12193 \ ******************************\
12194 \ RC5_ComputeC6bit \
12195 \ ******************************\
12196 BIT #BIT14,T \ test /C6 bit in T
12197 0= IF BIS #BIT6,X \ set C6 bit in X
12198 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
12199 \ ******************************\
12200 \ RC5_CommandByteIsDone \ -- BASE RC5_code
12201 \ ******************************\
12202 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12203 \ ******************************\
12204 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
12205 XOR @RSP,T \ (new XOR old) Toggle bits
12206 BIT #UF10,T \ repeated RC5_command ?
12207 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
12208 XOR #UF10,0(RSP) \ 5 toggle bit memory
12209 \ ******************************\
12210 \ Display IR_RC5 code \
12211 \ ******************************\
12212 SUB #8,PSP \ TOS -- x x x x TOS
12213 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
12214 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
12215 MOV #$10,&BASEADR \ set hexadecimal base
12216 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
12217 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
12218 LO2HI \ switch from assembler to FORTH
12219 LCD_CLEAR \ set LCD cursor at home
12220 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
12221 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
12222 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
12223 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
12224 HI2LO \ -- switch from FORTH to assembler
12225 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
12226 MOV @PSP+,TOS \ -- TOS
12230 \ ******************************\
12232 \ ******************************\
12234 \ ... \ insert here your background task
12237 CALL &RXON \ comment this line to disable TERMINAL_INPUT
12239 \ ******************************\
12240 \ here start all interrupts \
12241 \ ******************************\
12242 \ here return all interrupts \
12243 \ ******************************\
12246 \ ******************************\
12248 \ ------------------------------\
12249 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
12250 \ ------------------------------\
12251 \ ... \ init specific I/O sys as you want
12252 \ ... \ before executing default WARM
12253 MOV #WARM,X \ ['] WARM
12255 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
12257 \ ------------------------------\
12259 \ ------------------------------\
12260 CODE STOP \ stops multitasking, must to be used before downloading app
12261 \ ------------------------------\
12262 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
12263 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
12264 MOV X,-2(X) \ restore the default background: SLEEP
12266 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
12267 BIC.B #RC5,&IR_IE \ clear RC5_Int
12268 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
12269 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
12270 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
12271 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
12272 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
12273 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
12275 ." RC5toLCD is removed,"
12276 ." type START to restart"
12277 WARM \ performs reset to reset all interrupt vectors.
12279 \ ------------------------------\
12281 \ ------------------------------\
12282 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
12283 \ ------------------------------\
12284 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
12285 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12286 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12287 \ -- \ID input divider \ 10 = /4
12288 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12289 \ - \TBCLR TimerB Clear
12292 \ -------------------------------\
12293 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12294 \ -- \CM Capture Mode
12299 \ --- \OUTMOD \ 011 = set/reset
12305 \ -------------------------------\
12307 \ -------------------------------\
12309 \ ------------------------------\
12310 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
12311 \ ------------------------------\
12312 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
12313 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
12314 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
12315 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
12317 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
12318 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
12320 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
12321 \ ------------------------------\
12322 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
12323 \ ------------------------------\
12324 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
12325 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
12326 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12327 \ ------------------------------\
12328 BIS.B #LCDVo,&LCDVo_DIR \
12329 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
12330 \ ------------------------------\
12331 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12332 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12333 \ ------------------------------\
12334 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12335 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12336 \ ******************************\
12338 \ ******************************\
12339 BIS.B #RC5,&IR_IE \ enable RC5_Int
12340 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12341 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12342 \ ******************************\
12343 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
12344 \ ******************************\
12345 \ %01 0001 0100 \ TAxCTL
12346 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
12347 \ -- \ ID divided by 1
12348 \ -- \ MC MODE = up to TAxCCRn
12349 \ - \ TACLR clear timer count
12352 \ ------------------------------\
12353 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
12354 \ ------------------------------\
12356 \ --- \ TAIDEX pre divisor
12357 \ ------------------------------\
12358 \ %0000 0000 0000 0101 \ TAxCCR0
12359 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
12360 \ ------------------------------\
12361 \ %0000 0000 0001 0000 \ TAxCCTL0
12362 \ - \ CAP capture/compare mode = compare
12365 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
12366 \ ------------------------------\
12367 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
12368 \ ------------------------------\
12369 \ define LPM mode for ACCEPT \
12370 \ ------------------------------\
12371 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12372 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12373 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12374 \ ------------------------------\
12376 \ ------------------------------\
12377 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
12378 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
12379 \ ------------------------------\
12380 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
12381 \ ------------------------------\
12382 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
12383 \ CMP #2,Y \ Power_ON event
12384 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
12386 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
12388 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
12390 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
12392 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
12393 \ ------------------------------\
12395 \ ------------------------------\
12397 \ ------------------------------\
12398 #1000 20_US \ 1- wait 20 ms
12399 %011 TOP_LCD \ 2- send DB5=DB4=1
12400 #205 20_US \ 3- wait 4,1 ms
12401 %011 TOP_LCD \ 4- send again DB5=DB4=1
12402 #5 20_US \ 5- wait 0,1 ms
12403 %011 TOP_LCD \ 6- send again again DB5=DB4=1
12404 #2 20_US \ wait 40 us = LCD cycle
12405 %010 TOP_LCD \ 7- send DB5=1 DB4=0
12406 #2 20_US \ wait 40 us = LCD cycle
12407 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
12408 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
12409 LCD_CLEAR \ 10- "LCD_Clear"
12410 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
12411 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
12412 LCD_CLEAR \ 10- "LCD_Clear"
12413 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
12414 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
12415 CR ." I love you" \ display message on LCD
12416 ['] CR >BODY IS CR \ CR executes its default value
12417 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
12418 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
12419 PWR_STATE ABORT \ init DP and continues with ABORT
12421 \ ------------------------------\
12423 \ ------------------------------\
12424 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
12425 \ ------------------------------\
12426 MOV #SLEEP,X \ replace default background process SLEEP
12427 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
12428 MOV #WARM,X \ replace default WARM
12429 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
12430 MOV X,PC \ then execute new WARM
12432 \ ------------------------------\
12435 ; downloading RC5toLCD.4th is done
12436 RST_HERE ; this app is protected against <reset>
12441 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
12443 [UNDEFINED] MARKER [IF]
12444 \ https://forth-standard.org/standard/core/MARKER
12446 \ ( "<spaces>name" -- )
12447 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
12448 \ with the execution semantics defined below.
12450 \ name Execution: ( -- )
12451 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
12452 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
12453 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
12454 \ not necessarily provided. No other contextual information such as numeric base is affected
12459 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
12460 SUB #2,Y \ 1 Y = LFA
12461 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
12462 ADD #4,&DP \ 3 add 2 cells
12466 MOV @RSP+,IP \ -- PFA
12467 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
12468 MOV @TOS,&INIDP \ set DP value for RST_STATE
12470 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
12477 \ https://forth-standard.org/standard/core/Fetch
12478 \ @ c-addr -- char fetch char from memory
12485 [UNDEFINED] CONSTANT [IF]
12486 \ https://forth-standard.org/standard/core/CONSTANT
12487 \ CONSTANT <name> n -- define a Forth CONSTANT
12491 MOV TOS,-2(W) \ PFA = n
12498 [UNDEFINED] STATE [IF]
12499 \ https://forth-standard.org/standard/core/STATE
12500 \ STATE -- a-addr holds compiler state
12501 STATEADR CONSTANT STATE
12505 \ https://forth-standard.org/standard/core/Equal
12506 \ = x1 x2 -- flag test x1=x2
12513 XOR #-1,TOS \ 1 flag Z = 1
12518 [UNDEFINED] IF [IF]
12519 \ https://forth-standard.org/standard/core/IF
12520 \ IF -- IFadr initialize conditional forward branch
12521 CODE IF \ immediate
12524 MOV &DP,TOS \ -- HERE
12525 ADD #4,&DP \ compile one word, reserve one word
12526 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
12527 ADD #2,TOS \ -- HERE+2=IFadr
12532 [UNDEFINED] THEN [IF]
12533 \ https://forth-standard.org/standard/core/THEN
12534 \ THEN IFadr -- resolve forward branch
12535 CODE THEN \ immediate
12536 MOV &DP,0(TOS) \ -- IFadr
12542 [UNDEFINED] ELSE [IF]
12543 \ https://forth-standard.org/standard/core/ELSE
12544 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
12545 CODE ELSE \ immediate
12546 ADD #4,&DP \ make room to compile two words
12547 MOV &DP,W \ W=HERE+4
12549 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
12551 MOV W,TOS \ -- ELSEadr
12556 [UNDEFINED] DEFER [IF]
12557 \ https://forth-standard.org/standard/core/DEFER
12558 \ DEFER "<spaces>name" --
12559 \ Skip leading space delimiters. Parse name delimited by a space.
12560 \ Create a definition for name with the execution semantics defined below.
12562 \ name Execution: --
12563 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
12564 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
12568 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
12569 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
12575 [UNDEFINED] DEFER! [IF]
12576 \ https://forth-standard.org/standard/core/DEFERStore
12577 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
12578 CODE DEFER! \ xt2 xt1 --
12579 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
12585 [UNDEFINED] IS [IF]
12586 \ https://forth-standard.org/standard/core/IS
12589 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
12590 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
12591 \ or in a definition : ... ['] U. IS DISPLAY ...
12592 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
12594 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
12597 IF POSTPONE ['] POSTPONE DEFER!
12603 [UNDEFINED] >BODY [IF]
12604 \ https://forth-standard.org/standard/core/toBODY
12605 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
12612 \ CODE 20uS \ n -- 8MHz version
12613 \ BEGIN \ 4 + 16 ~ loop
12614 \ MOV #39,rDOCON \ 39
12621 \ MOV #XDOCON,rDOCON \ 2
12626 CODE 20_US \ n -- n * 20 us
12627 BEGIN \ here we presume that LCD_TIM_IFG = 1...
12629 BIT #1,&LCD_TIM_CTL \ 3
12630 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
12631 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
12633 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
12638 CODE TOP_LCD \ LCD Sample
12639 \ \ if write : %xxxx_WWWW --
12640 \ \ if read : -- %0000_RRRR
12641 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
12642 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
12643 0= IF \ write LCD bits pattern
12644 AND.B #LCD_DB,TOS \
12645 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
12646 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12649 THEN \ read LCD bits pattern
12652 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
12653 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
12654 AND.B #LCD_DB,TOS \
12658 CODE LCD_WRC \ char -- Write Char
12659 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12661 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
12662 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
12663 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
12664 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
12665 COLON \ high level word starts here
12666 TOP_LCD 2 20_US \ write high nibble first
12670 CODE LCD_WRF \ func -- Write Fonction
12671 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12675 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
12676 : LCD_HOME $02 LCD_WRF 100 20_us ;
12678 \ [UNDEFINED] OR [IF]
12680 \ \ https://forth-standard.org/standard/core/OR
12681 \ \ C OR x1 x2 -- x3 logical OR
12689 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
12690 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
12691 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
12692 \ : LCD_FN_SET $20 OR LCD_WrF ;
12693 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
12694 \ : LCD_GOTO $80 OR LCD_WrF ;
12697 \ CODE LCD_RDS \ -- status Read Status
12698 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
12699 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
12700 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
12701 \ COLON \ starts a FORTH word
12702 \ TOP_LCD 2 20_us \ -- %0000_HHHH
12703 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
12704 \ HI2LO \ switch from FORTH to assembler
12705 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
12706 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
12707 \ MOV @RSP+,IP \ restore IP saved by COLON
12711 \ CODE LCD_RDC \ -- char Read Char
12712 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
12717 \ ******************************\
12718 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
12719 \ ******************************\
12720 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12721 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
12722 BIT.B #SW2,&SW2_IN \ test switch S2
12723 0= IF \ case of switch S2 pressed
12724 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
12726 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
12729 BIT.B #SW1,&SW1_IN \ test switch S1 input
12730 0= IF \ case of Switch S1 pressed
12731 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
12733 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
12737 BW1 \ from quit on truncated RC5 message, repeated RC5 command
12741 \ ******************************\
12742 ASM RC5_INT \ wake up on Px.RC5 change interrupt
12743 \ ******************************\
12744 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
12745 \ ******************************\
12746 \ \ in : SR(9)=old Toggle bit memory (ADD on)
12747 \ \ SMclock = 8|16|24 MHz
12748 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
12749 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
12750 \ \ SR(9)=new Toggle bit memory (ADD on)
12751 \ ******************************\
12752 \ RC5_FirstStartBitHalfCycle: \
12753 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
12754 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
12755 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
12756 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
12758 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
12759 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
12761 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
12762 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
12764 MOV #1778,X \ RC5_Period * 1us
12765 MOV #14,W \ count of loop
12767 \ ******************************\
12768 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
12769 \ ******************************\ |
12770 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
12771 \ RC5_Compute_3/4_Period: \ |
12772 RRUM #1,X \ X=1/2 cycle |
12775 ADD X,Y \ Y=3/4 cycle
12776 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
12778 \ ******************************\
12779 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
12780 \ ******************************\
12781 BIT.B #RC5,&IR_IN \ C_flag = IR bit
12782 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
12783 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
12784 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
12785 SUB #1,W \ decrement count loop
12786 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
12787 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
12788 0<> WHILE \ ----> out of loop ----+
12789 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
12791 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
12792 CMP Y,X \ 1 | cycle time out of bound ?
12793 U>= IF \ 2 ^ | yes:
12794 BIC #$30,&RC5_TIM_CTL \ | | stop timer
12795 GOTO BW1 \ | | quit on truncated RC5 message
12797 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
12799 REPEAT \ ----> loop back --+ | with X = new RC5_period value
12800 \ ******************************\ |
12801 \ RC5_SampleEndOf: \ <---------------------+
12802 \ ******************************\
12803 BIC #$30,&RC5_TIM_CTL \ stop timer
12804 \ ******************************\
12805 \ RC5_ComputeNewRC5word \
12806 \ ******************************\
12807 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
12808 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
12809 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
12810 \ ******************************\
12811 \ RC5_ComputeC6bit \
12812 \ ******************************\
12813 BIT #BIT14,T \ test /C6 bit in T
12814 0= IF BIS #BIT6,X \ set C6 bit in X
12815 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
12816 \ ******************************\
12817 \ RC5_CommandByteIsDone \ -- BASE RC5_code
12818 \ ******************************\
12819 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
12820 \ ******************************\
12821 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
12822 XOR @RSP,T \ (new XOR old) Toggle bits
12823 BIT #UF10,T \ repeated RC5_command ?
12824 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
12825 XOR #UF10,0(RSP) \ 5 toggle bit memory
12826 \ ******************************\
12827 \ Display IR_RC5 code \
12828 \ ******************************\
12829 SUB #8,PSP \ TOS -- x x x x TOS
12830 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
12831 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
12832 MOV #$10,&BASEADR \ set hexadecimal base
12833 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
12834 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
12835 LO2HI \ switch from assembler to FORTH
12836 LCD_CLEAR \ set LCD cursor at home
12837 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
12838 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
12839 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
12840 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
12841 HI2LO \ -- switch from FORTH to assembler
12842 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
12843 MOV @PSP+,TOS \ -- TOS
12847 \ ******************************\
12849 \ ******************************\
12851 \ ... \ insert here your background task
12854 CALL &RXON \ comment this line to disable TERMINAL_INPUT
12856 \ ******************************\
12857 \ here start all interrupts \
12858 \ ******************************\
12859 \ here return all interrupts \
12860 \ ******************************\
12863 \ ******************************\
12865 \ ------------------------------\
12866 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
12867 \ ------------------------------\
12868 \ ... \ init specific I/O sys as you want
12869 \ ... \ before executing default WARM
12870 MOV #WARM,X \ ['] WARM
12872 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
12874 \ ------------------------------\
12876 \ ------------------------------\
12877 CODE STOP \ stops multitasking, must to be used before downloading app
12878 \ ------------------------------\
12879 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
12880 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
12881 MOV X,-2(X) \ restore the default background: SLEEP
12883 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
12884 BIC.B #RC5,&IR_IE \ clear RC5_Int
12885 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
12886 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
12887 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
12888 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
12889 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
12890 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
12892 ." RC5toLCD is removed,"
12893 ." type START to restart"
12894 WARM \ performs reset to reset all interrupt vectors.
12896 \ ------------------------------\
12898 \ ------------------------------\
12899 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
12900 \ ------------------------------\
12901 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
12902 \ - - \CNTL Counter lentgh \ 00 = 16 bits
12903 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
12904 \ -- \ID input divider \ 10 = /4
12905 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
12906 \ - \TBCLR TimerB Clear
12909 \ -------------------------------\
12910 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
12911 \ -- \CM Capture Mode
12916 \ --- \OUTMOD \ 011 = set/reset
12922 \ -------------------------------\
12924 \ -------------------------------\
12926 \ ------------------------------\
12927 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
12928 \ ------------------------------\
12929 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
12930 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
12931 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
12932 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
12934 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
12935 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
12937 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
12938 \ ------------------------------\
12939 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
12940 \ ------------------------------\
12941 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
12942 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
12943 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
12944 \ ------------------------------\
12945 BIS.B #LCDVo,&LCDVo_DIR \
12946 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
12947 \ ------------------------------\
12948 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
12949 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
12950 \ ------------------------------\
12951 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
12952 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
12953 \ ******************************\
12955 \ ******************************\
12956 BIS.B #RC5,&IR_IE \ enable RC5_Int
12957 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
12958 MOV #RC5_INT,&IR_Vec \ init interrupt vector
12959 \ ******************************\
12960 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
12961 \ ******************************\
12962 \ %01 0001 0100 \ TAxCTL
12963 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
12964 \ -- \ ID divided by 1
12965 \ -- \ MC MODE = up to TAxCCRn
12966 \ - \ TACLR clear timer count
12969 \ ------------------------------\
12970 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
12971 \ ------------------------------\
12973 \ --- \ TAIDEX pre divisor
12974 \ ------------------------------\
12975 \ %0000 0000 0000 0101 \ TAxCCR0
12976 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
12977 \ ------------------------------\
12978 \ %0000 0000 0001 0000 \ TAxCCTL0
12979 \ - \ CAP capture/compare mode = compare
12982 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
12983 \ ------------------------------\
12984 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
12985 \ ------------------------------\
12986 \ define LPM mode for ACCEPT \
12987 \ ------------------------------\
12988 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
12989 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
12990 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
12991 \ ------------------------------\
12993 \ ------------------------------\
12994 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
12995 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
12996 \ ------------------------------\
12997 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
12998 \ ------------------------------\
12999 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
13000 \ CMP #2,Y \ Power_ON event
13001 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
13003 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
13005 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
13007 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
13009 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
13010 \ ------------------------------\
13012 \ ------------------------------\
13014 \ ------------------------------\
13015 #1000 20_US \ 1- wait 20 ms
13016 %011 TOP_LCD \ 2- send DB5=DB4=1
13017 #205 20_US \ 3- wait 4,1 ms
13018 %011 TOP_LCD \ 4- send again DB5=DB4=1
13019 #5 20_US \ 5- wait 0,1 ms
13020 %011 TOP_LCD \ 6- send again again DB5=DB4=1
13021 #2 20_US \ wait 40 us = LCD cycle
13022 %010 TOP_LCD \ 7- send DB5=1 DB4=0
13023 #2 20_US \ wait 40 us = LCD cycle
13024 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13025 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13026 LCD_CLEAR \ 10- "LCD_Clear"
13027 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13028 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13029 LCD_CLEAR \ 10- "LCD_Clear"
13030 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13031 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13032 CR ." I love you" \ display message on LCD
13033 ['] CR >BODY IS CR \ CR executes its default value
13034 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
13035 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13036 PWR_STATE ABORT \ init DP and continues with ABORT
13038 \ ------------------------------\
13040 \ ------------------------------\
13041 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
13042 \ ------------------------------\
13043 MOV #SLEEP,X \ replace default background process SLEEP
13044 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
13045 MOV #WARM,X \ replace default WARM
13046 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
13047 MOV X,PC \ then execute new WARM
13049 \ ------------------------------\
13052 ; downloading RC5toLCD.4th is done
13053 RST_HERE ; this app is protected against <reset>
13058 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
13060 [UNDEFINED] MARKER [IF]
13061 \ https://forth-standard.org/standard/core/MARKER
13063 \ ( "<spaces>name" -- )
13064 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
13065 \ with the execution semantics defined below.
13067 \ name Execution: ( -- )
13068 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
13069 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
13070 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
13071 \ not necessarily provided. No other contextual information such as numeric base is affected
13076 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
13077 SUB #2,Y \ 1 Y = LFA
13078 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
13079 ADD #4,&DP \ 3 add 2 cells
13083 MOV @RSP+,IP \ -- PFA
13084 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
13085 MOV @TOS,&INIDP \ set DP value for RST_STATE
13087 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
13094 \ https://forth-standard.org/standard/core/Fetch
13095 \ @ c-addr -- char fetch char from memory
13102 [UNDEFINED] CONSTANT [IF]
13103 \ https://forth-standard.org/standard/core/CONSTANT
13104 \ CONSTANT <name> n -- define a Forth CONSTANT
13108 MOV TOS,-2(W) \ PFA = n
13115 [UNDEFINED] STATE [IF]
13116 \ https://forth-standard.org/standard/core/STATE
13117 \ STATE -- a-addr holds compiler state
13118 STATEADR CONSTANT STATE
13122 \ https://forth-standard.org/standard/core/Equal
13123 \ = x1 x2 -- flag test x1=x2
13130 XOR #-1,TOS \ 1 flag Z = 1
13135 [UNDEFINED] IF [IF]
13136 \ https://forth-standard.org/standard/core/IF
13137 \ IF -- IFadr initialize conditional forward branch
13138 CODE IF \ immediate
13141 MOV &DP,TOS \ -- HERE
13142 ADD #4,&DP \ compile one word, reserve one word
13143 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
13144 ADD #2,TOS \ -- HERE+2=IFadr
13149 [UNDEFINED] THEN [IF]
13150 \ https://forth-standard.org/standard/core/THEN
13151 \ THEN IFadr -- resolve forward branch
13152 CODE THEN \ immediate
13153 MOV &DP,0(TOS) \ -- IFadr
13159 [UNDEFINED] ELSE [IF]
13160 \ https://forth-standard.org/standard/core/ELSE
13161 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
13162 CODE ELSE \ immediate
13163 ADD #4,&DP \ make room to compile two words
13164 MOV &DP,W \ W=HERE+4
13166 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
13168 MOV W,TOS \ -- ELSEadr
13173 [UNDEFINED] DEFER [IF]
13174 \ https://forth-standard.org/standard/core/DEFER
13175 \ DEFER "<spaces>name" --
13176 \ Skip leading space delimiters. Parse name delimited by a space.
13177 \ Create a definition for name with the execution semantics defined below.
13179 \ name Execution: --
13180 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
13181 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
13185 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
13186 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
13192 [UNDEFINED] DEFER! [IF]
13193 \ https://forth-standard.org/standard/core/DEFERStore
13194 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
13195 CODE DEFER! \ xt2 xt1 --
13196 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
13202 [UNDEFINED] IS [IF]
13203 \ https://forth-standard.org/standard/core/IS
13206 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
13207 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
13208 \ or in a definition : ... ['] U. IS DISPLAY ...
13209 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
13211 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
13214 IF POSTPONE ['] POSTPONE DEFER!
13220 [UNDEFINED] >BODY [IF]
13221 \ https://forth-standard.org/standard/core/toBODY
13222 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
13229 \ CODE 20uS \ n -- 8MHz version
13230 \ BEGIN \ 4 + 16 ~ loop
13231 \ MOV #39,rDOCON \ 39
13238 \ MOV #XDOCON,rDOCON \ 2
13243 CODE 20_US \ n -- n * 20 us
13244 BEGIN \ here we presume that LCD_TIM_IFG = 1...
13246 BIT #1,&LCD_TIM_CTL \ 3
13247 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
13248 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
13250 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
13255 CODE TOP_LCD \ LCD Sample
13256 \ \ if write : %xxxx_WWWW --
13257 \ \ if read : -- %0000_RRRR
13258 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13259 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13260 0= IF \ write LCD bits pattern
13261 AND.B #LCD_DB,TOS \
13262 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13263 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13266 THEN \ read LCD bits pattern
13269 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13270 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13271 AND.B #LCD_DB,TOS \
13275 CODE LCD_WRC \ char -- Write Char
13276 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13278 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
13279 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
13280 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13281 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13282 COLON \ high level word starts here
13283 TOP_LCD 2 20_US \ write high nibble first
13287 CODE LCD_WRF \ func -- Write Fonction
13288 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13292 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
13293 : LCD_HOME $02 LCD_WRF 100 20_us ;
13295 \ [UNDEFINED] OR [IF]
13297 \ \ https://forth-standard.org/standard/core/OR
13298 \ \ C OR x1 x2 -- x3 logical OR
13306 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
13307 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
13308 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
13309 \ : LCD_FN_SET $20 OR LCD_WrF ;
13310 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
13311 \ : LCD_GOTO $80 OR LCD_WrF ;
13314 \ CODE LCD_RDS \ -- status Read Status
13315 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13316 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13317 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13318 \ COLON \ starts a FORTH word
13319 \ TOP_LCD 2 20_us \ -- %0000_HHHH
13320 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
13321 \ HI2LO \ switch from FORTH to assembler
13322 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
13323 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
13324 \ MOV @RSP+,IP \ restore IP saved by COLON
13328 \ CODE LCD_RDC \ -- char Read Char
13329 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13334 \ ******************************\
13335 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13336 \ ******************************\
13337 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
13338 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
13339 BIT.B #SW2,&SW2_IN \ test switch S2
13340 0= IF \ case of switch S2 pressed
13341 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
13343 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
13346 BIT.B #SW1,&SW1_IN \ test switch S1 input
13347 0= IF \ case of Switch S1 pressed
13348 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
13350 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
13354 BW1 \ from quit on truncated RC5 message, repeated RC5 command
13358 \ ******************************\
13359 ASM RC5_INT \ wake up on Px.RC5 change interrupt
13360 \ ******************************\
13361 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13362 \ ******************************\
13363 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13364 \ \ SMclock = 8|16|24 MHz
13365 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
13366 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
13367 \ \ SR(9)=new Toggle bit memory (ADD on)
13368 \ ******************************\
13369 \ RC5_FirstStartBitHalfCycle: \
13370 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
13371 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
13372 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
13373 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
13375 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
13376 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
13378 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
13379 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
13381 MOV #1778,X \ RC5_Period * 1us
13382 MOV #14,W \ count of loop
13384 \ ******************************\
13385 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
13386 \ ******************************\ |
13387 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
13388 \ RC5_Compute_3/4_Period: \ |
13389 RRUM #1,X \ X=1/2 cycle |
13392 ADD X,Y \ Y=3/4 cycle
13393 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
13395 \ ******************************\
13396 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
13397 \ ******************************\
13398 BIT.B #RC5,&IR_IN \ C_flag = IR bit
13399 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
13400 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
13401 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
13402 SUB #1,W \ decrement count loop
13403 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
13404 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
13405 0<> WHILE \ ----> out of loop ----+
13406 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
13408 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
13409 CMP Y,X \ 1 | cycle time out of bound ?
13410 U>= IF \ 2 ^ | yes:
13411 BIC #$30,&RC5_TIM_CTL \ | | stop timer
13412 GOTO BW1 \ | | quit on truncated RC5 message
13414 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
13416 REPEAT \ ----> loop back --+ | with X = new RC5_period value
13417 \ ******************************\ |
13418 \ RC5_SampleEndOf: \ <---------------------+
13419 \ ******************************\
13420 BIC #$30,&RC5_TIM_CTL \ stop timer
13421 \ ******************************\
13422 \ RC5_ComputeNewRC5word \
13423 \ ******************************\
13424 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
13425 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
13426 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
13427 \ ******************************\
13428 \ RC5_ComputeC6bit \
13429 \ ******************************\
13430 BIT #BIT14,T \ test /C6 bit in T
13431 0= IF BIS #BIT6,X \ set C6 bit in X
13432 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
13433 \ ******************************\
13434 \ RC5_CommandByteIsDone \ -- BASE RC5_code
13435 \ ******************************\
13436 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
13437 \ ******************************\
13438 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
13439 XOR @RSP,T \ (new XOR old) Toggle bits
13440 BIT #UF10,T \ repeated RC5_command ?
13441 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
13442 XOR #UF10,0(RSP) \ 5 toggle bit memory
13443 \ ******************************\
13444 \ Display IR_RC5 code \
13445 \ ******************************\
13446 SUB #8,PSP \ TOS -- x x x x TOS
13447 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
13448 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
13449 MOV #$10,&BASEADR \ set hexadecimal base
13450 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
13451 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
13452 LO2HI \ switch from assembler to FORTH
13453 LCD_CLEAR \ set LCD cursor at home
13454 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
13455 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
13456 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
13457 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
13458 HI2LO \ -- switch from FORTH to assembler
13459 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
13460 MOV @PSP+,TOS \ -- TOS
13464 \ ******************************\
13466 \ ******************************\
13468 \ ... \ insert here your background task
13471 CALL &RXON \ comment this line to disable TERMINAL_INPUT
13473 \ ******************************\
13474 \ here start all interrupts \
13475 \ ******************************\
13476 \ here return all interrupts \
13477 \ ******************************\
13480 \ ******************************\
13482 \ ------------------------------\
13483 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
13484 \ ------------------------------\
13485 \ ... \ init specific I/O sys as you want
13486 \ ... \ before executing default WARM
13487 MOV #WARM,X \ ['] WARM
13489 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
13491 \ ------------------------------\
13493 \ ------------------------------\
13494 CODE STOP \ stops multitasking, must to be used before downloading app
13495 \ ------------------------------\
13496 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
13497 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
13498 MOV X,-2(X) \ restore the default background: SLEEP
13500 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
13501 BIC.B #RC5,&IR_IE \ clear RC5_Int
13502 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
13503 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
13504 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
13505 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
13506 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
13507 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
13509 ." RC5toLCD is removed,"
13510 ." type START to restart"
13511 WARM \ performs reset to reset all interrupt vectors.
13513 \ ------------------------------\
13515 \ ------------------------------\
13516 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
13517 \ ------------------------------\
13518 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
13519 \ - - \CNTL Counter lentgh \ 00 = 16 bits
13520 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
13521 \ -- \ID input divider \ 10 = /4
13522 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
13523 \ - \TBCLR TimerB Clear
13526 \ -------------------------------\
13527 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
13528 \ -- \CM Capture Mode
13533 \ --- \OUTMOD \ 011 = set/reset
13539 \ -------------------------------\
13541 \ -------------------------------\
13543 \ ------------------------------\
13544 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
13545 \ ------------------------------\
13546 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
13547 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
13548 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
13549 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
13551 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
13552 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
13554 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
13555 \ ------------------------------\
13556 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
13557 \ ------------------------------\
13558 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
13559 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
13560 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
13561 \ ------------------------------\
13562 BIS.B #LCDVo,&LCDVo_DIR \
13563 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
13564 \ ------------------------------\
13565 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
13566 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
13567 \ ------------------------------\
13568 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
13569 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
13570 \ ******************************\
13572 \ ******************************\
13573 BIS.B #RC5,&IR_IE \ enable RC5_Int
13574 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
13575 MOV #RC5_INT,&IR_Vec \ init interrupt vector
13576 \ ******************************\
13577 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
13578 \ ******************************\
13579 \ %01 0001 0100 \ TAxCTL
13580 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
13581 \ -- \ ID divided by 1
13582 \ -- \ MC MODE = up to TAxCCRn
13583 \ - \ TACLR clear timer count
13586 \ ------------------------------\
13587 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
13588 \ ------------------------------\
13590 \ --- \ TAIDEX pre divisor
13591 \ ------------------------------\
13592 \ %0000 0000 0000 0101 \ TAxCCR0
13593 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
13594 \ ------------------------------\
13595 \ %0000 0000 0001 0000 \ TAxCCTL0
13596 \ - \ CAP capture/compare mode = compare
13599 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
13600 \ ------------------------------\
13601 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
13602 \ ------------------------------\
13603 \ define LPM mode for ACCEPT \
13604 \ ------------------------------\
13605 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
13606 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
13607 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
13608 \ ------------------------------\
13610 \ ------------------------------\
13611 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
13612 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
13613 \ ------------------------------\
13614 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
13615 \ ------------------------------\
13616 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
13617 \ CMP #2,Y \ Power_ON event
13618 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
13620 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
13622 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
13624 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
13626 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
13627 \ ------------------------------\
13629 \ ------------------------------\
13631 \ ------------------------------\
13632 #1000 20_US \ 1- wait 20 ms
13633 %011 TOP_LCD \ 2- send DB5=DB4=1
13634 #205 20_US \ 3- wait 4,1 ms
13635 %011 TOP_LCD \ 4- send again DB5=DB4=1
13636 #5 20_US \ 5- wait 0,1 ms
13637 %011 TOP_LCD \ 6- send again again DB5=DB4=1
13638 #2 20_US \ wait 40 us = LCD cycle
13639 %010 TOP_LCD \ 7- send DB5=1 DB4=0
13640 #2 20_US \ wait 40 us = LCD cycle
13641 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
13642 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
13643 LCD_CLEAR \ 10- "LCD_Clear"
13644 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
13645 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
13646 LCD_CLEAR \ 10- "LCD_Clear"
13647 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
13648 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
13649 CR ." I love you" \ display message on LCD
13650 ['] CR >BODY IS CR \ CR executes its default value
13651 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
13652 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
13653 PWR_STATE ABORT \ init DP and continues with ABORT
13655 \ ------------------------------\
13657 \ ------------------------------\
13658 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
13659 \ ------------------------------\
13660 MOV #SLEEP,X \ replace default background process SLEEP
13661 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
13662 MOV #WARM,X \ replace default WARM
13663 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
13664 MOV X,PC \ then execute new WARM
13666 \ ------------------------------\
13669 ; downloading RC5toLCD.4th is done
13670 RST_HERE ; this app is protected against <reset>
13675 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
13677 [UNDEFINED] MARKER [IF]
13678 \ https://forth-standard.org/standard/core/MARKER
13680 \ ( "<spaces>name" -- )
13681 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
13682 \ with the execution semantics defined below.
13684 \ name Execution: ( -- )
13685 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
13686 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
13687 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
13688 \ not necessarily provided. No other contextual information such as numeric base is affected
13693 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
13694 SUB #2,Y \ 1 Y = LFA
13695 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
13696 ADD #4,&DP \ 3 add 2 cells
13700 MOV @RSP+,IP \ -- PFA
13701 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
13702 MOV @TOS,&INIDP \ set DP value for RST_STATE
13704 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
13711 \ https://forth-standard.org/standard/core/Fetch
13712 \ @ c-addr -- char fetch char from memory
13719 [UNDEFINED] CONSTANT [IF]
13720 \ https://forth-standard.org/standard/core/CONSTANT
13721 \ CONSTANT <name> n -- define a Forth CONSTANT
13725 MOV TOS,-2(W) \ PFA = n
13732 [UNDEFINED] STATE [IF]
13733 \ https://forth-standard.org/standard/core/STATE
13734 \ STATE -- a-addr holds compiler state
13735 STATEADR CONSTANT STATE
13739 \ https://forth-standard.org/standard/core/Equal
13740 \ = x1 x2 -- flag test x1=x2
13747 XOR #-1,TOS \ 1 flag Z = 1
13752 [UNDEFINED] IF [IF]
13753 \ https://forth-standard.org/standard/core/IF
13754 \ IF -- IFadr initialize conditional forward branch
13755 CODE IF \ immediate
13758 MOV &DP,TOS \ -- HERE
13759 ADD #4,&DP \ compile one word, reserve one word
13760 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
13761 ADD #2,TOS \ -- HERE+2=IFadr
13766 [UNDEFINED] THEN [IF]
13767 \ https://forth-standard.org/standard/core/THEN
13768 \ THEN IFadr -- resolve forward branch
13769 CODE THEN \ immediate
13770 MOV &DP,0(TOS) \ -- IFadr
13776 [UNDEFINED] ELSE [IF]
13777 \ https://forth-standard.org/standard/core/ELSE
13778 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
13779 CODE ELSE \ immediate
13780 ADD #4,&DP \ make room to compile two words
13781 MOV &DP,W \ W=HERE+4
13783 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
13785 MOV W,TOS \ -- ELSEadr
13790 [UNDEFINED] DEFER [IF]
13791 \ https://forth-standard.org/standard/core/DEFER
13792 \ DEFER "<spaces>name" --
13793 \ Skip leading space delimiters. Parse name delimited by a space.
13794 \ Create a definition for name with the execution semantics defined below.
13796 \ name Execution: --
13797 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
13798 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
13802 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
13803 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
13809 [UNDEFINED] DEFER! [IF]
13810 \ https://forth-standard.org/standard/core/DEFERStore
13811 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
13812 CODE DEFER! \ xt2 xt1 --
13813 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
13819 [UNDEFINED] IS [IF]
13820 \ https://forth-standard.org/standard/core/IS
13823 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
13824 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
13825 \ or in a definition : ... ['] U. IS DISPLAY ...
13826 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
13828 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
13831 IF POSTPONE ['] POSTPONE DEFER!
13837 [UNDEFINED] >BODY [IF]
13838 \ https://forth-standard.org/standard/core/toBODY
13839 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
13846 \ CODE 20uS \ n -- 8MHz version
13847 \ BEGIN \ 4 + 16 ~ loop
13848 \ MOV #39,rDOCON \ 39
13855 \ MOV #XDOCON,rDOCON \ 2
13860 CODE 20_US \ n -- n * 20 us
13861 BEGIN \ here we presume that LCD_TIM_IFG = 1...
13863 BIT #1,&LCD_TIM_CTL \ 3
13864 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
13865 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
13867 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
13872 CODE TOP_LCD \ LCD Sample
13873 \ \ if write : %xxxx_WWWW --
13874 \ \ if read : -- %0000_RRRR
13875 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
13876 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
13877 0= IF \ write LCD bits pattern
13878 AND.B #LCD_DB,TOS \
13879 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
13880 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13883 THEN \ read LCD bits pattern
13886 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
13887 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
13888 AND.B #LCD_DB,TOS \
13892 CODE LCD_WRC \ char -- Write Char
13893 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13895 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
13896 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
13897 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
13898 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
13899 COLON \ high level word starts here
13900 TOP_LCD 2 20_US \ write high nibble first
13904 CODE LCD_WRF \ func -- Write Fonction
13905 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13909 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
13910 : LCD_HOME $02 LCD_WRF 100 20_us ;
13912 \ [UNDEFINED] OR [IF]
13914 \ \ https://forth-standard.org/standard/core/OR
13915 \ \ C OR x1 x2 -- x3 logical OR
13923 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
13924 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
13925 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
13926 \ : LCD_FN_SET $20 OR LCD_WrF ;
13927 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
13928 \ : LCD_GOTO $80 OR LCD_WrF ;
13931 \ CODE LCD_RDS \ -- status Read Status
13932 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
13933 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
13934 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
13935 \ COLON \ starts a FORTH word
13936 \ TOP_LCD 2 20_us \ -- %0000_HHHH
13937 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
13938 \ HI2LO \ switch from FORTH to assembler
13939 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
13940 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
13941 \ MOV @RSP+,IP \ restore IP saved by COLON
13945 \ CODE LCD_RDC \ -- char Read Char
13946 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
13951 \ ******************************\
13952 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
13953 \ ******************************\
13954 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
13955 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
13956 BIT.B #SW2,&SW2_IN \ test switch S2
13957 0= IF \ case of switch S2 pressed
13958 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
13960 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
13963 BIT.B #SW1,&SW1_IN \ test switch S1 input
13964 0= IF \ case of Switch S1 pressed
13965 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
13967 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
13971 BW1 \ from quit on truncated RC5 message, repeated RC5 command
13975 \ ******************************\
13976 ASM RC5_INT \ wake up on Px.RC5 change interrupt
13977 \ ******************************\
13978 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
13979 \ ******************************\
13980 \ \ in : SR(9)=old Toggle bit memory (ADD on)
13981 \ \ SMclock = 8|16|24 MHz
13982 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
13983 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
13984 \ \ SR(9)=new Toggle bit memory (ADD on)
13985 \ ******************************\
13986 \ RC5_FirstStartBitHalfCycle: \
13987 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
13988 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
13989 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
13990 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
13992 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
13993 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
13995 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
13996 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
13998 MOV #1778,X \ RC5_Period * 1us
13999 MOV #14,W \ count of loop
14001 \ ******************************\
14002 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
14003 \ ******************************\ |
14004 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14005 \ RC5_Compute_3/4_Period: \ |
14006 RRUM #1,X \ X=1/2 cycle |
14009 ADD X,Y \ Y=3/4 cycle
14010 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
14012 \ ******************************\
14013 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14014 \ ******************************\
14015 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14016 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
14017 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14018 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14019 SUB #1,W \ decrement count loop
14020 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
14021 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14022 0<> WHILE \ ----> out of loop ----+
14023 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14025 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
14026 CMP Y,X \ 1 | cycle time out of bound ?
14027 U>= IF \ 2 ^ | yes:
14028 BIC #$30,&RC5_TIM_CTL \ | | stop timer
14029 GOTO BW1 \ | | quit on truncated RC5 message
14031 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
14033 REPEAT \ ----> loop back --+ | with X = new RC5_period value
14034 \ ******************************\ |
14035 \ RC5_SampleEndOf: \ <---------------------+
14036 \ ******************************\
14037 BIC #$30,&RC5_TIM_CTL \ stop timer
14038 \ ******************************\
14039 \ RC5_ComputeNewRC5word \
14040 \ ******************************\
14041 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
14042 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
14043 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
14044 \ ******************************\
14045 \ RC5_ComputeC6bit \
14046 \ ******************************\
14047 BIT #BIT14,T \ test /C6 bit in T
14048 0= IF BIS #BIT6,X \ set C6 bit in X
14049 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
14050 \ ******************************\
14051 \ RC5_CommandByteIsDone \ -- BASE RC5_code
14052 \ ******************************\
14053 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14054 \ ******************************\
14055 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
14056 XOR @RSP,T \ (new XOR old) Toggle bits
14057 BIT #UF10,T \ repeated RC5_command ?
14058 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
14059 XOR #UF10,0(RSP) \ 5 toggle bit memory
14060 \ ******************************\
14061 \ Display IR_RC5 code \
14062 \ ******************************\
14063 SUB #8,PSP \ TOS -- x x x x TOS
14064 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
14065 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
14066 MOV #$10,&BASEADR \ set hexadecimal base
14067 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
14068 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
14069 LO2HI \ switch from assembler to FORTH
14070 LCD_CLEAR \ set LCD cursor at home
14071 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
14072 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
14073 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
14074 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
14075 HI2LO \ -- switch from FORTH to assembler
14076 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
14077 MOV @PSP+,TOS \ -- TOS
14081 \ ******************************\
14083 \ ******************************\
14085 \ ... \ insert here your background task
14088 CALL &RXON \ comment this line to disable TERMINAL_INPUT
14090 \ ******************************\
14091 \ here start all interrupts \
14092 \ ******************************\
14093 \ here return all interrupts \
14094 \ ******************************\
14097 \ ******************************\
14099 \ ------------------------------\
14100 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
14101 \ ------------------------------\
14102 \ ... \ init specific I/O sys as you want
14103 \ ... \ before executing default WARM
14104 MOV #WARM,X \ ['] WARM
14106 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
14108 \ ------------------------------\
14110 \ ------------------------------\
14111 CODE STOP \ stops multitasking, must to be used before downloading app
14112 \ ------------------------------\
14113 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
14114 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
14115 MOV X,-2(X) \ restore the default background: SLEEP
14117 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
14118 BIC.B #RC5,&IR_IE \ clear RC5_Int
14119 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
14120 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
14121 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
14122 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
14123 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
14124 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
14126 ." RC5toLCD is removed,"
14127 ." type START to restart"
14128 WARM \ performs reset to reset all interrupt vectors.
14130 \ ------------------------------\
14132 \ ------------------------------\
14133 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
14134 \ ------------------------------\
14135 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
14136 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14137 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14138 \ -- \ID input divider \ 10 = /4
14139 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
14140 \ - \TBCLR TimerB Clear
14143 \ -------------------------------\
14144 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14145 \ -- \CM Capture Mode
14150 \ --- \OUTMOD \ 011 = set/reset
14156 \ -------------------------------\
14158 \ -------------------------------\
14160 \ ------------------------------\
14161 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
14162 \ ------------------------------\
14163 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
14164 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
14165 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
14166 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
14168 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
14169 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
14171 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
14172 \ ------------------------------\
14173 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
14174 \ ------------------------------\
14175 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
14176 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
14177 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14178 \ ------------------------------\
14179 BIS.B #LCDVo,&LCDVo_DIR \
14180 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
14181 \ ------------------------------\
14182 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14183 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14184 \ ------------------------------\
14185 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14186 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14187 \ ******************************\
14189 \ ******************************\
14190 BIS.B #RC5,&IR_IE \ enable RC5_Int
14191 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14192 MOV #RC5_INT,&IR_Vec \ init interrupt vector
14193 \ ******************************\
14194 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
14195 \ ******************************\
14196 \ %01 0001 0100 \ TAxCTL
14197 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
14198 \ -- \ ID divided by 1
14199 \ -- \ MC MODE = up to TAxCCRn
14200 \ - \ TACLR clear timer count
14203 \ ------------------------------\
14204 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
14205 \ ------------------------------\
14207 \ --- \ TAIDEX pre divisor
14208 \ ------------------------------\
14209 \ %0000 0000 0000 0101 \ TAxCCR0
14210 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
14211 \ ------------------------------\
14212 \ %0000 0000 0001 0000 \ TAxCCTL0
14213 \ - \ CAP capture/compare mode = compare
14216 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
14217 \ ------------------------------\
14218 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
14219 \ ------------------------------\
14220 \ define LPM mode for ACCEPT \
14221 \ ------------------------------\
14222 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14223 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14224 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14225 \ ------------------------------\
14227 \ ------------------------------\
14228 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
14229 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
14230 \ ------------------------------\
14231 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
14232 \ ------------------------------\
14233 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
14234 \ CMP #2,Y \ Power_ON event
14235 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
14237 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
14239 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
14241 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
14243 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
14244 \ ------------------------------\
14246 \ ------------------------------\
14248 \ ------------------------------\
14249 #1000 20_US \ 1- wait 20 ms
14250 %011 TOP_LCD \ 2- send DB5=DB4=1
14251 #205 20_US \ 3- wait 4,1 ms
14252 %011 TOP_LCD \ 4- send again DB5=DB4=1
14253 #5 20_US \ 5- wait 0,1 ms
14254 %011 TOP_LCD \ 6- send again again DB5=DB4=1
14255 #2 20_US \ wait 40 us = LCD cycle
14256 %010 TOP_LCD \ 7- send DB5=1 DB4=0
14257 #2 20_US \ wait 40 us = LCD cycle
14258 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14259 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14260 LCD_CLEAR \ 10- "LCD_Clear"
14261 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14262 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14263 LCD_CLEAR \ 10- "LCD_Clear"
14264 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14265 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14266 CR ." I love you" \ display message on LCD
14267 ['] CR >BODY IS CR \ CR executes its default value
14268 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
14269 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
14270 PWR_STATE ABORT \ init DP and continues with ABORT
14272 \ ------------------------------\
14274 \ ------------------------------\
14275 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
14276 \ ------------------------------\
14277 MOV #SLEEP,X \ replace default background process SLEEP
14278 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
14279 MOV #WARM,X \ replace default WARM
14280 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
14281 MOV X,PC \ then execute new WARM
14283 \ ------------------------------\
14286 ; downloading RC5toLCD.4th is done
14287 RST_HERE ; this app is protected against <reset>
14292 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
14294 [UNDEFINED] MARKER [IF]
14295 \ https://forth-standard.org/standard/core/MARKER
14297 \ ( "<spaces>name" -- )
14298 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
14299 \ with the execution semantics defined below.
14301 \ name Execution: ( -- )
14302 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
14303 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
14304 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
14305 \ not necessarily provided. No other contextual information such as numeric base is affected
14310 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
14311 SUB #2,Y \ 1 Y = LFA
14312 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
14313 ADD #4,&DP \ 3 add 2 cells
14317 MOV @RSP+,IP \ -- PFA
14318 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
14319 MOV @TOS,&INIDP \ set DP value for RST_STATE
14321 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
14328 \ https://forth-standard.org/standard/core/Fetch
14329 \ @ c-addr -- char fetch char from memory
14336 [UNDEFINED] CONSTANT [IF]
14337 \ https://forth-standard.org/standard/core/CONSTANT
14338 \ CONSTANT <name> n -- define a Forth CONSTANT
14342 MOV TOS,-2(W) \ PFA = n
14349 [UNDEFINED] STATE [IF]
14350 \ https://forth-standard.org/standard/core/STATE
14351 \ STATE -- a-addr holds compiler state
14352 STATEADR CONSTANT STATE
14356 \ https://forth-standard.org/standard/core/Equal
14357 \ = x1 x2 -- flag test x1=x2
14364 XOR #-1,TOS \ 1 flag Z = 1
14369 [UNDEFINED] IF [IF]
14370 \ https://forth-standard.org/standard/core/IF
14371 \ IF -- IFadr initialize conditional forward branch
14372 CODE IF \ immediate
14375 MOV &DP,TOS \ -- HERE
14376 ADD #4,&DP \ compile one word, reserve one word
14377 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
14378 ADD #2,TOS \ -- HERE+2=IFadr
14383 [UNDEFINED] THEN [IF]
14384 \ https://forth-standard.org/standard/core/THEN
14385 \ THEN IFadr -- resolve forward branch
14386 CODE THEN \ immediate
14387 MOV &DP,0(TOS) \ -- IFadr
14393 [UNDEFINED] ELSE [IF]
14394 \ https://forth-standard.org/standard/core/ELSE
14395 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
14396 CODE ELSE \ immediate
14397 ADD #4,&DP \ make room to compile two words
14398 MOV &DP,W \ W=HERE+4
14400 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
14402 MOV W,TOS \ -- ELSEadr
14407 [UNDEFINED] DEFER [IF]
14408 \ https://forth-standard.org/standard/core/DEFER
14409 \ DEFER "<spaces>name" --
14410 \ Skip leading space delimiters. Parse name delimited by a space.
14411 \ Create a definition for name with the execution semantics defined below.
14413 \ name Execution: --
14414 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
14415 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
14419 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
14420 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
14426 [UNDEFINED] DEFER! [IF]
14427 \ https://forth-standard.org/standard/core/DEFERStore
14428 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
14429 CODE DEFER! \ xt2 xt1 --
14430 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
14436 [UNDEFINED] IS [IF]
14437 \ https://forth-standard.org/standard/core/IS
14440 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
14441 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
14442 \ or in a definition : ... ['] U. IS DISPLAY ...
14443 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
14445 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
14448 IF POSTPONE ['] POSTPONE DEFER!
14454 [UNDEFINED] >BODY [IF]
14455 \ https://forth-standard.org/standard/core/toBODY
14456 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
14463 \ CODE 20uS \ n -- 8MHz version
14464 \ BEGIN \ 4 + 16 ~ loop
14465 \ MOV #39,rDOCON \ 39
14472 \ MOV #XDOCON,rDOCON \ 2
14477 CODE 20_US \ n -- n * 20 us
14478 BEGIN \ here we presume that LCD_TIM_IFG = 1...
14480 BIT #1,&LCD_TIM_CTL \ 3
14481 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
14482 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
14484 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
14489 CODE TOP_LCD \ LCD Sample
14490 \ \ if write : %xxxx_WWWW --
14491 \ \ if read : -- %0000_RRRR
14492 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
14493 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
14494 0= IF \ write LCD bits pattern
14495 AND.B #LCD_DB,TOS \
14496 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
14497 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14500 THEN \ read LCD bits pattern
14503 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
14504 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
14505 AND.B #LCD_DB,TOS \
14509 CODE LCD_WRC \ char -- Write Char
14510 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14512 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
14513 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
14514 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
14515 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
14516 COLON \ high level word starts here
14517 TOP_LCD 2 20_US \ write high nibble first
14521 CODE LCD_WRF \ func -- Write Fonction
14522 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14526 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
14527 : LCD_HOME $02 LCD_WRF 100 20_us ;
14529 \ [UNDEFINED] OR [IF]
14531 \ \ https://forth-standard.org/standard/core/OR
14532 \ \ C OR x1 x2 -- x3 logical OR
14540 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
14541 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
14542 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
14543 \ : LCD_FN_SET $20 OR LCD_WrF ;
14544 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
14545 \ : LCD_GOTO $80 OR LCD_WrF ;
14548 \ CODE LCD_RDS \ -- status Read Status
14549 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
14550 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
14551 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
14552 \ COLON \ starts a FORTH word
14553 \ TOP_LCD 2 20_us \ -- %0000_HHHH
14554 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
14555 \ HI2LO \ switch from FORTH to assembler
14556 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
14557 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
14558 \ MOV @RSP+,IP \ restore IP saved by COLON
14562 \ CODE LCD_RDC \ -- char Read Char
14563 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
14568 \ ******************************\
14569 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
14570 \ ******************************\
14571 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
14572 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
14573 BIT.B #SW2,&SW2_IN \ test switch S2
14574 0= IF \ case of switch S2 pressed
14575 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
14577 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
14580 BIT.B #SW1,&SW1_IN \ test switch S1 input
14581 0= IF \ case of Switch S1 pressed
14582 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
14584 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
14588 BW1 \ from quit on truncated RC5 message, repeated RC5 command
14592 \ ******************************\
14593 ASM RC5_INT \ wake up on Px.RC5 change interrupt
14594 \ ******************************\
14595 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
14596 \ ******************************\
14597 \ \ in : SR(9)=old Toggle bit memory (ADD on)
14598 \ \ SMclock = 8|16|24 MHz
14599 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
14600 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
14601 \ \ SR(9)=new Toggle bit memory (ADD on)
14602 \ ******************************\
14603 \ RC5_FirstStartBitHalfCycle: \
14604 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
14605 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
14606 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
14607 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
14609 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
14610 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
14612 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
14613 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
14615 MOV #1778,X \ RC5_Period * 1us
14616 MOV #14,W \ count of loop
14618 \ ******************************\
14619 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
14620 \ ******************************\ |
14621 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
14622 \ RC5_Compute_3/4_Period: \ |
14623 RRUM #1,X \ X=1/2 cycle |
14626 ADD X,Y \ Y=3/4 cycle
14627 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
14629 \ ******************************\
14630 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
14631 \ ******************************\
14632 BIT.B #RC5,&IR_IN \ C_flag = IR bit
14633 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
14634 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
14635 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
14636 SUB #1,W \ decrement count loop
14637 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
14638 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
14639 0<> WHILE \ ----> out of loop ----+
14640 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
14642 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
14643 CMP Y,X \ 1 | cycle time out of bound ?
14644 U>= IF \ 2 ^ | yes:
14645 BIC #$30,&RC5_TIM_CTL \ | | stop timer
14646 GOTO BW1 \ | | quit on truncated RC5 message
14648 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
14650 REPEAT \ ----> loop back --+ | with X = new RC5_period value
14651 \ ******************************\ |
14652 \ RC5_SampleEndOf: \ <---------------------+
14653 \ ******************************\
14654 BIC #$30,&RC5_TIM_CTL \ stop timer
14655 \ ******************************\
14656 \ RC5_ComputeNewRC5word \
14657 \ ******************************\
14658 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
14659 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
14660 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
14661 \ ******************************\
14662 \ RC5_ComputeC6bit \
14663 \ ******************************\
14664 BIT #BIT14,T \ test /C6 bit in T
14665 0= IF BIS #BIT6,X \ set C6 bit in X
14666 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
14667 \ ******************************\
14668 \ RC5_CommandByteIsDone \ -- BASE RC5_code
14669 \ ******************************\
14670 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
14671 \ ******************************\
14672 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
14673 XOR @RSP,T \ (new XOR old) Toggle bits
14674 BIT #UF10,T \ repeated RC5_command ?
14675 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
14676 XOR #UF10,0(RSP) \ 5 toggle bit memory
14677 \ ******************************\
14678 \ Display IR_RC5 code \
14679 \ ******************************\
14680 SUB #8,PSP \ TOS -- x x x x TOS
14681 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
14682 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
14683 MOV #$10,&BASEADR \ set hexadecimal base
14684 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
14685 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
14686 LO2HI \ switch from assembler to FORTH
14687 LCD_CLEAR \ set LCD cursor at home
14688 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
14689 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
14690 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
14691 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
14692 HI2LO \ -- switch from FORTH to assembler
14693 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
14694 MOV @PSP+,TOS \ -- TOS
14698 \ ******************************\
14700 \ ******************************\
14702 \ ... \ insert here your background task
14705 CALL &RXON \ comment this line to disable TERMINAL_INPUT
14707 \ ******************************\
14708 \ here start all interrupts \
14709 \ ******************************\
14710 \ here return all interrupts \
14711 \ ******************************\
14714 \ ******************************\
14716 \ ------------------------------\
14717 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
14718 \ ------------------------------\
14719 \ ... \ init specific I/O sys as you want
14720 \ ... \ before executing default WARM
14721 MOV #WARM,X \ ['] WARM
14723 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
14725 \ ------------------------------\
14727 \ ------------------------------\
14728 CODE STOP \ stops multitasking, must to be used before downloading app
14729 \ ------------------------------\
14730 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
14731 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
14732 MOV X,-2(X) \ restore the default background: SLEEP
14734 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
14735 BIC.B #RC5,&IR_IE \ clear RC5_Int
14736 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
14737 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
14738 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
14739 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
14740 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
14741 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
14743 ." RC5toLCD is removed,"
14744 ." type START to restart"
14745 WARM \ performs reset to reset all interrupt vectors.
14747 \ ------------------------------\
14749 \ ------------------------------\
14750 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
14751 \ ------------------------------\
14752 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
14753 \ - - \CNTL Counter lentgh \ 00 = 16 bits
14754 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
14755 \ -- \ID input divider \ 10 = /4
14756 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
14757 \ - \TBCLR TimerB Clear
14760 \ -------------------------------\
14761 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
14762 \ -- \CM Capture Mode
14767 \ --- \OUTMOD \ 011 = set/reset
14773 \ -------------------------------\
14775 \ -------------------------------\
14777 \ ------------------------------\
14778 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
14779 \ ------------------------------\
14780 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
14781 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
14782 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
14783 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
14785 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
14786 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
14788 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
14789 \ ------------------------------\
14790 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
14791 \ ------------------------------\
14792 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
14793 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
14794 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
14795 \ ------------------------------\
14796 BIS.B #LCDVo,&LCDVo_DIR \
14797 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
14798 \ ------------------------------\
14799 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
14800 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
14801 \ ------------------------------\
14802 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
14803 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
14804 \ ******************************\
14806 \ ******************************\
14807 BIS.B #RC5,&IR_IE \ enable RC5_Int
14808 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
14809 MOV #RC5_INT,&IR_Vec \ init interrupt vector
14810 \ ******************************\
14811 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
14812 \ ******************************\
14813 \ %01 0001 0100 \ TAxCTL
14814 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
14815 \ -- \ ID divided by 1
14816 \ -- \ MC MODE = up to TAxCCRn
14817 \ - \ TACLR clear timer count
14820 \ ------------------------------\
14821 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
14822 \ ------------------------------\
14824 \ --- \ TAIDEX pre divisor
14825 \ ------------------------------\
14826 \ %0000 0000 0000 0101 \ TAxCCR0
14827 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
14828 \ ------------------------------\
14829 \ %0000 0000 0001 0000 \ TAxCCTL0
14830 \ - \ CAP capture/compare mode = compare
14833 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
14834 \ ------------------------------\
14835 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
14836 \ ------------------------------\
14837 \ define LPM mode for ACCEPT \
14838 \ ------------------------------\
14839 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
14840 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
14841 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
14842 \ ------------------------------\
14844 \ ------------------------------\
14845 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
14846 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
14847 \ ------------------------------\
14848 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
14849 \ ------------------------------\
14850 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
14851 \ CMP #2,Y \ Power_ON event
14852 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
14854 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
14856 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
14858 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
14860 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
14861 \ ------------------------------\
14863 \ ------------------------------\
14865 \ ------------------------------\
14866 #1000 20_US \ 1- wait 20 ms
14867 %011 TOP_LCD \ 2- send DB5=DB4=1
14868 #205 20_US \ 3- wait 4,1 ms
14869 %011 TOP_LCD \ 4- send again DB5=DB4=1
14870 #5 20_US \ 5- wait 0,1 ms
14871 %011 TOP_LCD \ 6- send again again DB5=DB4=1
14872 #2 20_US \ wait 40 us = LCD cycle
14873 %010 TOP_LCD \ 7- send DB5=1 DB4=0
14874 #2 20_US \ wait 40 us = LCD cycle
14875 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
14876 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
14877 LCD_CLEAR \ 10- "LCD_Clear"
14878 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
14879 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
14880 LCD_CLEAR \ 10- "LCD_Clear"
14881 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
14882 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
14883 CR ." I love you" \ display message on LCD
14884 ['] CR >BODY IS CR \ CR executes its default value
14885 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
14886 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
14887 PWR_STATE ABORT \ init DP and continues with ABORT
14889 \ ------------------------------\
14891 \ ------------------------------\
14892 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
14893 \ ------------------------------\
14894 MOV #SLEEP,X \ replace default background process SLEEP
14895 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
14896 MOV #WARM,X \ replace default WARM
14897 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
14898 MOV X,PC \ then execute new WARM
14900 \ ------------------------------\
14903 ; downloading RC5toLCD.4th is done
14904 RST_HERE ; this app is protected against <reset>
14909 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
14911 [UNDEFINED] MARKER [IF]
14912 \ https://forth-standard.org/standard/core/MARKER
14914 \ ( "<spaces>name" -- )
14915 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
14916 \ with the execution semantics defined below.
14918 \ name Execution: ( -- )
14919 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
14920 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
14921 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
14922 \ not necessarily provided. No other contextual information such as numeric base is affected
14927 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
14928 SUB #2,Y \ 1 Y = LFA
14929 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
14930 ADD #4,&DP \ 3 add 2 cells
14934 MOV @RSP+,IP \ -- PFA
14935 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
14936 MOV @TOS,&INIDP \ set DP value for RST_STATE
14938 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
14945 \ https://forth-standard.org/standard/core/Fetch
14946 \ @ c-addr -- char fetch char from memory
14953 [UNDEFINED] CONSTANT [IF]
14954 \ https://forth-standard.org/standard/core/CONSTANT
14955 \ CONSTANT <name> n -- define a Forth CONSTANT
14959 MOV TOS,-2(W) \ PFA = n
14966 [UNDEFINED] STATE [IF]
14967 \ https://forth-standard.org/standard/core/STATE
14968 \ STATE -- a-addr holds compiler state
14969 STATEADR CONSTANT STATE
14973 \ https://forth-standard.org/standard/core/Equal
14974 \ = x1 x2 -- flag test x1=x2
14981 XOR #-1,TOS \ 1 flag Z = 1
14986 [UNDEFINED] IF [IF]
14987 \ https://forth-standard.org/standard/core/IF
14988 \ IF -- IFadr initialize conditional forward branch
14989 CODE IF \ immediate
14992 MOV &DP,TOS \ -- HERE
14993 ADD #4,&DP \ compile one word, reserve one word
14994 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
14995 ADD #2,TOS \ -- HERE+2=IFadr
15000 [UNDEFINED] THEN [IF]
15001 \ https://forth-standard.org/standard/core/THEN
15002 \ THEN IFadr -- resolve forward branch
15003 CODE THEN \ immediate
15004 MOV &DP,0(TOS) \ -- IFadr
15010 [UNDEFINED] ELSE [IF]
15011 \ https://forth-standard.org/standard/core/ELSE
15012 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
15013 CODE ELSE \ immediate
15014 ADD #4,&DP \ make room to compile two words
15015 MOV &DP,W \ W=HERE+4
15017 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
15019 MOV W,TOS \ -- ELSEadr
15024 [UNDEFINED] DEFER [IF]
15025 \ https://forth-standard.org/standard/core/DEFER
15026 \ DEFER "<spaces>name" --
15027 \ Skip leading space delimiters. Parse name delimited by a space.
15028 \ Create a definition for name with the execution semantics defined below.
15030 \ name Execution: --
15031 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
15032 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
15036 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
15037 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
15043 [UNDEFINED] DEFER! [IF]
15044 \ https://forth-standard.org/standard/core/DEFERStore
15045 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
15046 CODE DEFER! \ xt2 xt1 --
15047 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
15053 [UNDEFINED] IS [IF]
15054 \ https://forth-standard.org/standard/core/IS
15057 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
15058 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
15059 \ or in a definition : ... ['] U. IS DISPLAY ...
15060 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
15062 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
15065 IF POSTPONE ['] POSTPONE DEFER!
15071 [UNDEFINED] >BODY [IF]
15072 \ https://forth-standard.org/standard/core/toBODY
15073 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
15080 \ CODE 20uS \ n -- 8MHz version
15081 \ BEGIN \ 4 + 16 ~ loop
15082 \ MOV #39,rDOCON \ 39
15089 \ MOV #XDOCON,rDOCON \ 2
15094 CODE 20_US \ n -- n * 20 us
15095 BEGIN \ here we presume that LCD_TIM_IFG = 1...
15097 BIT #1,&LCD_TIM_CTL \ 3
15098 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
15099 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
15101 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
15106 CODE TOP_LCD \ LCD Sample
15107 \ \ if write : %xxxx_WWWW --
15108 \ \ if read : -- %0000_RRRR
15109 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15110 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15111 0= IF \ write LCD bits pattern
15112 AND.B #LCD_DB,TOS \
15113 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15114 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15117 THEN \ read LCD bits pattern
15120 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15121 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15122 AND.B #LCD_DB,TOS \
15126 CODE LCD_WRC \ char -- Write Char
15127 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15129 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
15130 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
15131 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15132 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15133 COLON \ high level word starts here
15134 TOP_LCD 2 20_US \ write high nibble first
15138 CODE LCD_WRF \ func -- Write Fonction
15139 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15143 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
15144 : LCD_HOME $02 LCD_WRF 100 20_us ;
15146 \ [UNDEFINED] OR [IF]
15148 \ \ https://forth-standard.org/standard/core/OR
15149 \ \ C OR x1 x2 -- x3 logical OR
15157 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
15158 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
15159 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
15160 \ : LCD_FN_SET $20 OR LCD_WrF ;
15161 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
15162 \ : LCD_GOTO $80 OR LCD_WrF ;
15165 \ CODE LCD_RDS \ -- status Read Status
15166 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15167 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15168 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15169 \ COLON \ starts a FORTH word
15170 \ TOP_LCD 2 20_us \ -- %0000_HHHH
15171 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
15172 \ HI2LO \ switch from FORTH to assembler
15173 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
15174 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
15175 \ MOV @RSP+,IP \ restore IP saved by COLON
15179 \ CODE LCD_RDC \ -- char Read Char
15180 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15185 \ ******************************\
15186 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15187 \ ******************************\
15188 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
15189 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
15190 BIT.B #SW2,&SW2_IN \ test switch S2
15191 0= IF \ case of switch S2 pressed
15192 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
15194 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
15197 BIT.B #SW1,&SW1_IN \ test switch S1 input
15198 0= IF \ case of Switch S1 pressed
15199 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
15201 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
15205 BW1 \ from quit on truncated RC5 message, repeated RC5 command
15209 \ ******************************\
15210 ASM RC5_INT \ wake up on Px.RC5 change interrupt
15211 \ ******************************\
15212 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15213 \ ******************************\
15214 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15215 \ \ SMclock = 8|16|24 MHz
15216 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
15217 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
15218 \ \ SR(9)=new Toggle bit memory (ADD on)
15219 \ ******************************\
15220 \ RC5_FirstStartBitHalfCycle: \
15221 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
15222 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
15223 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
15224 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
15226 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
15227 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
15229 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
15230 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
15232 MOV #1778,X \ RC5_Period * 1us
15233 MOV #14,W \ count of loop
15235 \ ******************************\
15236 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
15237 \ ******************************\ |
15238 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
15239 \ RC5_Compute_3/4_Period: \ |
15240 RRUM #1,X \ X=1/2 cycle |
15243 ADD X,Y \ Y=3/4 cycle
15244 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
15246 \ ******************************\
15247 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
15248 \ ******************************\
15249 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15250 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
15251 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15252 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15253 SUB #1,W \ decrement count loop
15254 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
15255 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15256 0<> WHILE \ ----> out of loop ----+
15257 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
15259 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
15260 CMP Y,X \ 1 | cycle time out of bound ?
15261 U>= IF \ 2 ^ | yes:
15262 BIC #$30,&RC5_TIM_CTL \ | | stop timer
15263 GOTO BW1 \ | | quit on truncated RC5 message
15265 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
15267 REPEAT \ ----> loop back --+ | with X = new RC5_period value
15268 \ ******************************\ |
15269 \ RC5_SampleEndOf: \ <---------------------+
15270 \ ******************************\
15271 BIC #$30,&RC5_TIM_CTL \ stop timer
15272 \ ******************************\
15273 \ RC5_ComputeNewRC5word \
15274 \ ******************************\
15275 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
15276 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
15277 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
15278 \ ******************************\
15279 \ RC5_ComputeC6bit \
15280 \ ******************************\
15281 BIT #BIT14,T \ test /C6 bit in T
15282 0= IF BIS #BIT6,X \ set C6 bit in X
15283 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
15284 \ ******************************\
15285 \ RC5_CommandByteIsDone \ -- BASE RC5_code
15286 \ ******************************\
15287 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
15288 \ ******************************\
15289 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
15290 XOR @RSP,T \ (new XOR old) Toggle bits
15291 BIT #UF10,T \ repeated RC5_command ?
15292 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
15293 XOR #UF10,0(RSP) \ 5 toggle bit memory
15294 \ ******************************\
15295 \ Display IR_RC5 code \
15296 \ ******************************\
15297 SUB #8,PSP \ TOS -- x x x x TOS
15298 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
15299 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
15300 MOV #$10,&BASEADR \ set hexadecimal base
15301 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
15302 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
15303 LO2HI \ switch from assembler to FORTH
15304 LCD_CLEAR \ set LCD cursor at home
15305 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
15306 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
15307 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
15308 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
15309 HI2LO \ -- switch from FORTH to assembler
15310 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
15311 MOV @PSP+,TOS \ -- TOS
15315 \ ******************************\
15317 \ ******************************\
15319 \ ... \ insert here your background task
15322 CALL &RXON \ comment this line to disable TERMINAL_INPUT
15324 \ ******************************\
15325 \ here start all interrupts \
15326 \ ******************************\
15327 \ here return all interrupts \
15328 \ ******************************\
15331 \ ******************************\
15333 \ ------------------------------\
15334 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
15335 \ ------------------------------\
15336 \ ... \ init specific I/O sys as you want
15337 \ ... \ before executing default WARM
15338 MOV #WARM,X \ ['] WARM
15340 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
15342 \ ------------------------------\
15344 \ ------------------------------\
15345 CODE STOP \ stops multitasking, must to be used before downloading app
15346 \ ------------------------------\
15347 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
15348 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
15349 MOV X,-2(X) \ restore the default background: SLEEP
15351 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
15352 BIC.B #RC5,&IR_IE \ clear RC5_Int
15353 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
15354 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
15355 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
15356 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
15357 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
15358 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
15360 ." RC5toLCD is removed,"
15361 ." type START to restart"
15362 WARM \ performs reset to reset all interrupt vectors.
15364 \ ------------------------------\
15366 \ ------------------------------\
15367 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
15368 \ ------------------------------\
15369 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
15370 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15371 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15372 \ -- \ID input divider \ 10 = /4
15373 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15374 \ - \TBCLR TimerB Clear
15377 \ -------------------------------\
15378 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15379 \ -- \CM Capture Mode
15384 \ --- \OUTMOD \ 011 = set/reset
15390 \ -------------------------------\
15392 \ -------------------------------\
15394 \ ------------------------------\
15395 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
15396 \ ------------------------------\
15397 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
15398 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
15399 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
15400 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
15402 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
15403 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
15405 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
15406 \ ------------------------------\
15407 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
15408 \ ------------------------------\
15409 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
15410 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
15411 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
15412 \ ------------------------------\
15413 BIS.B #LCDVo,&LCDVo_DIR \
15414 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
15415 \ ------------------------------\
15416 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
15417 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
15418 \ ------------------------------\
15419 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
15420 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
15421 \ ******************************\
15423 \ ******************************\
15424 BIS.B #RC5,&IR_IE \ enable RC5_Int
15425 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
15426 MOV #RC5_INT,&IR_Vec \ init interrupt vector
15427 \ ******************************\
15428 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
15429 \ ******************************\
15430 \ %01 0001 0100 \ TAxCTL
15431 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
15432 \ -- \ ID divided by 1
15433 \ -- \ MC MODE = up to TAxCCRn
15434 \ - \ TACLR clear timer count
15437 \ ------------------------------\
15438 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
15439 \ ------------------------------\
15441 \ --- \ TAIDEX pre divisor
15442 \ ------------------------------\
15443 \ %0000 0000 0000 0101 \ TAxCCR0
15444 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
15445 \ ------------------------------\
15446 \ %0000 0000 0001 0000 \ TAxCCTL0
15447 \ - \ CAP capture/compare mode = compare
15450 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
15451 \ ------------------------------\
15452 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
15453 \ ------------------------------\
15454 \ define LPM mode for ACCEPT \
15455 \ ------------------------------\
15456 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
15457 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
15458 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
15459 \ ------------------------------\
15461 \ ------------------------------\
15462 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
15463 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
15464 \ ------------------------------\
15465 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
15466 \ ------------------------------\
15467 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
15468 \ CMP #2,Y \ Power_ON event
15469 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
15471 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
15473 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
15475 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
15477 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
15478 \ ------------------------------\
15480 \ ------------------------------\
15482 \ ------------------------------\
15483 #1000 20_US \ 1- wait 20 ms
15484 %011 TOP_LCD \ 2- send DB5=DB4=1
15485 #205 20_US \ 3- wait 4,1 ms
15486 %011 TOP_LCD \ 4- send again DB5=DB4=1
15487 #5 20_US \ 5- wait 0,1 ms
15488 %011 TOP_LCD \ 6- send again again DB5=DB4=1
15489 #2 20_US \ wait 40 us = LCD cycle
15490 %010 TOP_LCD \ 7- send DB5=1 DB4=0
15491 #2 20_US \ wait 40 us = LCD cycle
15492 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
15493 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
15494 LCD_CLEAR \ 10- "LCD_Clear"
15495 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
15496 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
15497 LCD_CLEAR \ 10- "LCD_Clear"
15498 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
15499 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
15500 CR ." I love you" \ display message on LCD
15501 ['] CR >BODY IS CR \ CR executes its default value
15502 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
15503 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
15504 PWR_STATE ABORT \ init DP and continues with ABORT
15506 \ ------------------------------\
15508 \ ------------------------------\
15509 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
15510 \ ------------------------------\
15511 MOV #SLEEP,X \ replace default background process SLEEP
15512 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
15513 MOV #WARM,X \ replace default WARM
15514 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
15515 MOV X,PC \ then execute new WARM
15517 \ ------------------------------\
15520 ; downloading RC5toLCD.4th is done
15521 RST_HERE ; this app is protected against <reset>
15526 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
15528 [UNDEFINED] MARKER [IF]
15529 \ https://forth-standard.org/standard/core/MARKER
15531 \ ( "<spaces>name" -- )
15532 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
15533 \ with the execution semantics defined below.
15535 \ name Execution: ( -- )
15536 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
15537 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
15538 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
15539 \ not necessarily provided. No other contextual information such as numeric base is affected
15544 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
15545 SUB #2,Y \ 1 Y = LFA
15546 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
15547 ADD #4,&DP \ 3 add 2 cells
15551 MOV @RSP+,IP \ -- PFA
15552 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
15553 MOV @TOS,&INIDP \ set DP value for RST_STATE
15555 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
15562 \ https://forth-standard.org/standard/core/Fetch
15563 \ @ c-addr -- char fetch char from memory
15570 [UNDEFINED] CONSTANT [IF]
15571 \ https://forth-standard.org/standard/core/CONSTANT
15572 \ CONSTANT <name> n -- define a Forth CONSTANT
15576 MOV TOS,-2(W) \ PFA = n
15583 [UNDEFINED] STATE [IF]
15584 \ https://forth-standard.org/standard/core/STATE
15585 \ STATE -- a-addr holds compiler state
15586 STATEADR CONSTANT STATE
15590 \ https://forth-standard.org/standard/core/Equal
15591 \ = x1 x2 -- flag test x1=x2
15598 XOR #-1,TOS \ 1 flag Z = 1
15603 [UNDEFINED] IF [IF]
15604 \ https://forth-standard.org/standard/core/IF
15605 \ IF -- IFadr initialize conditional forward branch
15606 CODE IF \ immediate
15609 MOV &DP,TOS \ -- HERE
15610 ADD #4,&DP \ compile one word, reserve one word
15611 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
15612 ADD #2,TOS \ -- HERE+2=IFadr
15617 [UNDEFINED] THEN [IF]
15618 \ https://forth-standard.org/standard/core/THEN
15619 \ THEN IFadr -- resolve forward branch
15620 CODE THEN \ immediate
15621 MOV &DP,0(TOS) \ -- IFadr
15627 [UNDEFINED] ELSE [IF]
15628 \ https://forth-standard.org/standard/core/ELSE
15629 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
15630 CODE ELSE \ immediate
15631 ADD #4,&DP \ make room to compile two words
15632 MOV &DP,W \ W=HERE+4
15634 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
15636 MOV W,TOS \ -- ELSEadr
15641 [UNDEFINED] DEFER [IF]
15642 \ https://forth-standard.org/standard/core/DEFER
15643 \ DEFER "<spaces>name" --
15644 \ Skip leading space delimiters. Parse name delimited by a space.
15645 \ Create a definition for name with the execution semantics defined below.
15647 \ name Execution: --
15648 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
15649 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
15653 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
15654 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
15660 [UNDEFINED] DEFER! [IF]
15661 \ https://forth-standard.org/standard/core/DEFERStore
15662 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
15663 CODE DEFER! \ xt2 xt1 --
15664 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
15670 [UNDEFINED] IS [IF]
15671 \ https://forth-standard.org/standard/core/IS
15674 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
15675 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
15676 \ or in a definition : ... ['] U. IS DISPLAY ...
15677 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
15679 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
15682 IF POSTPONE ['] POSTPONE DEFER!
15688 [UNDEFINED] >BODY [IF]
15689 \ https://forth-standard.org/standard/core/toBODY
15690 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
15697 \ CODE 20uS \ n -- 8MHz version
15698 \ BEGIN \ 4 + 16 ~ loop
15699 \ MOV #39,rDOCON \ 39
15706 \ MOV #XDOCON,rDOCON \ 2
15711 CODE 20_US \ n -- n * 20 us
15712 BEGIN \ here we presume that LCD_TIM_IFG = 1...
15714 BIT #1,&LCD_TIM_CTL \ 3
15715 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
15716 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
15718 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
15723 CODE TOP_LCD \ LCD Sample
15724 \ \ if write : %xxxx_WWWW --
15725 \ \ if read : -- %0000_RRRR
15726 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
15727 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
15728 0= IF \ write LCD bits pattern
15729 AND.B #LCD_DB,TOS \
15730 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
15731 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15734 THEN \ read LCD bits pattern
15737 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
15738 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
15739 AND.B #LCD_DB,TOS \
15743 CODE LCD_WRC \ char -- Write Char
15744 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15746 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
15747 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
15748 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
15749 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
15750 COLON \ high level word starts here
15751 TOP_LCD 2 20_US \ write high nibble first
15755 CODE LCD_WRF \ func -- Write Fonction
15756 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15760 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
15761 : LCD_HOME $02 LCD_WRF 100 20_us ;
15763 \ [UNDEFINED] OR [IF]
15765 \ \ https://forth-standard.org/standard/core/OR
15766 \ \ C OR x1 x2 -- x3 logical OR
15774 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
15775 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
15776 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
15777 \ : LCD_FN_SET $20 OR LCD_WrF ;
15778 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
15779 \ : LCD_GOTO $80 OR LCD_WrF ;
15782 \ CODE LCD_RDS \ -- status Read Status
15783 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
15784 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
15785 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
15786 \ COLON \ starts a FORTH word
15787 \ TOP_LCD 2 20_us \ -- %0000_HHHH
15788 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
15789 \ HI2LO \ switch from FORTH to assembler
15790 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
15791 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
15792 \ MOV @RSP+,IP \ restore IP saved by COLON
15796 \ CODE LCD_RDC \ -- char Read Char
15797 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
15802 \ ******************************\
15803 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
15804 \ ******************************\
15805 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
15806 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
15807 BIT.B #SW2,&SW2_IN \ test switch S2
15808 0= IF \ case of switch S2 pressed
15809 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
15811 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
15814 BIT.B #SW1,&SW1_IN \ test switch S1 input
15815 0= IF \ case of Switch S1 pressed
15816 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
15818 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
15822 BW1 \ from quit on truncated RC5 message, repeated RC5 command
15826 \ ******************************\
15827 ASM RC5_INT \ wake up on Px.RC5 change interrupt
15828 \ ******************************\
15829 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
15830 \ ******************************\
15831 \ \ in : SR(9)=old Toggle bit memory (ADD on)
15832 \ \ SMclock = 8|16|24 MHz
15833 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
15834 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
15835 \ \ SR(9)=new Toggle bit memory (ADD on)
15836 \ ******************************\
15837 \ RC5_FirstStartBitHalfCycle: \
15838 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
15839 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
15840 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
15841 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
15843 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
15844 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
15846 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
15847 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
15849 MOV #1778,X \ RC5_Period * 1us
15850 MOV #14,W \ count of loop
15852 \ ******************************\
15853 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
15854 \ ******************************\ |
15855 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
15856 \ RC5_Compute_3/4_Period: \ |
15857 RRUM #1,X \ X=1/2 cycle |
15860 ADD X,Y \ Y=3/4 cycle
15861 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
15863 \ ******************************\
15864 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
15865 \ ******************************\
15866 BIT.B #RC5,&IR_IN \ C_flag = IR bit
15867 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
15868 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
15869 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
15870 SUB #1,W \ decrement count loop
15871 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
15872 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
15873 0<> WHILE \ ----> out of loop ----+
15874 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
15876 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
15877 CMP Y,X \ 1 | cycle time out of bound ?
15878 U>= IF \ 2 ^ | yes:
15879 BIC #$30,&RC5_TIM_CTL \ | | stop timer
15880 GOTO BW1 \ | | quit on truncated RC5 message
15882 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
15884 REPEAT \ ----> loop back --+ | with X = new RC5_period value
15885 \ ******************************\ |
15886 \ RC5_SampleEndOf: \ <---------------------+
15887 \ ******************************\
15888 BIC #$30,&RC5_TIM_CTL \ stop timer
15889 \ ******************************\
15890 \ RC5_ComputeNewRC5word \
15891 \ ******************************\
15892 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
15893 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
15894 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
15895 \ ******************************\
15896 \ RC5_ComputeC6bit \
15897 \ ******************************\
15898 BIT #BIT14,T \ test /C6 bit in T
15899 0= IF BIS #BIT6,X \ set C6 bit in X
15900 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
15901 \ ******************************\
15902 \ RC5_CommandByteIsDone \ -- BASE RC5_code
15903 \ ******************************\
15904 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
15905 \ ******************************\
15906 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
15907 XOR @RSP,T \ (new XOR old) Toggle bits
15908 BIT #UF10,T \ repeated RC5_command ?
15909 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
15910 XOR #UF10,0(RSP) \ 5 toggle bit memory
15911 \ ******************************\
15912 \ Display IR_RC5 code \
15913 \ ******************************\
15914 SUB #8,PSP \ TOS -- x x x x TOS
15915 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
15916 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
15917 MOV #$10,&BASEADR \ set hexadecimal base
15918 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
15919 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
15920 LO2HI \ switch from assembler to FORTH
15921 LCD_CLEAR \ set LCD cursor at home
15922 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
15923 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
15924 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
15925 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
15926 HI2LO \ -- switch from FORTH to assembler
15927 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
15928 MOV @PSP+,TOS \ -- TOS
15932 \ ******************************\
15934 \ ******************************\
15936 \ ... \ insert here your background task
15939 CALL &RXON \ comment this line to disable TERMINAL_INPUT
15941 \ ******************************\
15942 \ here start all interrupts \
15943 \ ******************************\
15944 \ here return all interrupts \
15945 \ ******************************\
15948 \ ******************************\
15950 \ ------------------------------\
15951 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
15952 \ ------------------------------\
15953 \ ... \ init specific I/O sys as you want
15954 \ ... \ before executing default WARM
15955 MOV #WARM,X \ ['] WARM
15957 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
15959 \ ------------------------------\
15961 \ ------------------------------\
15962 CODE STOP \ stops multitasking, must to be used before downloading app
15963 \ ------------------------------\
15964 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
15965 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
15966 MOV X,-2(X) \ restore the default background: SLEEP
15968 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
15969 BIC.B #RC5,&IR_IE \ clear RC5_Int
15970 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
15971 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
15972 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
15973 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
15974 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
15975 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
15977 ." RC5toLCD is removed,"
15978 ." type START to restart"
15979 WARM \ performs reset to reset all interrupt vectors.
15981 \ ------------------------------\
15983 \ ------------------------------\
15984 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
15985 \ ------------------------------\
15986 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
15987 \ - - \CNTL Counter lentgh \ 00 = 16 bits
15988 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
15989 \ -- \ID input divider \ 10 = /4
15990 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
15991 \ - \TBCLR TimerB Clear
15994 \ -------------------------------\
15995 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
15996 \ -- \CM Capture Mode
16001 \ --- \OUTMOD \ 011 = set/reset
16007 \ -------------------------------\
16009 \ -------------------------------\
16011 \ ------------------------------\
16012 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
16013 \ ------------------------------\
16014 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
16015 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
16016 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
16017 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
16019 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
16020 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
16022 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
16023 \ ------------------------------\
16024 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
16025 \ ------------------------------\
16026 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
16027 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
16028 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16029 \ ------------------------------\
16030 BIS.B #LCDVo,&LCDVo_DIR \
16031 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
16032 \ ------------------------------\
16033 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16034 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16035 \ ------------------------------\
16036 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16037 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16038 \ ******************************\
16040 \ ******************************\
16041 BIS.B #RC5,&IR_IE \ enable RC5_Int
16042 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16043 MOV #RC5_INT,&IR_Vec \ init interrupt vector
16044 \ ******************************\
16045 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
16046 \ ******************************\
16047 \ %01 0001 0100 \ TAxCTL
16048 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
16049 \ -- \ ID divided by 1
16050 \ -- \ MC MODE = up to TAxCCRn
16051 \ - \ TACLR clear timer count
16054 \ ------------------------------\
16055 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
16056 \ ------------------------------\
16058 \ --- \ TAIDEX pre divisor
16059 \ ------------------------------\
16060 \ %0000 0000 0000 0101 \ TAxCCR0
16061 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
16062 \ ------------------------------\
16063 \ %0000 0000 0001 0000 \ TAxCCTL0
16064 \ - \ CAP capture/compare mode = compare
16067 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
16068 \ ------------------------------\
16069 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
16070 \ ------------------------------\
16071 \ define LPM mode for ACCEPT \
16072 \ ------------------------------\
16073 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16074 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16075 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16076 \ ------------------------------\
16078 \ ------------------------------\
16079 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
16080 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
16081 \ ------------------------------\
16082 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
16083 \ ------------------------------\
16084 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
16085 \ CMP #2,Y \ Power_ON event
16086 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
16088 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
16090 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
16092 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
16094 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
16095 \ ------------------------------\
16097 \ ------------------------------\
16099 \ ------------------------------\
16100 #1000 20_US \ 1- wait 20 ms
16101 %011 TOP_LCD \ 2- send DB5=DB4=1
16102 #205 20_US \ 3- wait 4,1 ms
16103 %011 TOP_LCD \ 4- send again DB5=DB4=1
16104 #5 20_US \ 5- wait 0,1 ms
16105 %011 TOP_LCD \ 6- send again again DB5=DB4=1
16106 #2 20_US \ wait 40 us = LCD cycle
16107 %010 TOP_LCD \ 7- send DB5=1 DB4=0
16108 #2 20_US \ wait 40 us = LCD cycle
16109 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16110 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16111 LCD_CLEAR \ 10- "LCD_Clear"
16112 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16113 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16114 LCD_CLEAR \ 10- "LCD_Clear"
16115 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16116 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16117 CR ." I love you" \ display message on LCD
16118 ['] CR >BODY IS CR \ CR executes its default value
16119 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
16120 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
16121 PWR_STATE ABORT \ init DP and continues with ABORT
16123 \ ------------------------------\
16125 \ ------------------------------\
16126 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
16127 \ ------------------------------\
16128 MOV #SLEEP,X \ replace default background process SLEEP
16129 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
16130 MOV #WARM,X \ replace default WARM
16131 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
16132 MOV X,PC \ then execute new WARM
16134 \ ------------------------------\
16137 ; downloading RC5toLCD.4th is done
16138 RST_HERE ; this app is protected against <reset>
16143 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
16145 [UNDEFINED] MARKER [IF]
16146 \ https://forth-standard.org/standard/core/MARKER
16148 \ ( "<spaces>name" -- )
16149 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
16150 \ with the execution semantics defined below.
16152 \ name Execution: ( -- )
16153 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
16154 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
16155 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
16156 \ not necessarily provided. No other contextual information such as numeric base is affected
16161 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
16162 SUB #2,Y \ 1 Y = LFA
16163 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
16164 ADD #4,&DP \ 3 add 2 cells
16168 MOV @RSP+,IP \ -- PFA
16169 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
16170 MOV @TOS,&INIDP \ set DP value for RST_STATE
16172 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
16179 \ https://forth-standard.org/standard/core/Fetch
16180 \ @ c-addr -- char fetch char from memory
16187 [UNDEFINED] CONSTANT [IF]
16188 \ https://forth-standard.org/standard/core/CONSTANT
16189 \ CONSTANT <name> n -- define a Forth CONSTANT
16193 MOV TOS,-2(W) \ PFA = n
16200 [UNDEFINED] STATE [IF]
16201 \ https://forth-standard.org/standard/core/STATE
16202 \ STATE -- a-addr holds compiler state
16203 STATEADR CONSTANT STATE
16207 \ https://forth-standard.org/standard/core/Equal
16208 \ = x1 x2 -- flag test x1=x2
16215 XOR #-1,TOS \ 1 flag Z = 1
16220 [UNDEFINED] IF [IF]
16221 \ https://forth-standard.org/standard/core/IF
16222 \ IF -- IFadr initialize conditional forward branch
16223 CODE IF \ immediate
16226 MOV &DP,TOS \ -- HERE
16227 ADD #4,&DP \ compile one word, reserve one word
16228 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
16229 ADD #2,TOS \ -- HERE+2=IFadr
16234 [UNDEFINED] THEN [IF]
16235 \ https://forth-standard.org/standard/core/THEN
16236 \ THEN IFadr -- resolve forward branch
16237 CODE THEN \ immediate
16238 MOV &DP,0(TOS) \ -- IFadr
16244 [UNDEFINED] ELSE [IF]
16245 \ https://forth-standard.org/standard/core/ELSE
16246 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
16247 CODE ELSE \ immediate
16248 ADD #4,&DP \ make room to compile two words
16249 MOV &DP,W \ W=HERE+4
16251 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
16253 MOV W,TOS \ -- ELSEadr
16258 [UNDEFINED] DEFER [IF]
16259 \ https://forth-standard.org/standard/core/DEFER
16260 \ DEFER "<spaces>name" --
16261 \ Skip leading space delimiters. Parse name delimited by a space.
16262 \ Create a definition for name with the execution semantics defined below.
16264 \ name Execution: --
16265 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
16266 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
16270 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
16271 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
16277 [UNDEFINED] DEFER! [IF]
16278 \ https://forth-standard.org/standard/core/DEFERStore
16279 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
16280 CODE DEFER! \ xt2 xt1 --
16281 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
16287 [UNDEFINED] IS [IF]
16288 \ https://forth-standard.org/standard/core/IS
16291 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
16292 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
16293 \ or in a definition : ... ['] U. IS DISPLAY ...
16294 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
16296 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
16299 IF POSTPONE ['] POSTPONE DEFER!
16305 [UNDEFINED] >BODY [IF]
16306 \ https://forth-standard.org/standard/core/toBODY
16307 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
16314 \ CODE 20uS \ n -- 8MHz version
16315 \ BEGIN \ 4 + 16 ~ loop
16316 \ MOV #39,rDOCON \ 39
16323 \ MOV #XDOCON,rDOCON \ 2
16328 CODE 20_US \ n -- n * 20 us
16329 BEGIN \ here we presume that LCD_TIM_IFG = 1...
16331 BIT #1,&LCD_TIM_CTL \ 3
16332 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
16333 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
16335 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
16340 CODE TOP_LCD \ LCD Sample
16341 \ \ if write : %xxxx_WWWW --
16342 \ \ if read : -- %0000_RRRR
16343 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16344 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16345 0= IF \ write LCD bits pattern
16346 AND.B #LCD_DB,TOS \
16347 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16348 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16351 THEN \ read LCD bits pattern
16354 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16355 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16356 AND.B #LCD_DB,TOS \
16360 CODE LCD_WRC \ char -- Write Char
16361 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16363 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
16364 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
16365 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16366 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16367 COLON \ high level word starts here
16368 TOP_LCD 2 20_US \ write high nibble first
16372 CODE LCD_WRF \ func -- Write Fonction
16373 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16377 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
16378 : LCD_HOME $02 LCD_WRF 100 20_us ;
16380 \ [UNDEFINED] OR [IF]
16382 \ \ https://forth-standard.org/standard/core/OR
16383 \ \ C OR x1 x2 -- x3 logical OR
16391 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
16392 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
16393 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
16394 \ : LCD_FN_SET $20 OR LCD_WrF ;
16395 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
16396 \ : LCD_GOTO $80 OR LCD_WrF ;
16399 \ CODE LCD_RDS \ -- status Read Status
16400 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16401 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
16402 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
16403 \ COLON \ starts a FORTH word
16404 \ TOP_LCD 2 20_us \ -- %0000_HHHH
16405 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
16406 \ HI2LO \ switch from FORTH to assembler
16407 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
16408 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
16409 \ MOV @RSP+,IP \ restore IP saved by COLON
16413 \ CODE LCD_RDC \ -- char Read Char
16414 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16419 \ ******************************\
16420 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
16421 \ ******************************\
16422 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
16423 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
16424 BIT.B #SW2,&SW2_IN \ test switch S2
16425 0= IF \ case of switch S2 pressed
16426 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
16428 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
16431 BIT.B #SW1,&SW1_IN \ test switch S1 input
16432 0= IF \ case of Switch S1 pressed
16433 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
16435 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
16439 BW1 \ from quit on truncated RC5 message, repeated RC5 command
16443 \ ******************************\
16444 ASM RC5_INT \ wake up on Px.RC5 change interrupt
16445 \ ******************************\
16446 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
16447 \ ******************************\
16448 \ \ in : SR(9)=old Toggle bit memory (ADD on)
16449 \ \ SMclock = 8|16|24 MHz
16450 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
16451 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
16452 \ \ SR(9)=new Toggle bit memory (ADD on)
16453 \ ******************************\
16454 \ RC5_FirstStartBitHalfCycle: \
16455 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
16456 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
16457 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
16458 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
16460 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
16461 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
16463 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
16464 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
16466 MOV #1778,X \ RC5_Period * 1us
16467 MOV #14,W \ count of loop
16469 \ ******************************\
16470 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
16471 \ ******************************\ |
16472 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
16473 \ RC5_Compute_3/4_Period: \ |
16474 RRUM #1,X \ X=1/2 cycle |
16477 ADD X,Y \ Y=3/4 cycle
16478 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
16480 \ ******************************\
16481 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
16482 \ ******************************\
16483 BIT.B #RC5,&IR_IN \ C_flag = IR bit
16484 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
16485 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
16486 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
16487 SUB #1,W \ decrement count loop
16488 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
16489 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
16490 0<> WHILE \ ----> out of loop ----+
16491 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
16493 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
16494 CMP Y,X \ 1 | cycle time out of bound ?
16495 U>= IF \ 2 ^ | yes:
16496 BIC #$30,&RC5_TIM_CTL \ | | stop timer
16497 GOTO BW1 \ | | quit on truncated RC5 message
16499 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
16501 REPEAT \ ----> loop back --+ | with X = new RC5_period value
16502 \ ******************************\ |
16503 \ RC5_SampleEndOf: \ <---------------------+
16504 \ ******************************\
16505 BIC #$30,&RC5_TIM_CTL \ stop timer
16506 \ ******************************\
16507 \ RC5_ComputeNewRC5word \
16508 \ ******************************\
16509 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
16510 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
16511 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
16512 \ ******************************\
16513 \ RC5_ComputeC6bit \
16514 \ ******************************\
16515 BIT #BIT14,T \ test /C6 bit in T
16516 0= IF BIS #BIT6,X \ set C6 bit in X
16517 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
16518 \ ******************************\
16519 \ RC5_CommandByteIsDone \ -- BASE RC5_code
16520 \ ******************************\
16521 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
16522 \ ******************************\
16523 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
16524 XOR @RSP,T \ (new XOR old) Toggle bits
16525 BIT #UF10,T \ repeated RC5_command ?
16526 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
16527 XOR #UF10,0(RSP) \ 5 toggle bit memory
16528 \ ******************************\
16529 \ Display IR_RC5 code \
16530 \ ******************************\
16531 SUB #8,PSP \ TOS -- x x x x TOS
16532 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
16533 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
16534 MOV #$10,&BASEADR \ set hexadecimal base
16535 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
16536 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
16537 LO2HI \ switch from assembler to FORTH
16538 LCD_CLEAR \ set LCD cursor at home
16539 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
16540 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
16541 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
16542 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
16543 HI2LO \ -- switch from FORTH to assembler
16544 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
16545 MOV @PSP+,TOS \ -- TOS
16549 \ ******************************\
16551 \ ******************************\
16553 \ ... \ insert here your background task
16556 CALL &RXON \ comment this line to disable TERMINAL_INPUT
16558 \ ******************************\
16559 \ here start all interrupts \
16560 \ ******************************\
16561 \ here return all interrupts \
16562 \ ******************************\
16565 \ ******************************\
16567 \ ------------------------------\
16568 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
16569 \ ------------------------------\
16570 \ ... \ init specific I/O sys as you want
16571 \ ... \ before executing default WARM
16572 MOV #WARM,X \ ['] WARM
16574 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
16576 \ ------------------------------\
16578 \ ------------------------------\
16579 CODE STOP \ stops multitasking, must to be used before downloading app
16580 \ ------------------------------\
16581 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
16582 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
16583 MOV X,-2(X) \ restore the default background: SLEEP
16585 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
16586 BIC.B #RC5,&IR_IE \ clear RC5_Int
16587 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
16588 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
16589 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
16590 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
16591 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
16592 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
16594 ." RC5toLCD is removed,"
16595 ." type START to restart"
16596 WARM \ performs reset to reset all interrupt vectors.
16598 \ ------------------------------\
16600 \ ------------------------------\
16601 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
16602 \ ------------------------------\
16603 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
16604 \ - - \CNTL Counter lentgh \ 00 = 16 bits
16605 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
16606 \ -- \ID input divider \ 10 = /4
16607 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
16608 \ - \TBCLR TimerB Clear
16611 \ -------------------------------\
16612 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
16613 \ -- \CM Capture Mode
16618 \ --- \OUTMOD \ 011 = set/reset
16624 \ -------------------------------\
16626 \ -------------------------------\
16628 \ ------------------------------\
16629 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
16630 \ ------------------------------\
16631 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
16632 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
16633 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
16634 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
16636 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
16637 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
16639 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
16640 \ ------------------------------\
16641 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
16642 \ ------------------------------\
16643 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
16644 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
16645 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
16646 \ ------------------------------\
16647 BIS.B #LCDVo,&LCDVo_DIR \
16648 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
16649 \ ------------------------------\
16650 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
16651 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
16652 \ ------------------------------\
16653 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
16654 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
16655 \ ******************************\
16657 \ ******************************\
16658 BIS.B #RC5,&IR_IE \ enable RC5_Int
16659 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
16660 MOV #RC5_INT,&IR_Vec \ init interrupt vector
16661 \ ******************************\
16662 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
16663 \ ******************************\
16664 \ %01 0001 0100 \ TAxCTL
16665 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
16666 \ -- \ ID divided by 1
16667 \ -- \ MC MODE = up to TAxCCRn
16668 \ - \ TACLR clear timer count
16671 \ ------------------------------\
16672 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
16673 \ ------------------------------\
16675 \ --- \ TAIDEX pre divisor
16676 \ ------------------------------\
16677 \ %0000 0000 0000 0101 \ TAxCCR0
16678 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
16679 \ ------------------------------\
16680 \ %0000 0000 0001 0000 \ TAxCCTL0
16681 \ - \ CAP capture/compare mode = compare
16684 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
16685 \ ------------------------------\
16686 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
16687 \ ------------------------------\
16688 \ define LPM mode for ACCEPT \
16689 \ ------------------------------\
16690 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
16691 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
16692 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
16693 \ ------------------------------\
16695 \ ------------------------------\
16696 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
16697 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
16698 \ ------------------------------\
16699 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
16700 \ ------------------------------\
16701 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
16702 \ CMP #2,Y \ Power_ON event
16703 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
16705 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
16707 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
16709 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
16711 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
16712 \ ------------------------------\
16714 \ ------------------------------\
16716 \ ------------------------------\
16717 #1000 20_US \ 1- wait 20 ms
16718 %011 TOP_LCD \ 2- send DB5=DB4=1
16719 #205 20_US \ 3- wait 4,1 ms
16720 %011 TOP_LCD \ 4- send again DB5=DB4=1
16721 #5 20_US \ 5- wait 0,1 ms
16722 %011 TOP_LCD \ 6- send again again DB5=DB4=1
16723 #2 20_US \ wait 40 us = LCD cycle
16724 %010 TOP_LCD \ 7- send DB5=1 DB4=0
16725 #2 20_US \ wait 40 us = LCD cycle
16726 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
16727 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
16728 LCD_CLEAR \ 10- "LCD_Clear"
16729 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
16730 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
16731 LCD_CLEAR \ 10- "LCD_Clear"
16732 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
16733 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
16734 CR ." I love you" \ display message on LCD
16735 ['] CR >BODY IS CR \ CR executes its default value
16736 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
16737 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
16738 PWR_STATE ABORT \ init DP and continues with ABORT
16740 \ ------------------------------\
16742 \ ------------------------------\
16743 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
16744 \ ------------------------------\
16745 MOV #SLEEP,X \ replace default background process SLEEP
16746 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
16747 MOV #WARM,X \ replace default WARM
16748 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
16749 MOV X,PC \ then execute new WARM
16751 \ ------------------------------\
16754 ; downloading RC5toLCD.4th is done
16755 RST_HERE ; this app is protected against <reset>
16760 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
16762 [UNDEFINED] MARKER [IF]
16763 \ https://forth-standard.org/standard/core/MARKER
16765 \ ( "<spaces>name" -- )
16766 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
16767 \ with the execution semantics defined below.
16769 \ name Execution: ( -- )
16770 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
16771 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
16772 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
16773 \ not necessarily provided. No other contextual information such as numeric base is affected
16778 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
16779 SUB #2,Y \ 1 Y = LFA
16780 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
16781 ADD #4,&DP \ 3 add 2 cells
16785 MOV @RSP+,IP \ -- PFA
16786 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
16787 MOV @TOS,&INIDP \ set DP value for RST_STATE
16789 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
16796 \ https://forth-standard.org/standard/core/Fetch
16797 \ @ c-addr -- char fetch char from memory
16804 [UNDEFINED] CONSTANT [IF]
16805 \ https://forth-standard.org/standard/core/CONSTANT
16806 \ CONSTANT <name> n -- define a Forth CONSTANT
16810 MOV TOS,-2(W) \ PFA = n
16817 [UNDEFINED] STATE [IF]
16818 \ https://forth-standard.org/standard/core/STATE
16819 \ STATE -- a-addr holds compiler state
16820 STATEADR CONSTANT STATE
16824 \ https://forth-standard.org/standard/core/Equal
16825 \ = x1 x2 -- flag test x1=x2
16832 XOR #-1,TOS \ 1 flag Z = 1
16837 [UNDEFINED] IF [IF]
16838 \ https://forth-standard.org/standard/core/IF
16839 \ IF -- IFadr initialize conditional forward branch
16840 CODE IF \ immediate
16843 MOV &DP,TOS \ -- HERE
16844 ADD #4,&DP \ compile one word, reserve one word
16845 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
16846 ADD #2,TOS \ -- HERE+2=IFadr
16851 [UNDEFINED] THEN [IF]
16852 \ https://forth-standard.org/standard/core/THEN
16853 \ THEN IFadr -- resolve forward branch
16854 CODE THEN \ immediate
16855 MOV &DP,0(TOS) \ -- IFadr
16861 [UNDEFINED] ELSE [IF]
16862 \ https://forth-standard.org/standard/core/ELSE
16863 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
16864 CODE ELSE \ immediate
16865 ADD #4,&DP \ make room to compile two words
16866 MOV &DP,W \ W=HERE+4
16868 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
16870 MOV W,TOS \ -- ELSEadr
16875 [UNDEFINED] DEFER [IF]
16876 \ https://forth-standard.org/standard/core/DEFER
16877 \ DEFER "<spaces>name" --
16878 \ Skip leading space delimiters. Parse name delimited by a space.
16879 \ Create a definition for name with the execution semantics defined below.
16881 \ name Execution: --
16882 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
16883 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
16887 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
16888 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
16894 [UNDEFINED] DEFER! [IF]
16895 \ https://forth-standard.org/standard/core/DEFERStore
16896 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
16897 CODE DEFER! \ xt2 xt1 --
16898 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
16904 [UNDEFINED] IS [IF]
16905 \ https://forth-standard.org/standard/core/IS
16908 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
16909 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
16910 \ or in a definition : ... ['] U. IS DISPLAY ...
16911 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
16913 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
16916 IF POSTPONE ['] POSTPONE DEFER!
16922 [UNDEFINED] >BODY [IF]
16923 \ https://forth-standard.org/standard/core/toBODY
16924 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
16931 \ CODE 20uS \ n -- 8MHz version
16932 \ BEGIN \ 4 + 16 ~ loop
16933 \ MOV #39,rDOCON \ 39
16940 \ MOV #XDOCON,rDOCON \ 2
16945 CODE 20_US \ n -- n * 20 us
16946 BEGIN \ here we presume that LCD_TIM_IFG = 1...
16948 BIT #1,&LCD_TIM_CTL \ 3
16949 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
16950 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
16952 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
16957 CODE TOP_LCD \ LCD Sample
16958 \ \ if write : %xxxx_WWWW --
16959 \ \ if read : -- %0000_RRRR
16960 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
16961 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
16962 0= IF \ write LCD bits pattern
16963 AND.B #LCD_DB,TOS \
16964 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
16965 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16968 THEN \ read LCD bits pattern
16971 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
16972 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
16973 AND.B #LCD_DB,TOS \
16977 CODE LCD_WRC \ char -- Write Char
16978 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
16980 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
16981 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
16982 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
16983 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
16984 COLON \ high level word starts here
16985 TOP_LCD 2 20_US \ write high nibble first
16989 CODE LCD_WRF \ func -- Write Fonction
16990 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
16994 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
16995 : LCD_HOME $02 LCD_WRF 100 20_us ;
16997 \ [UNDEFINED] OR [IF]
16999 \ \ https://forth-standard.org/standard/core/OR
17000 \ \ C OR x1 x2 -- x3 logical OR
17008 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
17009 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
17010 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
17011 \ : LCD_FN_SET $20 OR LCD_WrF ;
17012 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
17013 \ : LCD_GOTO $80 OR LCD_WrF ;
17016 \ CODE LCD_RDS \ -- status Read Status
17017 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17018 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17019 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17020 \ COLON \ starts a FORTH word
17021 \ TOP_LCD 2 20_us \ -- %0000_HHHH
17022 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
17023 \ HI2LO \ switch from FORTH to assembler
17024 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
17025 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
17026 \ MOV @RSP+,IP \ restore IP saved by COLON
17030 \ CODE LCD_RDC \ -- char Read Char
17031 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17036 \ ******************************\
17037 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17038 \ ******************************\
17039 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
17040 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
17041 BIT.B #SW2,&SW2_IN \ test switch S2
17042 0= IF \ case of switch S2 pressed
17043 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
17045 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
17048 BIT.B #SW1,&SW1_IN \ test switch S1 input
17049 0= IF \ case of Switch S1 pressed
17050 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
17052 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
17056 BW1 \ from quit on truncated RC5 message, repeated RC5 command
17060 \ ******************************\
17061 ASM RC5_INT \ wake up on Px.RC5 change interrupt
17062 \ ******************************\
17063 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17064 \ ******************************\
17065 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17066 \ \ SMclock = 8|16|24 MHz
17067 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
17068 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
17069 \ \ SR(9)=new Toggle bit memory (ADD on)
17070 \ ******************************\
17071 \ RC5_FirstStartBitHalfCycle: \
17072 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
17073 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
17074 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
17075 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
17077 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
17078 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
17080 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
17081 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
17083 MOV #1778,X \ RC5_Period * 1us
17084 MOV #14,W \ count of loop
17086 \ ******************************\
17087 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
17088 \ ******************************\ |
17089 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
17090 \ RC5_Compute_3/4_Period: \ |
17091 RRUM #1,X \ X=1/2 cycle |
17094 ADD X,Y \ Y=3/4 cycle
17095 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
17097 \ ******************************\
17098 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
17099 \ ******************************\
17100 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17101 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
17102 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17103 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17104 SUB #1,W \ decrement count loop
17105 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
17106 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17107 0<> WHILE \ ----> out of loop ----+
17108 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
17110 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
17111 CMP Y,X \ 1 | cycle time out of bound ?
17112 U>= IF \ 2 ^ | yes:
17113 BIC #$30,&RC5_TIM_CTL \ | | stop timer
17114 GOTO BW1 \ | | quit on truncated RC5 message
17116 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
17118 REPEAT \ ----> loop back --+ | with X = new RC5_period value
17119 \ ******************************\ |
17120 \ RC5_SampleEndOf: \ <---------------------+
17121 \ ******************************\
17122 BIC #$30,&RC5_TIM_CTL \ stop timer
17123 \ ******************************\
17124 \ RC5_ComputeNewRC5word \
17125 \ ******************************\
17126 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
17127 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
17128 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
17129 \ ******************************\
17130 \ RC5_ComputeC6bit \
17131 \ ******************************\
17132 BIT #BIT14,T \ test /C6 bit in T
17133 0= IF BIS #BIT6,X \ set C6 bit in X
17134 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
17135 \ ******************************\
17136 \ RC5_CommandByteIsDone \ -- BASE RC5_code
17137 \ ******************************\
17138 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17139 \ ******************************\
17140 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
17141 XOR @RSP,T \ (new XOR old) Toggle bits
17142 BIT #UF10,T \ repeated RC5_command ?
17143 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
17144 XOR #UF10,0(RSP) \ 5 toggle bit memory
17145 \ ******************************\
17146 \ Display IR_RC5 code \
17147 \ ******************************\
17148 SUB #8,PSP \ TOS -- x x x x TOS
17149 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
17150 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
17151 MOV #$10,&BASEADR \ set hexadecimal base
17152 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
17153 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
17154 LO2HI \ switch from assembler to FORTH
17155 LCD_CLEAR \ set LCD cursor at home
17156 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
17157 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
17158 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
17159 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
17160 HI2LO \ -- switch from FORTH to assembler
17161 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
17162 MOV @PSP+,TOS \ -- TOS
17166 \ ******************************\
17168 \ ******************************\
17170 \ ... \ insert here your background task
17173 CALL &RXON \ comment this line to disable TERMINAL_INPUT
17175 \ ******************************\
17176 \ here start all interrupts \
17177 \ ******************************\
17178 \ here return all interrupts \
17179 \ ******************************\
17182 \ ******************************\
17184 \ ------------------------------\
17185 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
17186 \ ------------------------------\
17187 \ ... \ init specific I/O sys as you want
17188 \ ... \ before executing default WARM
17189 MOV #WARM,X \ ['] WARM
17191 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
17193 \ ------------------------------\
17195 \ ------------------------------\
17196 CODE STOP \ stops multitasking, must to be used before downloading app
17197 \ ------------------------------\
17198 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
17199 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
17200 MOV X,-2(X) \ restore the default background: SLEEP
17202 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
17203 BIC.B #RC5,&IR_IE \ clear RC5_Int
17204 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
17205 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
17206 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
17207 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
17208 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
17209 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
17211 ." RC5toLCD is removed,"
17212 ." type START to restart"
17213 WARM \ performs reset to reset all interrupt vectors.
17215 \ ------------------------------\
17217 \ ------------------------------\
17218 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
17219 \ ------------------------------\
17220 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
17221 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17222 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17223 \ -- \ID input divider \ 10 = /4
17224 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
17225 \ - \TBCLR TimerB Clear
17228 \ -------------------------------\
17229 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17230 \ -- \CM Capture Mode
17235 \ --- \OUTMOD \ 011 = set/reset
17241 \ -------------------------------\
17243 \ -------------------------------\
17245 \ ------------------------------\
17246 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
17247 \ ------------------------------\
17248 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
17249 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
17250 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
17251 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
17253 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
17254 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
17256 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
17257 \ ------------------------------\
17258 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
17259 \ ------------------------------\
17260 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
17261 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
17262 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17263 \ ------------------------------\
17264 BIS.B #LCDVo,&LCDVo_DIR \
17265 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
17266 \ ------------------------------\
17267 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17268 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17269 \ ------------------------------\
17270 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17271 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17272 \ ******************************\
17274 \ ******************************\
17275 BIS.B #RC5,&IR_IE \ enable RC5_Int
17276 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17277 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17278 \ ******************************\
17279 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
17280 \ ******************************\
17281 \ %01 0001 0100 \ TAxCTL
17282 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
17283 \ -- \ ID divided by 1
17284 \ -- \ MC MODE = up to TAxCCRn
17285 \ - \ TACLR clear timer count
17288 \ ------------------------------\
17289 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
17290 \ ------------------------------\
17292 \ --- \ TAIDEX pre divisor
17293 \ ------------------------------\
17294 \ %0000 0000 0000 0101 \ TAxCCR0
17295 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
17296 \ ------------------------------\
17297 \ %0000 0000 0001 0000 \ TAxCCTL0
17298 \ - \ CAP capture/compare mode = compare
17301 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
17302 \ ------------------------------\
17303 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17304 \ ------------------------------\
17305 \ define LPM mode for ACCEPT \
17306 \ ------------------------------\
17307 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17308 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17309 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17310 \ ------------------------------\
17312 \ ------------------------------\
17313 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
17314 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
17315 \ ------------------------------\
17316 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
17317 \ ------------------------------\
17318 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
17319 \ CMP #2,Y \ Power_ON event
17320 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
17322 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
17324 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
17326 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
17328 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
17329 \ ------------------------------\
17331 \ ------------------------------\
17333 \ ------------------------------\
17334 #1000 20_US \ 1- wait 20 ms
17335 %011 TOP_LCD \ 2- send DB5=DB4=1
17336 #205 20_US \ 3- wait 4,1 ms
17337 %011 TOP_LCD \ 4- send again DB5=DB4=1
17338 #5 20_US \ 5- wait 0,1 ms
17339 %011 TOP_LCD \ 6- send again again DB5=DB4=1
17340 #2 20_US \ wait 40 us = LCD cycle
17341 %010 TOP_LCD \ 7- send DB5=1 DB4=0
17342 #2 20_US \ wait 40 us = LCD cycle
17343 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17344 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17345 LCD_CLEAR \ 10- "LCD_Clear"
17346 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17347 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17348 LCD_CLEAR \ 10- "LCD_Clear"
17349 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17350 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17351 CR ." I love you" \ display message on LCD
17352 ['] CR >BODY IS CR \ CR executes its default value
17353 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
17354 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17355 PWR_STATE ABORT \ init DP and continues with ABORT
17357 \ ------------------------------\
17359 \ ------------------------------\
17360 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
17361 \ ------------------------------\
17362 MOV #SLEEP,X \ replace default background process SLEEP
17363 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
17364 MOV #WARM,X \ replace default WARM
17365 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
17366 MOV X,PC \ then execute new WARM
17368 \ ------------------------------\
17371 ; downloading RC5toLCD.4th is done
17372 RST_HERE ; this app is protected against <reset>
17377 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
17379 [UNDEFINED] MARKER [IF]
17380 \ https://forth-standard.org/standard/core/MARKER
17382 \ ( "<spaces>name" -- )
17383 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
17384 \ with the execution semantics defined below.
17386 \ name Execution: ( -- )
17387 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
17388 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
17389 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
17390 \ not necessarily provided. No other contextual information such as numeric base is affected
17395 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
17396 SUB #2,Y \ 1 Y = LFA
17397 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
17398 ADD #4,&DP \ 3 add 2 cells
17402 MOV @RSP+,IP \ -- PFA
17403 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
17404 MOV @TOS,&INIDP \ set DP value for RST_STATE
17406 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
17413 \ https://forth-standard.org/standard/core/Fetch
17414 \ @ c-addr -- char fetch char from memory
17421 [UNDEFINED] CONSTANT [IF]
17422 \ https://forth-standard.org/standard/core/CONSTANT
17423 \ CONSTANT <name> n -- define a Forth CONSTANT
17427 MOV TOS,-2(W) \ PFA = n
17434 [UNDEFINED] STATE [IF]
17435 \ https://forth-standard.org/standard/core/STATE
17436 \ STATE -- a-addr holds compiler state
17437 STATEADR CONSTANT STATE
17441 \ https://forth-standard.org/standard/core/Equal
17442 \ = x1 x2 -- flag test x1=x2
17449 XOR #-1,TOS \ 1 flag Z = 1
17454 [UNDEFINED] IF [IF]
17455 \ https://forth-standard.org/standard/core/IF
17456 \ IF -- IFadr initialize conditional forward branch
17457 CODE IF \ immediate
17460 MOV &DP,TOS \ -- HERE
17461 ADD #4,&DP \ compile one word, reserve one word
17462 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
17463 ADD #2,TOS \ -- HERE+2=IFadr
17468 [UNDEFINED] THEN [IF]
17469 \ https://forth-standard.org/standard/core/THEN
17470 \ THEN IFadr -- resolve forward branch
17471 CODE THEN \ immediate
17472 MOV &DP,0(TOS) \ -- IFadr
17478 [UNDEFINED] ELSE [IF]
17479 \ https://forth-standard.org/standard/core/ELSE
17480 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
17481 CODE ELSE \ immediate
17482 ADD #4,&DP \ make room to compile two words
17483 MOV &DP,W \ W=HERE+4
17485 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
17487 MOV W,TOS \ -- ELSEadr
17492 [UNDEFINED] DEFER [IF]
17493 \ https://forth-standard.org/standard/core/DEFER
17494 \ DEFER "<spaces>name" --
17495 \ Skip leading space delimiters. Parse name delimited by a space.
17496 \ Create a definition for name with the execution semantics defined below.
17498 \ name Execution: --
17499 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
17500 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
17504 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
17505 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
17511 [UNDEFINED] DEFER! [IF]
17512 \ https://forth-standard.org/standard/core/DEFERStore
17513 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
17514 CODE DEFER! \ xt2 xt1 --
17515 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
17521 [UNDEFINED] IS [IF]
17522 \ https://forth-standard.org/standard/core/IS
17525 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
17526 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
17527 \ or in a definition : ... ['] U. IS DISPLAY ...
17528 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
17530 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
17533 IF POSTPONE ['] POSTPONE DEFER!
17539 [UNDEFINED] >BODY [IF]
17540 \ https://forth-standard.org/standard/core/toBODY
17541 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
17548 \ CODE 20uS \ n -- 8MHz version
17549 \ BEGIN \ 4 + 16 ~ loop
17550 \ MOV #39,rDOCON \ 39
17557 \ MOV #XDOCON,rDOCON \ 2
17562 CODE 20_US \ n -- n * 20 us
17563 BEGIN \ here we presume that LCD_TIM_IFG = 1...
17565 BIT #1,&LCD_TIM_CTL \ 3
17566 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
17567 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
17569 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
17574 CODE TOP_LCD \ LCD Sample
17575 \ \ if write : %xxxx_WWWW --
17576 \ \ if read : -- %0000_RRRR
17577 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
17578 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
17579 0= IF \ write LCD bits pattern
17580 AND.B #LCD_DB,TOS \
17581 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
17582 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17585 THEN \ read LCD bits pattern
17588 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
17589 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
17590 AND.B #LCD_DB,TOS \
17594 CODE LCD_WRC \ char -- Write Char
17595 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17597 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
17598 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
17599 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
17600 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
17601 COLON \ high level word starts here
17602 TOP_LCD 2 20_US \ write high nibble first
17606 CODE LCD_WRF \ func -- Write Fonction
17607 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17611 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
17612 : LCD_HOME $02 LCD_WRF 100 20_us ;
17614 \ [UNDEFINED] OR [IF]
17616 \ \ https://forth-standard.org/standard/core/OR
17617 \ \ C OR x1 x2 -- x3 logical OR
17625 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
17626 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
17627 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
17628 \ : LCD_FN_SET $20 OR LCD_WrF ;
17629 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
17630 \ : LCD_GOTO $80 OR LCD_WrF ;
17633 \ CODE LCD_RDS \ -- status Read Status
17634 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
17635 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
17636 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
17637 \ COLON \ starts a FORTH word
17638 \ TOP_LCD 2 20_us \ -- %0000_HHHH
17639 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
17640 \ HI2LO \ switch from FORTH to assembler
17641 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
17642 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
17643 \ MOV @RSP+,IP \ restore IP saved by COLON
17647 \ CODE LCD_RDC \ -- char Read Char
17648 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
17653 \ ******************************\
17654 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
17655 \ ******************************\
17656 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
17657 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
17658 BIT.B #SW2,&SW2_IN \ test switch S2
17659 0= IF \ case of switch S2 pressed
17660 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
17662 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
17665 BIT.B #SW1,&SW1_IN \ test switch S1 input
17666 0= IF \ case of Switch S1 pressed
17667 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
17669 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
17673 BW1 \ from quit on truncated RC5 message, repeated RC5 command
17677 \ ******************************\
17678 ASM RC5_INT \ wake up on Px.RC5 change interrupt
17679 \ ******************************\
17680 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
17681 \ ******************************\
17682 \ \ in : SR(9)=old Toggle bit memory (ADD on)
17683 \ \ SMclock = 8|16|24 MHz
17684 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
17685 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
17686 \ \ SR(9)=new Toggle bit memory (ADD on)
17687 \ ******************************\
17688 \ RC5_FirstStartBitHalfCycle: \
17689 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
17690 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
17691 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
17692 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
17694 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
17695 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
17697 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
17698 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
17700 MOV #1778,X \ RC5_Period * 1us
17701 MOV #14,W \ count of loop
17703 \ ******************************\
17704 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
17705 \ ******************************\ |
17706 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
17707 \ RC5_Compute_3/4_Period: \ |
17708 RRUM #1,X \ X=1/2 cycle |
17711 ADD X,Y \ Y=3/4 cycle
17712 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
17714 \ ******************************\
17715 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
17716 \ ******************************\
17717 BIT.B #RC5,&IR_IN \ C_flag = IR bit
17718 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
17719 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
17720 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
17721 SUB #1,W \ decrement count loop
17722 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
17723 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
17724 0<> WHILE \ ----> out of loop ----+
17725 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
17727 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
17728 CMP Y,X \ 1 | cycle time out of bound ?
17729 U>= IF \ 2 ^ | yes:
17730 BIC #$30,&RC5_TIM_CTL \ | | stop timer
17731 GOTO BW1 \ | | quit on truncated RC5 message
17733 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
17735 REPEAT \ ----> loop back --+ | with X = new RC5_period value
17736 \ ******************************\ |
17737 \ RC5_SampleEndOf: \ <---------------------+
17738 \ ******************************\
17739 BIC #$30,&RC5_TIM_CTL \ stop timer
17740 \ ******************************\
17741 \ RC5_ComputeNewRC5word \
17742 \ ******************************\
17743 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
17744 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
17745 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
17746 \ ******************************\
17747 \ RC5_ComputeC6bit \
17748 \ ******************************\
17749 BIT #BIT14,T \ test /C6 bit in T
17750 0= IF BIS #BIT6,X \ set C6 bit in X
17751 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
17752 \ ******************************\
17753 \ RC5_CommandByteIsDone \ -- BASE RC5_code
17754 \ ******************************\
17755 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
17756 \ ******************************\
17757 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
17758 XOR @RSP,T \ (new XOR old) Toggle bits
17759 BIT #UF10,T \ repeated RC5_command ?
17760 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
17761 XOR #UF10,0(RSP) \ 5 toggle bit memory
17762 \ ******************************\
17763 \ Display IR_RC5 code \
17764 \ ******************************\
17765 SUB #8,PSP \ TOS -- x x x x TOS
17766 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
17767 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
17768 MOV #$10,&BASEADR \ set hexadecimal base
17769 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
17770 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
17771 LO2HI \ switch from assembler to FORTH
17772 LCD_CLEAR \ set LCD cursor at home
17773 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
17774 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
17775 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
17776 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
17777 HI2LO \ -- switch from FORTH to assembler
17778 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
17779 MOV @PSP+,TOS \ -- TOS
17783 \ ******************************\
17785 \ ******************************\
17787 \ ... \ insert here your background task
17790 CALL &RXON \ comment this line to disable TERMINAL_INPUT
17792 \ ******************************\
17793 \ here start all interrupts \
17794 \ ******************************\
17795 \ here return all interrupts \
17796 \ ******************************\
17799 \ ******************************\
17801 \ ------------------------------\
17802 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
17803 \ ------------------------------\
17804 \ ... \ init specific I/O sys as you want
17805 \ ... \ before executing default WARM
17806 MOV #WARM,X \ ['] WARM
17808 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
17810 \ ------------------------------\
17812 \ ------------------------------\
17813 CODE STOP \ stops multitasking, must to be used before downloading app
17814 \ ------------------------------\
17815 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
17816 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
17817 MOV X,-2(X) \ restore the default background: SLEEP
17819 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
17820 BIC.B #RC5,&IR_IE \ clear RC5_Int
17821 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
17822 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
17823 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
17824 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
17825 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
17826 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
17828 ." RC5toLCD is removed,"
17829 ." type START to restart"
17830 WARM \ performs reset to reset all interrupt vectors.
17832 \ ------------------------------\
17834 \ ------------------------------\
17835 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
17836 \ ------------------------------\
17837 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
17838 \ - - \CNTL Counter lentgh \ 00 = 16 bits
17839 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
17840 \ -- \ID input divider \ 10 = /4
17841 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
17842 \ - \TBCLR TimerB Clear
17845 \ -------------------------------\
17846 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
17847 \ -- \CM Capture Mode
17852 \ --- \OUTMOD \ 011 = set/reset
17858 \ -------------------------------\
17860 \ -------------------------------\
17862 \ ------------------------------\
17863 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
17864 \ ------------------------------\
17865 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
17866 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
17867 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
17868 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
17870 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
17871 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
17873 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
17874 \ ------------------------------\
17875 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
17876 \ ------------------------------\
17877 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
17878 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
17879 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
17880 \ ------------------------------\
17881 BIS.B #LCDVo,&LCDVo_DIR \
17882 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
17883 \ ------------------------------\
17884 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
17885 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
17886 \ ------------------------------\
17887 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
17888 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
17889 \ ******************************\
17891 \ ******************************\
17892 BIS.B #RC5,&IR_IE \ enable RC5_Int
17893 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
17894 MOV #RC5_INT,&IR_Vec \ init interrupt vector
17895 \ ******************************\
17896 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
17897 \ ******************************\
17898 \ %01 0001 0100 \ TAxCTL
17899 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
17900 \ -- \ ID divided by 1
17901 \ -- \ MC MODE = up to TAxCCRn
17902 \ - \ TACLR clear timer count
17905 \ ------------------------------\
17906 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
17907 \ ------------------------------\
17909 \ --- \ TAIDEX pre divisor
17910 \ ------------------------------\
17911 \ %0000 0000 0000 0101 \ TAxCCR0
17912 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
17913 \ ------------------------------\
17914 \ %0000 0000 0001 0000 \ TAxCCTL0
17915 \ - \ CAP capture/compare mode = compare
17918 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
17919 \ ------------------------------\
17920 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
17921 \ ------------------------------\
17922 \ define LPM mode for ACCEPT \
17923 \ ------------------------------\
17924 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
17925 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
17926 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
17927 \ ------------------------------\
17929 \ ------------------------------\
17930 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
17931 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
17932 \ ------------------------------\
17933 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
17934 \ ------------------------------\
17935 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
17936 \ CMP #2,Y \ Power_ON event
17937 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
17939 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
17941 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
17943 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
17945 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
17946 \ ------------------------------\
17948 \ ------------------------------\
17950 \ ------------------------------\
17951 #1000 20_US \ 1- wait 20 ms
17952 %011 TOP_LCD \ 2- send DB5=DB4=1
17953 #205 20_US \ 3- wait 4,1 ms
17954 %011 TOP_LCD \ 4- send again DB5=DB4=1
17955 #5 20_US \ 5- wait 0,1 ms
17956 %011 TOP_LCD \ 6- send again again DB5=DB4=1
17957 #2 20_US \ wait 40 us = LCD cycle
17958 %010 TOP_LCD \ 7- send DB5=1 DB4=0
17959 #2 20_US \ wait 40 us = LCD cycle
17960 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
17961 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
17962 LCD_CLEAR \ 10- "LCD_Clear"
17963 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
17964 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
17965 LCD_CLEAR \ 10- "LCD_Clear"
17966 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
17967 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
17968 CR ." I love you" \ display message on LCD
17969 ['] CR >BODY IS CR \ CR executes its default value
17970 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
17971 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
17972 PWR_STATE ABORT \ init DP and continues with ABORT
17974 \ ------------------------------\
17976 \ ------------------------------\
17977 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
17978 \ ------------------------------\
17979 MOV #SLEEP,X \ replace default background process SLEEP
17980 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
17981 MOV #WARM,X \ replace default WARM
17982 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
17983 MOV X,PC \ then execute new WARM
17985 \ ------------------------------\
17988 ; downloading RC5toLCD.4th is done
17989 RST_HERE ; this app is protected against <reset>
17994 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
17996 [UNDEFINED] MARKER [IF]
17997 \ https://forth-standard.org/standard/core/MARKER
17999 \ ( "<spaces>name" -- )
18000 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
18001 \ with the execution semantics defined below.
18003 \ name Execution: ( -- )
18004 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
18005 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
18006 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
18007 \ not necessarily provided. No other contextual information such as numeric base is affected
18012 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
18013 SUB #2,Y \ 1 Y = LFA
18014 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
18015 ADD #4,&DP \ 3 add 2 cells
18019 MOV @RSP+,IP \ -- PFA
18020 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
18021 MOV @TOS,&INIDP \ set DP value for RST_STATE
18023 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
18030 \ https://forth-standard.org/standard/core/Fetch
18031 \ @ c-addr -- char fetch char from memory
18038 [UNDEFINED] CONSTANT [IF]
18039 \ https://forth-standard.org/standard/core/CONSTANT
18040 \ CONSTANT <name> n -- define a Forth CONSTANT
18044 MOV TOS,-2(W) \ PFA = n
18051 [UNDEFINED] STATE [IF]
18052 \ https://forth-standard.org/standard/core/STATE
18053 \ STATE -- a-addr holds compiler state
18054 STATEADR CONSTANT STATE
18058 \ https://forth-standard.org/standard/core/Equal
18059 \ = x1 x2 -- flag test x1=x2
18066 XOR #-1,TOS \ 1 flag Z = 1
18071 [UNDEFINED] IF [IF]
18072 \ https://forth-standard.org/standard/core/IF
18073 \ IF -- IFadr initialize conditional forward branch
18074 CODE IF \ immediate
18077 MOV &DP,TOS \ -- HERE
18078 ADD #4,&DP \ compile one word, reserve one word
18079 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
18080 ADD #2,TOS \ -- HERE+2=IFadr
18085 [UNDEFINED] THEN [IF]
18086 \ https://forth-standard.org/standard/core/THEN
18087 \ THEN IFadr -- resolve forward branch
18088 CODE THEN \ immediate
18089 MOV &DP,0(TOS) \ -- IFadr
18095 [UNDEFINED] ELSE [IF]
18096 \ https://forth-standard.org/standard/core/ELSE
18097 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
18098 CODE ELSE \ immediate
18099 ADD #4,&DP \ make room to compile two words
18100 MOV &DP,W \ W=HERE+4
18102 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
18104 MOV W,TOS \ -- ELSEadr
18109 [UNDEFINED] DEFER [IF]
18110 \ https://forth-standard.org/standard/core/DEFER
18111 \ DEFER "<spaces>name" --
18112 \ Skip leading space delimiters. Parse name delimited by a space.
18113 \ Create a definition for name with the execution semantics defined below.
18115 \ name Execution: --
18116 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
18117 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
18121 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
18122 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
18128 [UNDEFINED] DEFER! [IF]
18129 \ https://forth-standard.org/standard/core/DEFERStore
18130 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
18131 CODE DEFER! \ xt2 xt1 --
18132 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
18138 [UNDEFINED] IS [IF]
18139 \ https://forth-standard.org/standard/core/IS
18142 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
18143 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
18144 \ or in a definition : ... ['] U. IS DISPLAY ...
18145 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
18147 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
18150 IF POSTPONE ['] POSTPONE DEFER!
18156 [UNDEFINED] >BODY [IF]
18157 \ https://forth-standard.org/standard/core/toBODY
18158 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
18165 \ CODE 20uS \ n -- 8MHz version
18166 \ BEGIN \ 4 + 16 ~ loop
18167 \ MOV #39,rDOCON \ 39
18174 \ MOV #XDOCON,rDOCON \ 2
18179 CODE 20_US \ n -- n * 20 us
18180 BEGIN \ here we presume that LCD_TIM_IFG = 1...
18182 BIT #1,&LCD_TIM_CTL \ 3
18183 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
18184 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
18186 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
18191 CODE TOP_LCD \ LCD Sample
18192 \ \ if write : %xxxx_WWWW --
18193 \ \ if read : -- %0000_RRRR
18194 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18195 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18196 0= IF \ write LCD bits pattern
18197 AND.B #LCD_DB,TOS \
18198 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18199 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18202 THEN \ read LCD bits pattern
18205 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18206 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18207 AND.B #LCD_DB,TOS \
18211 CODE LCD_WRC \ char -- Write Char
18212 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18214 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
18215 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
18216 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18217 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18218 COLON \ high level word starts here
18219 TOP_LCD 2 20_US \ write high nibble first
18223 CODE LCD_WRF \ func -- Write Fonction
18224 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18228 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
18229 : LCD_HOME $02 LCD_WRF 100 20_us ;
18231 \ [UNDEFINED] OR [IF]
18233 \ \ https://forth-standard.org/standard/core/OR
18234 \ \ C OR x1 x2 -- x3 logical OR
18242 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
18243 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
18244 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
18245 \ : LCD_FN_SET $20 OR LCD_WrF ;
18246 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
18247 \ : LCD_GOTO $80 OR LCD_WrF ;
18250 \ CODE LCD_RDS \ -- status Read Status
18251 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18252 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18253 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18254 \ COLON \ starts a FORTH word
18255 \ TOP_LCD 2 20_us \ -- %0000_HHHH
18256 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
18257 \ HI2LO \ switch from FORTH to assembler
18258 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
18259 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
18260 \ MOV @RSP+,IP \ restore IP saved by COLON
18264 \ CODE LCD_RDC \ -- char Read Char
18265 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18270 \ ******************************\
18271 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18272 \ ******************************\
18273 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18274 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
18275 BIT.B #SW2,&SW2_IN \ test switch S2
18276 0= IF \ case of switch S2 pressed
18277 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18279 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
18282 BIT.B #SW1,&SW1_IN \ test switch S1 input
18283 0= IF \ case of Switch S1 pressed
18284 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18286 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18290 BW1 \ from quit on truncated RC5 message, repeated RC5 command
18294 \ ******************************\
18295 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18296 \ ******************************\
18297 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18298 \ ******************************\
18299 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18300 \ \ SMclock = 8|16|24 MHz
18301 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18302 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18303 \ \ SR(9)=new Toggle bit memory (ADD on)
18304 \ ******************************\
18305 \ RC5_FirstStartBitHalfCycle: \
18306 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18307 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18308 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
18309 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
18311 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
18312 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
18314 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
18315 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
18317 MOV #1778,X \ RC5_Period * 1us
18318 MOV #14,W \ count of loop
18320 \ ******************************\
18321 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
18322 \ ******************************\ |
18323 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18324 \ RC5_Compute_3/4_Period: \ |
18325 RRUM #1,X \ X=1/2 cycle |
18328 ADD X,Y \ Y=3/4 cycle
18329 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
18331 \ ******************************\
18332 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18333 \ ******************************\
18334 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18335 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
18336 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18337 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18338 SUB #1,W \ decrement count loop
18339 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
18340 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18341 0<> WHILE \ ----> out of loop ----+
18342 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18344 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
18345 CMP Y,X \ 1 | cycle time out of bound ?
18346 U>= IF \ 2 ^ | yes:
18347 BIC #$30,&RC5_TIM_CTL \ | | stop timer
18348 GOTO BW1 \ | | quit on truncated RC5 message
18350 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
18352 REPEAT \ ----> loop back --+ | with X = new RC5_period value
18353 \ ******************************\ |
18354 \ RC5_SampleEndOf: \ <---------------------+
18355 \ ******************************\
18356 BIC #$30,&RC5_TIM_CTL \ stop timer
18357 \ ******************************\
18358 \ RC5_ComputeNewRC5word \
18359 \ ******************************\
18360 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
18361 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
18362 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
18363 \ ******************************\
18364 \ RC5_ComputeC6bit \
18365 \ ******************************\
18366 BIT #BIT14,T \ test /C6 bit in T
18367 0= IF BIS #BIT6,X \ set C6 bit in X
18368 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
18369 \ ******************************\
18370 \ RC5_CommandByteIsDone \ -- BASE RC5_code
18371 \ ******************************\
18372 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
18373 \ ******************************\
18374 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
18375 XOR @RSP,T \ (new XOR old) Toggle bits
18376 BIT #UF10,T \ repeated RC5_command ?
18377 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
18378 XOR #UF10,0(RSP) \ 5 toggle bit memory
18379 \ ******************************\
18380 \ Display IR_RC5 code \
18381 \ ******************************\
18382 SUB #8,PSP \ TOS -- x x x x TOS
18383 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
18384 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
18385 MOV #$10,&BASEADR \ set hexadecimal base
18386 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
18387 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
18388 LO2HI \ switch from assembler to FORTH
18389 LCD_CLEAR \ set LCD cursor at home
18390 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
18391 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
18392 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
18393 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
18394 HI2LO \ -- switch from FORTH to assembler
18395 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
18396 MOV @PSP+,TOS \ -- TOS
18400 \ ******************************\
18402 \ ******************************\
18404 \ ... \ insert here your background task
18407 CALL &RXON \ comment this line to disable TERMINAL_INPUT
18409 \ ******************************\
18410 \ here start all interrupts \
18411 \ ******************************\
18412 \ here return all interrupts \
18413 \ ******************************\
18416 \ ******************************\
18418 \ ------------------------------\
18419 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
18420 \ ------------------------------\
18421 \ ... \ init specific I/O sys as you want
18422 \ ... \ before executing default WARM
18423 MOV #WARM,X \ ['] WARM
18425 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
18427 \ ------------------------------\
18429 \ ------------------------------\
18430 CODE STOP \ stops multitasking, must to be used before downloading app
18431 \ ------------------------------\
18432 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
18433 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
18434 MOV X,-2(X) \ restore the default background: SLEEP
18436 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
18437 BIC.B #RC5,&IR_IE \ clear RC5_Int
18438 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
18439 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
18440 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
18441 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
18442 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
18443 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
18445 ." RC5toLCD is removed,"
18446 ." type START to restart"
18447 WARM \ performs reset to reset all interrupt vectors.
18449 \ ------------------------------\
18451 \ ------------------------------\
18452 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
18453 \ ------------------------------\
18454 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
18455 \ - - \CNTL Counter lentgh \ 00 = 16 bits
18456 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
18457 \ -- \ID input divider \ 10 = /4
18458 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
18459 \ - \TBCLR TimerB Clear
18462 \ -------------------------------\
18463 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
18464 \ -- \CM Capture Mode
18469 \ --- \OUTMOD \ 011 = set/reset
18475 \ -------------------------------\
18477 \ -------------------------------\
18479 \ ------------------------------\
18480 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
18481 \ ------------------------------\
18482 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
18483 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
18484 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
18485 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
18487 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
18488 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
18490 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
18491 \ ------------------------------\
18492 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
18493 \ ------------------------------\
18494 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
18495 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
18496 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
18497 \ ------------------------------\
18498 BIS.B #LCDVo,&LCDVo_DIR \
18499 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
18500 \ ------------------------------\
18501 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
18502 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
18503 \ ------------------------------\
18504 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
18505 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
18506 \ ******************************\
18508 \ ******************************\
18509 BIS.B #RC5,&IR_IE \ enable RC5_Int
18510 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
18511 MOV #RC5_INT,&IR_Vec \ init interrupt vector
18512 \ ******************************\
18513 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
18514 \ ******************************\
18515 \ %01 0001 0100 \ TAxCTL
18516 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
18517 \ -- \ ID divided by 1
18518 \ -- \ MC MODE = up to TAxCCRn
18519 \ - \ TACLR clear timer count
18522 \ ------------------------------\
18523 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
18524 \ ------------------------------\
18526 \ --- \ TAIDEX pre divisor
18527 \ ------------------------------\
18528 \ %0000 0000 0000 0101 \ TAxCCR0
18529 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
18530 \ ------------------------------\
18531 \ %0000 0000 0001 0000 \ TAxCCTL0
18532 \ - \ CAP capture/compare mode = compare
18535 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
18536 \ ------------------------------\
18537 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
18538 \ ------------------------------\
18539 \ define LPM mode for ACCEPT \
18540 \ ------------------------------\
18541 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
18542 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
18543 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
18544 \ ------------------------------\
18546 \ ------------------------------\
18547 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
18548 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
18549 \ ------------------------------\
18550 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
18551 \ ------------------------------\
18552 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
18553 \ CMP #2,Y \ Power_ON event
18554 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
18556 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
18558 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
18560 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
18562 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
18563 \ ------------------------------\
18565 \ ------------------------------\
18567 \ ------------------------------\
18568 #1000 20_US \ 1- wait 20 ms
18569 %011 TOP_LCD \ 2- send DB5=DB4=1
18570 #205 20_US \ 3- wait 4,1 ms
18571 %011 TOP_LCD \ 4- send again DB5=DB4=1
18572 #5 20_US \ 5- wait 0,1 ms
18573 %011 TOP_LCD \ 6- send again again DB5=DB4=1
18574 #2 20_US \ wait 40 us = LCD cycle
18575 %010 TOP_LCD \ 7- send DB5=1 DB4=0
18576 #2 20_US \ wait 40 us = LCD cycle
18577 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
18578 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
18579 LCD_CLEAR \ 10- "LCD_Clear"
18580 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
18581 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
18582 LCD_CLEAR \ 10- "LCD_Clear"
18583 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
18584 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
18585 CR ." I love you" \ display message on LCD
18586 ['] CR >BODY IS CR \ CR executes its default value
18587 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
18588 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
18589 PWR_STATE ABORT \ init DP and continues with ABORT
18591 \ ------------------------------\
18593 \ ------------------------------\
18594 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
18595 \ ------------------------------\
18596 MOV #SLEEP,X \ replace default background process SLEEP
18597 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
18598 MOV #WARM,X \ replace default WARM
18599 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
18600 MOV X,PC \ then execute new WARM
18602 \ ------------------------------\
18605 ; downloading RC5toLCD.4th is done
18606 RST_HERE ; this app is protected against <reset>
18611 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
18613 [UNDEFINED] MARKER [IF]
18614 \ https://forth-standard.org/standard/core/MARKER
18616 \ ( "<spaces>name" -- )
18617 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
18618 \ with the execution semantics defined below.
18620 \ name Execution: ( -- )
18621 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
18622 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
18623 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
18624 \ not necessarily provided. No other contextual information such as numeric base is affected
18629 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
18630 SUB #2,Y \ 1 Y = LFA
18631 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
18632 ADD #4,&DP \ 3 add 2 cells
18636 MOV @RSP+,IP \ -- PFA
18637 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
18638 MOV @TOS,&INIDP \ set DP value for RST_STATE
18640 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
18647 \ https://forth-standard.org/standard/core/Fetch
18648 \ @ c-addr -- char fetch char from memory
18655 [UNDEFINED] CONSTANT [IF]
18656 \ https://forth-standard.org/standard/core/CONSTANT
18657 \ CONSTANT <name> n -- define a Forth CONSTANT
18661 MOV TOS,-2(W) \ PFA = n
18668 [UNDEFINED] STATE [IF]
18669 \ https://forth-standard.org/standard/core/STATE
18670 \ STATE -- a-addr holds compiler state
18671 STATEADR CONSTANT STATE
18675 \ https://forth-standard.org/standard/core/Equal
18676 \ = x1 x2 -- flag test x1=x2
18683 XOR #-1,TOS \ 1 flag Z = 1
18688 [UNDEFINED] IF [IF]
18689 \ https://forth-standard.org/standard/core/IF
18690 \ IF -- IFadr initialize conditional forward branch
18691 CODE IF \ immediate
18694 MOV &DP,TOS \ -- HERE
18695 ADD #4,&DP \ compile one word, reserve one word
18696 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
18697 ADD #2,TOS \ -- HERE+2=IFadr
18702 [UNDEFINED] THEN [IF]
18703 \ https://forth-standard.org/standard/core/THEN
18704 \ THEN IFadr -- resolve forward branch
18705 CODE THEN \ immediate
18706 MOV &DP,0(TOS) \ -- IFadr
18712 [UNDEFINED] ELSE [IF]
18713 \ https://forth-standard.org/standard/core/ELSE
18714 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
18715 CODE ELSE \ immediate
18716 ADD #4,&DP \ make room to compile two words
18717 MOV &DP,W \ W=HERE+4
18719 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
18721 MOV W,TOS \ -- ELSEadr
18726 [UNDEFINED] DEFER [IF]
18727 \ https://forth-standard.org/standard/core/DEFER
18728 \ DEFER "<spaces>name" --
18729 \ Skip leading space delimiters. Parse name delimited by a space.
18730 \ Create a definition for name with the execution semantics defined below.
18732 \ name Execution: --
18733 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
18734 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
18738 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
18739 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
18745 [UNDEFINED] DEFER! [IF]
18746 \ https://forth-standard.org/standard/core/DEFERStore
18747 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
18748 CODE DEFER! \ xt2 xt1 --
18749 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
18755 [UNDEFINED] IS [IF]
18756 \ https://forth-standard.org/standard/core/IS
18759 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
18760 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
18761 \ or in a definition : ... ['] U. IS DISPLAY ...
18762 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
18764 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
18767 IF POSTPONE ['] POSTPONE DEFER!
18773 [UNDEFINED] >BODY [IF]
18774 \ https://forth-standard.org/standard/core/toBODY
18775 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
18782 \ CODE 20uS \ n -- 8MHz version
18783 \ BEGIN \ 4 + 16 ~ loop
18784 \ MOV #39,rDOCON \ 39
18791 \ MOV #XDOCON,rDOCON \ 2
18796 CODE 20_US \ n -- n * 20 us
18797 BEGIN \ here we presume that LCD_TIM_IFG = 1...
18799 BIT #1,&LCD_TIM_CTL \ 3
18800 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
18801 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
18803 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
18808 CODE TOP_LCD \ LCD Sample
18809 \ \ if write : %xxxx_WWWW --
18810 \ \ if read : -- %0000_RRRR
18811 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
18812 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
18813 0= IF \ write LCD bits pattern
18814 AND.B #LCD_DB,TOS \
18815 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
18816 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18819 THEN \ read LCD bits pattern
18822 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
18823 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
18824 AND.B #LCD_DB,TOS \
18828 CODE LCD_WRC \ char -- Write Char
18829 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18831 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
18832 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
18833 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
18834 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
18835 COLON \ high level word starts here
18836 TOP_LCD 2 20_US \ write high nibble first
18840 CODE LCD_WRF \ func -- Write Fonction
18841 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18845 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
18846 : LCD_HOME $02 LCD_WRF 100 20_us ;
18848 \ [UNDEFINED] OR [IF]
18850 \ \ https://forth-standard.org/standard/core/OR
18851 \ \ C OR x1 x2 -- x3 logical OR
18859 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
18860 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
18861 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
18862 \ : LCD_FN_SET $20 OR LCD_WrF ;
18863 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
18864 \ : LCD_GOTO $80 OR LCD_WrF ;
18867 \ CODE LCD_RDS \ -- status Read Status
18868 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
18869 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
18870 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
18871 \ COLON \ starts a FORTH word
18872 \ TOP_LCD 2 20_us \ -- %0000_HHHH
18873 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
18874 \ HI2LO \ switch from FORTH to assembler
18875 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
18876 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
18877 \ MOV @RSP+,IP \ restore IP saved by COLON
18881 \ CODE LCD_RDC \ -- char Read Char
18882 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
18887 \ ******************************\
18888 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
18889 \ ******************************\
18890 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18891 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
18892 BIT.B #SW2,&SW2_IN \ test switch S2
18893 0= IF \ case of switch S2 pressed
18894 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
18896 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
18899 BIT.B #SW1,&SW1_IN \ test switch S1 input
18900 0= IF \ case of Switch S1 pressed
18901 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
18903 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
18907 BW1 \ from quit on truncated RC5 message, repeated RC5 command
18911 \ ******************************\
18912 ASM RC5_INT \ wake up on Px.RC5 change interrupt
18913 \ ******************************\
18914 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
18915 \ ******************************\
18916 \ \ in : SR(9)=old Toggle bit memory (ADD on)
18917 \ \ SMclock = 8|16|24 MHz
18918 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
18919 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
18920 \ \ SR(9)=new Toggle bit memory (ADD on)
18921 \ ******************************\
18922 \ RC5_FirstStartBitHalfCycle: \
18923 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
18924 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
18925 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
18926 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
18928 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
18929 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
18931 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
18932 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
18934 MOV #1778,X \ RC5_Period * 1us
18935 MOV #14,W \ count of loop
18937 \ ******************************\
18938 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
18939 \ ******************************\ |
18940 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
18941 \ RC5_Compute_3/4_Period: \ |
18942 RRUM #1,X \ X=1/2 cycle |
18945 ADD X,Y \ Y=3/4 cycle
18946 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
18948 \ ******************************\
18949 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
18950 \ ******************************\
18951 BIT.B #RC5,&IR_IN \ C_flag = IR bit
18952 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
18953 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
18954 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
18955 SUB #1,W \ decrement count loop
18956 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
18957 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
18958 0<> WHILE \ ----> out of loop ----+
18959 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
18961 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
18962 CMP Y,X \ 1 | cycle time out of bound ?
18963 U>= IF \ 2 ^ | yes:
18964 BIC #$30,&RC5_TIM_CTL \ | | stop timer
18965 GOTO BW1 \ | | quit on truncated RC5 message
18967 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
18969 REPEAT \ ----> loop back --+ | with X = new RC5_period value
18970 \ ******************************\ |
18971 \ RC5_SampleEndOf: \ <---------------------+
18972 \ ******************************\
18973 BIC #$30,&RC5_TIM_CTL \ stop timer
18974 \ ******************************\
18975 \ RC5_ComputeNewRC5word \
18976 \ ******************************\
18977 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
18978 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
18979 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
18980 \ ******************************\
18981 \ RC5_ComputeC6bit \
18982 \ ******************************\
18983 BIT #BIT14,T \ test /C6 bit in T
18984 0= IF BIS #BIT6,X \ set C6 bit in X
18985 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
18986 \ ******************************\
18987 \ RC5_CommandByteIsDone \ -- BASE RC5_code
18988 \ ******************************\
18989 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
18990 \ ******************************\
18991 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
18992 XOR @RSP,T \ (new XOR old) Toggle bits
18993 BIT #UF10,T \ repeated RC5_command ?
18994 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
18995 XOR #UF10,0(RSP) \ 5 toggle bit memory
18996 \ ******************************\
18997 \ Display IR_RC5 code \
18998 \ ******************************\
18999 SUB #8,PSP \ TOS -- x x x x TOS
19000 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
19001 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
19002 MOV #$10,&BASEADR \ set hexadecimal base
19003 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
19004 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
19005 LO2HI \ switch from assembler to FORTH
19006 LCD_CLEAR \ set LCD cursor at home
19007 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
19008 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
19009 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
19010 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
19011 HI2LO \ -- switch from FORTH to assembler
19012 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
19013 MOV @PSP+,TOS \ -- TOS
19017 \ ******************************\
19019 \ ******************************\
19021 \ ... \ insert here your background task
19024 CALL &RXON \ comment this line to disable TERMINAL_INPUT
19026 \ ******************************\
19027 \ here start all interrupts \
19028 \ ******************************\
19029 \ here return all interrupts \
19030 \ ******************************\
19033 \ ******************************\
19035 \ ------------------------------\
19036 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
19037 \ ------------------------------\
19038 \ ... \ init specific I/O sys as you want
19039 \ ... \ before executing default WARM
19040 MOV #WARM,X \ ['] WARM
19042 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
19044 \ ------------------------------\
19046 \ ------------------------------\
19047 CODE STOP \ stops multitasking, must to be used before downloading app
19048 \ ------------------------------\
19049 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
19050 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
19051 MOV X,-2(X) \ restore the default background: SLEEP
19053 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
19054 BIC.B #RC5,&IR_IE \ clear RC5_Int
19055 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
19056 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
19057 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
19058 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
19059 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
19060 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
19062 ." RC5toLCD is removed,"
19063 ." type START to restart"
19064 WARM \ performs reset to reset all interrupt vectors.
19066 \ ------------------------------\
19068 \ ------------------------------\
19069 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
19070 \ ------------------------------\
19071 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
19072 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19073 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19074 \ -- \ID input divider \ 10 = /4
19075 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19076 \ - \TBCLR TimerB Clear
19079 \ -------------------------------\
19080 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19081 \ -- \CM Capture Mode
19086 \ --- \OUTMOD \ 011 = set/reset
19092 \ -------------------------------\
19094 \ -------------------------------\
19096 \ ------------------------------\
19097 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19098 \ ------------------------------\
19099 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19100 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19101 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
19102 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19104 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
19105 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19107 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
19108 \ ------------------------------\
19109 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19110 \ ------------------------------\
19111 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
19112 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19113 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19114 \ ------------------------------\
19115 BIS.B #LCDVo,&LCDVo_DIR \
19116 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
19117 \ ------------------------------\
19118 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19119 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19120 \ ------------------------------\
19121 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19122 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19123 \ ******************************\
19125 \ ******************************\
19126 BIS.B #RC5,&IR_IE \ enable RC5_Int
19127 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19128 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19129 \ ******************************\
19130 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19131 \ ******************************\
19132 \ %01 0001 0100 \ TAxCTL
19133 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
19134 \ -- \ ID divided by 1
19135 \ -- \ MC MODE = up to TAxCCRn
19136 \ - \ TACLR clear timer count
19139 \ ------------------------------\
19140 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
19141 \ ------------------------------\
19143 \ --- \ TAIDEX pre divisor
19144 \ ------------------------------\
19145 \ %0000 0000 0000 0101 \ TAxCCR0
19146 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19147 \ ------------------------------\
19148 \ %0000 0000 0001 0000 \ TAxCCTL0
19149 \ - \ CAP capture/compare mode = compare
19152 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
19153 \ ------------------------------\
19154 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19155 \ ------------------------------\
19156 \ define LPM mode for ACCEPT \
19157 \ ------------------------------\
19158 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19159 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19160 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19161 \ ------------------------------\
19163 \ ------------------------------\
19164 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
19165 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
19166 \ ------------------------------\
19167 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
19168 \ ------------------------------\
19169 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
19170 \ CMP #2,Y \ Power_ON event
19171 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
19173 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
19175 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
19177 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
19179 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
19180 \ ------------------------------\
19182 \ ------------------------------\
19184 \ ------------------------------\
19185 #1000 20_US \ 1- wait 20 ms
19186 %011 TOP_LCD \ 2- send DB5=DB4=1
19187 #205 20_US \ 3- wait 4,1 ms
19188 %011 TOP_LCD \ 4- send again DB5=DB4=1
19189 #5 20_US \ 5- wait 0,1 ms
19190 %011 TOP_LCD \ 6- send again again DB5=DB4=1
19191 #2 20_US \ wait 40 us = LCD cycle
19192 %010 TOP_LCD \ 7- send DB5=1 DB4=0
19193 #2 20_US \ wait 40 us = LCD cycle
19194 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19195 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19196 LCD_CLEAR \ 10- "LCD_Clear"
19197 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19198 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19199 LCD_CLEAR \ 10- "LCD_Clear"
19200 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19201 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19202 CR ." I love you" \ display message on LCD
19203 ['] CR >BODY IS CR \ CR executes its default value
19204 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
19205 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
19206 PWR_STATE ABORT \ init DP and continues with ABORT
19208 \ ------------------------------\
19210 \ ------------------------------\
19211 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
19212 \ ------------------------------\
19213 MOV #SLEEP,X \ replace default background process SLEEP
19214 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
19215 MOV #WARM,X \ replace default WARM
19216 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
19217 MOV X,PC \ then execute new WARM
19219 \ ------------------------------\
19222 ; downloading RC5toLCD.4th is done
19223 RST_HERE ; this app is protected against <reset>
19228 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
19230 [UNDEFINED] MARKER [IF]
19231 \ https://forth-standard.org/standard/core/MARKER
19233 \ ( "<spaces>name" -- )
19234 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
19235 \ with the execution semantics defined below.
19237 \ name Execution: ( -- )
19238 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
19239 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
19240 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
19241 \ not necessarily provided. No other contextual information such as numeric base is affected
19246 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
19247 SUB #2,Y \ 1 Y = LFA
19248 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
19249 ADD #4,&DP \ 3 add 2 cells
19253 MOV @RSP+,IP \ -- PFA
19254 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
19255 MOV @TOS,&INIDP \ set DP value for RST_STATE
19257 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
19264 \ https://forth-standard.org/standard/core/Fetch
19265 \ @ c-addr -- char fetch char from memory
19272 [UNDEFINED] CONSTANT [IF]
19273 \ https://forth-standard.org/standard/core/CONSTANT
19274 \ CONSTANT <name> n -- define a Forth CONSTANT
19278 MOV TOS,-2(W) \ PFA = n
19285 [UNDEFINED] STATE [IF]
19286 \ https://forth-standard.org/standard/core/STATE
19287 \ STATE -- a-addr holds compiler state
19288 STATEADR CONSTANT STATE
19292 \ https://forth-standard.org/standard/core/Equal
19293 \ = x1 x2 -- flag test x1=x2
19300 XOR #-1,TOS \ 1 flag Z = 1
19305 [UNDEFINED] IF [IF]
19306 \ https://forth-standard.org/standard/core/IF
19307 \ IF -- IFadr initialize conditional forward branch
19308 CODE IF \ immediate
19311 MOV &DP,TOS \ -- HERE
19312 ADD #4,&DP \ compile one word, reserve one word
19313 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
19314 ADD #2,TOS \ -- HERE+2=IFadr
19319 [UNDEFINED] THEN [IF]
19320 \ https://forth-standard.org/standard/core/THEN
19321 \ THEN IFadr -- resolve forward branch
19322 CODE THEN \ immediate
19323 MOV &DP,0(TOS) \ -- IFadr
19329 [UNDEFINED] ELSE [IF]
19330 \ https://forth-standard.org/standard/core/ELSE
19331 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
19332 CODE ELSE \ immediate
19333 ADD #4,&DP \ make room to compile two words
19334 MOV &DP,W \ W=HERE+4
19336 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
19338 MOV W,TOS \ -- ELSEadr
19343 [UNDEFINED] DEFER [IF]
19344 \ https://forth-standard.org/standard/core/DEFER
19345 \ DEFER "<spaces>name" --
19346 \ Skip leading space delimiters. Parse name delimited by a space.
19347 \ Create a definition for name with the execution semantics defined below.
19349 \ name Execution: --
19350 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
19351 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
19355 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
19356 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
19362 [UNDEFINED] DEFER! [IF]
19363 \ https://forth-standard.org/standard/core/DEFERStore
19364 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
19365 CODE DEFER! \ xt2 xt1 --
19366 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
19372 [UNDEFINED] IS [IF]
19373 \ https://forth-standard.org/standard/core/IS
19376 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
19377 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
19378 \ or in a definition : ... ['] U. IS DISPLAY ...
19379 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
19381 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
19384 IF POSTPONE ['] POSTPONE DEFER!
19390 [UNDEFINED] >BODY [IF]
19391 \ https://forth-standard.org/standard/core/toBODY
19392 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
19399 \ CODE 20uS \ n -- 8MHz version
19400 \ BEGIN \ 4 + 16 ~ loop
19401 \ MOV #39,rDOCON \ 39
19408 \ MOV #XDOCON,rDOCON \ 2
19413 CODE 20_US \ n -- n * 20 us
19414 BEGIN \ here we presume that LCD_TIM_IFG = 1...
19416 BIT #1,&LCD_TIM_CTL \ 3
19417 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
19418 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
19420 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
19425 CODE TOP_LCD \ LCD Sample
19426 \ \ if write : %xxxx_WWWW --
19427 \ \ if read : -- %0000_RRRR
19428 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
19429 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
19430 0= IF \ write LCD bits pattern
19431 AND.B #LCD_DB,TOS \
19432 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
19433 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19436 THEN \ read LCD bits pattern
19439 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
19440 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
19441 AND.B #LCD_DB,TOS \
19445 CODE LCD_WRC \ char -- Write Char
19446 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19448 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
19449 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
19450 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
19451 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
19452 COLON \ high level word starts here
19453 TOP_LCD 2 20_US \ write high nibble first
19457 CODE LCD_WRF \ func -- Write Fonction
19458 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19462 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
19463 : LCD_HOME $02 LCD_WRF 100 20_us ;
19465 \ [UNDEFINED] OR [IF]
19467 \ \ https://forth-standard.org/standard/core/OR
19468 \ \ C OR x1 x2 -- x3 logical OR
19476 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
19477 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
19478 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
19479 \ : LCD_FN_SET $20 OR LCD_WrF ;
19480 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
19481 \ : LCD_GOTO $80 OR LCD_WrF ;
19484 \ CODE LCD_RDS \ -- status Read Status
19485 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
19486 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
19487 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
19488 \ COLON \ starts a FORTH word
19489 \ TOP_LCD 2 20_us \ -- %0000_HHHH
19490 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
19491 \ HI2LO \ switch from FORTH to assembler
19492 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
19493 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
19494 \ MOV @RSP+,IP \ restore IP saved by COLON
19498 \ CODE LCD_RDC \ -- char Read Char
19499 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
19504 \ ******************************\
19505 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
19506 \ ******************************\
19507 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
19508 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
19509 BIT.B #SW2,&SW2_IN \ test switch S2
19510 0= IF \ case of switch S2 pressed
19511 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
19513 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
19516 BIT.B #SW1,&SW1_IN \ test switch S1 input
19517 0= IF \ case of Switch S1 pressed
19518 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
19520 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
19524 BW1 \ from quit on truncated RC5 message, repeated RC5 command
19528 \ ******************************\
19529 ASM RC5_INT \ wake up on Px.RC5 change interrupt
19530 \ ******************************\
19531 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
19532 \ ******************************\
19533 \ \ in : SR(9)=old Toggle bit memory (ADD on)
19534 \ \ SMclock = 8|16|24 MHz
19535 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
19536 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
19537 \ \ SR(9)=new Toggle bit memory (ADD on)
19538 \ ******************************\
19539 \ RC5_FirstStartBitHalfCycle: \
19540 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
19541 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
19542 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
19543 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
19545 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
19546 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
19548 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
19549 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
19551 MOV #1778,X \ RC5_Period * 1us
19552 MOV #14,W \ count of loop
19554 \ ******************************\
19555 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
19556 \ ******************************\ |
19557 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
19558 \ RC5_Compute_3/4_Period: \ |
19559 RRUM #1,X \ X=1/2 cycle |
19562 ADD X,Y \ Y=3/4 cycle
19563 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
19565 \ ******************************\
19566 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
19567 \ ******************************\
19568 BIT.B #RC5,&IR_IN \ C_flag = IR bit
19569 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
19570 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
19571 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
19572 SUB #1,W \ decrement count loop
19573 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
19574 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
19575 0<> WHILE \ ----> out of loop ----+
19576 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
19578 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
19579 CMP Y,X \ 1 | cycle time out of bound ?
19580 U>= IF \ 2 ^ | yes:
19581 BIC #$30,&RC5_TIM_CTL \ | | stop timer
19582 GOTO BW1 \ | | quit on truncated RC5 message
19584 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
19586 REPEAT \ ----> loop back --+ | with X = new RC5_period value
19587 \ ******************************\ |
19588 \ RC5_SampleEndOf: \ <---------------------+
19589 \ ******************************\
19590 BIC #$30,&RC5_TIM_CTL \ stop timer
19591 \ ******************************\
19592 \ RC5_ComputeNewRC5word \
19593 \ ******************************\
19594 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
19595 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
19596 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
19597 \ ******************************\
19598 \ RC5_ComputeC6bit \
19599 \ ******************************\
19600 BIT #BIT14,T \ test /C6 bit in T
19601 0= IF BIS #BIT6,X \ set C6 bit in X
19602 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
19603 \ ******************************\
19604 \ RC5_CommandByteIsDone \ -- BASE RC5_code
19605 \ ******************************\
19606 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
19607 \ ******************************\
19608 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
19609 XOR @RSP,T \ (new XOR old) Toggle bits
19610 BIT #UF10,T \ repeated RC5_command ?
19611 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
19612 XOR #UF10,0(RSP) \ 5 toggle bit memory
19613 \ ******************************\
19614 \ Display IR_RC5 code \
19615 \ ******************************\
19616 SUB #8,PSP \ TOS -- x x x x TOS
19617 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
19618 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
19619 MOV #$10,&BASEADR \ set hexadecimal base
19620 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
19621 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
19622 LO2HI \ switch from assembler to FORTH
19623 LCD_CLEAR \ set LCD cursor at home
19624 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
19625 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
19626 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
19627 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
19628 HI2LO \ -- switch from FORTH to assembler
19629 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
19630 MOV @PSP+,TOS \ -- TOS
19634 \ ******************************\
19636 \ ******************************\
19638 \ ... \ insert here your background task
19641 CALL &RXON \ comment this line to disable TERMINAL_INPUT
19643 \ ******************************\
19644 \ here start all interrupts \
19645 \ ******************************\
19646 \ here return all interrupts \
19647 \ ******************************\
19650 \ ******************************\
19652 \ ------------------------------\
19653 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
19654 \ ------------------------------\
19655 \ ... \ init specific I/O sys as you want
19656 \ ... \ before executing default WARM
19657 MOV #WARM,X \ ['] WARM
19659 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
19661 \ ------------------------------\
19663 \ ------------------------------\
19664 CODE STOP \ stops multitasking, must to be used before downloading app
19665 \ ------------------------------\
19666 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
19667 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
19668 MOV X,-2(X) \ restore the default background: SLEEP
19670 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
19671 BIC.B #RC5,&IR_IE \ clear RC5_Int
19672 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
19673 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
19674 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
19675 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
19676 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
19677 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
19679 ." RC5toLCD is removed,"
19680 ." type START to restart"
19681 WARM \ performs reset to reset all interrupt vectors.
19683 \ ------------------------------\
19685 \ ------------------------------\
19686 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
19687 \ ------------------------------\
19688 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
19689 \ - - \CNTL Counter lentgh \ 00 = 16 bits
19690 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
19691 \ -- \ID input divider \ 10 = /4
19692 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
19693 \ - \TBCLR TimerB Clear
19696 \ -------------------------------\
19697 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
19698 \ -- \CM Capture Mode
19703 \ --- \OUTMOD \ 011 = set/reset
19709 \ -------------------------------\
19711 \ -------------------------------\
19713 \ ------------------------------\
19714 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
19715 \ ------------------------------\
19716 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
19717 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
19718 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
19719 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
19721 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
19722 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
19724 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
19725 \ ------------------------------\
19726 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
19727 \ ------------------------------\
19728 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
19729 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
19730 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
19731 \ ------------------------------\
19732 BIS.B #LCDVo,&LCDVo_DIR \
19733 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
19734 \ ------------------------------\
19735 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
19736 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
19737 \ ------------------------------\
19738 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
19739 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
19740 \ ******************************\
19742 \ ******************************\
19743 BIS.B #RC5,&IR_IE \ enable RC5_Int
19744 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
19745 MOV #RC5_INT,&IR_Vec \ init interrupt vector
19746 \ ******************************\
19747 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
19748 \ ******************************\
19749 \ %01 0001 0100 \ TAxCTL
19750 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
19751 \ -- \ ID divided by 1
19752 \ -- \ MC MODE = up to TAxCCRn
19753 \ - \ TACLR clear timer count
19756 \ ------------------------------\
19757 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
19758 \ ------------------------------\
19760 \ --- \ TAIDEX pre divisor
19761 \ ------------------------------\
19762 \ %0000 0000 0000 0101 \ TAxCCR0
19763 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
19764 \ ------------------------------\
19765 \ %0000 0000 0001 0000 \ TAxCCTL0
19766 \ - \ CAP capture/compare mode = compare
19769 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
19770 \ ------------------------------\
19771 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
19772 \ ------------------------------\
19773 \ define LPM mode for ACCEPT \
19774 \ ------------------------------\
19775 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
19776 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
19777 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
19778 \ ------------------------------\
19780 \ ------------------------------\
19781 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
19782 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
19783 \ ------------------------------\
19784 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
19785 \ ------------------------------\
19786 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
19787 \ CMP #2,Y \ Power_ON event
19788 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
19790 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
19792 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
19794 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
19796 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
19797 \ ------------------------------\
19799 \ ------------------------------\
19801 \ ------------------------------\
19802 #1000 20_US \ 1- wait 20 ms
19803 %011 TOP_LCD \ 2- send DB5=DB4=1
19804 #205 20_US \ 3- wait 4,1 ms
19805 %011 TOP_LCD \ 4- send again DB5=DB4=1
19806 #5 20_US \ 5- wait 0,1 ms
19807 %011 TOP_LCD \ 6- send again again DB5=DB4=1
19808 #2 20_US \ wait 40 us = LCD cycle
19809 %010 TOP_LCD \ 7- send DB5=1 DB4=0
19810 #2 20_US \ wait 40 us = LCD cycle
19811 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
19812 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
19813 LCD_CLEAR \ 10- "LCD_Clear"
19814 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
19815 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
19816 LCD_CLEAR \ 10- "LCD_Clear"
19817 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
19818 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
19819 CR ." I love you" \ display message on LCD
19820 ['] CR >BODY IS CR \ CR executes its default value
19821 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
19822 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
19823 PWR_STATE ABORT \ init DP and continues with ABORT
19825 \ ------------------------------\
19827 \ ------------------------------\
19828 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
19829 \ ------------------------------\
19830 MOV #SLEEP,X \ replace default background process SLEEP
19831 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
19832 MOV #WARM,X \ replace default WARM
19833 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
19834 MOV X,PC \ then execute new WARM
19836 \ ------------------------------\
19839 ; downloading RC5toLCD.4th is done
19840 RST_HERE ; this app is protected against <reset>
19845 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
19847 [UNDEFINED] MARKER [IF]
19848 \ https://forth-standard.org/standard/core/MARKER
19850 \ ( "<spaces>name" -- )
19851 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
19852 \ with the execution semantics defined below.
19854 \ name Execution: ( -- )
19855 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
19856 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
19857 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
19858 \ not necessarily provided. No other contextual information such as numeric base is affected
19863 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
19864 SUB #2,Y \ 1 Y = LFA
19865 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
19866 ADD #4,&DP \ 3 add 2 cells
19870 MOV @RSP+,IP \ -- PFA
19871 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
19872 MOV @TOS,&INIDP \ set DP value for RST_STATE
19874 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
19881 \ https://forth-standard.org/standard/core/Fetch
19882 \ @ c-addr -- char fetch char from memory
19889 [UNDEFINED] CONSTANT [IF]
19890 \ https://forth-standard.org/standard/core/CONSTANT
19891 \ CONSTANT <name> n -- define a Forth CONSTANT
19895 MOV TOS,-2(W) \ PFA = n
19902 [UNDEFINED] STATE [IF]
19903 \ https://forth-standard.org/standard/core/STATE
19904 \ STATE -- a-addr holds compiler state
19905 STATEADR CONSTANT STATE
19909 \ https://forth-standard.org/standard/core/Equal
19910 \ = x1 x2 -- flag test x1=x2
19917 XOR #-1,TOS \ 1 flag Z = 1
19922 [UNDEFINED] IF [IF]
19923 \ https://forth-standard.org/standard/core/IF
19924 \ IF -- IFadr initialize conditional forward branch
19925 CODE IF \ immediate
19928 MOV &DP,TOS \ -- HERE
19929 ADD #4,&DP \ compile one word, reserve one word
19930 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
19931 ADD #2,TOS \ -- HERE+2=IFadr
19936 [UNDEFINED] THEN [IF]
19937 \ https://forth-standard.org/standard/core/THEN
19938 \ THEN IFadr -- resolve forward branch
19939 CODE THEN \ immediate
19940 MOV &DP,0(TOS) \ -- IFadr
19946 [UNDEFINED] ELSE [IF]
19947 \ https://forth-standard.org/standard/core/ELSE
19948 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
19949 CODE ELSE \ immediate
19950 ADD #4,&DP \ make room to compile two words
19951 MOV &DP,W \ W=HERE+4
19953 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
19955 MOV W,TOS \ -- ELSEadr
19960 [UNDEFINED] DEFER [IF]
19961 \ https://forth-standard.org/standard/core/DEFER
19962 \ DEFER "<spaces>name" --
19963 \ Skip leading space delimiters. Parse name delimited by a space.
19964 \ Create a definition for name with the execution semantics defined below.
19966 \ name Execution: --
19967 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
19968 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
19972 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
19973 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
19979 [UNDEFINED] DEFER! [IF]
19980 \ https://forth-standard.org/standard/core/DEFERStore
19981 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
19982 CODE DEFER! \ xt2 xt1 --
19983 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
19989 [UNDEFINED] IS [IF]
19990 \ https://forth-standard.org/standard/core/IS
19993 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
19994 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
19995 \ or in a definition : ... ['] U. IS DISPLAY ...
19996 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
19998 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
20001 IF POSTPONE ['] POSTPONE DEFER!
20007 [UNDEFINED] >BODY [IF]
20008 \ https://forth-standard.org/standard/core/toBODY
20009 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
20016 \ CODE 20uS \ n -- 8MHz version
20017 \ BEGIN \ 4 + 16 ~ loop
20018 \ MOV #39,rDOCON \ 39
20025 \ MOV #XDOCON,rDOCON \ 2
20030 CODE 20_US \ n -- n * 20 us
20031 BEGIN \ here we presume that LCD_TIM_IFG = 1...
20033 BIT #1,&LCD_TIM_CTL \ 3
20034 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
20035 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
20037 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
20042 CODE TOP_LCD \ LCD Sample
20043 \ \ if write : %xxxx_WWWW --
20044 \ \ if read : -- %0000_RRRR
20045 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20046 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20047 0= IF \ write LCD bits pattern
20048 AND.B #LCD_DB,TOS \
20049 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20050 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20053 THEN \ read LCD bits pattern
20056 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20057 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20058 AND.B #LCD_DB,TOS \
20062 CODE LCD_WRC \ char -- Write Char
20063 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20065 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
20066 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
20067 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20068 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20069 COLON \ high level word starts here
20070 TOP_LCD 2 20_US \ write high nibble first
20074 CODE LCD_WRF \ func -- Write Fonction
20075 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20079 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
20080 : LCD_HOME $02 LCD_WRF 100 20_us ;
20082 \ [UNDEFINED] OR [IF]
20084 \ \ https://forth-standard.org/standard/core/OR
20085 \ \ C OR x1 x2 -- x3 logical OR
20093 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
20094 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
20095 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
20096 \ : LCD_FN_SET $20 OR LCD_WrF ;
20097 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
20098 \ : LCD_GOTO $80 OR LCD_WrF ;
20101 \ CODE LCD_RDS \ -- status Read Status
20102 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20103 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20104 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20105 \ COLON \ starts a FORTH word
20106 \ TOP_LCD 2 20_us \ -- %0000_HHHH
20107 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
20108 \ HI2LO \ switch from FORTH to assembler
20109 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
20110 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
20111 \ MOV @RSP+,IP \ restore IP saved by COLON
20115 \ CODE LCD_RDC \ -- char Read Char
20116 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20121 \ ******************************\
20122 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20123 \ ******************************\
20124 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20125 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
20126 BIT.B #SW2,&SW2_IN \ test switch S2
20127 0= IF \ case of switch S2 pressed
20128 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20130 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
20133 BIT.B #SW1,&SW1_IN \ test switch S1 input
20134 0= IF \ case of Switch S1 pressed
20135 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20137 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20141 BW1 \ from quit on truncated RC5 message, repeated RC5 command
20145 \ ******************************\
20146 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20147 \ ******************************\
20148 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20149 \ ******************************\
20150 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20151 \ \ SMclock = 8|16|24 MHz
20152 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20153 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20154 \ \ SR(9)=new Toggle bit memory (ADD on)
20155 \ ******************************\
20156 \ RC5_FirstStartBitHalfCycle: \
20157 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20158 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20159 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
20160 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
20162 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
20163 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
20165 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
20166 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
20168 MOV #1778,X \ RC5_Period * 1us
20169 MOV #14,W \ count of loop
20171 \ ******************************\
20172 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
20173 \ ******************************\ |
20174 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
20175 \ RC5_Compute_3/4_Period: \ |
20176 RRUM #1,X \ X=1/2 cycle |
20179 ADD X,Y \ Y=3/4 cycle
20180 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
20182 \ ******************************\
20183 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
20184 \ ******************************\
20185 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20186 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
20187 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20188 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20189 SUB #1,W \ decrement count loop
20190 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
20191 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20192 0<> WHILE \ ----> out of loop ----+
20193 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
20195 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
20196 CMP Y,X \ 1 | cycle time out of bound ?
20197 U>= IF \ 2 ^ | yes:
20198 BIC #$30,&RC5_TIM_CTL \ | | stop timer
20199 GOTO BW1 \ | | quit on truncated RC5 message
20201 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
20203 REPEAT \ ----> loop back --+ | with X = new RC5_period value
20204 \ ******************************\ |
20205 \ RC5_SampleEndOf: \ <---------------------+
20206 \ ******************************\
20207 BIC #$30,&RC5_TIM_CTL \ stop timer
20208 \ ******************************\
20209 \ RC5_ComputeNewRC5word \
20210 \ ******************************\
20211 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
20212 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
20213 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
20214 \ ******************************\
20215 \ RC5_ComputeC6bit \
20216 \ ******************************\
20217 BIT #BIT14,T \ test /C6 bit in T
20218 0= IF BIS #BIT6,X \ set C6 bit in X
20219 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
20220 \ ******************************\
20221 \ RC5_CommandByteIsDone \ -- BASE RC5_code
20222 \ ******************************\
20223 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
20224 \ ******************************\
20225 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
20226 XOR @RSP,T \ (new XOR old) Toggle bits
20227 BIT #UF10,T \ repeated RC5_command ?
20228 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
20229 XOR #UF10,0(RSP) \ 5 toggle bit memory
20230 \ ******************************\
20231 \ Display IR_RC5 code \
20232 \ ******************************\
20233 SUB #8,PSP \ TOS -- x x x x TOS
20234 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
20235 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
20236 MOV #$10,&BASEADR \ set hexadecimal base
20237 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
20238 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
20239 LO2HI \ switch from assembler to FORTH
20240 LCD_CLEAR \ set LCD cursor at home
20241 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
20242 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
20243 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
20244 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
20245 HI2LO \ -- switch from FORTH to assembler
20246 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
20247 MOV @PSP+,TOS \ -- TOS
20251 \ ******************************\
20253 \ ******************************\
20255 \ ... \ insert here your background task
20258 CALL &RXON \ comment this line to disable TERMINAL_INPUT
20260 \ ******************************\
20261 \ here start all interrupts \
20262 \ ******************************\
20263 \ here return all interrupts \
20264 \ ******************************\
20267 \ ******************************\
20269 \ ------------------------------\
20270 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
20271 \ ------------------------------\
20272 \ ... \ init specific I/O sys as you want
20273 \ ... \ before executing default WARM
20274 MOV #WARM,X \ ['] WARM
20276 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
20278 \ ------------------------------\
20280 \ ------------------------------\
20281 CODE STOP \ stops multitasking, must to be used before downloading app
20282 \ ------------------------------\
20283 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
20284 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
20285 MOV X,-2(X) \ restore the default background: SLEEP
20287 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
20288 BIC.B #RC5,&IR_IE \ clear RC5_Int
20289 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
20290 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
20291 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
20292 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
20293 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
20294 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
20296 ." RC5toLCD is removed,"
20297 ." type START to restart"
20298 WARM \ performs reset to reset all interrupt vectors.
20300 \ ------------------------------\
20302 \ ------------------------------\
20303 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
20304 \ ------------------------------\
20305 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
20306 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20307 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20308 \ -- \ID input divider \ 10 = /4
20309 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
20310 \ - \TBCLR TimerB Clear
20313 \ -------------------------------\
20314 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20315 \ -- \CM Capture Mode
20320 \ --- \OUTMOD \ 011 = set/reset
20326 \ -------------------------------\
20328 \ -------------------------------\
20330 \ ------------------------------\
20331 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
20332 \ ------------------------------\
20333 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
20334 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
20335 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
20336 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
20338 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
20339 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
20341 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
20342 \ ------------------------------\
20343 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
20344 \ ------------------------------\
20345 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
20346 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
20347 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20348 \ ------------------------------\
20349 BIS.B #LCDVo,&LCDVo_DIR \
20350 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
20351 \ ------------------------------\
20352 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20353 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20354 \ ------------------------------\
20355 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20356 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20357 \ ******************************\
20359 \ ******************************\
20360 BIS.B #RC5,&IR_IE \ enable RC5_Int
20361 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20362 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20363 \ ******************************\
20364 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
20365 \ ******************************\
20366 \ %01 0001 0100 \ TAxCTL
20367 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
20368 \ -- \ ID divided by 1
20369 \ -- \ MC MODE = up to TAxCCRn
20370 \ - \ TACLR clear timer count
20373 \ ------------------------------\
20374 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
20375 \ ------------------------------\
20377 \ --- \ TAIDEX pre divisor
20378 \ ------------------------------\
20379 \ %0000 0000 0000 0101 \ TAxCCR0
20380 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
20381 \ ------------------------------\
20382 \ %0000 0000 0001 0000 \ TAxCCTL0
20383 \ - \ CAP capture/compare mode = compare
20386 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
20387 \ ------------------------------\
20388 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
20389 \ ------------------------------\
20390 \ define LPM mode for ACCEPT \
20391 \ ------------------------------\
20392 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
20393 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
20394 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
20395 \ ------------------------------\
20397 \ ------------------------------\
20398 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
20399 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
20400 \ ------------------------------\
20401 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
20402 \ ------------------------------\
20403 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
20404 \ CMP #2,Y \ Power_ON event
20405 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
20407 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
20409 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
20411 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
20413 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
20414 \ ------------------------------\
20416 \ ------------------------------\
20418 \ ------------------------------\
20419 #1000 20_US \ 1- wait 20 ms
20420 %011 TOP_LCD \ 2- send DB5=DB4=1
20421 #205 20_US \ 3- wait 4,1 ms
20422 %011 TOP_LCD \ 4- send again DB5=DB4=1
20423 #5 20_US \ 5- wait 0,1 ms
20424 %011 TOP_LCD \ 6- send again again DB5=DB4=1
20425 #2 20_US \ wait 40 us = LCD cycle
20426 %010 TOP_LCD \ 7- send DB5=1 DB4=0
20427 #2 20_US \ wait 40 us = LCD cycle
20428 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
20429 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
20430 LCD_CLEAR \ 10- "LCD_Clear"
20431 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
20432 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
20433 LCD_CLEAR \ 10- "LCD_Clear"
20434 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
20435 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
20436 CR ." I love you" \ display message on LCD
20437 ['] CR >BODY IS CR \ CR executes its default value
20438 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
20439 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
20440 PWR_STATE ABORT \ init DP and continues with ABORT
20442 \ ------------------------------\
20444 \ ------------------------------\
20445 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
20446 \ ------------------------------\
20447 MOV #SLEEP,X \ replace default background process SLEEP
20448 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
20449 MOV #WARM,X \ replace default WARM
20450 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
20451 MOV X,PC \ then execute new WARM
20453 \ ------------------------------\
20456 ; downloading RC5toLCD.4th is done
20457 RST_HERE ; this app is protected against <reset>
20462 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
20464 [UNDEFINED] MARKER [IF]
20465 \ https://forth-standard.org/standard/core/MARKER
20467 \ ( "<spaces>name" -- )
20468 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
20469 \ with the execution semantics defined below.
20471 \ name Execution: ( -- )
20472 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
20473 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
20474 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
20475 \ not necessarily provided. No other contextual information such as numeric base is affected
20480 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
20481 SUB #2,Y \ 1 Y = LFA
20482 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
20483 ADD #4,&DP \ 3 add 2 cells
20487 MOV @RSP+,IP \ -- PFA
20488 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
20489 MOV @TOS,&INIDP \ set DP value for RST_STATE
20491 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
20498 \ https://forth-standard.org/standard/core/Fetch
20499 \ @ c-addr -- char fetch char from memory
20506 [UNDEFINED] CONSTANT [IF]
20507 \ https://forth-standard.org/standard/core/CONSTANT
20508 \ CONSTANT <name> n -- define a Forth CONSTANT
20512 MOV TOS,-2(W) \ PFA = n
20519 [UNDEFINED] STATE [IF]
20520 \ https://forth-standard.org/standard/core/STATE
20521 \ STATE -- a-addr holds compiler state
20522 STATEADR CONSTANT STATE
20526 \ https://forth-standard.org/standard/core/Equal
20527 \ = x1 x2 -- flag test x1=x2
20534 XOR #-1,TOS \ 1 flag Z = 1
20539 [UNDEFINED] IF [IF]
20540 \ https://forth-standard.org/standard/core/IF
20541 \ IF -- IFadr initialize conditional forward branch
20542 CODE IF \ immediate
20545 MOV &DP,TOS \ -- HERE
20546 ADD #4,&DP \ compile one word, reserve one word
20547 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
20548 ADD #2,TOS \ -- HERE+2=IFadr
20553 [UNDEFINED] THEN [IF]
20554 \ https://forth-standard.org/standard/core/THEN
20555 \ THEN IFadr -- resolve forward branch
20556 CODE THEN \ immediate
20557 MOV &DP,0(TOS) \ -- IFadr
20563 [UNDEFINED] ELSE [IF]
20564 \ https://forth-standard.org/standard/core/ELSE
20565 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
20566 CODE ELSE \ immediate
20567 ADD #4,&DP \ make room to compile two words
20568 MOV &DP,W \ W=HERE+4
20570 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
20572 MOV W,TOS \ -- ELSEadr
20577 [UNDEFINED] DEFER [IF]
20578 \ https://forth-standard.org/standard/core/DEFER
20579 \ DEFER "<spaces>name" --
20580 \ Skip leading space delimiters. Parse name delimited by a space.
20581 \ Create a definition for name with the execution semantics defined below.
20583 \ name Execution: --
20584 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
20585 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
20589 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
20590 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
20596 [UNDEFINED] DEFER! [IF]
20597 \ https://forth-standard.org/standard/core/DEFERStore
20598 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
20599 CODE DEFER! \ xt2 xt1 --
20600 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
20606 [UNDEFINED] IS [IF]
20607 \ https://forth-standard.org/standard/core/IS
20610 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
20611 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
20612 \ or in a definition : ... ['] U. IS DISPLAY ...
20613 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
20615 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
20618 IF POSTPONE ['] POSTPONE DEFER!
20624 [UNDEFINED] >BODY [IF]
20625 \ https://forth-standard.org/standard/core/toBODY
20626 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
20633 \ CODE 20uS \ n -- 8MHz version
20634 \ BEGIN \ 4 + 16 ~ loop
20635 \ MOV #39,rDOCON \ 39
20642 \ MOV #XDOCON,rDOCON \ 2
20647 CODE 20_US \ n -- n * 20 us
20648 BEGIN \ here we presume that LCD_TIM_IFG = 1...
20650 BIT #1,&LCD_TIM_CTL \ 3
20651 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
20652 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
20654 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
20659 CODE TOP_LCD \ LCD Sample
20660 \ \ if write : %xxxx_WWWW --
20661 \ \ if read : -- %0000_RRRR
20662 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
20663 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
20664 0= IF \ write LCD bits pattern
20665 AND.B #LCD_DB,TOS \
20666 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
20667 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20670 THEN \ read LCD bits pattern
20673 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
20674 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
20675 AND.B #LCD_DB,TOS \
20679 CODE LCD_WRC \ char -- Write Char
20680 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20682 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
20683 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
20684 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
20685 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
20686 COLON \ high level word starts here
20687 TOP_LCD 2 20_US \ write high nibble first
20691 CODE LCD_WRF \ func -- Write Fonction
20692 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20696 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
20697 : LCD_HOME $02 LCD_WRF 100 20_us ;
20699 \ [UNDEFINED] OR [IF]
20701 \ \ https://forth-standard.org/standard/core/OR
20702 \ \ C OR x1 x2 -- x3 logical OR
20710 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
20711 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
20712 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
20713 \ : LCD_FN_SET $20 OR LCD_WrF ;
20714 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
20715 \ : LCD_GOTO $80 OR LCD_WrF ;
20718 \ CODE LCD_RDS \ -- status Read Status
20719 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
20720 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
20721 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
20722 \ COLON \ starts a FORTH word
20723 \ TOP_LCD 2 20_us \ -- %0000_HHHH
20724 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
20725 \ HI2LO \ switch from FORTH to assembler
20726 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
20727 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
20728 \ MOV @RSP+,IP \ restore IP saved by COLON
20732 \ CODE LCD_RDC \ -- char Read Char
20733 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
20738 \ ******************************\
20739 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
20740 \ ******************************\
20741 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20742 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
20743 BIT.B #SW2,&SW2_IN \ test switch S2
20744 0= IF \ case of switch S2 pressed
20745 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
20747 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
20750 BIT.B #SW1,&SW1_IN \ test switch S1 input
20751 0= IF \ case of Switch S1 pressed
20752 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
20754 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
20758 BW1 \ from quit on truncated RC5 message, repeated RC5 command
20762 \ ******************************\
20763 ASM RC5_INT \ wake up on Px.RC5 change interrupt
20764 \ ******************************\
20765 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
20766 \ ******************************\
20767 \ \ in : SR(9)=old Toggle bit memory (ADD on)
20768 \ \ SMclock = 8|16|24 MHz
20769 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
20770 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
20771 \ \ SR(9)=new Toggle bit memory (ADD on)
20772 \ ******************************\
20773 \ RC5_FirstStartBitHalfCycle: \
20774 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
20775 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
20776 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
20777 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
20779 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
20780 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
20782 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
20783 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
20785 MOV #1778,X \ RC5_Period * 1us
20786 MOV #14,W \ count of loop
20788 \ ******************************\
20789 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
20790 \ ******************************\ |
20791 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
20792 \ RC5_Compute_3/4_Period: \ |
20793 RRUM #1,X \ X=1/2 cycle |
20796 ADD X,Y \ Y=3/4 cycle
20797 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
20799 \ ******************************\
20800 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
20801 \ ******************************\
20802 BIT.B #RC5,&IR_IN \ C_flag = IR bit
20803 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
20804 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
20805 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
20806 SUB #1,W \ decrement count loop
20807 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
20808 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
20809 0<> WHILE \ ----> out of loop ----+
20810 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
20812 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
20813 CMP Y,X \ 1 | cycle time out of bound ?
20814 U>= IF \ 2 ^ | yes:
20815 BIC #$30,&RC5_TIM_CTL \ | | stop timer
20816 GOTO BW1 \ | | quit on truncated RC5 message
20818 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
20820 REPEAT \ ----> loop back --+ | with X = new RC5_period value
20821 \ ******************************\ |
20822 \ RC5_SampleEndOf: \ <---------------------+
20823 \ ******************************\
20824 BIC #$30,&RC5_TIM_CTL \ stop timer
20825 \ ******************************\
20826 \ RC5_ComputeNewRC5word \
20827 \ ******************************\
20828 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
20829 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
20830 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
20831 \ ******************************\
20832 \ RC5_ComputeC6bit \
20833 \ ******************************\
20834 BIT #BIT14,T \ test /C6 bit in T
20835 0= IF BIS #BIT6,X \ set C6 bit in X
20836 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
20837 \ ******************************\
20838 \ RC5_CommandByteIsDone \ -- BASE RC5_code
20839 \ ******************************\
20840 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
20841 \ ******************************\
20842 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
20843 XOR @RSP,T \ (new XOR old) Toggle bits
20844 BIT #UF10,T \ repeated RC5_command ?
20845 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
20846 XOR #UF10,0(RSP) \ 5 toggle bit memory
20847 \ ******************************\
20848 \ Display IR_RC5 code \
20849 \ ******************************\
20850 SUB #8,PSP \ TOS -- x x x x TOS
20851 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
20852 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
20853 MOV #$10,&BASEADR \ set hexadecimal base
20854 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
20855 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
20856 LO2HI \ switch from assembler to FORTH
20857 LCD_CLEAR \ set LCD cursor at home
20858 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
20859 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
20860 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
20861 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
20862 HI2LO \ -- switch from FORTH to assembler
20863 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
20864 MOV @PSP+,TOS \ -- TOS
20868 \ ******************************\
20870 \ ******************************\
20872 \ ... \ insert here your background task
20875 CALL &RXON \ comment this line to disable TERMINAL_INPUT
20877 \ ******************************\
20878 \ here start all interrupts \
20879 \ ******************************\
20880 \ here return all interrupts \
20881 \ ******************************\
20884 \ ******************************\
20886 \ ------------------------------\
20887 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
20888 \ ------------------------------\
20889 \ ... \ init specific I/O sys as you want
20890 \ ... \ before executing default WARM
20891 MOV #WARM,X \ ['] WARM
20893 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
20895 \ ------------------------------\
20897 \ ------------------------------\
20898 CODE STOP \ stops multitasking, must to be used before downloading app
20899 \ ------------------------------\
20900 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
20901 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
20902 MOV X,-2(X) \ restore the default background: SLEEP
20904 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
20905 BIC.B #RC5,&IR_IE \ clear RC5_Int
20906 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
20907 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
20908 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
20909 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
20910 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
20911 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
20913 ." RC5toLCD is removed,"
20914 ." type START to restart"
20915 WARM \ performs reset to reset all interrupt vectors.
20917 \ ------------------------------\
20919 \ ------------------------------\
20920 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
20921 \ ------------------------------\
20922 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
20923 \ - - \CNTL Counter lentgh \ 00 = 16 bits
20924 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
20925 \ -- \ID input divider \ 10 = /4
20926 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
20927 \ - \TBCLR TimerB Clear
20930 \ -------------------------------\
20931 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
20932 \ -- \CM Capture Mode
20937 \ --- \OUTMOD \ 011 = set/reset
20943 \ -------------------------------\
20945 \ -------------------------------\
20947 \ ------------------------------\
20948 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
20949 \ ------------------------------\
20950 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
20951 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
20952 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
20953 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
20955 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
20956 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
20958 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
20959 \ ------------------------------\
20960 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
20961 \ ------------------------------\
20962 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
20963 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
20964 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
20965 \ ------------------------------\
20966 BIS.B #LCDVo,&LCDVo_DIR \
20967 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
20968 \ ------------------------------\
20969 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
20970 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
20971 \ ------------------------------\
20972 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
20973 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
20974 \ ******************************\
20976 \ ******************************\
20977 BIS.B #RC5,&IR_IE \ enable RC5_Int
20978 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
20979 MOV #RC5_INT,&IR_Vec \ init interrupt vector
20980 \ ******************************\
20981 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
20982 \ ******************************\
20983 \ %01 0001 0100 \ TAxCTL
20984 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
20985 \ -- \ ID divided by 1
20986 \ -- \ MC MODE = up to TAxCCRn
20987 \ - \ TACLR clear timer count
20990 \ ------------------------------\
20991 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
20992 \ ------------------------------\
20994 \ --- \ TAIDEX pre divisor
20995 \ ------------------------------\
20996 \ %0000 0000 0000 0101 \ TAxCCR0
20997 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
20998 \ ------------------------------\
20999 \ %0000 0000 0001 0000 \ TAxCCTL0
21000 \ - \ CAP capture/compare mode = compare
21003 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
21004 \ ------------------------------\
21005 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
21006 \ ------------------------------\
21007 \ define LPM mode for ACCEPT \
21008 \ ------------------------------\
21009 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21010 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21011 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21012 \ ------------------------------\
21014 \ ------------------------------\
21015 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
21016 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
21017 \ ------------------------------\
21018 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
21019 \ ------------------------------\
21020 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
21021 \ CMP #2,Y \ Power_ON event
21022 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
21024 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
21026 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
21028 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
21030 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
21031 \ ------------------------------\
21033 \ ------------------------------\
21035 \ ------------------------------\
21036 #1000 20_US \ 1- wait 20 ms
21037 %011 TOP_LCD \ 2- send DB5=DB4=1
21038 #205 20_US \ 3- wait 4,1 ms
21039 %011 TOP_LCD \ 4- send again DB5=DB4=1
21040 #5 20_US \ 5- wait 0,1 ms
21041 %011 TOP_LCD \ 6- send again again DB5=DB4=1
21042 #2 20_US \ wait 40 us = LCD cycle
21043 %010 TOP_LCD \ 7- send DB5=1 DB4=0
21044 #2 20_US \ wait 40 us = LCD cycle
21045 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21046 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21047 LCD_CLEAR \ 10- "LCD_Clear"
21048 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21049 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21050 LCD_CLEAR \ 10- "LCD_Clear"
21051 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21052 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21053 CR ." I love you" \ display message on LCD
21054 ['] CR >BODY IS CR \ CR executes its default value
21055 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
21056 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
21057 PWR_STATE ABORT \ init DP and continues with ABORT
21059 \ ------------------------------\
21061 \ ------------------------------\
21062 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
21063 \ ------------------------------\
21064 MOV #SLEEP,X \ replace default background process SLEEP
21065 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
21066 MOV #WARM,X \ replace default WARM
21067 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
21068 MOV X,PC \ then execute new WARM
21070 \ ------------------------------\
21073 ; downloading RC5toLCD.4th is done
21074 RST_HERE ; this app is protected against <reset>
21079 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
21081 [UNDEFINED] MARKER [IF]
21082 \ https://forth-standard.org/standard/core/MARKER
21084 \ ( "<spaces>name" -- )
21085 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
21086 \ with the execution semantics defined below.
21088 \ name Execution: ( -- )
21089 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
21090 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
21091 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
21092 \ not necessarily provided. No other contextual information such as numeric base is affected
21097 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
21098 SUB #2,Y \ 1 Y = LFA
21099 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
21100 ADD #4,&DP \ 3 add 2 cells
21104 MOV @RSP+,IP \ -- PFA
21105 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
21106 MOV @TOS,&INIDP \ set DP value for RST_STATE
21108 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
21115 \ https://forth-standard.org/standard/core/Fetch
21116 \ @ c-addr -- char fetch char from memory
21123 [UNDEFINED] CONSTANT [IF]
21124 \ https://forth-standard.org/standard/core/CONSTANT
21125 \ CONSTANT <name> n -- define a Forth CONSTANT
21129 MOV TOS,-2(W) \ PFA = n
21136 [UNDEFINED] STATE [IF]
21137 \ https://forth-standard.org/standard/core/STATE
21138 \ STATE -- a-addr holds compiler state
21139 STATEADR CONSTANT STATE
21143 \ https://forth-standard.org/standard/core/Equal
21144 \ = x1 x2 -- flag test x1=x2
21151 XOR #-1,TOS \ 1 flag Z = 1
21156 [UNDEFINED] IF [IF]
21157 \ https://forth-standard.org/standard/core/IF
21158 \ IF -- IFadr initialize conditional forward branch
21159 CODE IF \ immediate
21162 MOV &DP,TOS \ -- HERE
21163 ADD #4,&DP \ compile one word, reserve one word
21164 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
21165 ADD #2,TOS \ -- HERE+2=IFadr
21170 [UNDEFINED] THEN [IF]
21171 \ https://forth-standard.org/standard/core/THEN
21172 \ THEN IFadr -- resolve forward branch
21173 CODE THEN \ immediate
21174 MOV &DP,0(TOS) \ -- IFadr
21180 [UNDEFINED] ELSE [IF]
21181 \ https://forth-standard.org/standard/core/ELSE
21182 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
21183 CODE ELSE \ immediate
21184 ADD #4,&DP \ make room to compile two words
21185 MOV &DP,W \ W=HERE+4
21187 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
21189 MOV W,TOS \ -- ELSEadr
21194 [UNDEFINED] DEFER [IF]
21195 \ https://forth-standard.org/standard/core/DEFER
21196 \ DEFER "<spaces>name" --
21197 \ Skip leading space delimiters. Parse name delimited by a space.
21198 \ Create a definition for name with the execution semantics defined below.
21200 \ name Execution: --
21201 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
21202 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
21206 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
21207 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
21213 [UNDEFINED] DEFER! [IF]
21214 \ https://forth-standard.org/standard/core/DEFERStore
21215 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
21216 CODE DEFER! \ xt2 xt1 --
21217 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
21223 [UNDEFINED] IS [IF]
21224 \ https://forth-standard.org/standard/core/IS
21227 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
21228 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
21229 \ or in a definition : ... ['] U. IS DISPLAY ...
21230 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
21232 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
21235 IF POSTPONE ['] POSTPONE DEFER!
21241 [UNDEFINED] >BODY [IF]
21242 \ https://forth-standard.org/standard/core/toBODY
21243 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
21250 \ CODE 20uS \ n -- 8MHz version
21251 \ BEGIN \ 4 + 16 ~ loop
21252 \ MOV #39,rDOCON \ 39
21259 \ MOV #XDOCON,rDOCON \ 2
21264 CODE 20_US \ n -- n * 20 us
21265 BEGIN \ here we presume that LCD_TIM_IFG = 1...
21267 BIT #1,&LCD_TIM_CTL \ 3
21268 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
21269 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
21271 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
21276 CODE TOP_LCD \ LCD Sample
21277 \ \ if write : %xxxx_WWWW --
21278 \ \ if read : -- %0000_RRRR
21279 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21280 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21281 0= IF \ write LCD bits pattern
21282 AND.B #LCD_DB,TOS \
21283 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21284 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21287 THEN \ read LCD bits pattern
21290 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21291 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21292 AND.B #LCD_DB,TOS \
21296 CODE LCD_WRC \ char -- Write Char
21297 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21299 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
21300 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
21301 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21302 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21303 COLON \ high level word starts here
21304 TOP_LCD 2 20_US \ write high nibble first
21308 CODE LCD_WRF \ func -- Write Fonction
21309 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21313 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
21314 : LCD_HOME $02 LCD_WRF 100 20_us ;
21316 \ [UNDEFINED] OR [IF]
21318 \ \ https://forth-standard.org/standard/core/OR
21319 \ \ C OR x1 x2 -- x3 logical OR
21327 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
21328 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
21329 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
21330 \ : LCD_FN_SET $20 OR LCD_WrF ;
21331 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
21332 \ : LCD_GOTO $80 OR LCD_WrF ;
21335 \ CODE LCD_RDS \ -- status Read Status
21336 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21337 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21338 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21339 \ COLON \ starts a FORTH word
21340 \ TOP_LCD 2 20_us \ -- %0000_HHHH
21341 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
21342 \ HI2LO \ switch from FORTH to assembler
21343 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
21344 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
21345 \ MOV @RSP+,IP \ restore IP saved by COLON
21349 \ CODE LCD_RDC \ -- char Read Char
21350 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21355 \ ******************************\
21356 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21357 \ ******************************\
21358 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
21359 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
21360 BIT.B #SW2,&SW2_IN \ test switch S2
21361 0= IF \ case of switch S2 pressed
21362 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
21364 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
21367 BIT.B #SW1,&SW1_IN \ test switch S1 input
21368 0= IF \ case of Switch S1 pressed
21369 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
21371 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
21375 BW1 \ from quit on truncated RC5 message, repeated RC5 command
21379 \ ******************************\
21380 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21381 \ ******************************\
21382 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
21383 \ ******************************\
21384 \ \ in : SR(9)=old Toggle bit memory (ADD on)
21385 \ \ SMclock = 8|16|24 MHz
21386 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
21387 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
21388 \ \ SR(9)=new Toggle bit memory (ADD on)
21389 \ ******************************\
21390 \ RC5_FirstStartBitHalfCycle: \
21391 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
21392 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
21393 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
21394 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
21396 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
21397 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
21399 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
21400 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
21402 MOV #1778,X \ RC5_Period * 1us
21403 MOV #14,W \ count of loop
21405 \ ******************************\
21406 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
21407 \ ******************************\ |
21408 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
21409 \ RC5_Compute_3/4_Period: \ |
21410 RRUM #1,X \ X=1/2 cycle |
21413 ADD X,Y \ Y=3/4 cycle
21414 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
21416 \ ******************************\
21417 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
21418 \ ******************************\
21419 BIT.B #RC5,&IR_IN \ C_flag = IR bit
21420 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
21421 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
21422 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
21423 SUB #1,W \ decrement count loop
21424 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
21425 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
21426 0<> WHILE \ ----> out of loop ----+
21427 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
21429 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
21430 CMP Y,X \ 1 | cycle time out of bound ?
21431 U>= IF \ 2 ^ | yes:
21432 BIC #$30,&RC5_TIM_CTL \ | | stop timer
21433 GOTO BW1 \ | | quit on truncated RC5 message
21435 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
21437 REPEAT \ ----> loop back --+ | with X = new RC5_period value
21438 \ ******************************\ |
21439 \ RC5_SampleEndOf: \ <---------------------+
21440 \ ******************************\
21441 BIC #$30,&RC5_TIM_CTL \ stop timer
21442 \ ******************************\
21443 \ RC5_ComputeNewRC5word \
21444 \ ******************************\
21445 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
21446 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
21447 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
21448 \ ******************************\
21449 \ RC5_ComputeC6bit \
21450 \ ******************************\
21451 BIT #BIT14,T \ test /C6 bit in T
21452 0= IF BIS #BIT6,X \ set C6 bit in X
21453 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
21454 \ ******************************\
21455 \ RC5_CommandByteIsDone \ -- BASE RC5_code
21456 \ ******************************\
21457 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
21458 \ ******************************\
21459 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
21460 XOR @RSP,T \ (new XOR old) Toggle bits
21461 BIT #UF10,T \ repeated RC5_command ?
21462 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
21463 XOR #UF10,0(RSP) \ 5 toggle bit memory
21464 \ ******************************\
21465 \ Display IR_RC5 code \
21466 \ ******************************\
21467 SUB #8,PSP \ TOS -- x x x x TOS
21468 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
21469 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
21470 MOV #$10,&BASEADR \ set hexadecimal base
21471 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
21472 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
21473 LO2HI \ switch from assembler to FORTH
21474 LCD_CLEAR \ set LCD cursor at home
21475 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
21476 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
21477 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
21478 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
21479 HI2LO \ -- switch from FORTH to assembler
21480 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
21481 MOV @PSP+,TOS \ -- TOS
21485 \ ******************************\
21487 \ ******************************\
21489 \ ... \ insert here your background task
21492 CALL &RXON \ comment this line to disable TERMINAL_INPUT
21494 \ ******************************\
21495 \ here start all interrupts \
21496 \ ******************************\
21497 \ here return all interrupts \
21498 \ ******************************\
21501 \ ******************************\
21503 \ ------------------------------\
21504 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
21505 \ ------------------------------\
21506 \ ... \ init specific I/O sys as you want
21507 \ ... \ before executing default WARM
21508 MOV #WARM,X \ ['] WARM
21510 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
21512 \ ------------------------------\
21514 \ ------------------------------\
21515 CODE STOP \ stops multitasking, must to be used before downloading app
21516 \ ------------------------------\
21517 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
21518 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
21519 MOV X,-2(X) \ restore the default background: SLEEP
21521 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
21522 BIC.B #RC5,&IR_IE \ clear RC5_Int
21523 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
21524 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
21525 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
21526 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
21527 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
21528 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
21530 ." RC5toLCD is removed,"
21531 ." type START to restart"
21532 WARM \ performs reset to reset all interrupt vectors.
21534 \ ------------------------------\
21536 \ ------------------------------\
21537 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
21538 \ ------------------------------\
21539 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
21540 \ - - \CNTL Counter lentgh \ 00 = 16 bits
21541 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
21542 \ -- \ID input divider \ 10 = /4
21543 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
21544 \ - \TBCLR TimerB Clear
21547 \ -------------------------------\
21548 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
21549 \ -- \CM Capture Mode
21554 \ --- \OUTMOD \ 011 = set/reset
21560 \ -------------------------------\
21562 \ -------------------------------\
21564 \ ------------------------------\
21565 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
21566 \ ------------------------------\
21567 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
21568 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
21569 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
21570 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
21572 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
21573 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
21575 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
21576 \ ------------------------------\
21577 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
21578 \ ------------------------------\
21579 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
21580 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
21581 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
21582 \ ------------------------------\
21583 BIS.B #LCDVo,&LCDVo_DIR \
21584 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
21585 \ ------------------------------\
21586 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
21587 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
21588 \ ------------------------------\
21589 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
21590 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
21591 \ ******************************\
21593 \ ******************************\
21594 BIS.B #RC5,&IR_IE \ enable RC5_Int
21595 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
21596 MOV #RC5_INT,&IR_Vec \ init interrupt vector
21597 \ ******************************\
21598 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
21599 \ ******************************\
21600 \ %01 0001 0100 \ TAxCTL
21601 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
21602 \ -- \ ID divided by 1
21603 \ -- \ MC MODE = up to TAxCCRn
21604 \ - \ TACLR clear timer count
21607 \ ------------------------------\
21608 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
21609 \ ------------------------------\
21611 \ --- \ TAIDEX pre divisor
21612 \ ------------------------------\
21613 \ %0000 0000 0000 0101 \ TAxCCR0
21614 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
21615 \ ------------------------------\
21616 \ %0000 0000 0001 0000 \ TAxCCTL0
21617 \ - \ CAP capture/compare mode = compare
21620 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
21621 \ ------------------------------\
21622 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
21623 \ ------------------------------\
21624 \ define LPM mode for ACCEPT \
21625 \ ------------------------------\
21626 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
21627 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
21628 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
21629 \ ------------------------------\
21631 \ ------------------------------\
21632 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
21633 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
21634 \ ------------------------------\
21635 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
21636 \ ------------------------------\
21637 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
21638 \ CMP #2,Y \ Power_ON event
21639 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
21641 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
21643 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
21645 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
21647 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
21648 \ ------------------------------\
21650 \ ------------------------------\
21652 \ ------------------------------\
21653 #1000 20_US \ 1- wait 20 ms
21654 %011 TOP_LCD \ 2- send DB5=DB4=1
21655 #205 20_US \ 3- wait 4,1 ms
21656 %011 TOP_LCD \ 4- send again DB5=DB4=1
21657 #5 20_US \ 5- wait 0,1 ms
21658 %011 TOP_LCD \ 6- send again again DB5=DB4=1
21659 #2 20_US \ wait 40 us = LCD cycle
21660 %010 TOP_LCD \ 7- send DB5=1 DB4=0
21661 #2 20_US \ wait 40 us = LCD cycle
21662 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
21663 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
21664 LCD_CLEAR \ 10- "LCD_Clear"
21665 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
21666 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
21667 LCD_CLEAR \ 10- "LCD_Clear"
21668 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
21669 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
21670 CR ." I love you" \ display message on LCD
21671 ['] CR >BODY IS CR \ CR executes its default value
21672 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
21673 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
21674 PWR_STATE ABORT \ init DP and continues with ABORT
21676 \ ------------------------------\
21678 \ ------------------------------\
21679 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
21680 \ ------------------------------\
21681 MOV #SLEEP,X \ replace default background process SLEEP
21682 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
21683 MOV #WARM,X \ replace default WARM
21684 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
21685 MOV X,PC \ then execute new WARM
21687 \ ------------------------------\
21690 ; downloading RC5toLCD.4th is done
21691 RST_HERE ; this app is protected against <reset>
21696 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
21698 [UNDEFINED] MARKER [IF]
21699 \ https://forth-standard.org/standard/core/MARKER
21701 \ ( "<spaces>name" -- )
21702 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
21703 \ with the execution semantics defined below.
21705 \ name Execution: ( -- )
21706 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
21707 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
21708 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
21709 \ not necessarily provided. No other contextual information such as numeric base is affected
21714 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
21715 SUB #2,Y \ 1 Y = LFA
21716 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
21717 ADD #4,&DP \ 3 add 2 cells
21721 MOV @RSP+,IP \ -- PFA
21722 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
21723 MOV @TOS,&INIDP \ set DP value for RST_STATE
21725 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
21732 \ https://forth-standard.org/standard/core/Fetch
21733 \ @ c-addr -- char fetch char from memory
21740 [UNDEFINED] CONSTANT [IF]
21741 \ https://forth-standard.org/standard/core/CONSTANT
21742 \ CONSTANT <name> n -- define a Forth CONSTANT
21746 MOV TOS,-2(W) \ PFA = n
21753 [UNDEFINED] STATE [IF]
21754 \ https://forth-standard.org/standard/core/STATE
21755 \ STATE -- a-addr holds compiler state
21756 STATEADR CONSTANT STATE
21760 \ https://forth-standard.org/standard/core/Equal
21761 \ = x1 x2 -- flag test x1=x2
21768 XOR #-1,TOS \ 1 flag Z = 1
21773 [UNDEFINED] IF [IF]
21774 \ https://forth-standard.org/standard/core/IF
21775 \ IF -- IFadr initialize conditional forward branch
21776 CODE IF \ immediate
21779 MOV &DP,TOS \ -- HERE
21780 ADD #4,&DP \ compile one word, reserve one word
21781 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
21782 ADD #2,TOS \ -- HERE+2=IFadr
21787 [UNDEFINED] THEN [IF]
21788 \ https://forth-standard.org/standard/core/THEN
21789 \ THEN IFadr -- resolve forward branch
21790 CODE THEN \ immediate
21791 MOV &DP,0(TOS) \ -- IFadr
21797 [UNDEFINED] ELSE [IF]
21798 \ https://forth-standard.org/standard/core/ELSE
21799 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
21800 CODE ELSE \ immediate
21801 ADD #4,&DP \ make room to compile two words
21802 MOV &DP,W \ W=HERE+4
21804 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
21806 MOV W,TOS \ -- ELSEadr
21811 [UNDEFINED] DEFER [IF]
21812 \ https://forth-standard.org/standard/core/DEFER
21813 \ DEFER "<spaces>name" --
21814 \ Skip leading space delimiters. Parse name delimited by a space.
21815 \ Create a definition for name with the execution semantics defined below.
21817 \ name Execution: --
21818 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
21819 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
21823 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
21824 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
21830 [UNDEFINED] DEFER! [IF]
21831 \ https://forth-standard.org/standard/core/DEFERStore
21832 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
21833 CODE DEFER! \ xt2 xt1 --
21834 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
21840 [UNDEFINED] IS [IF]
21841 \ https://forth-standard.org/standard/core/IS
21844 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
21845 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
21846 \ or in a definition : ... ['] U. IS DISPLAY ...
21847 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
21849 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
21852 IF POSTPONE ['] POSTPONE DEFER!
21858 [UNDEFINED] >BODY [IF]
21859 \ https://forth-standard.org/standard/core/toBODY
21860 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
21867 \ CODE 20uS \ n -- 8MHz version
21868 \ BEGIN \ 4 + 16 ~ loop
21869 \ MOV #39,rDOCON \ 39
21876 \ MOV #XDOCON,rDOCON \ 2
21881 CODE 20_US \ n -- n * 20 us
21882 BEGIN \ here we presume that LCD_TIM_IFG = 1...
21884 BIT #1,&LCD_TIM_CTL \ 3
21885 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
21886 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
21888 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
21893 CODE TOP_LCD \ LCD Sample
21894 \ \ if write : %xxxx_WWWW --
21895 \ \ if read : -- %0000_RRRR
21896 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
21897 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
21898 0= IF \ write LCD bits pattern
21899 AND.B #LCD_DB,TOS \
21900 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
21901 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21904 THEN \ read LCD bits pattern
21907 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
21908 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
21909 AND.B #LCD_DB,TOS \
21913 CODE LCD_WRC \ char -- Write Char
21914 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21916 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
21917 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
21918 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
21919 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
21920 COLON \ high level word starts here
21921 TOP_LCD 2 20_US \ write high nibble first
21925 CODE LCD_WRF \ func -- Write Fonction
21926 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21930 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
21931 : LCD_HOME $02 LCD_WRF 100 20_us ;
21933 \ [UNDEFINED] OR [IF]
21935 \ \ https://forth-standard.org/standard/core/OR
21936 \ \ C OR x1 x2 -- x3 logical OR
21944 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
21945 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
21946 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
21947 \ : LCD_FN_SET $20 OR LCD_WrF ;
21948 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
21949 \ : LCD_GOTO $80 OR LCD_WrF ;
21952 \ CODE LCD_RDS \ -- status Read Status
21953 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
21954 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
21955 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
21956 \ COLON \ starts a FORTH word
21957 \ TOP_LCD 2 20_us \ -- %0000_HHHH
21958 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
21959 \ HI2LO \ switch from FORTH to assembler
21960 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
21961 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
21962 \ MOV @RSP+,IP \ restore IP saved by COLON
21966 \ CODE LCD_RDC \ -- char Read Char
21967 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
21972 \ ******************************\
21973 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
21974 \ ******************************\
21975 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
21976 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
21977 BIT.B #SW2,&SW2_IN \ test switch S2
21978 0= IF \ case of switch S2 pressed
21979 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
21981 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
21984 BIT.B #SW1,&SW1_IN \ test switch S1 input
21985 0= IF \ case of Switch S1 pressed
21986 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
21988 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
21992 BW1 \ from quit on truncated RC5 message, repeated RC5 command
21996 \ ******************************\
21997 ASM RC5_INT \ wake up on Px.RC5 change interrupt
21998 \ ******************************\
21999 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22000 \ ******************************\
22001 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22002 \ \ SMclock = 8|16|24 MHz
22003 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
22004 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
22005 \ \ SR(9)=new Toggle bit memory (ADD on)
22006 \ ******************************\
22007 \ RC5_FirstStartBitHalfCycle: \
22008 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
22009 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
22010 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
22011 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
22013 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
22014 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
22016 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
22017 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
22019 MOV #1778,X \ RC5_Period * 1us
22020 MOV #14,W \ count of loop
22022 \ ******************************\
22023 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
22024 \ ******************************\ |
22025 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
22026 \ RC5_Compute_3/4_Period: \ |
22027 RRUM #1,X \ X=1/2 cycle |
22030 ADD X,Y \ Y=3/4 cycle
22031 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
22033 \ ******************************\
22034 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
22035 \ ******************************\
22036 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22037 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
22038 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22039 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22040 SUB #1,W \ decrement count loop
22041 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
22042 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22043 0<> WHILE \ ----> out of loop ----+
22044 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
22046 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
22047 CMP Y,X \ 1 | cycle time out of bound ?
22048 U>= IF \ 2 ^ | yes:
22049 BIC #$30,&RC5_TIM_CTL \ | | stop timer
22050 GOTO BW1 \ | | quit on truncated RC5 message
22052 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
22054 REPEAT \ ----> loop back --+ | with X = new RC5_period value
22055 \ ******************************\ |
22056 \ RC5_SampleEndOf: \ <---------------------+
22057 \ ******************************\
22058 BIC #$30,&RC5_TIM_CTL \ stop timer
22059 \ ******************************\
22060 \ RC5_ComputeNewRC5word \
22061 \ ******************************\
22062 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
22063 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
22064 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
22065 \ ******************************\
22066 \ RC5_ComputeC6bit \
22067 \ ******************************\
22068 BIT #BIT14,T \ test /C6 bit in T
22069 0= IF BIS #BIT6,X \ set C6 bit in X
22070 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
22071 \ ******************************\
22072 \ RC5_CommandByteIsDone \ -- BASE RC5_code
22073 \ ******************************\
22074 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22075 \ ******************************\
22076 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
22077 XOR @RSP,T \ (new XOR old) Toggle bits
22078 BIT #UF10,T \ repeated RC5_command ?
22079 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
22080 XOR #UF10,0(RSP) \ 5 toggle bit memory
22081 \ ******************************\
22082 \ Display IR_RC5 code \
22083 \ ******************************\
22084 SUB #8,PSP \ TOS -- x x x x TOS
22085 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
22086 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
22087 MOV #$10,&BASEADR \ set hexadecimal base
22088 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
22089 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
22090 LO2HI \ switch from assembler to FORTH
22091 LCD_CLEAR \ set LCD cursor at home
22092 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
22093 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
22094 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
22095 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
22096 HI2LO \ -- switch from FORTH to assembler
22097 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
22098 MOV @PSP+,TOS \ -- TOS
22102 \ ******************************\
22104 \ ******************************\
22106 \ ... \ insert here your background task
22109 CALL &RXON \ comment this line to disable TERMINAL_INPUT
22111 \ ******************************\
22112 \ here start all interrupts \
22113 \ ******************************\
22114 \ here return all interrupts \
22115 \ ******************************\
22118 \ ******************************\
22120 \ ------------------------------\
22121 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
22122 \ ------------------------------\
22123 \ ... \ init specific I/O sys as you want
22124 \ ... \ before executing default WARM
22125 MOV #WARM,X \ ['] WARM
22127 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
22129 \ ------------------------------\
22131 \ ------------------------------\
22132 CODE STOP \ stops multitasking, must to be used before downloading app
22133 \ ------------------------------\
22134 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
22135 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
22136 MOV X,-2(X) \ restore the default background: SLEEP
22138 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
22139 BIC.B #RC5,&IR_IE \ clear RC5_Int
22140 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
22141 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
22142 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
22143 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
22144 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
22145 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
22147 ." RC5toLCD is removed,"
22148 ." type START to restart"
22149 WARM \ performs reset to reset all interrupt vectors.
22151 \ ------------------------------\
22153 \ ------------------------------\
22154 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
22155 \ ------------------------------\
22156 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
22157 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22158 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22159 \ -- \ID input divider \ 10 = /4
22160 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
22161 \ - \TBCLR TimerB Clear
22164 \ -------------------------------\
22165 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22166 \ -- \CM Capture Mode
22171 \ --- \OUTMOD \ 011 = set/reset
22177 \ -------------------------------\
22179 \ -------------------------------\
22181 \ ------------------------------\
22182 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
22183 \ ------------------------------\
22184 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
22185 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
22186 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
22187 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
22189 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
22190 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
22192 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
22193 \ ------------------------------\
22194 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
22195 \ ------------------------------\
22196 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
22197 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
22198 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22199 \ ------------------------------\
22200 BIS.B #LCDVo,&LCDVo_DIR \
22201 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
22202 \ ------------------------------\
22203 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22204 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22205 \ ------------------------------\
22206 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22207 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22208 \ ******************************\
22210 \ ******************************\
22211 BIS.B #RC5,&IR_IE \ enable RC5_Int
22212 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22213 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22214 \ ******************************\
22215 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
22216 \ ******************************\
22217 \ %01 0001 0100 \ TAxCTL
22218 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
22219 \ -- \ ID divided by 1
22220 \ -- \ MC MODE = up to TAxCCRn
22221 \ - \ TACLR clear timer count
22224 \ ------------------------------\
22225 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
22226 \ ------------------------------\
22228 \ --- \ TAIDEX pre divisor
22229 \ ------------------------------\
22230 \ %0000 0000 0000 0101 \ TAxCCR0
22231 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
22232 \ ------------------------------\
22233 \ %0000 0000 0001 0000 \ TAxCCTL0
22234 \ - \ CAP capture/compare mode = compare
22237 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
22238 \ ------------------------------\
22239 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
22240 \ ------------------------------\
22241 \ define LPM mode for ACCEPT \
22242 \ ------------------------------\
22243 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22244 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22245 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22246 \ ------------------------------\
22248 \ ------------------------------\
22249 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
22250 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
22251 \ ------------------------------\
22252 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
22253 \ ------------------------------\
22254 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
22255 \ CMP #2,Y \ Power_ON event
22256 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
22258 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
22260 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
22262 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
22264 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
22265 \ ------------------------------\
22267 \ ------------------------------\
22269 \ ------------------------------\
22270 #1000 20_US \ 1- wait 20 ms
22271 %011 TOP_LCD \ 2- send DB5=DB4=1
22272 #205 20_US \ 3- wait 4,1 ms
22273 %011 TOP_LCD \ 4- send again DB5=DB4=1
22274 #5 20_US \ 5- wait 0,1 ms
22275 %011 TOP_LCD \ 6- send again again DB5=DB4=1
22276 #2 20_US \ wait 40 us = LCD cycle
22277 %010 TOP_LCD \ 7- send DB5=1 DB4=0
22278 #2 20_US \ wait 40 us = LCD cycle
22279 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22280 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22281 LCD_CLEAR \ 10- "LCD_Clear"
22282 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22283 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22284 LCD_CLEAR \ 10- "LCD_Clear"
22285 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22286 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22287 CR ." I love you" \ display message on LCD
22288 ['] CR >BODY IS CR \ CR executes its default value
22289 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
22290 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
22291 PWR_STATE ABORT \ init DP and continues with ABORT
22293 \ ------------------------------\
22295 \ ------------------------------\
22296 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
22297 \ ------------------------------\
22298 MOV #SLEEP,X \ replace default background process SLEEP
22299 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
22300 MOV #WARM,X \ replace default WARM
22301 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
22302 MOV X,PC \ then execute new WARM
22304 \ ------------------------------\
22307 ; downloading RC5toLCD.4th is done
22308 RST_HERE ; this app is protected against <reset>
22313 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
22315 [UNDEFINED] MARKER [IF]
22316 \ https://forth-standard.org/standard/core/MARKER
22318 \ ( "<spaces>name" -- )
22319 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
22320 \ with the execution semantics defined below.
22322 \ name Execution: ( -- )
22323 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
22324 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
22325 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
22326 \ not necessarily provided. No other contextual information such as numeric base is affected
22331 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
22332 SUB #2,Y \ 1 Y = LFA
22333 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
22334 ADD #4,&DP \ 3 add 2 cells
22338 MOV @RSP+,IP \ -- PFA
22339 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
22340 MOV @TOS,&INIDP \ set DP value for RST_STATE
22342 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
22349 \ https://forth-standard.org/standard/core/Fetch
22350 \ @ c-addr -- char fetch char from memory
22357 [UNDEFINED] CONSTANT [IF]
22358 \ https://forth-standard.org/standard/core/CONSTANT
22359 \ CONSTANT <name> n -- define a Forth CONSTANT
22363 MOV TOS,-2(W) \ PFA = n
22370 [UNDEFINED] STATE [IF]
22371 \ https://forth-standard.org/standard/core/STATE
22372 \ STATE -- a-addr holds compiler state
22373 STATEADR CONSTANT STATE
22377 \ https://forth-standard.org/standard/core/Equal
22378 \ = x1 x2 -- flag test x1=x2
22385 XOR #-1,TOS \ 1 flag Z = 1
22390 [UNDEFINED] IF [IF]
22391 \ https://forth-standard.org/standard/core/IF
22392 \ IF -- IFadr initialize conditional forward branch
22393 CODE IF \ immediate
22396 MOV &DP,TOS \ -- HERE
22397 ADD #4,&DP \ compile one word, reserve one word
22398 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
22399 ADD #2,TOS \ -- HERE+2=IFadr
22404 [UNDEFINED] THEN [IF]
22405 \ https://forth-standard.org/standard/core/THEN
22406 \ THEN IFadr -- resolve forward branch
22407 CODE THEN \ immediate
22408 MOV &DP,0(TOS) \ -- IFadr
22414 [UNDEFINED] ELSE [IF]
22415 \ https://forth-standard.org/standard/core/ELSE
22416 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
22417 CODE ELSE \ immediate
22418 ADD #4,&DP \ make room to compile two words
22419 MOV &DP,W \ W=HERE+4
22421 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
22423 MOV W,TOS \ -- ELSEadr
22428 [UNDEFINED] DEFER [IF]
22429 \ https://forth-standard.org/standard/core/DEFER
22430 \ DEFER "<spaces>name" --
22431 \ Skip leading space delimiters. Parse name delimited by a space.
22432 \ Create a definition for name with the execution semantics defined below.
22434 \ name Execution: --
22435 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
22436 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
22440 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
22441 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
22447 [UNDEFINED] DEFER! [IF]
22448 \ https://forth-standard.org/standard/core/DEFERStore
22449 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
22450 CODE DEFER! \ xt2 xt1 --
22451 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
22457 [UNDEFINED] IS [IF]
22458 \ https://forth-standard.org/standard/core/IS
22461 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
22462 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
22463 \ or in a definition : ... ['] U. IS DISPLAY ...
22464 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
22466 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
22469 IF POSTPONE ['] POSTPONE DEFER!
22475 [UNDEFINED] >BODY [IF]
22476 \ https://forth-standard.org/standard/core/toBODY
22477 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
22484 \ CODE 20uS \ n -- 8MHz version
22485 \ BEGIN \ 4 + 16 ~ loop
22486 \ MOV #39,rDOCON \ 39
22493 \ MOV #XDOCON,rDOCON \ 2
22498 CODE 20_US \ n -- n * 20 us
22499 BEGIN \ here we presume that LCD_TIM_IFG = 1...
22501 BIT #1,&LCD_TIM_CTL \ 3
22502 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
22503 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
22505 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
22510 CODE TOP_LCD \ LCD Sample
22511 \ \ if write : %xxxx_WWWW --
22512 \ \ if read : -- %0000_RRRR
22513 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
22514 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
22515 0= IF \ write LCD bits pattern
22516 AND.B #LCD_DB,TOS \
22517 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
22518 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22521 THEN \ read LCD bits pattern
22524 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
22525 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
22526 AND.B #LCD_DB,TOS \
22530 CODE LCD_WRC \ char -- Write Char
22531 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22533 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
22534 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
22535 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
22536 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
22537 COLON \ high level word starts here
22538 TOP_LCD 2 20_US \ write high nibble first
22542 CODE LCD_WRF \ func -- Write Fonction
22543 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22547 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
22548 : LCD_HOME $02 LCD_WRF 100 20_us ;
22550 \ [UNDEFINED] OR [IF]
22552 \ \ https://forth-standard.org/standard/core/OR
22553 \ \ C OR x1 x2 -- x3 logical OR
22561 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
22562 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
22563 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
22564 \ : LCD_FN_SET $20 OR LCD_WrF ;
22565 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
22566 \ : LCD_GOTO $80 OR LCD_WrF ;
22569 \ CODE LCD_RDS \ -- status Read Status
22570 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
22571 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
22572 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
22573 \ COLON \ starts a FORTH word
22574 \ TOP_LCD 2 20_us \ -- %0000_HHHH
22575 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
22576 \ HI2LO \ switch from FORTH to assembler
22577 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
22578 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
22579 \ MOV @RSP+,IP \ restore IP saved by COLON
22583 \ CODE LCD_RDC \ -- char Read Char
22584 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
22589 \ ******************************\
22590 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
22591 \ ******************************\
22592 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
22593 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
22594 BIT.B #SW2,&SW2_IN \ test switch S2
22595 0= IF \ case of switch S2 pressed
22596 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
22598 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
22601 BIT.B #SW1,&SW1_IN \ test switch S1 input
22602 0= IF \ case of Switch S1 pressed
22603 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
22605 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
22609 BW1 \ from quit on truncated RC5 message, repeated RC5 command
22613 \ ******************************\
22614 ASM RC5_INT \ wake up on Px.RC5 change interrupt
22615 \ ******************************\
22616 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
22617 \ ******************************\
22618 \ \ in : SR(9)=old Toggle bit memory (ADD on)
22619 \ \ SMclock = 8|16|24 MHz
22620 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
22621 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
22622 \ \ SR(9)=new Toggle bit memory (ADD on)
22623 \ ******************************\
22624 \ RC5_FirstStartBitHalfCycle: \
22625 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
22626 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
22627 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
22628 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
22630 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
22631 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
22633 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
22634 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
22636 MOV #1778,X \ RC5_Period * 1us
22637 MOV #14,W \ count of loop
22639 \ ******************************\
22640 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
22641 \ ******************************\ |
22642 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
22643 \ RC5_Compute_3/4_Period: \ |
22644 RRUM #1,X \ X=1/2 cycle |
22647 ADD X,Y \ Y=3/4 cycle
22648 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
22650 \ ******************************\
22651 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
22652 \ ******************************\
22653 BIT.B #RC5,&IR_IN \ C_flag = IR bit
22654 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
22655 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
22656 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
22657 SUB #1,W \ decrement count loop
22658 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
22659 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
22660 0<> WHILE \ ----> out of loop ----+
22661 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
22663 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
22664 CMP Y,X \ 1 | cycle time out of bound ?
22665 U>= IF \ 2 ^ | yes:
22666 BIC #$30,&RC5_TIM_CTL \ | | stop timer
22667 GOTO BW1 \ | | quit on truncated RC5 message
22669 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
22671 REPEAT \ ----> loop back --+ | with X = new RC5_period value
22672 \ ******************************\ |
22673 \ RC5_SampleEndOf: \ <---------------------+
22674 \ ******************************\
22675 BIC #$30,&RC5_TIM_CTL \ stop timer
22676 \ ******************************\
22677 \ RC5_ComputeNewRC5word \
22678 \ ******************************\
22679 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
22680 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
22681 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
22682 \ ******************************\
22683 \ RC5_ComputeC6bit \
22684 \ ******************************\
22685 BIT #BIT14,T \ test /C6 bit in T
22686 0= IF BIS #BIT6,X \ set C6 bit in X
22687 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
22688 \ ******************************\
22689 \ RC5_CommandByteIsDone \ -- BASE RC5_code
22690 \ ******************************\
22691 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
22692 \ ******************************\
22693 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
22694 XOR @RSP,T \ (new XOR old) Toggle bits
22695 BIT #UF10,T \ repeated RC5_command ?
22696 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
22697 XOR #UF10,0(RSP) \ 5 toggle bit memory
22698 \ ******************************\
22699 \ Display IR_RC5 code \
22700 \ ******************************\
22701 SUB #8,PSP \ TOS -- x x x x TOS
22702 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
22703 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
22704 MOV #$10,&BASEADR \ set hexadecimal base
22705 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
22706 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
22707 LO2HI \ switch from assembler to FORTH
22708 LCD_CLEAR \ set LCD cursor at home
22709 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
22710 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
22711 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
22712 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
22713 HI2LO \ -- switch from FORTH to assembler
22714 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
22715 MOV @PSP+,TOS \ -- TOS
22719 \ ******************************\
22721 \ ******************************\
22723 \ ... \ insert here your background task
22726 CALL &RXON \ comment this line to disable TERMINAL_INPUT
22728 \ ******************************\
22729 \ here start all interrupts \
22730 \ ******************************\
22731 \ here return all interrupts \
22732 \ ******************************\
22735 \ ******************************\
22737 \ ------------------------------\
22738 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
22739 \ ------------------------------\
22740 \ ... \ init specific I/O sys as you want
22741 \ ... \ before executing default WARM
22742 MOV #WARM,X \ ['] WARM
22744 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
22746 \ ------------------------------\
22748 \ ------------------------------\
22749 CODE STOP \ stops multitasking, must to be used before downloading app
22750 \ ------------------------------\
22751 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
22752 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
22753 MOV X,-2(X) \ restore the default background: SLEEP
22755 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
22756 BIC.B #RC5,&IR_IE \ clear RC5_Int
22757 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
22758 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
22759 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
22760 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
22761 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
22762 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
22764 ." RC5toLCD is removed,"
22765 ." type START to restart"
22766 WARM \ performs reset to reset all interrupt vectors.
22768 \ ------------------------------\
22770 \ ------------------------------\
22771 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
22772 \ ------------------------------\
22773 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
22774 \ - - \CNTL Counter lentgh \ 00 = 16 bits
22775 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
22776 \ -- \ID input divider \ 10 = /4
22777 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
22778 \ - \TBCLR TimerB Clear
22781 \ -------------------------------\
22782 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
22783 \ -- \CM Capture Mode
22788 \ --- \OUTMOD \ 011 = set/reset
22794 \ -------------------------------\
22796 \ -------------------------------\
22798 \ ------------------------------\
22799 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
22800 \ ------------------------------\
22801 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
22802 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
22803 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
22804 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
22806 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
22807 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
22809 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
22810 \ ------------------------------\
22811 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
22812 \ ------------------------------\
22813 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
22814 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
22815 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
22816 \ ------------------------------\
22817 BIS.B #LCDVo,&LCDVo_DIR \
22818 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
22819 \ ------------------------------\
22820 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
22821 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
22822 \ ------------------------------\
22823 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
22824 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
22825 \ ******************************\
22827 \ ******************************\
22828 BIS.B #RC5,&IR_IE \ enable RC5_Int
22829 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
22830 MOV #RC5_INT,&IR_Vec \ init interrupt vector
22831 \ ******************************\
22832 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
22833 \ ******************************\
22834 \ %01 0001 0100 \ TAxCTL
22835 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
22836 \ -- \ ID divided by 1
22837 \ -- \ MC MODE = up to TAxCCRn
22838 \ - \ TACLR clear timer count
22841 \ ------------------------------\
22842 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
22843 \ ------------------------------\
22845 \ --- \ TAIDEX pre divisor
22846 \ ------------------------------\
22847 \ %0000 0000 0000 0101 \ TAxCCR0
22848 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
22849 \ ------------------------------\
22850 \ %0000 0000 0001 0000 \ TAxCCTL0
22851 \ - \ CAP capture/compare mode = compare
22854 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
22855 \ ------------------------------\
22856 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
22857 \ ------------------------------\
22858 \ define LPM mode for ACCEPT \
22859 \ ------------------------------\
22860 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
22861 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
22862 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
22863 \ ------------------------------\
22865 \ ------------------------------\
22866 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
22867 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
22868 \ ------------------------------\
22869 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
22870 \ ------------------------------\
22871 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
22872 \ CMP #2,Y \ Power_ON event
22873 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
22875 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
22877 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
22879 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
22881 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
22882 \ ------------------------------\
22884 \ ------------------------------\
22886 \ ------------------------------\
22887 #1000 20_US \ 1- wait 20 ms
22888 %011 TOP_LCD \ 2- send DB5=DB4=1
22889 #205 20_US \ 3- wait 4,1 ms
22890 %011 TOP_LCD \ 4- send again DB5=DB4=1
22891 #5 20_US \ 5- wait 0,1 ms
22892 %011 TOP_LCD \ 6- send again again DB5=DB4=1
22893 #2 20_US \ wait 40 us = LCD cycle
22894 %010 TOP_LCD \ 7- send DB5=1 DB4=0
22895 #2 20_US \ wait 40 us = LCD cycle
22896 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
22897 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
22898 LCD_CLEAR \ 10- "LCD_Clear"
22899 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
22900 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
22901 LCD_CLEAR \ 10- "LCD_Clear"
22902 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
22903 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
22904 CR ." I love you" \ display message on LCD
22905 ['] CR >BODY IS CR \ CR executes its default value
22906 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
22907 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
22908 PWR_STATE ABORT \ init DP and continues with ABORT
22910 \ ------------------------------\
22912 \ ------------------------------\
22913 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
22914 \ ------------------------------\
22915 MOV #SLEEP,X \ replace default background process SLEEP
22916 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
22917 MOV #WARM,X \ replace default WARM
22918 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
22919 MOV X,PC \ then execute new WARM
22921 \ ------------------------------\
22924 ; downloading RC5toLCD.4th is done
22925 RST_HERE ; this app is protected against <reset>
22930 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
22932 [UNDEFINED] MARKER [IF]
22933 \ https://forth-standard.org/standard/core/MARKER
22935 \ ( "<spaces>name" -- )
22936 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
22937 \ with the execution semantics defined below.
22939 \ name Execution: ( -- )
22940 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
22941 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
22942 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
22943 \ not necessarily provided. No other contextual information such as numeric base is affected
22948 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
22949 SUB #2,Y \ 1 Y = LFA
22950 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
22951 ADD #4,&DP \ 3 add 2 cells
22955 MOV @RSP+,IP \ -- PFA
22956 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
22957 MOV @TOS,&INIDP \ set DP value for RST_STATE
22959 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
22966 \ https://forth-standard.org/standard/core/Fetch
22967 \ @ c-addr -- char fetch char from memory
22974 [UNDEFINED] CONSTANT [IF]
22975 \ https://forth-standard.org/standard/core/CONSTANT
22976 \ CONSTANT <name> n -- define a Forth CONSTANT
22980 MOV TOS,-2(W) \ PFA = n
22987 [UNDEFINED] STATE [IF]
22988 \ https://forth-standard.org/standard/core/STATE
22989 \ STATE -- a-addr holds compiler state
22990 STATEADR CONSTANT STATE
22994 \ https://forth-standard.org/standard/core/Equal
22995 \ = x1 x2 -- flag test x1=x2
23002 XOR #-1,TOS \ 1 flag Z = 1
23007 [UNDEFINED] IF [IF]
23008 \ https://forth-standard.org/standard/core/IF
23009 \ IF -- IFadr initialize conditional forward branch
23010 CODE IF \ immediate
23013 MOV &DP,TOS \ -- HERE
23014 ADD #4,&DP \ compile one word, reserve one word
23015 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
23016 ADD #2,TOS \ -- HERE+2=IFadr
23021 [UNDEFINED] THEN [IF]
23022 \ https://forth-standard.org/standard/core/THEN
23023 \ THEN IFadr -- resolve forward branch
23024 CODE THEN \ immediate
23025 MOV &DP,0(TOS) \ -- IFadr
23031 [UNDEFINED] ELSE [IF]
23032 \ https://forth-standard.org/standard/core/ELSE
23033 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
23034 CODE ELSE \ immediate
23035 ADD #4,&DP \ make room to compile two words
23036 MOV &DP,W \ W=HERE+4
23038 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
23040 MOV W,TOS \ -- ELSEadr
23045 [UNDEFINED] DEFER [IF]
23046 \ https://forth-standard.org/standard/core/DEFER
23047 \ DEFER "<spaces>name" --
23048 \ Skip leading space delimiters. Parse name delimited by a space.
23049 \ Create a definition for name with the execution semantics defined below.
23051 \ name Execution: --
23052 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
23053 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
23057 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
23058 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
23064 [UNDEFINED] DEFER! [IF]
23065 \ https://forth-standard.org/standard/core/DEFERStore
23066 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
23067 CODE DEFER! \ xt2 xt1 --
23068 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
23074 [UNDEFINED] IS [IF]
23075 \ https://forth-standard.org/standard/core/IS
23078 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
23079 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
23080 \ or in a definition : ... ['] U. IS DISPLAY ...
23081 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
23083 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
23086 IF POSTPONE ['] POSTPONE DEFER!
23092 [UNDEFINED] >BODY [IF]
23093 \ https://forth-standard.org/standard/core/toBODY
23094 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
23101 \ CODE 20uS \ n -- 8MHz version
23102 \ BEGIN \ 4 + 16 ~ loop
23103 \ MOV #39,rDOCON \ 39
23110 \ MOV #XDOCON,rDOCON \ 2
23115 CODE 20_US \ n -- n * 20 us
23116 BEGIN \ here we presume that LCD_TIM_IFG = 1...
23118 BIT #1,&LCD_TIM_CTL \ 3
23119 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
23120 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
23122 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
23127 CODE TOP_LCD \ LCD Sample
23128 \ \ if write : %xxxx_WWWW --
23129 \ \ if read : -- %0000_RRRR
23130 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23131 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23132 0= IF \ write LCD bits pattern
23133 AND.B #LCD_DB,TOS \
23134 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23135 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23138 THEN \ read LCD bits pattern
23141 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23142 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23143 AND.B #LCD_DB,TOS \
23147 CODE LCD_WRC \ char -- Write Char
23148 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23150 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
23151 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
23152 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23153 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23154 COLON \ high level word starts here
23155 TOP_LCD 2 20_US \ write high nibble first
23159 CODE LCD_WRF \ func -- Write Fonction
23160 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23164 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
23165 : LCD_HOME $02 LCD_WRF 100 20_us ;
23167 \ [UNDEFINED] OR [IF]
23169 \ \ https://forth-standard.org/standard/core/OR
23170 \ \ C OR x1 x2 -- x3 logical OR
23178 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
23179 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
23180 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
23181 \ : LCD_FN_SET $20 OR LCD_WrF ;
23182 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
23183 \ : LCD_GOTO $80 OR LCD_WrF ;
23186 \ CODE LCD_RDS \ -- status Read Status
23187 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23188 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23189 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23190 \ COLON \ starts a FORTH word
23191 \ TOP_LCD 2 20_us \ -- %0000_HHHH
23192 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
23193 \ HI2LO \ switch from FORTH to assembler
23194 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
23195 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
23196 \ MOV @RSP+,IP \ restore IP saved by COLON
23200 \ CODE LCD_RDC \ -- char Read Char
23201 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23206 \ ******************************\
23207 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23208 \ ******************************\
23209 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23210 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
23211 BIT.B #SW2,&SW2_IN \ test switch S2
23212 0= IF \ case of switch S2 pressed
23213 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
23215 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
23218 BIT.B #SW1,&SW1_IN \ test switch S1 input
23219 0= IF \ case of Switch S1 pressed
23220 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23222 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23226 BW1 \ from quit on truncated RC5 message, repeated RC5 command
23230 \ ******************************\
23231 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23232 \ ******************************\
23233 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23234 \ ******************************\
23235 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23236 \ \ SMclock = 8|16|24 MHz
23237 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23238 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23239 \ \ SR(9)=new Toggle bit memory (ADD on)
23240 \ ******************************\
23241 \ RC5_FirstStartBitHalfCycle: \
23242 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23243 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23244 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
23245 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
23247 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
23248 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
23250 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
23251 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
23253 MOV #1778,X \ RC5_Period * 1us
23254 MOV #14,W \ count of loop
23256 \ ******************************\
23257 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
23258 \ ******************************\ |
23259 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23260 \ RC5_Compute_3/4_Period: \ |
23261 RRUM #1,X \ X=1/2 cycle |
23264 ADD X,Y \ Y=3/4 cycle
23265 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
23267 \ ******************************\
23268 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23269 \ ******************************\
23270 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23271 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
23272 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23273 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23274 SUB #1,W \ decrement count loop
23275 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
23276 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23277 0<> WHILE \ ----> out of loop ----+
23278 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23280 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
23281 CMP Y,X \ 1 | cycle time out of bound ?
23282 U>= IF \ 2 ^ | yes:
23283 BIC #$30,&RC5_TIM_CTL \ | | stop timer
23284 GOTO BW1 \ | | quit on truncated RC5 message
23286 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
23288 REPEAT \ ----> loop back --+ | with X = new RC5_period value
23289 \ ******************************\ |
23290 \ RC5_SampleEndOf: \ <---------------------+
23291 \ ******************************\
23292 BIC #$30,&RC5_TIM_CTL \ stop timer
23293 \ ******************************\
23294 \ RC5_ComputeNewRC5word \
23295 \ ******************************\
23296 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
23297 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
23298 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
23299 \ ******************************\
23300 \ RC5_ComputeC6bit \
23301 \ ******************************\
23302 BIT #BIT14,T \ test /C6 bit in T
23303 0= IF BIS #BIT6,X \ set C6 bit in X
23304 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
23305 \ ******************************\
23306 \ RC5_CommandByteIsDone \ -- BASE RC5_code
23307 \ ******************************\
23308 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23309 \ ******************************\
23310 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
23311 XOR @RSP,T \ (new XOR old) Toggle bits
23312 BIT #UF10,T \ repeated RC5_command ?
23313 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
23314 XOR #UF10,0(RSP) \ 5 toggle bit memory
23315 \ ******************************\
23316 \ Display IR_RC5 code \
23317 \ ******************************\
23318 SUB #8,PSP \ TOS -- x x x x TOS
23319 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
23320 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
23321 MOV #$10,&BASEADR \ set hexadecimal base
23322 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
23323 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
23324 LO2HI \ switch from assembler to FORTH
23325 LCD_CLEAR \ set LCD cursor at home
23326 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
23327 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
23328 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
23329 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
23330 HI2LO \ -- switch from FORTH to assembler
23331 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
23332 MOV @PSP+,TOS \ -- TOS
23336 \ ******************************\
23338 \ ******************************\
23340 \ ... \ insert here your background task
23343 CALL &RXON \ comment this line to disable TERMINAL_INPUT
23345 \ ******************************\
23346 \ here start all interrupts \
23347 \ ******************************\
23348 \ here return all interrupts \
23349 \ ******************************\
23352 \ ******************************\
23354 \ ------------------------------\
23355 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
23356 \ ------------------------------\
23357 \ ... \ init specific I/O sys as you want
23358 \ ... \ before executing default WARM
23359 MOV #WARM,X \ ['] WARM
23361 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
23363 \ ------------------------------\
23365 \ ------------------------------\
23366 CODE STOP \ stops multitasking, must to be used before downloading app
23367 \ ------------------------------\
23368 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
23369 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
23370 MOV X,-2(X) \ restore the default background: SLEEP
23372 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
23373 BIC.B #RC5,&IR_IE \ clear RC5_Int
23374 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
23375 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
23376 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
23377 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
23378 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
23379 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
23381 ." RC5toLCD is removed,"
23382 ." type START to restart"
23383 WARM \ performs reset to reset all interrupt vectors.
23385 \ ------------------------------\
23387 \ ------------------------------\
23388 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
23389 \ ------------------------------\
23390 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
23391 \ - - \CNTL Counter lentgh \ 00 = 16 bits
23392 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
23393 \ -- \ID input divider \ 10 = /4
23394 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
23395 \ - \TBCLR TimerB Clear
23398 \ -------------------------------\
23399 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
23400 \ -- \CM Capture Mode
23405 \ --- \OUTMOD \ 011 = set/reset
23411 \ -------------------------------\
23413 \ -------------------------------\
23415 \ ------------------------------\
23416 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
23417 \ ------------------------------\
23418 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
23419 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
23420 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
23421 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
23423 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
23424 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
23426 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
23427 \ ------------------------------\
23428 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
23429 \ ------------------------------\
23430 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
23431 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
23432 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
23433 \ ------------------------------\
23434 BIS.B #LCDVo,&LCDVo_DIR \
23435 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
23436 \ ------------------------------\
23437 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
23438 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
23439 \ ------------------------------\
23440 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
23441 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
23442 \ ******************************\
23444 \ ******************************\
23445 BIS.B #RC5,&IR_IE \ enable RC5_Int
23446 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
23447 MOV #RC5_INT,&IR_Vec \ init interrupt vector
23448 \ ******************************\
23449 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
23450 \ ******************************\
23451 \ %01 0001 0100 \ TAxCTL
23452 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
23453 \ -- \ ID divided by 1
23454 \ -- \ MC MODE = up to TAxCCRn
23455 \ - \ TACLR clear timer count
23458 \ ------------------------------\
23459 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
23460 \ ------------------------------\
23462 \ --- \ TAIDEX pre divisor
23463 \ ------------------------------\
23464 \ %0000 0000 0000 0101 \ TAxCCR0
23465 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
23466 \ ------------------------------\
23467 \ %0000 0000 0001 0000 \ TAxCCTL0
23468 \ - \ CAP capture/compare mode = compare
23471 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
23472 \ ------------------------------\
23473 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
23474 \ ------------------------------\
23475 \ define LPM mode for ACCEPT \
23476 \ ------------------------------\
23477 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
23478 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
23479 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
23480 \ ------------------------------\
23482 \ ------------------------------\
23483 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
23484 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
23485 \ ------------------------------\
23486 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
23487 \ ------------------------------\
23488 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
23489 \ CMP #2,Y \ Power_ON event
23490 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
23492 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
23494 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
23496 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
23498 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
23499 \ ------------------------------\
23501 \ ------------------------------\
23503 \ ------------------------------\
23504 #1000 20_US \ 1- wait 20 ms
23505 %011 TOP_LCD \ 2- send DB5=DB4=1
23506 #205 20_US \ 3- wait 4,1 ms
23507 %011 TOP_LCD \ 4- send again DB5=DB4=1
23508 #5 20_US \ 5- wait 0,1 ms
23509 %011 TOP_LCD \ 6- send again again DB5=DB4=1
23510 #2 20_US \ wait 40 us = LCD cycle
23511 %010 TOP_LCD \ 7- send DB5=1 DB4=0
23512 #2 20_US \ wait 40 us = LCD cycle
23513 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
23514 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
23515 LCD_CLEAR \ 10- "LCD_Clear"
23516 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
23517 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
23518 LCD_CLEAR \ 10- "LCD_Clear"
23519 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
23520 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
23521 CR ." I love you" \ display message on LCD
23522 ['] CR >BODY IS CR \ CR executes its default value
23523 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
23524 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
23525 PWR_STATE ABORT \ init DP and continues with ABORT
23527 \ ------------------------------\
23529 \ ------------------------------\
23530 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
23531 \ ------------------------------\
23532 MOV #SLEEP,X \ replace default background process SLEEP
23533 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
23534 MOV #WARM,X \ replace default WARM
23535 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
23536 MOV X,PC \ then execute new WARM
23538 \ ------------------------------\
23541 ; downloading RC5toLCD.4th is done
23542 RST_HERE ; this app is protected against <reset>
23547 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
23549 [UNDEFINED] MARKER [IF]
23550 \ https://forth-standard.org/standard/core/MARKER
23552 \ ( "<spaces>name" -- )
23553 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
23554 \ with the execution semantics defined below.
23556 \ name Execution: ( -- )
23557 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
23558 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
23559 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
23560 \ not necessarily provided. No other contextual information such as numeric base is affected
23565 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
23566 SUB #2,Y \ 1 Y = LFA
23567 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
23568 ADD #4,&DP \ 3 add 2 cells
23572 MOV @RSP+,IP \ -- PFA
23573 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
23574 MOV @TOS,&INIDP \ set DP value for RST_STATE
23576 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
23583 \ https://forth-standard.org/standard/core/Fetch
23584 \ @ c-addr -- char fetch char from memory
23591 [UNDEFINED] CONSTANT [IF]
23592 \ https://forth-standard.org/standard/core/CONSTANT
23593 \ CONSTANT <name> n -- define a Forth CONSTANT
23597 MOV TOS,-2(W) \ PFA = n
23604 [UNDEFINED] STATE [IF]
23605 \ https://forth-standard.org/standard/core/STATE
23606 \ STATE -- a-addr holds compiler state
23607 STATEADR CONSTANT STATE
23611 \ https://forth-standard.org/standard/core/Equal
23612 \ = x1 x2 -- flag test x1=x2
23619 XOR #-1,TOS \ 1 flag Z = 1
23624 [UNDEFINED] IF [IF]
23625 \ https://forth-standard.org/standard/core/IF
23626 \ IF -- IFadr initialize conditional forward branch
23627 CODE IF \ immediate
23630 MOV &DP,TOS \ -- HERE
23631 ADD #4,&DP \ compile one word, reserve one word
23632 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
23633 ADD #2,TOS \ -- HERE+2=IFadr
23638 [UNDEFINED] THEN [IF]
23639 \ https://forth-standard.org/standard/core/THEN
23640 \ THEN IFadr -- resolve forward branch
23641 CODE THEN \ immediate
23642 MOV &DP,0(TOS) \ -- IFadr
23648 [UNDEFINED] ELSE [IF]
23649 \ https://forth-standard.org/standard/core/ELSE
23650 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
23651 CODE ELSE \ immediate
23652 ADD #4,&DP \ make room to compile two words
23653 MOV &DP,W \ W=HERE+4
23655 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
23657 MOV W,TOS \ -- ELSEadr
23662 [UNDEFINED] DEFER [IF]
23663 \ https://forth-standard.org/standard/core/DEFER
23664 \ DEFER "<spaces>name" --
23665 \ Skip leading space delimiters. Parse name delimited by a space.
23666 \ Create a definition for name with the execution semantics defined below.
23668 \ name Execution: --
23669 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
23670 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
23674 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
23675 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
23681 [UNDEFINED] DEFER! [IF]
23682 \ https://forth-standard.org/standard/core/DEFERStore
23683 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
23684 CODE DEFER! \ xt2 xt1 --
23685 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
23691 [UNDEFINED] IS [IF]
23692 \ https://forth-standard.org/standard/core/IS
23695 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
23696 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
23697 \ or in a definition : ... ['] U. IS DISPLAY ...
23698 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
23700 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
23703 IF POSTPONE ['] POSTPONE DEFER!
23709 [UNDEFINED] >BODY [IF]
23710 \ https://forth-standard.org/standard/core/toBODY
23711 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
23718 \ CODE 20uS \ n -- 8MHz version
23719 \ BEGIN \ 4 + 16 ~ loop
23720 \ MOV #39,rDOCON \ 39
23727 \ MOV #XDOCON,rDOCON \ 2
23732 CODE 20_US \ n -- n * 20 us
23733 BEGIN \ here we presume that LCD_TIM_IFG = 1...
23735 BIT #1,&LCD_TIM_CTL \ 3
23736 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
23737 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
23739 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
23744 CODE TOP_LCD \ LCD Sample
23745 \ \ if write : %xxxx_WWWW --
23746 \ \ if read : -- %0000_RRRR
23747 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
23748 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
23749 0= IF \ write LCD bits pattern
23750 AND.B #LCD_DB,TOS \
23751 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
23752 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23755 THEN \ read LCD bits pattern
23758 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
23759 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
23760 AND.B #LCD_DB,TOS \
23764 CODE LCD_WRC \ char -- Write Char
23765 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23767 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
23768 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
23769 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
23770 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
23771 COLON \ high level word starts here
23772 TOP_LCD 2 20_US \ write high nibble first
23776 CODE LCD_WRF \ func -- Write Fonction
23777 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23781 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
23782 : LCD_HOME $02 LCD_WRF 100 20_us ;
23784 \ [UNDEFINED] OR [IF]
23786 \ \ https://forth-standard.org/standard/core/OR
23787 \ \ C OR x1 x2 -- x3 logical OR
23795 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
23796 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
23797 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
23798 \ : LCD_FN_SET $20 OR LCD_WrF ;
23799 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
23800 \ : LCD_GOTO $80 OR LCD_WrF ;
23803 \ CODE LCD_RDS \ -- status Read Status
23804 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
23805 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
23806 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
23807 \ COLON \ starts a FORTH word
23808 \ TOP_LCD 2 20_us \ -- %0000_HHHH
23809 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
23810 \ HI2LO \ switch from FORTH to assembler
23811 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
23812 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
23813 \ MOV @RSP+,IP \ restore IP saved by COLON
23817 \ CODE LCD_RDC \ -- char Read Char
23818 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
23823 \ ******************************\
23824 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
23825 \ ******************************\
23826 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23827 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
23828 BIT.B #SW2,&SW2_IN \ test switch S2
23829 0= IF \ case of switch S2 pressed
23830 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
23832 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
23835 BIT.B #SW1,&SW1_IN \ test switch S1 input
23836 0= IF \ case of Switch S1 pressed
23837 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
23839 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
23843 BW1 \ from quit on truncated RC5 message, repeated RC5 command
23847 \ ******************************\
23848 ASM RC5_INT \ wake up on Px.RC5 change interrupt
23849 \ ******************************\
23850 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
23851 \ ******************************\
23852 \ \ in : SR(9)=old Toggle bit memory (ADD on)
23853 \ \ SMclock = 8|16|24 MHz
23854 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
23855 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
23856 \ \ SR(9)=new Toggle bit memory (ADD on)
23857 \ ******************************\
23858 \ RC5_FirstStartBitHalfCycle: \
23859 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
23860 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
23861 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
23862 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
23864 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
23865 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
23867 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
23868 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
23870 MOV #1778,X \ RC5_Period * 1us
23871 MOV #14,W \ count of loop
23873 \ ******************************\
23874 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
23875 \ ******************************\ |
23876 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
23877 \ RC5_Compute_3/4_Period: \ |
23878 RRUM #1,X \ X=1/2 cycle |
23881 ADD X,Y \ Y=3/4 cycle
23882 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
23884 \ ******************************\
23885 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
23886 \ ******************************\
23887 BIT.B #RC5,&IR_IN \ C_flag = IR bit
23888 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
23889 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
23890 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
23891 SUB #1,W \ decrement count loop
23892 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
23893 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
23894 0<> WHILE \ ----> out of loop ----+
23895 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
23897 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
23898 CMP Y,X \ 1 | cycle time out of bound ?
23899 U>= IF \ 2 ^ | yes:
23900 BIC #$30,&RC5_TIM_CTL \ | | stop timer
23901 GOTO BW1 \ | | quit on truncated RC5 message
23903 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
23905 REPEAT \ ----> loop back --+ | with X = new RC5_period value
23906 \ ******************************\ |
23907 \ RC5_SampleEndOf: \ <---------------------+
23908 \ ******************************\
23909 BIC #$30,&RC5_TIM_CTL \ stop timer
23910 \ ******************************\
23911 \ RC5_ComputeNewRC5word \
23912 \ ******************************\
23913 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
23914 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
23915 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
23916 \ ******************************\
23917 \ RC5_ComputeC6bit \
23918 \ ******************************\
23919 BIT #BIT14,T \ test /C6 bit in T
23920 0= IF BIS #BIT6,X \ set C6 bit in X
23921 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
23922 \ ******************************\
23923 \ RC5_CommandByteIsDone \ -- BASE RC5_code
23924 \ ******************************\
23925 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
23926 \ ******************************\
23927 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
23928 XOR @RSP,T \ (new XOR old) Toggle bits
23929 BIT #UF10,T \ repeated RC5_command ?
23930 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
23931 XOR #UF10,0(RSP) \ 5 toggle bit memory
23932 \ ******************************\
23933 \ Display IR_RC5 code \
23934 \ ******************************\
23935 SUB #8,PSP \ TOS -- x x x x TOS
23936 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
23937 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
23938 MOV #$10,&BASEADR \ set hexadecimal base
23939 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
23940 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
23941 LO2HI \ switch from assembler to FORTH
23942 LCD_CLEAR \ set LCD cursor at home
23943 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
23944 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
23945 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
23946 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
23947 HI2LO \ -- switch from FORTH to assembler
23948 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
23949 MOV @PSP+,TOS \ -- TOS
23953 \ ******************************\
23955 \ ******************************\
23957 \ ... \ insert here your background task
23960 CALL &RXON \ comment this line to disable TERMINAL_INPUT
23962 \ ******************************\
23963 \ here start all interrupts \
23964 \ ******************************\
23965 \ here return all interrupts \
23966 \ ******************************\
23969 \ ******************************\
23971 \ ------------------------------\
23972 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
23973 \ ------------------------------\
23974 \ ... \ init specific I/O sys as you want
23975 \ ... \ before executing default WARM
23976 MOV #WARM,X \ ['] WARM
23978 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
23980 \ ------------------------------\
23982 \ ------------------------------\
23983 CODE STOP \ stops multitasking, must to be used before downloading app
23984 \ ------------------------------\
23985 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
23986 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
23987 MOV X,-2(X) \ restore the default background: SLEEP
23989 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
23990 BIC.B #RC5,&IR_IE \ clear RC5_Int
23991 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
23992 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
23993 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
23994 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
23995 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
23996 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
23998 ." RC5toLCD is removed,"
23999 ." type START to restart"
24000 WARM \ performs reset to reset all interrupt vectors.
24002 \ ------------------------------\
24004 \ ------------------------------\
24005 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
24006 \ ------------------------------\
24007 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
24008 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24009 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24010 \ -- \ID input divider \ 10 = /4
24011 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
24012 \ - \TBCLR TimerB Clear
24015 \ -------------------------------\
24016 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24017 \ -- \CM Capture Mode
24022 \ --- \OUTMOD \ 011 = set/reset
24028 \ -------------------------------\
24030 \ -------------------------------\
24032 \ ------------------------------\
24033 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
24034 \ ------------------------------\
24035 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
24036 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
24037 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
24038 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
24040 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
24041 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24043 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
24044 \ ------------------------------\
24045 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24046 \ ------------------------------\
24047 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
24048 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24049 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24050 \ ------------------------------\
24051 BIS.B #LCDVo,&LCDVo_DIR \
24052 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
24053 \ ------------------------------\
24054 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24055 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24056 \ ------------------------------\
24057 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24058 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24059 \ ******************************\
24061 \ ******************************\
24062 BIS.B #RC5,&IR_IE \ enable RC5_Int
24063 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24064 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24065 \ ******************************\
24066 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24067 \ ******************************\
24068 \ %01 0001 0100 \ TAxCTL
24069 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
24070 \ -- \ ID divided by 1
24071 \ -- \ MC MODE = up to TAxCCRn
24072 \ - \ TACLR clear timer count
24075 \ ------------------------------\
24076 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
24077 \ ------------------------------\
24079 \ --- \ TAIDEX pre divisor
24080 \ ------------------------------\
24081 \ %0000 0000 0000 0101 \ TAxCCR0
24082 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24083 \ ------------------------------\
24084 \ %0000 0000 0001 0000 \ TAxCCTL0
24085 \ - \ CAP capture/compare mode = compare
24088 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
24089 \ ------------------------------\
24090 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24091 \ ------------------------------\
24092 \ define LPM mode for ACCEPT \
24093 \ ------------------------------\
24094 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24095 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24096 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24097 \ ------------------------------\
24099 \ ------------------------------\
24100 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
24101 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
24102 \ ------------------------------\
24103 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
24104 \ ------------------------------\
24105 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
24106 \ CMP #2,Y \ Power_ON event
24107 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
24109 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
24111 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
24113 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
24115 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
24116 \ ------------------------------\
24118 \ ------------------------------\
24120 \ ------------------------------\
24121 #1000 20_US \ 1- wait 20 ms
24122 %011 TOP_LCD \ 2- send DB5=DB4=1
24123 #205 20_US \ 3- wait 4,1 ms
24124 %011 TOP_LCD \ 4- send again DB5=DB4=1
24125 #5 20_US \ 5- wait 0,1 ms
24126 %011 TOP_LCD \ 6- send again again DB5=DB4=1
24127 #2 20_US \ wait 40 us = LCD cycle
24128 %010 TOP_LCD \ 7- send DB5=1 DB4=0
24129 #2 20_US \ wait 40 us = LCD cycle
24130 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24131 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24132 LCD_CLEAR \ 10- "LCD_Clear"
24133 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24134 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24135 LCD_CLEAR \ 10- "LCD_Clear"
24136 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24137 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24138 CR ." I love you" \ display message on LCD
24139 ['] CR >BODY IS CR \ CR executes its default value
24140 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
24141 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24142 PWR_STATE ABORT \ init DP and continues with ABORT
24144 \ ------------------------------\
24146 \ ------------------------------\
24147 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
24148 \ ------------------------------\
24149 MOV #SLEEP,X \ replace default background process SLEEP
24150 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
24151 MOV #WARM,X \ replace default WARM
24152 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
24153 MOV X,PC \ then execute new WARM
24155 \ ------------------------------\
24158 ; downloading RC5toLCD.4th is done
24159 RST_HERE ; this app is protected against <reset>
24164 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
24166 [UNDEFINED] MARKER [IF]
24167 \ https://forth-standard.org/standard/core/MARKER
24169 \ ( "<spaces>name" -- )
24170 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
24171 \ with the execution semantics defined below.
24173 \ name Execution: ( -- )
24174 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
24175 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
24176 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
24177 \ not necessarily provided. No other contextual information such as numeric base is affected
24182 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
24183 SUB #2,Y \ 1 Y = LFA
24184 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
24185 ADD #4,&DP \ 3 add 2 cells
24189 MOV @RSP+,IP \ -- PFA
24190 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
24191 MOV @TOS,&INIDP \ set DP value for RST_STATE
24193 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
24200 \ https://forth-standard.org/standard/core/Fetch
24201 \ @ c-addr -- char fetch char from memory
24208 [UNDEFINED] CONSTANT [IF]
24209 \ https://forth-standard.org/standard/core/CONSTANT
24210 \ CONSTANT <name> n -- define a Forth CONSTANT
24214 MOV TOS,-2(W) \ PFA = n
24221 [UNDEFINED] STATE [IF]
24222 \ https://forth-standard.org/standard/core/STATE
24223 \ STATE -- a-addr holds compiler state
24224 STATEADR CONSTANT STATE
24228 \ https://forth-standard.org/standard/core/Equal
24229 \ = x1 x2 -- flag test x1=x2
24236 XOR #-1,TOS \ 1 flag Z = 1
24241 [UNDEFINED] IF [IF]
24242 \ https://forth-standard.org/standard/core/IF
24243 \ IF -- IFadr initialize conditional forward branch
24244 CODE IF \ immediate
24247 MOV &DP,TOS \ -- HERE
24248 ADD #4,&DP \ compile one word, reserve one word
24249 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
24250 ADD #2,TOS \ -- HERE+2=IFadr
24255 [UNDEFINED] THEN [IF]
24256 \ https://forth-standard.org/standard/core/THEN
24257 \ THEN IFadr -- resolve forward branch
24258 CODE THEN \ immediate
24259 MOV &DP,0(TOS) \ -- IFadr
24265 [UNDEFINED] ELSE [IF]
24266 \ https://forth-standard.org/standard/core/ELSE
24267 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
24268 CODE ELSE \ immediate
24269 ADD #4,&DP \ make room to compile two words
24270 MOV &DP,W \ W=HERE+4
24272 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
24274 MOV W,TOS \ -- ELSEadr
24279 [UNDEFINED] DEFER [IF]
24280 \ https://forth-standard.org/standard/core/DEFER
24281 \ DEFER "<spaces>name" --
24282 \ Skip leading space delimiters. Parse name delimited by a space.
24283 \ Create a definition for name with the execution semantics defined below.
24285 \ name Execution: --
24286 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
24287 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
24291 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
24292 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
24298 [UNDEFINED] DEFER! [IF]
24299 \ https://forth-standard.org/standard/core/DEFERStore
24300 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
24301 CODE DEFER! \ xt2 xt1 --
24302 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
24308 [UNDEFINED] IS [IF]
24309 \ https://forth-standard.org/standard/core/IS
24312 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
24313 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
24314 \ or in a definition : ... ['] U. IS DISPLAY ...
24315 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
24317 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
24320 IF POSTPONE ['] POSTPONE DEFER!
24326 [UNDEFINED] >BODY [IF]
24327 \ https://forth-standard.org/standard/core/toBODY
24328 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
24335 \ CODE 20uS \ n -- 8MHz version
24336 \ BEGIN \ 4 + 16 ~ loop
24337 \ MOV #39,rDOCON \ 39
24344 \ MOV #XDOCON,rDOCON \ 2
24349 CODE 20_US \ n -- n * 20 us
24350 BEGIN \ here we presume that LCD_TIM_IFG = 1...
24352 BIT #1,&LCD_TIM_CTL \ 3
24353 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
24354 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
24356 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
24361 CODE TOP_LCD \ LCD Sample
24362 \ \ if write : %xxxx_WWWW --
24363 \ \ if read : -- %0000_RRRR
24364 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24365 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24366 0= IF \ write LCD bits pattern
24367 AND.B #LCD_DB,TOS \
24368 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24369 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24372 THEN \ read LCD bits pattern
24375 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24376 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24377 AND.B #LCD_DB,TOS \
24381 CODE LCD_WRC \ char -- Write Char
24382 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24384 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
24385 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
24386 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
24387 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
24388 COLON \ high level word starts here
24389 TOP_LCD 2 20_US \ write high nibble first
24393 CODE LCD_WRF \ func -- Write Fonction
24394 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24398 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
24399 : LCD_HOME $02 LCD_WRF 100 20_us ;
24401 \ [UNDEFINED] OR [IF]
24403 \ \ https://forth-standard.org/standard/core/OR
24404 \ \ C OR x1 x2 -- x3 logical OR
24412 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
24413 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
24414 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
24415 \ : LCD_FN_SET $20 OR LCD_WrF ;
24416 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
24417 \ : LCD_GOTO $80 OR LCD_WrF ;
24420 \ CODE LCD_RDS \ -- status Read Status
24421 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
24422 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
24423 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
24424 \ COLON \ starts a FORTH word
24425 \ TOP_LCD 2 20_us \ -- %0000_HHHH
24426 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
24427 \ HI2LO \ switch from FORTH to assembler
24428 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
24429 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
24430 \ MOV @RSP+,IP \ restore IP saved by COLON
24434 \ CODE LCD_RDC \ -- char Read Char
24435 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
24440 \ ******************************\
24441 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
24442 \ ******************************\
24443 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
24444 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
24445 BIT.B #SW2,&SW2_IN \ test switch S2
24446 0= IF \ case of switch S2 pressed
24447 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
24449 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
24452 BIT.B #SW1,&SW1_IN \ test switch S1 input
24453 0= IF \ case of Switch S1 pressed
24454 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
24456 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
24460 BW1 \ from quit on truncated RC5 message, repeated RC5 command
24464 \ ******************************\
24465 ASM RC5_INT \ wake up on Px.RC5 change interrupt
24466 \ ******************************\
24467 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
24468 \ ******************************\
24469 \ \ in : SR(9)=old Toggle bit memory (ADD on)
24470 \ \ SMclock = 8|16|24 MHz
24471 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
24472 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
24473 \ \ SR(9)=new Toggle bit memory (ADD on)
24474 \ ******************************\
24475 \ RC5_FirstStartBitHalfCycle: \
24476 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
24477 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
24478 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
24479 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
24481 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
24482 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
24484 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
24485 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
24487 MOV #1778,X \ RC5_Period * 1us
24488 MOV #14,W \ count of loop
24490 \ ******************************\
24491 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
24492 \ ******************************\ |
24493 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
24494 \ RC5_Compute_3/4_Period: \ |
24495 RRUM #1,X \ X=1/2 cycle |
24498 ADD X,Y \ Y=3/4 cycle
24499 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
24501 \ ******************************\
24502 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
24503 \ ******************************\
24504 BIT.B #RC5,&IR_IN \ C_flag = IR bit
24505 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
24506 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
24507 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
24508 SUB #1,W \ decrement count loop
24509 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
24510 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
24511 0<> WHILE \ ----> out of loop ----+
24512 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
24514 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
24515 CMP Y,X \ 1 | cycle time out of bound ?
24516 U>= IF \ 2 ^ | yes:
24517 BIC #$30,&RC5_TIM_CTL \ | | stop timer
24518 GOTO BW1 \ | | quit on truncated RC5 message
24520 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
24522 REPEAT \ ----> loop back --+ | with X = new RC5_period value
24523 \ ******************************\ |
24524 \ RC5_SampleEndOf: \ <---------------------+
24525 \ ******************************\
24526 BIC #$30,&RC5_TIM_CTL \ stop timer
24527 \ ******************************\
24528 \ RC5_ComputeNewRC5word \
24529 \ ******************************\
24530 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
24531 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
24532 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
24533 \ ******************************\
24534 \ RC5_ComputeC6bit \
24535 \ ******************************\
24536 BIT #BIT14,T \ test /C6 bit in T
24537 0= IF BIS #BIT6,X \ set C6 bit in X
24538 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
24539 \ ******************************\
24540 \ RC5_CommandByteIsDone \ -- BASE RC5_code
24541 \ ******************************\
24542 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
24543 \ ******************************\
24544 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
24545 XOR @RSP,T \ (new XOR old) Toggle bits
24546 BIT #UF10,T \ repeated RC5_command ?
24547 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
24548 XOR #UF10,0(RSP) \ 5 toggle bit memory
24549 \ ******************************\
24550 \ Display IR_RC5 code \
24551 \ ******************************\
24552 SUB #8,PSP \ TOS -- x x x x TOS
24553 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
24554 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
24555 MOV #$10,&BASEADR \ set hexadecimal base
24556 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
24557 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
24558 LO2HI \ switch from assembler to FORTH
24559 LCD_CLEAR \ set LCD cursor at home
24560 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
24561 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
24562 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
24563 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
24564 HI2LO \ -- switch from FORTH to assembler
24565 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
24566 MOV @PSP+,TOS \ -- TOS
24570 \ ******************************\
24572 \ ******************************\
24574 \ ... \ insert here your background task
24577 CALL &RXON \ comment this line to disable TERMINAL_INPUT
24579 \ ******************************\
24580 \ here start all interrupts \
24581 \ ******************************\
24582 \ here return all interrupts \
24583 \ ******************************\
24586 \ ******************************\
24588 \ ------------------------------\
24589 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
24590 \ ------------------------------\
24591 \ ... \ init specific I/O sys as you want
24592 \ ... \ before executing default WARM
24593 MOV #WARM,X \ ['] WARM
24595 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
24597 \ ------------------------------\
24599 \ ------------------------------\
24600 CODE STOP \ stops multitasking, must to be used before downloading app
24601 \ ------------------------------\
24602 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
24603 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
24604 MOV X,-2(X) \ restore the default background: SLEEP
24606 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
24607 BIC.B #RC5,&IR_IE \ clear RC5_Int
24608 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
24609 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
24610 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
24611 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
24612 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
24613 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
24615 ." RC5toLCD is removed,"
24616 ." type START to restart"
24617 WARM \ performs reset to reset all interrupt vectors.
24619 \ ------------------------------\
24621 \ ------------------------------\
24622 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
24623 \ ------------------------------\
24624 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
24625 \ - - \CNTL Counter lentgh \ 00 = 16 bits
24626 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
24627 \ -- \ID input divider \ 10 = /4
24628 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
24629 \ - \TBCLR TimerB Clear
24632 \ -------------------------------\
24633 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
24634 \ -- \CM Capture Mode
24639 \ --- \OUTMOD \ 011 = set/reset
24645 \ -------------------------------\
24647 \ -------------------------------\
24649 \ ------------------------------\
24650 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
24651 \ ------------------------------\
24652 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
24653 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
24654 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
24655 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
24657 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
24658 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
24660 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
24661 \ ------------------------------\
24662 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
24663 \ ------------------------------\
24664 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
24665 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
24666 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
24667 \ ------------------------------\
24668 BIS.B #LCDVo,&LCDVo_DIR \
24669 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
24670 \ ------------------------------\
24671 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
24672 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
24673 \ ------------------------------\
24674 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
24675 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
24676 \ ******************************\
24678 \ ******************************\
24679 BIS.B #RC5,&IR_IE \ enable RC5_Int
24680 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
24681 MOV #RC5_INT,&IR_Vec \ init interrupt vector
24682 \ ******************************\
24683 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
24684 \ ******************************\
24685 \ %01 0001 0100 \ TAxCTL
24686 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
24687 \ -- \ ID divided by 1
24688 \ -- \ MC MODE = up to TAxCCRn
24689 \ - \ TACLR clear timer count
24692 \ ------------------------------\
24693 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
24694 \ ------------------------------\
24696 \ --- \ TAIDEX pre divisor
24697 \ ------------------------------\
24698 \ %0000 0000 0000 0101 \ TAxCCR0
24699 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
24700 \ ------------------------------\
24701 \ %0000 0000 0001 0000 \ TAxCCTL0
24702 \ - \ CAP capture/compare mode = compare
24705 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
24706 \ ------------------------------\
24707 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
24708 \ ------------------------------\
24709 \ define LPM mode for ACCEPT \
24710 \ ------------------------------\
24711 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
24712 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
24713 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
24714 \ ------------------------------\
24716 \ ------------------------------\
24717 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
24718 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
24719 \ ------------------------------\
24720 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
24721 \ ------------------------------\
24722 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
24723 \ CMP #2,Y \ Power_ON event
24724 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
24726 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
24728 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
24730 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
24732 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
24733 \ ------------------------------\
24735 \ ------------------------------\
24737 \ ------------------------------\
24738 #1000 20_US \ 1- wait 20 ms
24739 %011 TOP_LCD \ 2- send DB5=DB4=1
24740 #205 20_US \ 3- wait 4,1 ms
24741 %011 TOP_LCD \ 4- send again DB5=DB4=1
24742 #5 20_US \ 5- wait 0,1 ms
24743 %011 TOP_LCD \ 6- send again again DB5=DB4=1
24744 #2 20_US \ wait 40 us = LCD cycle
24745 %010 TOP_LCD \ 7- send DB5=1 DB4=0
24746 #2 20_US \ wait 40 us = LCD cycle
24747 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
24748 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
24749 LCD_CLEAR \ 10- "LCD_Clear"
24750 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
24751 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
24752 LCD_CLEAR \ 10- "LCD_Clear"
24753 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
24754 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
24755 CR ." I love you" \ display message on LCD
24756 ['] CR >BODY IS CR \ CR executes its default value
24757 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
24758 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
24759 PWR_STATE ABORT \ init DP and continues with ABORT
24761 \ ------------------------------\
24763 \ ------------------------------\
24764 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
24765 \ ------------------------------\
24766 MOV #SLEEP,X \ replace default background process SLEEP
24767 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
24768 MOV #WARM,X \ replace default WARM
24769 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
24770 MOV X,PC \ then execute new WARM
24772 \ ------------------------------\
24775 ; downloading RC5toLCD.4th is done
24776 RST_HERE ; this app is protected against <reset>
24781 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
24783 [UNDEFINED] MARKER [IF]
24784 \ https://forth-standard.org/standard/core/MARKER
24786 \ ( "<spaces>name" -- )
24787 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
24788 \ with the execution semantics defined below.
24790 \ name Execution: ( -- )
24791 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
24792 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
24793 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
24794 \ not necessarily provided. No other contextual information such as numeric base is affected
24799 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
24800 SUB #2,Y \ 1 Y = LFA
24801 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
24802 ADD #4,&DP \ 3 add 2 cells
24806 MOV @RSP+,IP \ -- PFA
24807 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
24808 MOV @TOS,&INIDP \ set DP value for RST_STATE
24810 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
24817 \ https://forth-standard.org/standard/core/Fetch
24818 \ @ c-addr -- char fetch char from memory
24825 [UNDEFINED] CONSTANT [IF]
24826 \ https://forth-standard.org/standard/core/CONSTANT
24827 \ CONSTANT <name> n -- define a Forth CONSTANT
24831 MOV TOS,-2(W) \ PFA = n
24838 [UNDEFINED] STATE [IF]
24839 \ https://forth-standard.org/standard/core/STATE
24840 \ STATE -- a-addr holds compiler state
24841 STATEADR CONSTANT STATE
24845 \ https://forth-standard.org/standard/core/Equal
24846 \ = x1 x2 -- flag test x1=x2
24853 XOR #-1,TOS \ 1 flag Z = 1
24858 [UNDEFINED] IF [IF]
24859 \ https://forth-standard.org/standard/core/IF
24860 \ IF -- IFadr initialize conditional forward branch
24861 CODE IF \ immediate
24864 MOV &DP,TOS \ -- HERE
24865 ADD #4,&DP \ compile one word, reserve one word
24866 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
24867 ADD #2,TOS \ -- HERE+2=IFadr
24872 [UNDEFINED] THEN [IF]
24873 \ https://forth-standard.org/standard/core/THEN
24874 \ THEN IFadr -- resolve forward branch
24875 CODE THEN \ immediate
24876 MOV &DP,0(TOS) \ -- IFadr
24882 [UNDEFINED] ELSE [IF]
24883 \ https://forth-standard.org/standard/core/ELSE
24884 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
24885 CODE ELSE \ immediate
24886 ADD #4,&DP \ make room to compile two words
24887 MOV &DP,W \ W=HERE+4
24889 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
24891 MOV W,TOS \ -- ELSEadr
24896 [UNDEFINED] DEFER [IF]
24897 \ https://forth-standard.org/standard/core/DEFER
24898 \ DEFER "<spaces>name" --
24899 \ Skip leading space delimiters. Parse name delimited by a space.
24900 \ Create a definition for name with the execution semantics defined below.
24902 \ name Execution: --
24903 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
24904 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
24908 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
24909 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
24915 [UNDEFINED] DEFER! [IF]
24916 \ https://forth-standard.org/standard/core/DEFERStore
24917 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
24918 CODE DEFER! \ xt2 xt1 --
24919 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
24925 [UNDEFINED] IS [IF]
24926 \ https://forth-standard.org/standard/core/IS
24929 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
24930 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
24931 \ or in a definition : ... ['] U. IS DISPLAY ...
24932 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
24934 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
24937 IF POSTPONE ['] POSTPONE DEFER!
24943 [UNDEFINED] >BODY [IF]
24944 \ https://forth-standard.org/standard/core/toBODY
24945 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
24952 \ CODE 20uS \ n -- 8MHz version
24953 \ BEGIN \ 4 + 16 ~ loop
24954 \ MOV #39,rDOCON \ 39
24961 \ MOV #XDOCON,rDOCON \ 2
24966 CODE 20_US \ n -- n * 20 us
24967 BEGIN \ here we presume that LCD_TIM_IFG = 1...
24969 BIT #1,&LCD_TIM_CTL \ 3
24970 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
24971 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
24973 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
24978 CODE TOP_LCD \ LCD Sample
24979 \ \ if write : %xxxx_WWWW --
24980 \ \ if read : -- %0000_RRRR
24981 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
24982 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
24983 0= IF \ write LCD bits pattern
24984 AND.B #LCD_DB,TOS \
24985 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
24986 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24989 THEN \ read LCD bits pattern
24992 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
24993 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
24994 AND.B #LCD_DB,TOS \
24998 CODE LCD_WRC \ char -- Write Char
24999 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25001 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
25002 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
25003 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25004 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25005 COLON \ high level word starts here
25006 TOP_LCD 2 20_US \ write high nibble first
25010 CODE LCD_WRF \ func -- Write Fonction
25011 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25015 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
25016 : LCD_HOME $02 LCD_WRF 100 20_us ;
25018 \ [UNDEFINED] OR [IF]
25020 \ \ https://forth-standard.org/standard/core/OR
25021 \ \ C OR x1 x2 -- x3 logical OR
25029 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
25030 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
25031 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
25032 \ : LCD_FN_SET $20 OR LCD_WrF ;
25033 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
25034 \ : LCD_GOTO $80 OR LCD_WrF ;
25037 \ CODE LCD_RDS \ -- status Read Status
25038 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25039 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25040 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25041 \ COLON \ starts a FORTH word
25042 \ TOP_LCD 2 20_us \ -- %0000_HHHH
25043 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
25044 \ HI2LO \ switch from FORTH to assembler
25045 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
25046 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
25047 \ MOV @RSP+,IP \ restore IP saved by COLON
25051 \ CODE LCD_RDC \ -- char Read Char
25052 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25057 \ ******************************\
25058 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25059 \ ******************************\
25060 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25061 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
25062 BIT.B #SW2,&SW2_IN \ test switch S2
25063 0= IF \ case of switch S2 pressed
25064 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
25066 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
25069 BIT.B #SW1,&SW1_IN \ test switch S1 input
25070 0= IF \ case of Switch S1 pressed
25071 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
25073 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
25077 BW1 \ from quit on truncated RC5 message, repeated RC5 command
25081 \ ******************************\
25082 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25083 \ ******************************\
25084 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25085 \ ******************************\
25086 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25087 \ \ SMclock = 8|16|24 MHz
25088 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
25089 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
25090 \ \ SR(9)=new Toggle bit memory (ADD on)
25091 \ ******************************\
25092 \ RC5_FirstStartBitHalfCycle: \
25093 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
25094 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25095 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
25096 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
25098 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
25099 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
25101 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
25102 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
25104 MOV #1778,X \ RC5_Period * 1us
25105 MOV #14,W \ count of loop
25107 \ ******************************\
25108 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
25109 \ ******************************\ |
25110 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
25111 \ RC5_Compute_3/4_Period: \ |
25112 RRUM #1,X \ X=1/2 cycle |
25115 ADD X,Y \ Y=3/4 cycle
25116 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
25118 \ ******************************\
25119 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
25120 \ ******************************\
25121 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25122 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
25123 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25124 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25125 SUB #1,W \ decrement count loop
25126 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
25127 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25128 0<> WHILE \ ----> out of loop ----+
25129 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25131 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
25132 CMP Y,X \ 1 | cycle time out of bound ?
25133 U>= IF \ 2 ^ | yes:
25134 BIC #$30,&RC5_TIM_CTL \ | | stop timer
25135 GOTO BW1 \ | | quit on truncated RC5 message
25137 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
25139 REPEAT \ ----> loop back --+ | with X = new RC5_period value
25140 \ ******************************\ |
25141 \ RC5_SampleEndOf: \ <---------------------+
25142 \ ******************************\
25143 BIC #$30,&RC5_TIM_CTL \ stop timer
25144 \ ******************************\
25145 \ RC5_ComputeNewRC5word \
25146 \ ******************************\
25147 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
25148 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
25149 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
25150 \ ******************************\
25151 \ RC5_ComputeC6bit \
25152 \ ******************************\
25153 BIT #BIT14,T \ test /C6 bit in T
25154 0= IF BIS #BIT6,X \ set C6 bit in X
25155 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
25156 \ ******************************\
25157 \ RC5_CommandByteIsDone \ -- BASE RC5_code
25158 \ ******************************\
25159 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25160 \ ******************************\
25161 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
25162 XOR @RSP,T \ (new XOR old) Toggle bits
25163 BIT #UF10,T \ repeated RC5_command ?
25164 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
25165 XOR #UF10,0(RSP) \ 5 toggle bit memory
25166 \ ******************************\
25167 \ Display IR_RC5 code \
25168 \ ******************************\
25169 SUB #8,PSP \ TOS -- x x x x TOS
25170 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
25171 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
25172 MOV #$10,&BASEADR \ set hexadecimal base
25173 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
25174 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
25175 LO2HI \ switch from assembler to FORTH
25176 LCD_CLEAR \ set LCD cursor at home
25177 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
25178 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
25179 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
25180 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
25181 HI2LO \ -- switch from FORTH to assembler
25182 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
25183 MOV @PSP+,TOS \ -- TOS
25187 \ ******************************\
25189 \ ******************************\
25191 \ ... \ insert here your background task
25194 CALL &RXON \ comment this line to disable TERMINAL_INPUT
25196 \ ******************************\
25197 \ here start all interrupts \
25198 \ ******************************\
25199 \ here return all interrupts \
25200 \ ******************************\
25203 \ ******************************\
25205 \ ------------------------------\
25206 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
25207 \ ------------------------------\
25208 \ ... \ init specific I/O sys as you want
25209 \ ... \ before executing default WARM
25210 MOV #WARM,X \ ['] WARM
25212 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
25214 \ ------------------------------\
25216 \ ------------------------------\
25217 CODE STOP \ stops multitasking, must to be used before downloading app
25218 \ ------------------------------\
25219 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
25220 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
25221 MOV X,-2(X) \ restore the default background: SLEEP
25223 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
25224 BIC.B #RC5,&IR_IE \ clear RC5_Int
25225 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
25226 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
25227 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
25228 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
25229 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
25230 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
25232 ." RC5toLCD is removed,"
25233 ." type START to restart"
25234 WARM \ performs reset to reset all interrupt vectors.
25236 \ ------------------------------\
25238 \ ------------------------------\
25239 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
25240 \ ------------------------------\
25241 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
25242 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25243 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25244 \ -- \ID input divider \ 10 = /4
25245 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
25246 \ - \TBCLR TimerB Clear
25249 \ -------------------------------\
25250 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25251 \ -- \CM Capture Mode
25256 \ --- \OUTMOD \ 011 = set/reset
25262 \ -------------------------------\
25264 \ -------------------------------\
25266 \ ------------------------------\
25267 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
25268 \ ------------------------------\
25269 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
25270 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
25271 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
25272 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
25274 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
25275 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
25277 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
25278 \ ------------------------------\
25279 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
25280 \ ------------------------------\
25281 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
25282 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
25283 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25284 \ ------------------------------\
25285 BIS.B #LCDVo,&LCDVo_DIR \
25286 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
25287 \ ------------------------------\
25288 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25289 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25290 \ ------------------------------\
25291 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25292 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25293 \ ******************************\
25295 \ ******************************\
25296 BIS.B #RC5,&IR_IE \ enable RC5_Int
25297 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25298 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25299 \ ******************************\
25300 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
25301 \ ******************************\
25302 \ %01 0001 0100 \ TAxCTL
25303 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
25304 \ -- \ ID divided by 1
25305 \ -- \ MC MODE = up to TAxCCRn
25306 \ - \ TACLR clear timer count
25309 \ ------------------------------\
25310 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
25311 \ ------------------------------\
25313 \ --- \ TAIDEX pre divisor
25314 \ ------------------------------\
25315 \ %0000 0000 0000 0101 \ TAxCCR0
25316 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
25317 \ ------------------------------\
25318 \ %0000 0000 0001 0000 \ TAxCCTL0
25319 \ - \ CAP capture/compare mode = compare
25322 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
25323 \ ------------------------------\
25324 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
25325 \ ------------------------------\
25326 \ define LPM mode for ACCEPT \
25327 \ ------------------------------\
25328 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25329 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25330 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25331 \ ------------------------------\
25333 \ ------------------------------\
25334 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
25335 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
25336 \ ------------------------------\
25337 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
25338 \ ------------------------------\
25339 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
25340 \ CMP #2,Y \ Power_ON event
25341 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
25343 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
25345 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
25347 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
25349 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
25350 \ ------------------------------\
25352 \ ------------------------------\
25354 \ ------------------------------\
25355 #1000 20_US \ 1- wait 20 ms
25356 %011 TOP_LCD \ 2- send DB5=DB4=1
25357 #205 20_US \ 3- wait 4,1 ms
25358 %011 TOP_LCD \ 4- send again DB5=DB4=1
25359 #5 20_US \ 5- wait 0,1 ms
25360 %011 TOP_LCD \ 6- send again again DB5=DB4=1
25361 #2 20_US \ wait 40 us = LCD cycle
25362 %010 TOP_LCD \ 7- send DB5=1 DB4=0
25363 #2 20_US \ wait 40 us = LCD cycle
25364 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25365 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25366 LCD_CLEAR \ 10- "LCD_Clear"
25367 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25368 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25369 LCD_CLEAR \ 10- "LCD_Clear"
25370 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25371 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25372 CR ." I love you" \ display message on LCD
25373 ['] CR >BODY IS CR \ CR executes its default value
25374 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
25375 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
25376 PWR_STATE ABORT \ init DP and continues with ABORT
25378 \ ------------------------------\
25380 \ ------------------------------\
25381 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
25382 \ ------------------------------\
25383 MOV #SLEEP,X \ replace default background process SLEEP
25384 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
25385 MOV #WARM,X \ replace default WARM
25386 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
25387 MOV X,PC \ then execute new WARM
25389 \ ------------------------------\
25392 ; downloading RC5toLCD.4th is done
25393 RST_HERE ; this app is protected against <reset>
25398 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
25400 [UNDEFINED] MARKER [IF]
25401 \ https://forth-standard.org/standard/core/MARKER
25403 \ ( "<spaces>name" -- )
25404 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
25405 \ with the execution semantics defined below.
25407 \ name Execution: ( -- )
25408 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
25409 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
25410 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
25411 \ not necessarily provided. No other contextual information such as numeric base is affected
25416 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
25417 SUB #2,Y \ 1 Y = LFA
25418 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
25419 ADD #4,&DP \ 3 add 2 cells
25423 MOV @RSP+,IP \ -- PFA
25424 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
25425 MOV @TOS,&INIDP \ set DP value for RST_STATE
25427 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
25434 \ https://forth-standard.org/standard/core/Fetch
25435 \ @ c-addr -- char fetch char from memory
25442 [UNDEFINED] CONSTANT [IF]
25443 \ https://forth-standard.org/standard/core/CONSTANT
25444 \ CONSTANT <name> n -- define a Forth CONSTANT
25448 MOV TOS,-2(W) \ PFA = n
25455 [UNDEFINED] STATE [IF]
25456 \ https://forth-standard.org/standard/core/STATE
25457 \ STATE -- a-addr holds compiler state
25458 STATEADR CONSTANT STATE
25462 \ https://forth-standard.org/standard/core/Equal
25463 \ = x1 x2 -- flag test x1=x2
25470 XOR #-1,TOS \ 1 flag Z = 1
25475 [UNDEFINED] IF [IF]
25476 \ https://forth-standard.org/standard/core/IF
25477 \ IF -- IFadr initialize conditional forward branch
25478 CODE IF \ immediate
25481 MOV &DP,TOS \ -- HERE
25482 ADD #4,&DP \ compile one word, reserve one word
25483 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
25484 ADD #2,TOS \ -- HERE+2=IFadr
25489 [UNDEFINED] THEN [IF]
25490 \ https://forth-standard.org/standard/core/THEN
25491 \ THEN IFadr -- resolve forward branch
25492 CODE THEN \ immediate
25493 MOV &DP,0(TOS) \ -- IFadr
25499 [UNDEFINED] ELSE [IF]
25500 \ https://forth-standard.org/standard/core/ELSE
25501 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
25502 CODE ELSE \ immediate
25503 ADD #4,&DP \ make room to compile two words
25504 MOV &DP,W \ W=HERE+4
25506 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
25508 MOV W,TOS \ -- ELSEadr
25513 [UNDEFINED] DEFER [IF]
25514 \ https://forth-standard.org/standard/core/DEFER
25515 \ DEFER "<spaces>name" --
25516 \ Skip leading space delimiters. Parse name delimited by a space.
25517 \ Create a definition for name with the execution semantics defined below.
25519 \ name Execution: --
25520 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
25521 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
25525 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
25526 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
25532 [UNDEFINED] DEFER! [IF]
25533 \ https://forth-standard.org/standard/core/DEFERStore
25534 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
25535 CODE DEFER! \ xt2 xt1 --
25536 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
25542 [UNDEFINED] IS [IF]
25543 \ https://forth-standard.org/standard/core/IS
25546 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
25547 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
25548 \ or in a definition : ... ['] U. IS DISPLAY ...
25549 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
25551 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
25554 IF POSTPONE ['] POSTPONE DEFER!
25560 [UNDEFINED] >BODY [IF]
25561 \ https://forth-standard.org/standard/core/toBODY
25562 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
25569 \ CODE 20uS \ n -- 8MHz version
25570 \ BEGIN \ 4 + 16 ~ loop
25571 \ MOV #39,rDOCON \ 39
25578 \ MOV #XDOCON,rDOCON \ 2
25583 CODE 20_US \ n -- n * 20 us
25584 BEGIN \ here we presume that LCD_TIM_IFG = 1...
25586 BIT #1,&LCD_TIM_CTL \ 3
25587 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
25588 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
25590 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
25595 CODE TOP_LCD \ LCD Sample
25596 \ \ if write : %xxxx_WWWW --
25597 \ \ if read : -- %0000_RRRR
25598 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
25599 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
25600 0= IF \ write LCD bits pattern
25601 AND.B #LCD_DB,TOS \
25602 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
25603 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25606 THEN \ read LCD bits pattern
25609 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
25610 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
25611 AND.B #LCD_DB,TOS \
25615 CODE LCD_WRC \ char -- Write Char
25616 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25618 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
25619 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
25620 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
25621 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
25622 COLON \ high level word starts here
25623 TOP_LCD 2 20_US \ write high nibble first
25627 CODE LCD_WRF \ func -- Write Fonction
25628 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25632 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
25633 : LCD_HOME $02 LCD_WRF 100 20_us ;
25635 \ [UNDEFINED] OR [IF]
25637 \ \ https://forth-standard.org/standard/core/OR
25638 \ \ C OR x1 x2 -- x3 logical OR
25646 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
25647 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
25648 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
25649 \ : LCD_FN_SET $20 OR LCD_WrF ;
25650 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
25651 \ : LCD_GOTO $80 OR LCD_WrF ;
25654 \ CODE LCD_RDS \ -- status Read Status
25655 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
25656 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
25657 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
25658 \ COLON \ starts a FORTH word
25659 \ TOP_LCD 2 20_us \ -- %0000_HHHH
25660 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
25661 \ HI2LO \ switch from FORTH to assembler
25662 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
25663 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
25664 \ MOV @RSP+,IP \ restore IP saved by COLON
25668 \ CODE LCD_RDC \ -- char Read Char
25669 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
25674 \ ******************************\
25675 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
25676 \ ******************************\
25677 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25678 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
25679 BIT.B #SW2,&SW2_IN \ test switch S2
25680 0= IF \ case of switch S2 pressed
25681 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
25683 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
25686 BIT.B #SW1,&SW1_IN \ test switch S1 input
25687 0= IF \ case of Switch S1 pressed
25688 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
25690 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
25694 BW1 \ from quit on truncated RC5 message, repeated RC5 command
25698 \ ******************************\
25699 ASM RC5_INT \ wake up on Px.RC5 change interrupt
25700 \ ******************************\
25701 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
25702 \ ******************************\
25703 \ \ in : SR(9)=old Toggle bit memory (ADD on)
25704 \ \ SMclock = 8|16|24 MHz
25705 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
25706 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
25707 \ \ SR(9)=new Toggle bit memory (ADD on)
25708 \ ******************************\
25709 \ RC5_FirstStartBitHalfCycle: \
25710 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
25711 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
25712 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
25713 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
25715 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
25716 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
25718 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
25719 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
25721 MOV #1778,X \ RC5_Period * 1us
25722 MOV #14,W \ count of loop
25724 \ ******************************\
25725 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
25726 \ ******************************\ |
25727 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
25728 \ RC5_Compute_3/4_Period: \ |
25729 RRUM #1,X \ X=1/2 cycle |
25732 ADD X,Y \ Y=3/4 cycle
25733 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
25735 \ ******************************\
25736 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
25737 \ ******************************\
25738 BIT.B #RC5,&IR_IN \ C_flag = IR bit
25739 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
25740 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
25741 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
25742 SUB #1,W \ decrement count loop
25743 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
25744 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
25745 0<> WHILE \ ----> out of loop ----+
25746 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
25748 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
25749 CMP Y,X \ 1 | cycle time out of bound ?
25750 U>= IF \ 2 ^ | yes:
25751 BIC #$30,&RC5_TIM_CTL \ | | stop timer
25752 GOTO BW1 \ | | quit on truncated RC5 message
25754 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
25756 REPEAT \ ----> loop back --+ | with X = new RC5_period value
25757 \ ******************************\ |
25758 \ RC5_SampleEndOf: \ <---------------------+
25759 \ ******************************\
25760 BIC #$30,&RC5_TIM_CTL \ stop timer
25761 \ ******************************\
25762 \ RC5_ComputeNewRC5word \
25763 \ ******************************\
25764 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
25765 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
25766 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
25767 \ ******************************\
25768 \ RC5_ComputeC6bit \
25769 \ ******************************\
25770 BIT #BIT14,T \ test /C6 bit in T
25771 0= IF BIS #BIT6,X \ set C6 bit in X
25772 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
25773 \ ******************************\
25774 \ RC5_CommandByteIsDone \ -- BASE RC5_code
25775 \ ******************************\
25776 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
25777 \ ******************************\
25778 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
25779 XOR @RSP,T \ (new XOR old) Toggle bits
25780 BIT #UF10,T \ repeated RC5_command ?
25781 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
25782 XOR #UF10,0(RSP) \ 5 toggle bit memory
25783 \ ******************************\
25784 \ Display IR_RC5 code \
25785 \ ******************************\
25786 SUB #8,PSP \ TOS -- x x x x TOS
25787 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
25788 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
25789 MOV #$10,&BASEADR \ set hexadecimal base
25790 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
25791 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
25792 LO2HI \ switch from assembler to FORTH
25793 LCD_CLEAR \ set LCD cursor at home
25794 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
25795 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
25796 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
25797 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
25798 HI2LO \ -- switch from FORTH to assembler
25799 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
25800 MOV @PSP+,TOS \ -- TOS
25804 \ ******************************\
25806 \ ******************************\
25808 \ ... \ insert here your background task
25811 CALL &RXON \ comment this line to disable TERMINAL_INPUT
25813 \ ******************************\
25814 \ here start all interrupts \
25815 \ ******************************\
25816 \ here return all interrupts \
25817 \ ******************************\
25820 \ ******************************\
25822 \ ------------------------------\
25823 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
25824 \ ------------------------------\
25825 \ ... \ init specific I/O sys as you want
25826 \ ... \ before executing default WARM
25827 MOV #WARM,X \ ['] WARM
25829 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
25831 \ ------------------------------\
25833 \ ------------------------------\
25834 CODE STOP \ stops multitasking, must to be used before downloading app
25835 \ ------------------------------\
25836 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
25837 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
25838 MOV X,-2(X) \ restore the default background: SLEEP
25840 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
25841 BIC.B #RC5,&IR_IE \ clear RC5_Int
25842 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
25843 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
25844 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
25845 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
25846 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
25847 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
25849 ." RC5toLCD is removed,"
25850 ." type START to restart"
25851 WARM \ performs reset to reset all interrupt vectors.
25853 \ ------------------------------\
25855 \ ------------------------------\
25856 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
25857 \ ------------------------------\
25858 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
25859 \ - - \CNTL Counter lentgh \ 00 = 16 bits
25860 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
25861 \ -- \ID input divider \ 10 = /4
25862 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
25863 \ - \TBCLR TimerB Clear
25866 \ -------------------------------\
25867 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
25868 \ -- \CM Capture Mode
25873 \ --- \OUTMOD \ 011 = set/reset
25879 \ -------------------------------\
25881 \ -------------------------------\
25883 \ ------------------------------\
25884 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
25885 \ ------------------------------\
25886 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
25887 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
25888 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
25889 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
25891 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
25892 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
25894 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
25895 \ ------------------------------\
25896 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
25897 \ ------------------------------\
25898 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
25899 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
25900 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
25901 \ ------------------------------\
25902 BIS.B #LCDVo,&LCDVo_DIR \
25903 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
25904 \ ------------------------------\
25905 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
25906 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
25907 \ ------------------------------\
25908 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
25909 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
25910 \ ******************************\
25912 \ ******************************\
25913 BIS.B #RC5,&IR_IE \ enable RC5_Int
25914 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
25915 MOV #RC5_INT,&IR_Vec \ init interrupt vector
25916 \ ******************************\
25917 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
25918 \ ******************************\
25919 \ %01 0001 0100 \ TAxCTL
25920 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
25921 \ -- \ ID divided by 1
25922 \ -- \ MC MODE = up to TAxCCRn
25923 \ - \ TACLR clear timer count
25926 \ ------------------------------\
25927 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
25928 \ ------------------------------\
25930 \ --- \ TAIDEX pre divisor
25931 \ ------------------------------\
25932 \ %0000 0000 0000 0101 \ TAxCCR0
25933 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
25934 \ ------------------------------\
25935 \ %0000 0000 0001 0000 \ TAxCCTL0
25936 \ - \ CAP capture/compare mode = compare
25939 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
25940 \ ------------------------------\
25941 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
25942 \ ------------------------------\
25943 \ define LPM mode for ACCEPT \
25944 \ ------------------------------\
25945 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
25946 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
25947 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
25948 \ ------------------------------\
25950 \ ------------------------------\
25951 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
25952 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
25953 \ ------------------------------\
25954 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
25955 \ ------------------------------\
25956 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
25957 \ CMP #2,Y \ Power_ON event
25958 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
25960 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
25962 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
25964 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
25966 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
25967 \ ------------------------------\
25969 \ ------------------------------\
25971 \ ------------------------------\
25972 #1000 20_US \ 1- wait 20 ms
25973 %011 TOP_LCD \ 2- send DB5=DB4=1
25974 #205 20_US \ 3- wait 4,1 ms
25975 %011 TOP_LCD \ 4- send again DB5=DB4=1
25976 #5 20_US \ 5- wait 0,1 ms
25977 %011 TOP_LCD \ 6- send again again DB5=DB4=1
25978 #2 20_US \ wait 40 us = LCD cycle
25979 %010 TOP_LCD \ 7- send DB5=1 DB4=0
25980 #2 20_US \ wait 40 us = LCD cycle
25981 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
25982 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
25983 LCD_CLEAR \ 10- "LCD_Clear"
25984 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
25985 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
25986 LCD_CLEAR \ 10- "LCD_Clear"
25987 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
25988 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
25989 CR ." I love you" \ display message on LCD
25990 ['] CR >BODY IS CR \ CR executes its default value
25991 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
25992 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
25993 PWR_STATE ABORT \ init DP and continues with ABORT
25995 \ ------------------------------\
25997 \ ------------------------------\
25998 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
25999 \ ------------------------------\
26000 MOV #SLEEP,X \ replace default background process SLEEP
26001 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
26002 MOV #WARM,X \ replace default WARM
26003 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
26004 MOV X,PC \ then execute new WARM
26006 \ ------------------------------\
26009 ; downloading RC5toLCD.4th is done
26010 RST_HERE ; this app is protected against <reset>
26015 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
26017 [UNDEFINED] MARKER [IF]
26018 \ https://forth-standard.org/standard/core/MARKER
26020 \ ( "<spaces>name" -- )
26021 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
26022 \ with the execution semantics defined below.
26024 \ name Execution: ( -- )
26025 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
26026 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
26027 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
26028 \ not necessarily provided. No other contextual information such as numeric base is affected
26033 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
26034 SUB #2,Y \ 1 Y = LFA
26035 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
26036 ADD #4,&DP \ 3 add 2 cells
26040 MOV @RSP+,IP \ -- PFA
26041 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
26042 MOV @TOS,&INIDP \ set DP value for RST_STATE
26044 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
26051 \ https://forth-standard.org/standard/core/Fetch
26052 \ @ c-addr -- char fetch char from memory
26059 [UNDEFINED] CONSTANT [IF]
26060 \ https://forth-standard.org/standard/core/CONSTANT
26061 \ CONSTANT <name> n -- define a Forth CONSTANT
26065 MOV TOS,-2(W) \ PFA = n
26072 [UNDEFINED] STATE [IF]
26073 \ https://forth-standard.org/standard/core/STATE
26074 \ STATE -- a-addr holds compiler state
26075 STATEADR CONSTANT STATE
26079 \ https://forth-standard.org/standard/core/Equal
26080 \ = x1 x2 -- flag test x1=x2
26087 XOR #-1,TOS \ 1 flag Z = 1
26092 [UNDEFINED] IF [IF]
26093 \ https://forth-standard.org/standard/core/IF
26094 \ IF -- IFadr initialize conditional forward branch
26095 CODE IF \ immediate
26098 MOV &DP,TOS \ -- HERE
26099 ADD #4,&DP \ compile one word, reserve one word
26100 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
26101 ADD #2,TOS \ -- HERE+2=IFadr
26106 [UNDEFINED] THEN [IF]
26107 \ https://forth-standard.org/standard/core/THEN
26108 \ THEN IFadr -- resolve forward branch
26109 CODE THEN \ immediate
26110 MOV &DP,0(TOS) \ -- IFadr
26116 [UNDEFINED] ELSE [IF]
26117 \ https://forth-standard.org/standard/core/ELSE
26118 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
26119 CODE ELSE \ immediate
26120 ADD #4,&DP \ make room to compile two words
26121 MOV &DP,W \ W=HERE+4
26123 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
26125 MOV W,TOS \ -- ELSEadr
26130 [UNDEFINED] DEFER [IF]
26131 \ https://forth-standard.org/standard/core/DEFER
26132 \ DEFER "<spaces>name" --
26133 \ Skip leading space delimiters. Parse name delimited by a space.
26134 \ Create a definition for name with the execution semantics defined below.
26136 \ name Execution: --
26137 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
26138 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
26142 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
26143 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
26149 [UNDEFINED] DEFER! [IF]
26150 \ https://forth-standard.org/standard/core/DEFERStore
26151 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
26152 CODE DEFER! \ xt2 xt1 --
26153 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
26159 [UNDEFINED] IS [IF]
26160 \ https://forth-standard.org/standard/core/IS
26163 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
26164 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
26165 \ or in a definition : ... ['] U. IS DISPLAY ...
26166 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
26168 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
26171 IF POSTPONE ['] POSTPONE DEFER!
26177 [UNDEFINED] >BODY [IF]
26178 \ https://forth-standard.org/standard/core/toBODY
26179 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
26186 \ CODE 20uS \ n -- 8MHz version
26187 \ BEGIN \ 4 + 16 ~ loop
26188 \ MOV #39,rDOCON \ 39
26195 \ MOV #XDOCON,rDOCON \ 2
26200 CODE 20_US \ n -- n * 20 us
26201 BEGIN \ here we presume that LCD_TIM_IFG = 1...
26203 BIT #1,&LCD_TIM_CTL \ 3
26204 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
26205 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
26207 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
26212 CODE TOP_LCD \ LCD Sample
26213 \ \ if write : %xxxx_WWWW --
26214 \ \ if read : -- %0000_RRRR
26215 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26216 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26217 0= IF \ write LCD bits pattern
26218 AND.B #LCD_DB,TOS \
26219 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26220 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26223 THEN \ read LCD bits pattern
26226 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26227 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26228 AND.B #LCD_DB,TOS \
26232 CODE LCD_WRC \ char -- Write Char
26233 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26235 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
26236 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
26237 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26238 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26239 COLON \ high level word starts here
26240 TOP_LCD 2 20_US \ write high nibble first
26244 CODE LCD_WRF \ func -- Write Fonction
26245 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26249 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
26250 : LCD_HOME $02 LCD_WRF 100 20_us ;
26252 \ [UNDEFINED] OR [IF]
26254 \ \ https://forth-standard.org/standard/core/OR
26255 \ \ C OR x1 x2 -- x3 logical OR
26263 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
26264 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
26265 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
26266 \ : LCD_FN_SET $20 OR LCD_WrF ;
26267 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
26268 \ : LCD_GOTO $80 OR LCD_WrF ;
26271 \ CODE LCD_RDS \ -- status Read Status
26272 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26273 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26274 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26275 \ COLON \ starts a FORTH word
26276 \ TOP_LCD 2 20_us \ -- %0000_HHHH
26277 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
26278 \ HI2LO \ switch from FORTH to assembler
26279 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
26280 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
26281 \ MOV @RSP+,IP \ restore IP saved by COLON
26285 \ CODE LCD_RDC \ -- char Read Char
26286 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26291 \ ******************************\
26292 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26293 \ ******************************\
26294 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
26295 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
26296 BIT.B #SW2,&SW2_IN \ test switch S2
26297 0= IF \ case of switch S2 pressed
26298 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
26300 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
26303 BIT.B #SW1,&SW1_IN \ test switch S1 input
26304 0= IF \ case of Switch S1 pressed
26305 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
26307 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
26311 BW1 \ from quit on truncated RC5 message, repeated RC5 command
26315 \ ******************************\
26316 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26317 \ ******************************\
26318 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26319 \ ******************************\
26320 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26321 \ \ SMclock = 8|16|24 MHz
26322 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
26323 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
26324 \ \ SR(9)=new Toggle bit memory (ADD on)
26325 \ ******************************\
26326 \ RC5_FirstStartBitHalfCycle: \
26327 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
26328 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
26329 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
26330 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
26332 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
26333 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
26335 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
26336 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
26338 MOV #1778,X \ RC5_Period * 1us
26339 MOV #14,W \ count of loop
26341 \ ******************************\
26342 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
26343 \ ******************************\ |
26344 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
26345 \ RC5_Compute_3/4_Period: \ |
26346 RRUM #1,X \ X=1/2 cycle |
26349 ADD X,Y \ Y=3/4 cycle
26350 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
26352 \ ******************************\
26353 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
26354 \ ******************************\
26355 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26356 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
26357 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26358 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26359 SUB #1,W \ decrement count loop
26360 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
26361 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26362 0<> WHILE \ ----> out of loop ----+
26363 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
26365 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
26366 CMP Y,X \ 1 | cycle time out of bound ?
26367 U>= IF \ 2 ^ | yes:
26368 BIC #$30,&RC5_TIM_CTL \ | | stop timer
26369 GOTO BW1 \ | | quit on truncated RC5 message
26371 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
26373 REPEAT \ ----> loop back --+ | with X = new RC5_period value
26374 \ ******************************\ |
26375 \ RC5_SampleEndOf: \ <---------------------+
26376 \ ******************************\
26377 BIC #$30,&RC5_TIM_CTL \ stop timer
26378 \ ******************************\
26379 \ RC5_ComputeNewRC5word \
26380 \ ******************************\
26381 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
26382 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
26383 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
26384 \ ******************************\
26385 \ RC5_ComputeC6bit \
26386 \ ******************************\
26387 BIT #BIT14,T \ test /C6 bit in T
26388 0= IF BIS #BIT6,X \ set C6 bit in X
26389 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
26390 \ ******************************\
26391 \ RC5_CommandByteIsDone \ -- BASE RC5_code
26392 \ ******************************\
26393 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
26394 \ ******************************\
26395 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
26396 XOR @RSP,T \ (new XOR old) Toggle bits
26397 BIT #UF10,T \ repeated RC5_command ?
26398 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
26399 XOR #UF10,0(RSP) \ 5 toggle bit memory
26400 \ ******************************\
26401 \ Display IR_RC5 code \
26402 \ ******************************\
26403 SUB #8,PSP \ TOS -- x x x x TOS
26404 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
26405 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
26406 MOV #$10,&BASEADR \ set hexadecimal base
26407 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
26408 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
26409 LO2HI \ switch from assembler to FORTH
26410 LCD_CLEAR \ set LCD cursor at home
26411 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
26412 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
26413 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
26414 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
26415 HI2LO \ -- switch from FORTH to assembler
26416 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
26417 MOV @PSP+,TOS \ -- TOS
26421 \ ******************************\
26423 \ ******************************\
26425 \ ... \ insert here your background task
26428 CALL &RXON \ comment this line to disable TERMINAL_INPUT
26430 \ ******************************\
26431 \ here start all interrupts \
26432 \ ******************************\
26433 \ here return all interrupts \
26434 \ ******************************\
26437 \ ******************************\
26439 \ ------------------------------\
26440 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
26441 \ ------------------------------\
26442 \ ... \ init specific I/O sys as you want
26443 \ ... \ before executing default WARM
26444 MOV #WARM,X \ ['] WARM
26446 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
26448 \ ------------------------------\
26450 \ ------------------------------\
26451 CODE STOP \ stops multitasking, must to be used before downloading app
26452 \ ------------------------------\
26453 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
26454 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
26455 MOV X,-2(X) \ restore the default background: SLEEP
26457 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
26458 BIC.B #RC5,&IR_IE \ clear RC5_Int
26459 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
26460 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
26461 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
26462 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
26463 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
26464 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
26466 ." RC5toLCD is removed,"
26467 ." type START to restart"
26468 WARM \ performs reset to reset all interrupt vectors.
26470 \ ------------------------------\
26472 \ ------------------------------\
26473 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
26474 \ ------------------------------\
26475 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
26476 \ - - \CNTL Counter lentgh \ 00 = 16 bits
26477 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
26478 \ -- \ID input divider \ 10 = /4
26479 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
26480 \ - \TBCLR TimerB Clear
26483 \ -------------------------------\
26484 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
26485 \ -- \CM Capture Mode
26490 \ --- \OUTMOD \ 011 = set/reset
26496 \ -------------------------------\
26498 \ -------------------------------\
26500 \ ------------------------------\
26501 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
26502 \ ------------------------------\
26503 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
26504 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
26505 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
26506 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
26508 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
26509 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
26511 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
26512 \ ------------------------------\
26513 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
26514 \ ------------------------------\
26515 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
26516 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
26517 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
26518 \ ------------------------------\
26519 BIS.B #LCDVo,&LCDVo_DIR \
26520 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
26521 \ ------------------------------\
26522 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
26523 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
26524 \ ------------------------------\
26525 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
26526 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
26527 \ ******************************\
26529 \ ******************************\
26530 BIS.B #RC5,&IR_IE \ enable RC5_Int
26531 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
26532 MOV #RC5_INT,&IR_Vec \ init interrupt vector
26533 \ ******************************\
26534 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
26535 \ ******************************\
26536 \ %01 0001 0100 \ TAxCTL
26537 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
26538 \ -- \ ID divided by 1
26539 \ -- \ MC MODE = up to TAxCCRn
26540 \ - \ TACLR clear timer count
26543 \ ------------------------------\
26544 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
26545 \ ------------------------------\
26547 \ --- \ TAIDEX pre divisor
26548 \ ------------------------------\
26549 \ %0000 0000 0000 0101 \ TAxCCR0
26550 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
26551 \ ------------------------------\
26552 \ %0000 0000 0001 0000 \ TAxCCTL0
26553 \ - \ CAP capture/compare mode = compare
26556 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
26557 \ ------------------------------\
26558 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
26559 \ ------------------------------\
26560 \ define LPM mode for ACCEPT \
26561 \ ------------------------------\
26562 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
26563 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
26564 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
26565 \ ------------------------------\
26567 \ ------------------------------\
26568 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
26569 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
26570 \ ------------------------------\
26571 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
26572 \ ------------------------------\
26573 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
26574 \ CMP #2,Y \ Power_ON event
26575 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
26577 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
26579 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
26581 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
26583 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
26584 \ ------------------------------\
26586 \ ------------------------------\
26588 \ ------------------------------\
26589 #1000 20_US \ 1- wait 20 ms
26590 %011 TOP_LCD \ 2- send DB5=DB4=1
26591 #205 20_US \ 3- wait 4,1 ms
26592 %011 TOP_LCD \ 4- send again DB5=DB4=1
26593 #5 20_US \ 5- wait 0,1 ms
26594 %011 TOP_LCD \ 6- send again again DB5=DB4=1
26595 #2 20_US \ wait 40 us = LCD cycle
26596 %010 TOP_LCD \ 7- send DB5=1 DB4=0
26597 #2 20_US \ wait 40 us = LCD cycle
26598 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
26599 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
26600 LCD_CLEAR \ 10- "LCD_Clear"
26601 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
26602 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
26603 LCD_CLEAR \ 10- "LCD_Clear"
26604 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
26605 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
26606 CR ." I love you" \ display message on LCD
26607 ['] CR >BODY IS CR \ CR executes its default value
26608 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
26609 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
26610 PWR_STATE ABORT \ init DP and continues with ABORT
26612 \ ------------------------------\
26614 \ ------------------------------\
26615 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
26616 \ ------------------------------\
26617 MOV #SLEEP,X \ replace default background process SLEEP
26618 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
26619 MOV #WARM,X \ replace default WARM
26620 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
26621 MOV X,PC \ then execute new WARM
26623 \ ------------------------------\
26626 ; downloading RC5toLCD.4th is done
26627 RST_HERE ; this app is protected against <reset>
26632 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
26634 [UNDEFINED] MARKER [IF]
26635 \ https://forth-standard.org/standard/core/MARKER
26637 \ ( "<spaces>name" -- )
26638 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
26639 \ with the execution semantics defined below.
26641 \ name Execution: ( -- )
26642 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
26643 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
26644 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
26645 \ not necessarily provided. No other contextual information such as numeric base is affected
26650 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
26651 SUB #2,Y \ 1 Y = LFA
26652 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
26653 ADD #4,&DP \ 3 add 2 cells
26657 MOV @RSP+,IP \ -- PFA
26658 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
26659 MOV @TOS,&INIDP \ set DP value for RST_STATE
26661 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
26668 \ https://forth-standard.org/standard/core/Fetch
26669 \ @ c-addr -- char fetch char from memory
26676 [UNDEFINED] CONSTANT [IF]
26677 \ https://forth-standard.org/standard/core/CONSTANT
26678 \ CONSTANT <name> n -- define a Forth CONSTANT
26682 MOV TOS,-2(W) \ PFA = n
26689 [UNDEFINED] STATE [IF]
26690 \ https://forth-standard.org/standard/core/STATE
26691 \ STATE -- a-addr holds compiler state
26692 STATEADR CONSTANT STATE
26696 \ https://forth-standard.org/standard/core/Equal
26697 \ = x1 x2 -- flag test x1=x2
26704 XOR #-1,TOS \ 1 flag Z = 1
26709 [UNDEFINED] IF [IF]
26710 \ https://forth-standard.org/standard/core/IF
26711 \ IF -- IFadr initialize conditional forward branch
26712 CODE IF \ immediate
26715 MOV &DP,TOS \ -- HERE
26716 ADD #4,&DP \ compile one word, reserve one word
26717 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
26718 ADD #2,TOS \ -- HERE+2=IFadr
26723 [UNDEFINED] THEN [IF]
26724 \ https://forth-standard.org/standard/core/THEN
26725 \ THEN IFadr -- resolve forward branch
26726 CODE THEN \ immediate
26727 MOV &DP,0(TOS) \ -- IFadr
26733 [UNDEFINED] ELSE [IF]
26734 \ https://forth-standard.org/standard/core/ELSE
26735 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
26736 CODE ELSE \ immediate
26737 ADD #4,&DP \ make room to compile two words
26738 MOV &DP,W \ W=HERE+4
26740 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
26742 MOV W,TOS \ -- ELSEadr
26747 [UNDEFINED] DEFER [IF]
26748 \ https://forth-standard.org/standard/core/DEFER
26749 \ DEFER "<spaces>name" --
26750 \ Skip leading space delimiters. Parse name delimited by a space.
26751 \ Create a definition for name with the execution semantics defined below.
26753 \ name Execution: --
26754 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
26755 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
26759 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
26760 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
26766 [UNDEFINED] DEFER! [IF]
26767 \ https://forth-standard.org/standard/core/DEFERStore
26768 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
26769 CODE DEFER! \ xt2 xt1 --
26770 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
26776 [UNDEFINED] IS [IF]
26777 \ https://forth-standard.org/standard/core/IS
26780 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
26781 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
26782 \ or in a definition : ... ['] U. IS DISPLAY ...
26783 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
26785 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
26788 IF POSTPONE ['] POSTPONE DEFER!
26794 [UNDEFINED] >BODY [IF]
26795 \ https://forth-standard.org/standard/core/toBODY
26796 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
26803 \ CODE 20uS \ n -- 8MHz version
26804 \ BEGIN \ 4 + 16 ~ loop
26805 \ MOV #39,rDOCON \ 39
26812 \ MOV #XDOCON,rDOCON \ 2
26817 CODE 20_US \ n -- n * 20 us
26818 BEGIN \ here we presume that LCD_TIM_IFG = 1...
26820 BIT #1,&LCD_TIM_CTL \ 3
26821 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
26822 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
26824 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
26829 CODE TOP_LCD \ LCD Sample
26830 \ \ if write : %xxxx_WWWW --
26831 \ \ if read : -- %0000_RRRR
26832 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
26833 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
26834 0= IF \ write LCD bits pattern
26835 AND.B #LCD_DB,TOS \
26836 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
26837 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26840 THEN \ read LCD bits pattern
26843 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
26844 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
26845 AND.B #LCD_DB,TOS \
26849 CODE LCD_WRC \ char -- Write Char
26850 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26852 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
26853 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
26854 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
26855 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
26856 COLON \ high level word starts here
26857 TOP_LCD 2 20_US \ write high nibble first
26861 CODE LCD_WRF \ func -- Write Fonction
26862 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26866 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
26867 : LCD_HOME $02 LCD_WRF 100 20_us ;
26869 \ [UNDEFINED] OR [IF]
26871 \ \ https://forth-standard.org/standard/core/OR
26872 \ \ C OR x1 x2 -- x3 logical OR
26880 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
26881 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
26882 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
26883 \ : LCD_FN_SET $20 OR LCD_WrF ;
26884 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
26885 \ : LCD_GOTO $80 OR LCD_WrF ;
26888 \ CODE LCD_RDS \ -- status Read Status
26889 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
26890 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
26891 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
26892 \ COLON \ starts a FORTH word
26893 \ TOP_LCD 2 20_us \ -- %0000_HHHH
26894 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
26895 \ HI2LO \ switch from FORTH to assembler
26896 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
26897 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
26898 \ MOV @RSP+,IP \ restore IP saved by COLON
26902 \ CODE LCD_RDC \ -- char Read Char
26903 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
26908 \ ******************************\
26909 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
26910 \ ******************************\
26911 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
26912 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
26913 BIT.B #SW2,&SW2_IN \ test switch S2
26914 0= IF \ case of switch S2 pressed
26915 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
26917 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
26920 BIT.B #SW1,&SW1_IN \ test switch S1 input
26921 0= IF \ case of Switch S1 pressed
26922 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
26924 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
26928 BW1 \ from quit on truncated RC5 message, repeated RC5 command
26932 \ ******************************\
26933 ASM RC5_INT \ wake up on Px.RC5 change interrupt
26934 \ ******************************\
26935 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
26936 \ ******************************\
26937 \ \ in : SR(9)=old Toggle bit memory (ADD on)
26938 \ \ SMclock = 8|16|24 MHz
26939 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
26940 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
26941 \ \ SR(9)=new Toggle bit memory (ADD on)
26942 \ ******************************\
26943 \ RC5_FirstStartBitHalfCycle: \
26944 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
26945 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
26946 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
26947 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
26949 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
26950 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
26952 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
26953 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
26955 MOV #1778,X \ RC5_Period * 1us
26956 MOV #14,W \ count of loop
26958 \ ******************************\
26959 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
26960 \ ******************************\ |
26961 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
26962 \ RC5_Compute_3/4_Period: \ |
26963 RRUM #1,X \ X=1/2 cycle |
26966 ADD X,Y \ Y=3/4 cycle
26967 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
26969 \ ******************************\
26970 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
26971 \ ******************************\
26972 BIT.B #RC5,&IR_IN \ C_flag = IR bit
26973 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
26974 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
26975 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
26976 SUB #1,W \ decrement count loop
26977 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
26978 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
26979 0<> WHILE \ ----> out of loop ----+
26980 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
26982 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
26983 CMP Y,X \ 1 | cycle time out of bound ?
26984 U>= IF \ 2 ^ | yes:
26985 BIC #$30,&RC5_TIM_CTL \ | | stop timer
26986 GOTO BW1 \ | | quit on truncated RC5 message
26988 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
26990 REPEAT \ ----> loop back --+ | with X = new RC5_period value
26991 \ ******************************\ |
26992 \ RC5_SampleEndOf: \ <---------------------+
26993 \ ******************************\
26994 BIC #$30,&RC5_TIM_CTL \ stop timer
26995 \ ******************************\
26996 \ RC5_ComputeNewRC5word \
26997 \ ******************************\
26998 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
26999 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
27000 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
27001 \ ******************************\
27002 \ RC5_ComputeC6bit \
27003 \ ******************************\
27004 BIT #BIT14,T \ test /C6 bit in T
27005 0= IF BIS #BIT6,X \ set C6 bit in X
27006 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
27007 \ ******************************\
27008 \ RC5_CommandByteIsDone \ -- BASE RC5_code
27009 \ ******************************\
27010 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27011 \ ******************************\
27012 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
27013 XOR @RSP,T \ (new XOR old) Toggle bits
27014 BIT #UF10,T \ repeated RC5_command ?
27015 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
27016 XOR #UF10,0(RSP) \ 5 toggle bit memory
27017 \ ******************************\
27018 \ Display IR_RC5 code \
27019 \ ******************************\
27020 SUB #8,PSP \ TOS -- x x x x TOS
27021 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
27022 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
27023 MOV #$10,&BASEADR \ set hexadecimal base
27024 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
27025 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
27026 LO2HI \ switch from assembler to FORTH
27027 LCD_CLEAR \ set LCD cursor at home
27028 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
27029 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
27030 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
27031 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
27032 HI2LO \ -- switch from FORTH to assembler
27033 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
27034 MOV @PSP+,TOS \ -- TOS
27038 \ ******************************\
27040 \ ******************************\
27042 \ ... \ insert here your background task
27045 CALL &RXON \ comment this line to disable TERMINAL_INPUT
27047 \ ******************************\
27048 \ here start all interrupts \
27049 \ ******************************\
27050 \ here return all interrupts \
27051 \ ******************************\
27054 \ ******************************\
27056 \ ------------------------------\
27057 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
27058 \ ------------------------------\
27059 \ ... \ init specific I/O sys as you want
27060 \ ... \ before executing default WARM
27061 MOV #WARM,X \ ['] WARM
27063 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
27065 \ ------------------------------\
27067 \ ------------------------------\
27068 CODE STOP \ stops multitasking, must to be used before downloading app
27069 \ ------------------------------\
27070 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
27071 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
27072 MOV X,-2(X) \ restore the default background: SLEEP
27074 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
27075 BIC.B #RC5,&IR_IE \ clear RC5_Int
27076 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
27077 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
27078 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
27079 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
27080 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
27081 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
27083 ." RC5toLCD is removed,"
27084 ." type START to restart"
27085 WARM \ performs reset to reset all interrupt vectors.
27087 \ ------------------------------\
27089 \ ------------------------------\
27090 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
27091 \ ------------------------------\
27092 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
27093 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27094 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27095 \ -- \ID input divider \ 10 = /4
27096 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
27097 \ - \TBCLR TimerB Clear
27100 \ -------------------------------\
27101 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27102 \ -- \CM Capture Mode
27107 \ --- \OUTMOD \ 011 = set/reset
27113 \ -------------------------------\
27115 \ -------------------------------\
27117 \ ------------------------------\
27118 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
27119 \ ------------------------------\
27120 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
27121 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
27122 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
27123 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
27125 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
27126 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
27128 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
27129 \ ------------------------------\
27130 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
27131 \ ------------------------------\
27132 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
27133 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
27134 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27135 \ ------------------------------\
27136 BIS.B #LCDVo,&LCDVo_DIR \
27137 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
27138 \ ------------------------------\
27139 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27140 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27141 \ ------------------------------\
27142 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27143 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27144 \ ******************************\
27146 \ ******************************\
27147 BIS.B #RC5,&IR_IE \ enable RC5_Int
27148 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27149 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27150 \ ******************************\
27151 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
27152 \ ******************************\
27153 \ %01 0001 0100 \ TAxCTL
27154 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
27155 \ -- \ ID divided by 1
27156 \ -- \ MC MODE = up to TAxCCRn
27157 \ - \ TACLR clear timer count
27160 \ ------------------------------\
27161 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
27162 \ ------------------------------\
27164 \ --- \ TAIDEX pre divisor
27165 \ ------------------------------\
27166 \ %0000 0000 0000 0101 \ TAxCCR0
27167 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
27168 \ ------------------------------\
27169 \ %0000 0000 0001 0000 \ TAxCCTL0
27170 \ - \ CAP capture/compare mode = compare
27173 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
27174 \ ------------------------------\
27175 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
27176 \ ------------------------------\
27177 \ define LPM mode for ACCEPT \
27178 \ ------------------------------\
27179 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27180 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27181 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27182 \ ------------------------------\
27184 \ ------------------------------\
27185 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
27186 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
27187 \ ------------------------------\
27188 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
27189 \ ------------------------------\
27190 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
27191 \ CMP #2,Y \ Power_ON event
27192 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
27194 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
27196 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
27198 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
27200 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
27201 \ ------------------------------\
27203 \ ------------------------------\
27205 \ ------------------------------\
27206 #1000 20_US \ 1- wait 20 ms
27207 %011 TOP_LCD \ 2- send DB5=DB4=1
27208 #205 20_US \ 3- wait 4,1 ms
27209 %011 TOP_LCD \ 4- send again DB5=DB4=1
27210 #5 20_US \ 5- wait 0,1 ms
27211 %011 TOP_LCD \ 6- send again again DB5=DB4=1
27212 #2 20_US \ wait 40 us = LCD cycle
27213 %010 TOP_LCD \ 7- send DB5=1 DB4=0
27214 #2 20_US \ wait 40 us = LCD cycle
27215 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27216 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27217 LCD_CLEAR \ 10- "LCD_Clear"
27218 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27219 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27220 LCD_CLEAR \ 10- "LCD_Clear"
27221 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27222 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27223 CR ." I love you" \ display message on LCD
27224 ['] CR >BODY IS CR \ CR executes its default value
27225 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
27226 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
27227 PWR_STATE ABORT \ init DP and continues with ABORT
27229 \ ------------------------------\
27231 \ ------------------------------\
27232 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
27233 \ ------------------------------\
27234 MOV #SLEEP,X \ replace default background process SLEEP
27235 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
27236 MOV #WARM,X \ replace default WARM
27237 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
27238 MOV X,PC \ then execute new WARM
27240 \ ------------------------------\
27243 ; downloading RC5toLCD.4th is done
27244 RST_HERE ; this app is protected against <reset>
27249 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
27251 [UNDEFINED] MARKER [IF]
27252 \ https://forth-standard.org/standard/core/MARKER
27254 \ ( "<spaces>name" -- )
27255 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
27256 \ with the execution semantics defined below.
27258 \ name Execution: ( -- )
27259 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
27260 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
27261 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
27262 \ not necessarily provided. No other contextual information such as numeric base is affected
27267 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
27268 SUB #2,Y \ 1 Y = LFA
27269 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
27270 ADD #4,&DP \ 3 add 2 cells
27274 MOV @RSP+,IP \ -- PFA
27275 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
27276 MOV @TOS,&INIDP \ set DP value for RST_STATE
27278 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
27285 \ https://forth-standard.org/standard/core/Fetch
27286 \ @ c-addr -- char fetch char from memory
27293 [UNDEFINED] CONSTANT [IF]
27294 \ https://forth-standard.org/standard/core/CONSTANT
27295 \ CONSTANT <name> n -- define a Forth CONSTANT
27299 MOV TOS,-2(W) \ PFA = n
27306 [UNDEFINED] STATE [IF]
27307 \ https://forth-standard.org/standard/core/STATE
27308 \ STATE -- a-addr holds compiler state
27309 STATEADR CONSTANT STATE
27313 \ https://forth-standard.org/standard/core/Equal
27314 \ = x1 x2 -- flag test x1=x2
27321 XOR #-1,TOS \ 1 flag Z = 1
27326 [UNDEFINED] IF [IF]
27327 \ https://forth-standard.org/standard/core/IF
27328 \ IF -- IFadr initialize conditional forward branch
27329 CODE IF \ immediate
27332 MOV &DP,TOS \ -- HERE
27333 ADD #4,&DP \ compile one word, reserve one word
27334 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
27335 ADD #2,TOS \ -- HERE+2=IFadr
27340 [UNDEFINED] THEN [IF]
27341 \ https://forth-standard.org/standard/core/THEN
27342 \ THEN IFadr -- resolve forward branch
27343 CODE THEN \ immediate
27344 MOV &DP,0(TOS) \ -- IFadr
27350 [UNDEFINED] ELSE [IF]
27351 \ https://forth-standard.org/standard/core/ELSE
27352 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
27353 CODE ELSE \ immediate
27354 ADD #4,&DP \ make room to compile two words
27355 MOV &DP,W \ W=HERE+4
27357 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
27359 MOV W,TOS \ -- ELSEadr
27364 [UNDEFINED] DEFER [IF]
27365 \ https://forth-standard.org/standard/core/DEFER
27366 \ DEFER "<spaces>name" --
27367 \ Skip leading space delimiters. Parse name delimited by a space.
27368 \ Create a definition for name with the execution semantics defined below.
27370 \ name Execution: --
27371 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
27372 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
27376 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
27377 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
27383 [UNDEFINED] DEFER! [IF]
27384 \ https://forth-standard.org/standard/core/DEFERStore
27385 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
27386 CODE DEFER! \ xt2 xt1 --
27387 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
27393 [UNDEFINED] IS [IF]
27394 \ https://forth-standard.org/standard/core/IS
27397 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
27398 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
27399 \ or in a definition : ... ['] U. IS DISPLAY ...
27400 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
27402 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
27405 IF POSTPONE ['] POSTPONE DEFER!
27411 [UNDEFINED] >BODY [IF]
27412 \ https://forth-standard.org/standard/core/toBODY
27413 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
27420 \ CODE 20uS \ n -- 8MHz version
27421 \ BEGIN \ 4 + 16 ~ loop
27422 \ MOV #39,rDOCON \ 39
27429 \ MOV #XDOCON,rDOCON \ 2
27434 CODE 20_US \ n -- n * 20 us
27435 BEGIN \ here we presume that LCD_TIM_IFG = 1...
27437 BIT #1,&LCD_TIM_CTL \ 3
27438 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
27439 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
27441 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
27446 CODE TOP_LCD \ LCD Sample
27447 \ \ if write : %xxxx_WWWW --
27448 \ \ if read : -- %0000_RRRR
27449 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
27450 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
27451 0= IF \ write LCD bits pattern
27452 AND.B #LCD_DB,TOS \
27453 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
27454 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27457 THEN \ read LCD bits pattern
27460 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
27461 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
27462 AND.B #LCD_DB,TOS \
27466 CODE LCD_WRC \ char -- Write Char
27467 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27469 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
27470 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
27471 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
27472 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
27473 COLON \ high level word starts here
27474 TOP_LCD 2 20_US \ write high nibble first
27478 CODE LCD_WRF \ func -- Write Fonction
27479 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27483 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
27484 : LCD_HOME $02 LCD_WRF 100 20_us ;
27486 \ [UNDEFINED] OR [IF]
27488 \ \ https://forth-standard.org/standard/core/OR
27489 \ \ C OR x1 x2 -- x3 logical OR
27497 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
27498 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
27499 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
27500 \ : LCD_FN_SET $20 OR LCD_WrF ;
27501 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
27502 \ : LCD_GOTO $80 OR LCD_WrF ;
27505 \ CODE LCD_RDS \ -- status Read Status
27506 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
27507 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
27508 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
27509 \ COLON \ starts a FORTH word
27510 \ TOP_LCD 2 20_us \ -- %0000_HHHH
27511 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
27512 \ HI2LO \ switch from FORTH to assembler
27513 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
27514 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
27515 \ MOV @RSP+,IP \ restore IP saved by COLON
27519 \ CODE LCD_RDC \ -- char Read Char
27520 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
27525 \ ******************************\
27526 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
27527 \ ******************************\
27528 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
27529 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
27530 BIT.B #SW2,&SW2_IN \ test switch S2
27531 0= IF \ case of switch S2 pressed
27532 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
27534 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
27537 BIT.B #SW1,&SW1_IN \ test switch S1 input
27538 0= IF \ case of Switch S1 pressed
27539 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
27541 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
27545 BW1 \ from quit on truncated RC5 message, repeated RC5 command
27549 \ ******************************\
27550 ASM RC5_INT \ wake up on Px.RC5 change interrupt
27551 \ ******************************\
27552 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
27553 \ ******************************\
27554 \ \ in : SR(9)=old Toggle bit memory (ADD on)
27555 \ \ SMclock = 8|16|24 MHz
27556 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
27557 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
27558 \ \ SR(9)=new Toggle bit memory (ADD on)
27559 \ ******************************\
27560 \ RC5_FirstStartBitHalfCycle: \
27561 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
27562 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
27563 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
27564 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
27566 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
27567 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
27569 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
27570 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
27572 MOV #1778,X \ RC5_Period * 1us
27573 MOV #14,W \ count of loop
27575 \ ******************************\
27576 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
27577 \ ******************************\ |
27578 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
27579 \ RC5_Compute_3/4_Period: \ |
27580 RRUM #1,X \ X=1/2 cycle |
27583 ADD X,Y \ Y=3/4 cycle
27584 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
27586 \ ******************************\
27587 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
27588 \ ******************************\
27589 BIT.B #RC5,&IR_IN \ C_flag = IR bit
27590 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
27591 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
27592 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
27593 SUB #1,W \ decrement count loop
27594 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
27595 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
27596 0<> WHILE \ ----> out of loop ----+
27597 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
27599 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
27600 CMP Y,X \ 1 | cycle time out of bound ?
27601 U>= IF \ 2 ^ | yes:
27602 BIC #$30,&RC5_TIM_CTL \ | | stop timer
27603 GOTO BW1 \ | | quit on truncated RC5 message
27605 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
27607 REPEAT \ ----> loop back --+ | with X = new RC5_period value
27608 \ ******************************\ |
27609 \ RC5_SampleEndOf: \ <---------------------+
27610 \ ******************************\
27611 BIC #$30,&RC5_TIM_CTL \ stop timer
27612 \ ******************************\
27613 \ RC5_ComputeNewRC5word \
27614 \ ******************************\
27615 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
27616 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
27617 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
27618 \ ******************************\
27619 \ RC5_ComputeC6bit \
27620 \ ******************************\
27621 BIT #BIT14,T \ test /C6 bit in T
27622 0= IF BIS #BIT6,X \ set C6 bit in X
27623 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
27624 \ ******************************\
27625 \ RC5_CommandByteIsDone \ -- BASE RC5_code
27626 \ ******************************\
27627 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
27628 \ ******************************\
27629 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
27630 XOR @RSP,T \ (new XOR old) Toggle bits
27631 BIT #UF10,T \ repeated RC5_command ?
27632 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
27633 XOR #UF10,0(RSP) \ 5 toggle bit memory
27634 \ ******************************\
27635 \ Display IR_RC5 code \
27636 \ ******************************\
27637 SUB #8,PSP \ TOS -- x x x x TOS
27638 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
27639 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
27640 MOV #$10,&BASEADR \ set hexadecimal base
27641 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
27642 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
27643 LO2HI \ switch from assembler to FORTH
27644 LCD_CLEAR \ set LCD cursor at home
27645 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
27646 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
27647 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
27648 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
27649 HI2LO \ -- switch from FORTH to assembler
27650 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
27651 MOV @PSP+,TOS \ -- TOS
27655 \ ******************************\
27657 \ ******************************\
27659 \ ... \ insert here your background task
27662 CALL &RXON \ comment this line to disable TERMINAL_INPUT
27664 \ ******************************\
27665 \ here start all interrupts \
27666 \ ******************************\
27667 \ here return all interrupts \
27668 \ ******************************\
27671 \ ******************************\
27673 \ ------------------------------\
27674 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
27675 \ ------------------------------\
27676 \ ... \ init specific I/O sys as you want
27677 \ ... \ before executing default WARM
27678 MOV #WARM,X \ ['] WARM
27680 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
27682 \ ------------------------------\
27684 \ ------------------------------\
27685 CODE STOP \ stops multitasking, must to be used before downloading app
27686 \ ------------------------------\
27687 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
27688 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
27689 MOV X,-2(X) \ restore the default background: SLEEP
27691 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
27692 BIC.B #RC5,&IR_IE \ clear RC5_Int
27693 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
27694 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
27695 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
27696 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
27697 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
27698 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
27700 ." RC5toLCD is removed,"
27701 ." type START to restart"
27702 WARM \ performs reset to reset all interrupt vectors.
27704 \ ------------------------------\
27706 \ ------------------------------\
27707 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
27708 \ ------------------------------\
27709 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
27710 \ - - \CNTL Counter lentgh \ 00 = 16 bits
27711 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
27712 \ -- \ID input divider \ 10 = /4
27713 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
27714 \ - \TBCLR TimerB Clear
27717 \ -------------------------------\
27718 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
27719 \ -- \CM Capture Mode
27724 \ --- \OUTMOD \ 011 = set/reset
27730 \ -------------------------------\
27732 \ -------------------------------\
27734 \ ------------------------------\
27735 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
27736 \ ------------------------------\
27737 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
27738 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
27739 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
27740 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
27742 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
27743 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
27745 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
27746 \ ------------------------------\
27747 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
27748 \ ------------------------------\
27749 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
27750 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
27751 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
27752 \ ------------------------------\
27753 BIS.B #LCDVo,&LCDVo_DIR \
27754 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
27755 \ ------------------------------\
27756 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
27757 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
27758 \ ------------------------------\
27759 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
27760 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
27761 \ ******************************\
27763 \ ******************************\
27764 BIS.B #RC5,&IR_IE \ enable RC5_Int
27765 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
27766 MOV #RC5_INT,&IR_Vec \ init interrupt vector
27767 \ ******************************\
27768 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
27769 \ ******************************\
27770 \ %01 0001 0100 \ TAxCTL
27771 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
27772 \ -- \ ID divided by 1
27773 \ -- \ MC MODE = up to TAxCCRn
27774 \ - \ TACLR clear timer count
27777 \ ------------------------------\
27778 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
27779 \ ------------------------------\
27781 \ --- \ TAIDEX pre divisor
27782 \ ------------------------------\
27783 \ %0000 0000 0000 0101 \ TAxCCR0
27784 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
27785 \ ------------------------------\
27786 \ %0000 0000 0001 0000 \ TAxCCTL0
27787 \ - \ CAP capture/compare mode = compare
27790 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
27791 \ ------------------------------\
27792 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
27793 \ ------------------------------\
27794 \ define LPM mode for ACCEPT \
27795 \ ------------------------------\
27796 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
27797 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
27798 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
27799 \ ------------------------------\
27801 \ ------------------------------\
27802 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
27803 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
27804 \ ------------------------------\
27805 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
27806 \ ------------------------------\
27807 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
27808 \ CMP #2,Y \ Power_ON event
27809 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
27811 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
27813 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
27815 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
27817 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
27818 \ ------------------------------\
27820 \ ------------------------------\
27822 \ ------------------------------\
27823 #1000 20_US \ 1- wait 20 ms
27824 %011 TOP_LCD \ 2- send DB5=DB4=1
27825 #205 20_US \ 3- wait 4,1 ms
27826 %011 TOP_LCD \ 4- send again DB5=DB4=1
27827 #5 20_US \ 5- wait 0,1 ms
27828 %011 TOP_LCD \ 6- send again again DB5=DB4=1
27829 #2 20_US \ wait 40 us = LCD cycle
27830 %010 TOP_LCD \ 7- send DB5=1 DB4=0
27831 #2 20_US \ wait 40 us = LCD cycle
27832 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
27833 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
27834 LCD_CLEAR \ 10- "LCD_Clear"
27835 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
27836 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
27837 LCD_CLEAR \ 10- "LCD_Clear"
27838 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
27839 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
27840 CR ." I love you" \ display message on LCD
27841 ['] CR >BODY IS CR \ CR executes its default value
27842 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
27843 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
27844 PWR_STATE ABORT \ init DP and continues with ABORT
27846 \ ------------------------------\
27848 \ ------------------------------\
27849 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
27850 \ ------------------------------\
27851 MOV #SLEEP,X \ replace default background process SLEEP
27852 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
27853 MOV #WARM,X \ replace default WARM
27854 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
27855 MOV X,PC \ then execute new WARM
27857 \ ------------------------------\
27860 ; downloading RC5toLCD.4th is done
27861 RST_HERE ; this app is protected against <reset>
27866 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
27868 [UNDEFINED] MARKER [IF]
27869 \ https://forth-standard.org/standard/core/MARKER
27871 \ ( "<spaces>name" -- )
27872 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
27873 \ with the execution semantics defined below.
27875 \ name Execution: ( -- )
27876 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
27877 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
27878 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
27879 \ not necessarily provided. No other contextual information such as numeric base is affected
27884 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
27885 SUB #2,Y \ 1 Y = LFA
27886 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
27887 ADD #4,&DP \ 3 add 2 cells
27891 MOV @RSP+,IP \ -- PFA
27892 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
27893 MOV @TOS,&INIDP \ set DP value for RST_STATE
27895 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
27902 \ https://forth-standard.org/standard/core/Fetch
27903 \ @ c-addr -- char fetch char from memory
27910 [UNDEFINED] CONSTANT [IF]
27911 \ https://forth-standard.org/standard/core/CONSTANT
27912 \ CONSTANT <name> n -- define a Forth CONSTANT
27916 MOV TOS,-2(W) \ PFA = n
27923 [UNDEFINED] STATE [IF]
27924 \ https://forth-standard.org/standard/core/STATE
27925 \ STATE -- a-addr holds compiler state
27926 STATEADR CONSTANT STATE
27930 \ https://forth-standard.org/standard/core/Equal
27931 \ = x1 x2 -- flag test x1=x2
27938 XOR #-1,TOS \ 1 flag Z = 1
27943 [UNDEFINED] IF [IF]
27944 \ https://forth-standard.org/standard/core/IF
27945 \ IF -- IFadr initialize conditional forward branch
27946 CODE IF \ immediate
27949 MOV &DP,TOS \ -- HERE
27950 ADD #4,&DP \ compile one word, reserve one word
27951 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
27952 ADD #2,TOS \ -- HERE+2=IFadr
27957 [UNDEFINED] THEN [IF]
27958 \ https://forth-standard.org/standard/core/THEN
27959 \ THEN IFadr -- resolve forward branch
27960 CODE THEN \ immediate
27961 MOV &DP,0(TOS) \ -- IFadr
27967 [UNDEFINED] ELSE [IF]
27968 \ https://forth-standard.org/standard/core/ELSE
27969 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
27970 CODE ELSE \ immediate
27971 ADD #4,&DP \ make room to compile two words
27972 MOV &DP,W \ W=HERE+4
27974 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
27976 MOV W,TOS \ -- ELSEadr
27981 [UNDEFINED] DEFER [IF]
27982 \ https://forth-standard.org/standard/core/DEFER
27983 \ DEFER "<spaces>name" --
27984 \ Skip leading space delimiters. Parse name delimited by a space.
27985 \ Create a definition for name with the execution semantics defined below.
27987 \ name Execution: --
27988 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
27989 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
27993 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
27994 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
28000 [UNDEFINED] DEFER! [IF]
28001 \ https://forth-standard.org/standard/core/DEFERStore
28002 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
28003 CODE DEFER! \ xt2 xt1 --
28004 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
28010 [UNDEFINED] IS [IF]
28011 \ https://forth-standard.org/standard/core/IS
28014 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
28015 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
28016 \ or in a definition : ... ['] U. IS DISPLAY ...
28017 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
28019 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
28022 IF POSTPONE ['] POSTPONE DEFER!
28028 [UNDEFINED] >BODY [IF]
28029 \ https://forth-standard.org/standard/core/toBODY
28030 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
28037 \ CODE 20uS \ n -- 8MHz version
28038 \ BEGIN \ 4 + 16 ~ loop
28039 \ MOV #39,rDOCON \ 39
28046 \ MOV #XDOCON,rDOCON \ 2
28051 CODE 20_US \ n -- n * 20 us
28052 BEGIN \ here we presume that LCD_TIM_IFG = 1...
28054 BIT #1,&LCD_TIM_CTL \ 3
28055 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
28056 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
28058 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
28063 CODE TOP_LCD \ LCD Sample
28064 \ \ if write : %xxxx_WWWW --
28065 \ \ if read : -- %0000_RRRR
28066 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28067 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28068 0= IF \ write LCD bits pattern
28069 AND.B #LCD_DB,TOS \
28070 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28071 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28074 THEN \ read LCD bits pattern
28077 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28078 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28079 AND.B #LCD_DB,TOS \
28083 CODE LCD_WRC \ char -- Write Char
28084 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28086 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
28087 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
28088 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28089 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28090 COLON \ high level word starts here
28091 TOP_LCD 2 20_US \ write high nibble first
28095 CODE LCD_WRF \ func -- Write Fonction
28096 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28100 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
28101 : LCD_HOME $02 LCD_WRF 100 20_us ;
28103 \ [UNDEFINED] OR [IF]
28105 \ \ https://forth-standard.org/standard/core/OR
28106 \ \ C OR x1 x2 -- x3 logical OR
28114 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
28115 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
28116 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
28117 \ : LCD_FN_SET $20 OR LCD_WrF ;
28118 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
28119 \ : LCD_GOTO $80 OR LCD_WrF ;
28122 \ CODE LCD_RDS \ -- status Read Status
28123 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28124 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28125 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28126 \ COLON \ starts a FORTH word
28127 \ TOP_LCD 2 20_us \ -- %0000_HHHH
28128 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
28129 \ HI2LO \ switch from FORTH to assembler
28130 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
28131 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
28132 \ MOV @RSP+,IP \ restore IP saved by COLON
28136 \ CODE LCD_RDC \ -- char Read Char
28137 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28142 \ ******************************\
28143 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28144 \ ******************************\
28145 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
28146 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
28147 BIT.B #SW2,&SW2_IN \ test switch S2
28148 0= IF \ case of switch S2 pressed
28149 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
28151 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
28154 BIT.B #SW1,&SW1_IN \ test switch S1 input
28155 0= IF \ case of Switch S1 pressed
28156 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
28158 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
28162 BW1 \ from quit on truncated RC5 message, repeated RC5 command
28166 \ ******************************\
28167 ASM RC5_INT \ wake up on Px.RC5 change interrupt
28168 \ ******************************\
28169 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28170 \ ******************************\
28171 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28172 \ \ SMclock = 8|16|24 MHz
28173 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
28174 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
28175 \ \ SR(9)=new Toggle bit memory (ADD on)
28176 \ ******************************\
28177 \ RC5_FirstStartBitHalfCycle: \
28178 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
28179 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
28180 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
28181 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
28183 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
28184 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
28186 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
28187 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
28189 MOV #1778,X \ RC5_Period * 1us
28190 MOV #14,W \ count of loop
28192 \ ******************************\
28193 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
28194 \ ******************************\ |
28195 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
28196 \ RC5_Compute_3/4_Period: \ |
28197 RRUM #1,X \ X=1/2 cycle |
28200 ADD X,Y \ Y=3/4 cycle
28201 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
28203 \ ******************************\
28204 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
28205 \ ******************************\
28206 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28207 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
28208 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28209 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28210 SUB #1,W \ decrement count loop
28211 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
28212 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28213 0<> WHILE \ ----> out of loop ----+
28214 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
28216 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
28217 CMP Y,X \ 1 | cycle time out of bound ?
28218 U>= IF \ 2 ^ | yes:
28219 BIC #$30,&RC5_TIM_CTL \ | | stop timer
28220 GOTO BW1 \ | | quit on truncated RC5 message
28222 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
28224 REPEAT \ ----> loop back --+ | with X = new RC5_period value
28225 \ ******************************\ |
28226 \ RC5_SampleEndOf: \ <---------------------+
28227 \ ******************************\
28228 BIC #$30,&RC5_TIM_CTL \ stop timer
28229 \ ******************************\
28230 \ RC5_ComputeNewRC5word \
28231 \ ******************************\
28232 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
28233 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
28234 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
28235 \ ******************************\
28236 \ RC5_ComputeC6bit \
28237 \ ******************************\
28238 BIT #BIT14,T \ test /C6 bit in T
28239 0= IF BIS #BIT6,X \ set C6 bit in X
28240 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
28241 \ ******************************\
28242 \ RC5_CommandByteIsDone \ -- BASE RC5_code
28243 \ ******************************\
28244 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
28245 \ ******************************\
28246 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
28247 XOR @RSP,T \ (new XOR old) Toggle bits
28248 BIT #UF10,T \ repeated RC5_command ?
28249 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
28250 XOR #UF10,0(RSP) \ 5 toggle bit memory
28251 \ ******************************\
28252 \ Display IR_RC5 code \
28253 \ ******************************\
28254 SUB #8,PSP \ TOS -- x x x x TOS
28255 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
28256 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
28257 MOV #$10,&BASEADR \ set hexadecimal base
28258 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
28259 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
28260 LO2HI \ switch from assembler to FORTH
28261 LCD_CLEAR \ set LCD cursor at home
28262 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
28263 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
28264 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
28265 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
28266 HI2LO \ -- switch from FORTH to assembler
28267 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
28268 MOV @PSP+,TOS \ -- TOS
28272 \ ******************************\
28274 \ ******************************\
28276 \ ... \ insert here your background task
28279 CALL &RXON \ comment this line to disable TERMINAL_INPUT
28281 \ ******************************\
28282 \ here start all interrupts \
28283 \ ******************************\
28284 \ here return all interrupts \
28285 \ ******************************\
28288 \ ******************************\
28290 \ ------------------------------\
28291 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
28292 \ ------------------------------\
28293 \ ... \ init specific I/O sys as you want
28294 \ ... \ before executing default WARM
28295 MOV #WARM,X \ ['] WARM
28297 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
28299 \ ------------------------------\
28301 \ ------------------------------\
28302 CODE STOP \ stops multitasking, must to be used before downloading app
28303 \ ------------------------------\
28304 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
28305 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
28306 MOV X,-2(X) \ restore the default background: SLEEP
28308 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
28309 BIC.B #RC5,&IR_IE \ clear RC5_Int
28310 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
28311 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
28312 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
28313 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
28314 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
28315 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
28317 ." RC5toLCD is removed,"
28318 ." type START to restart"
28319 WARM \ performs reset to reset all interrupt vectors.
28321 \ ------------------------------\
28323 \ ------------------------------\
28324 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
28325 \ ------------------------------\
28326 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
28327 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28328 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28329 \ -- \ID input divider \ 10 = /4
28330 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28331 \ - \TBCLR TimerB Clear
28334 \ -------------------------------\
28335 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28336 \ -- \CM Capture Mode
28341 \ --- \OUTMOD \ 011 = set/reset
28347 \ -------------------------------\
28349 \ -------------------------------\
28351 \ ------------------------------\
28352 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28353 \ ------------------------------\
28354 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28355 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28356 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
28357 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28359 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
28360 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28362 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
28363 \ ------------------------------\
28364 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28365 \ ------------------------------\
28366 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
28367 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28368 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28369 \ ------------------------------\
28370 BIS.B #LCDVo,&LCDVo_DIR \
28371 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
28372 \ ------------------------------\
28373 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28374 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28375 \ ------------------------------\
28376 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28377 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28378 \ ******************************\
28380 \ ******************************\
28381 BIS.B #RC5,&IR_IE \ enable RC5_Int
28382 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
28383 MOV #RC5_INT,&IR_Vec \ init interrupt vector
28384 \ ******************************\
28385 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
28386 \ ******************************\
28387 \ %01 0001 0100 \ TAxCTL
28388 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
28389 \ -- \ ID divided by 1
28390 \ -- \ MC MODE = up to TAxCCRn
28391 \ - \ TACLR clear timer count
28394 \ ------------------------------\
28395 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
28396 \ ------------------------------\
28398 \ --- \ TAIDEX pre divisor
28399 \ ------------------------------\
28400 \ %0000 0000 0000 0101 \ TAxCCR0
28401 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
28402 \ ------------------------------\
28403 \ %0000 0000 0001 0000 \ TAxCCTL0
28404 \ - \ CAP capture/compare mode = compare
28407 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
28408 \ ------------------------------\
28409 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
28410 \ ------------------------------\
28411 \ define LPM mode for ACCEPT \
28412 \ ------------------------------\
28413 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
28414 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
28415 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
28416 \ ------------------------------\
28418 \ ------------------------------\
28419 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
28420 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
28421 \ ------------------------------\
28422 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
28423 \ ------------------------------\
28424 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
28425 \ CMP #2,Y \ Power_ON event
28426 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
28428 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
28430 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
28432 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
28434 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
28435 \ ------------------------------\
28437 \ ------------------------------\
28439 \ ------------------------------\
28440 #1000 20_US \ 1- wait 20 ms
28441 %011 TOP_LCD \ 2- send DB5=DB4=1
28442 #205 20_US \ 3- wait 4,1 ms
28443 %011 TOP_LCD \ 4- send again DB5=DB4=1
28444 #5 20_US \ 5- wait 0,1 ms
28445 %011 TOP_LCD \ 6- send again again DB5=DB4=1
28446 #2 20_US \ wait 40 us = LCD cycle
28447 %010 TOP_LCD \ 7- send DB5=1 DB4=0
28448 #2 20_US \ wait 40 us = LCD cycle
28449 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
28450 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
28451 LCD_CLEAR \ 10- "LCD_Clear"
28452 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
28453 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
28454 LCD_CLEAR \ 10- "LCD_Clear"
28455 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
28456 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
28457 CR ." I love you" \ display message on LCD
28458 ['] CR >BODY IS CR \ CR executes its default value
28459 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
28460 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
28461 PWR_STATE ABORT \ init DP and continues with ABORT
28463 \ ------------------------------\
28465 \ ------------------------------\
28466 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
28467 \ ------------------------------\
28468 MOV #SLEEP,X \ replace default background process SLEEP
28469 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
28470 MOV #WARM,X \ replace default WARM
28471 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
28472 MOV X,PC \ then execute new WARM
28474 \ ------------------------------\
28477 ; downloading RC5toLCD.4th is done
28478 RST_HERE ; this app is protected against <reset>
28483 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
28485 [UNDEFINED] MARKER [IF]
28486 \ https://forth-standard.org/standard/core/MARKER
28488 \ ( "<spaces>name" -- )
28489 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
28490 \ with the execution semantics defined below.
28492 \ name Execution: ( -- )
28493 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
28494 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
28495 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
28496 \ not necessarily provided. No other contextual information such as numeric base is affected
28501 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
28502 SUB #2,Y \ 1 Y = LFA
28503 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
28504 ADD #4,&DP \ 3 add 2 cells
28508 MOV @RSP+,IP \ -- PFA
28509 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
28510 MOV @TOS,&INIDP \ set DP value for RST_STATE
28512 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
28519 \ https://forth-standard.org/standard/core/Fetch
28520 \ @ c-addr -- char fetch char from memory
28527 [UNDEFINED] CONSTANT [IF]
28528 \ https://forth-standard.org/standard/core/CONSTANT
28529 \ CONSTANT <name> n -- define a Forth CONSTANT
28533 MOV TOS,-2(W) \ PFA = n
28540 [UNDEFINED] STATE [IF]
28541 \ https://forth-standard.org/standard/core/STATE
28542 \ STATE -- a-addr holds compiler state
28543 STATEADR CONSTANT STATE
28547 \ https://forth-standard.org/standard/core/Equal
28548 \ = x1 x2 -- flag test x1=x2
28555 XOR #-1,TOS \ 1 flag Z = 1
28560 [UNDEFINED] IF [IF]
28561 \ https://forth-standard.org/standard/core/IF
28562 \ IF -- IFadr initialize conditional forward branch
28563 CODE IF \ immediate
28566 MOV &DP,TOS \ -- HERE
28567 ADD #4,&DP \ compile one word, reserve one word
28568 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
28569 ADD #2,TOS \ -- HERE+2=IFadr
28574 [UNDEFINED] THEN [IF]
28575 \ https://forth-standard.org/standard/core/THEN
28576 \ THEN IFadr -- resolve forward branch
28577 CODE THEN \ immediate
28578 MOV &DP,0(TOS) \ -- IFadr
28584 [UNDEFINED] ELSE [IF]
28585 \ https://forth-standard.org/standard/core/ELSE
28586 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
28587 CODE ELSE \ immediate
28588 ADD #4,&DP \ make room to compile two words
28589 MOV &DP,W \ W=HERE+4
28591 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
28593 MOV W,TOS \ -- ELSEadr
28598 [UNDEFINED] DEFER [IF]
28599 \ https://forth-standard.org/standard/core/DEFER
28600 \ DEFER "<spaces>name" --
28601 \ Skip leading space delimiters. Parse name delimited by a space.
28602 \ Create a definition for name with the execution semantics defined below.
28604 \ name Execution: --
28605 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
28606 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
28610 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
28611 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
28617 [UNDEFINED] DEFER! [IF]
28618 \ https://forth-standard.org/standard/core/DEFERStore
28619 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
28620 CODE DEFER! \ xt2 xt1 --
28621 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
28627 [UNDEFINED] IS [IF]
28628 \ https://forth-standard.org/standard/core/IS
28631 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
28632 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
28633 \ or in a definition : ... ['] U. IS DISPLAY ...
28634 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
28636 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
28639 IF POSTPONE ['] POSTPONE DEFER!
28645 [UNDEFINED] >BODY [IF]
28646 \ https://forth-standard.org/standard/core/toBODY
28647 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
28654 \ CODE 20uS \ n -- 8MHz version
28655 \ BEGIN \ 4 + 16 ~ loop
28656 \ MOV #39,rDOCON \ 39
28663 \ MOV #XDOCON,rDOCON \ 2
28668 CODE 20_US \ n -- n * 20 us
28669 BEGIN \ here we presume that LCD_TIM_IFG = 1...
28671 BIT #1,&LCD_TIM_CTL \ 3
28672 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
28673 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
28675 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
28680 CODE TOP_LCD \ LCD Sample
28681 \ \ if write : %xxxx_WWWW --
28682 \ \ if read : -- %0000_RRRR
28683 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
28684 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
28685 0= IF \ write LCD bits pattern
28686 AND.B #LCD_DB,TOS \
28687 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
28688 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28691 THEN \ read LCD bits pattern
28694 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
28695 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
28696 AND.B #LCD_DB,TOS \
28700 CODE LCD_WRC \ char -- Write Char
28701 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28703 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
28704 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
28705 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
28706 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
28707 COLON \ high level word starts here
28708 TOP_LCD 2 20_US \ write high nibble first
28712 CODE LCD_WRF \ func -- Write Fonction
28713 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28717 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
28718 : LCD_HOME $02 LCD_WRF 100 20_us ;
28720 \ [UNDEFINED] OR [IF]
28722 \ \ https://forth-standard.org/standard/core/OR
28723 \ \ C OR x1 x2 -- x3 logical OR
28731 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
28732 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
28733 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
28734 \ : LCD_FN_SET $20 OR LCD_WrF ;
28735 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
28736 \ : LCD_GOTO $80 OR LCD_WrF ;
28739 \ CODE LCD_RDS \ -- status Read Status
28740 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
28741 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
28742 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
28743 \ COLON \ starts a FORTH word
28744 \ TOP_LCD 2 20_us \ -- %0000_HHHH
28745 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
28746 \ HI2LO \ switch from FORTH to assembler
28747 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
28748 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
28749 \ MOV @RSP+,IP \ restore IP saved by COLON
28753 \ CODE LCD_RDC \ -- char Read Char
28754 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
28759 \ ******************************\
28760 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
28761 \ ******************************\
28762 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
28763 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
28764 BIT.B #SW2,&SW2_IN \ test switch S2
28765 0= IF \ case of switch S2 pressed
28766 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
28768 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
28771 BIT.B #SW1,&SW1_IN \ test switch S1 input
28772 0= IF \ case of Switch S1 pressed
28773 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
28775 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
28779 BW1 \ from quit on truncated RC5 message, repeated RC5 command
28783 \ ******************************\
28784 ASM RC5_INT \ wake up on Px.RC5 change interrupt
28785 \ ******************************\
28786 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
28787 \ ******************************\
28788 \ \ in : SR(9)=old Toggle bit memory (ADD on)
28789 \ \ SMclock = 8|16|24 MHz
28790 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
28791 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
28792 \ \ SR(9)=new Toggle bit memory (ADD on)
28793 \ ******************************\
28794 \ RC5_FirstStartBitHalfCycle: \
28795 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
28796 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
28797 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
28798 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
28800 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
28801 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
28803 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
28804 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
28806 MOV #1778,X \ RC5_Period * 1us
28807 MOV #14,W \ count of loop
28809 \ ******************************\
28810 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
28811 \ ******************************\ |
28812 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
28813 \ RC5_Compute_3/4_Period: \ |
28814 RRUM #1,X \ X=1/2 cycle |
28817 ADD X,Y \ Y=3/4 cycle
28818 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
28820 \ ******************************\
28821 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
28822 \ ******************************\
28823 BIT.B #RC5,&IR_IN \ C_flag = IR bit
28824 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
28825 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
28826 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
28827 SUB #1,W \ decrement count loop
28828 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
28829 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
28830 0<> WHILE \ ----> out of loop ----+
28831 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
28833 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
28834 CMP Y,X \ 1 | cycle time out of bound ?
28835 U>= IF \ 2 ^ | yes:
28836 BIC #$30,&RC5_TIM_CTL \ | | stop timer
28837 GOTO BW1 \ | | quit on truncated RC5 message
28839 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
28841 REPEAT \ ----> loop back --+ | with X = new RC5_period value
28842 \ ******************************\ |
28843 \ RC5_SampleEndOf: \ <---------------------+
28844 \ ******************************\
28845 BIC #$30,&RC5_TIM_CTL \ stop timer
28846 \ ******************************\
28847 \ RC5_ComputeNewRC5word \
28848 \ ******************************\
28849 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
28850 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
28851 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
28852 \ ******************************\
28853 \ RC5_ComputeC6bit \
28854 \ ******************************\
28855 BIT #BIT14,T \ test /C6 bit in T
28856 0= IF BIS #BIT6,X \ set C6 bit in X
28857 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
28858 \ ******************************\
28859 \ RC5_CommandByteIsDone \ -- BASE RC5_code
28860 \ ******************************\
28861 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
28862 \ ******************************\
28863 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
28864 XOR @RSP,T \ (new XOR old) Toggle bits
28865 BIT #UF10,T \ repeated RC5_command ?
28866 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
28867 XOR #UF10,0(RSP) \ 5 toggle bit memory
28868 \ ******************************\
28869 \ Display IR_RC5 code \
28870 \ ******************************\
28871 SUB #8,PSP \ TOS -- x x x x TOS
28872 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
28873 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
28874 MOV #$10,&BASEADR \ set hexadecimal base
28875 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
28876 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
28877 LO2HI \ switch from assembler to FORTH
28878 LCD_CLEAR \ set LCD cursor at home
28879 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
28880 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
28881 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
28882 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
28883 HI2LO \ -- switch from FORTH to assembler
28884 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
28885 MOV @PSP+,TOS \ -- TOS
28889 \ ******************************\
28891 \ ******************************\
28893 \ ... \ insert here your background task
28896 CALL &RXON \ comment this line to disable TERMINAL_INPUT
28898 \ ******************************\
28899 \ here start all interrupts \
28900 \ ******************************\
28901 \ here return all interrupts \
28902 \ ******************************\
28905 \ ******************************\
28907 \ ------------------------------\
28908 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
28909 \ ------------------------------\
28910 \ ... \ init specific I/O sys as you want
28911 \ ... \ before executing default WARM
28912 MOV #WARM,X \ ['] WARM
28914 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
28916 \ ------------------------------\
28918 \ ------------------------------\
28919 CODE STOP \ stops multitasking, must to be used before downloading app
28920 \ ------------------------------\
28921 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
28922 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
28923 MOV X,-2(X) \ restore the default background: SLEEP
28925 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
28926 BIC.B #RC5,&IR_IE \ clear RC5_Int
28927 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
28928 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
28929 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
28930 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
28931 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
28932 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
28934 ." RC5toLCD is removed,"
28935 ." type START to restart"
28936 WARM \ performs reset to reset all interrupt vectors.
28938 \ ------------------------------\
28940 \ ------------------------------\
28941 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
28942 \ ------------------------------\
28943 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
28944 \ - - \CNTL Counter lentgh \ 00 = 16 bits
28945 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
28946 \ -- \ID input divider \ 10 = /4
28947 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
28948 \ - \TBCLR TimerB Clear
28951 \ -------------------------------\
28952 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
28953 \ -- \CM Capture Mode
28958 \ --- \OUTMOD \ 011 = set/reset
28964 \ -------------------------------\
28966 \ -------------------------------\
28968 \ ------------------------------\
28969 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
28970 \ ------------------------------\
28971 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
28972 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
28973 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
28974 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
28976 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
28977 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
28979 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
28980 \ ------------------------------\
28981 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
28982 \ ------------------------------\
28983 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
28984 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
28985 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
28986 \ ------------------------------\
28987 BIS.B #LCDVo,&LCDVo_DIR \
28988 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
28989 \ ------------------------------\
28990 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
28991 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
28992 \ ------------------------------\
28993 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
28994 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
28995 \ ******************************\
28997 \ ******************************\
28998 BIS.B #RC5,&IR_IE \ enable RC5_Int
28999 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29000 MOV #RC5_INT,&IR_Vec \ init interrupt vector
29001 \ ******************************\
29002 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
29003 \ ******************************\
29004 \ %01 0001 0100 \ TAxCTL
29005 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
29006 \ -- \ ID divided by 1
29007 \ -- \ MC MODE = up to TAxCCRn
29008 \ - \ TACLR clear timer count
29011 \ ------------------------------\
29012 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
29013 \ ------------------------------\
29015 \ --- \ TAIDEX pre divisor
29016 \ ------------------------------\
29017 \ %0000 0000 0000 0101 \ TAxCCR0
29018 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
29019 \ ------------------------------\
29020 \ %0000 0000 0001 0000 \ TAxCCTL0
29021 \ - \ CAP capture/compare mode = compare
29024 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
29025 \ ------------------------------\
29026 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
29027 \ ------------------------------\
29028 \ define LPM mode for ACCEPT \
29029 \ ------------------------------\
29030 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29031 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29032 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29033 \ ------------------------------\
29035 \ ------------------------------\
29036 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
29037 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
29038 \ ------------------------------\
29039 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
29040 \ ------------------------------\
29041 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
29042 \ CMP #2,Y \ Power_ON event
29043 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
29045 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
29047 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
29049 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
29051 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
29052 \ ------------------------------\
29054 \ ------------------------------\
29056 \ ------------------------------\
29057 #1000 20_US \ 1- wait 20 ms
29058 %011 TOP_LCD \ 2- send DB5=DB4=1
29059 #205 20_US \ 3- wait 4,1 ms
29060 %011 TOP_LCD \ 4- send again DB5=DB4=1
29061 #5 20_US \ 5- wait 0,1 ms
29062 %011 TOP_LCD \ 6- send again again DB5=DB4=1
29063 #2 20_US \ wait 40 us = LCD cycle
29064 %010 TOP_LCD \ 7- send DB5=1 DB4=0
29065 #2 20_US \ wait 40 us = LCD cycle
29066 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29067 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29068 LCD_CLEAR \ 10- "LCD_Clear"
29069 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29070 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29071 LCD_CLEAR \ 10- "LCD_Clear"
29072 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29073 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29074 CR ." I love you" \ display message on LCD
29075 ['] CR >BODY IS CR \ CR executes its default value
29076 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
29077 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
29078 PWR_STATE ABORT \ init DP and continues with ABORT
29080 \ ------------------------------\
29082 \ ------------------------------\
29083 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
29084 \ ------------------------------\
29085 MOV #SLEEP,X \ replace default background process SLEEP
29086 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
29087 MOV #WARM,X \ replace default WARM
29088 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
29089 MOV X,PC \ then execute new WARM
29091 \ ------------------------------\
29094 ; downloading RC5toLCD.4th is done
29095 RST_HERE ; this app is protected against <reset>
29100 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
29102 [UNDEFINED] MARKER [IF]
29103 \ https://forth-standard.org/standard/core/MARKER
29105 \ ( "<spaces>name" -- )
29106 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
29107 \ with the execution semantics defined below.
29109 \ name Execution: ( -- )
29110 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
29111 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
29112 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
29113 \ not necessarily provided. No other contextual information such as numeric base is affected
29118 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
29119 SUB #2,Y \ 1 Y = LFA
29120 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
29121 ADD #4,&DP \ 3 add 2 cells
29125 MOV @RSP+,IP \ -- PFA
29126 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
29127 MOV @TOS,&INIDP \ set DP value for RST_STATE
29129 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
29136 \ https://forth-standard.org/standard/core/Fetch
29137 \ @ c-addr -- char fetch char from memory
29144 [UNDEFINED] CONSTANT [IF]
29145 \ https://forth-standard.org/standard/core/CONSTANT
29146 \ CONSTANT <name> n -- define a Forth CONSTANT
29150 MOV TOS,-2(W) \ PFA = n
29157 [UNDEFINED] STATE [IF]
29158 \ https://forth-standard.org/standard/core/STATE
29159 \ STATE -- a-addr holds compiler state
29160 STATEADR CONSTANT STATE
29164 \ https://forth-standard.org/standard/core/Equal
29165 \ = x1 x2 -- flag test x1=x2
29172 XOR #-1,TOS \ 1 flag Z = 1
29177 [UNDEFINED] IF [IF]
29178 \ https://forth-standard.org/standard/core/IF
29179 \ IF -- IFadr initialize conditional forward branch
29180 CODE IF \ immediate
29183 MOV &DP,TOS \ -- HERE
29184 ADD #4,&DP \ compile one word, reserve one word
29185 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
29186 ADD #2,TOS \ -- HERE+2=IFadr
29191 [UNDEFINED] THEN [IF]
29192 \ https://forth-standard.org/standard/core/THEN
29193 \ THEN IFadr -- resolve forward branch
29194 CODE THEN \ immediate
29195 MOV &DP,0(TOS) \ -- IFadr
29201 [UNDEFINED] ELSE [IF]
29202 \ https://forth-standard.org/standard/core/ELSE
29203 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
29204 CODE ELSE \ immediate
29205 ADD #4,&DP \ make room to compile two words
29206 MOV &DP,W \ W=HERE+4
29208 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
29210 MOV W,TOS \ -- ELSEadr
29215 [UNDEFINED] DEFER [IF]
29216 \ https://forth-standard.org/standard/core/DEFER
29217 \ DEFER "<spaces>name" --
29218 \ Skip leading space delimiters. Parse name delimited by a space.
29219 \ Create a definition for name with the execution semantics defined below.
29221 \ name Execution: --
29222 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
29223 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
29227 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
29228 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
29234 [UNDEFINED] DEFER! [IF]
29235 \ https://forth-standard.org/standard/core/DEFERStore
29236 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
29237 CODE DEFER! \ xt2 xt1 --
29238 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
29244 [UNDEFINED] IS [IF]
29245 \ https://forth-standard.org/standard/core/IS
29248 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
29249 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
29250 \ or in a definition : ... ['] U. IS DISPLAY ...
29251 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
29253 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
29256 IF POSTPONE ['] POSTPONE DEFER!
29262 [UNDEFINED] >BODY [IF]
29263 \ https://forth-standard.org/standard/core/toBODY
29264 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
29271 \ CODE 20uS \ n -- 8MHz version
29272 \ BEGIN \ 4 + 16 ~ loop
29273 \ MOV #39,rDOCON \ 39
29280 \ MOV #XDOCON,rDOCON \ 2
29285 CODE 20_US \ n -- n * 20 us
29286 BEGIN \ here we presume that LCD_TIM_IFG = 1...
29288 BIT #1,&LCD_TIM_CTL \ 3
29289 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
29290 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
29292 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
29297 CODE TOP_LCD \ LCD Sample
29298 \ \ if write : %xxxx_WWWW --
29299 \ \ if read : -- %0000_RRRR
29300 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29301 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29302 0= IF \ write LCD bits pattern
29303 AND.B #LCD_DB,TOS \
29304 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29305 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29308 THEN \ read LCD bits pattern
29311 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29312 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29313 AND.B #LCD_DB,TOS \
29317 CODE LCD_WRC \ char -- Write Char
29318 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29320 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
29321 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
29322 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29323 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29324 COLON \ high level word starts here
29325 TOP_LCD 2 20_US \ write high nibble first
29329 CODE LCD_WRF \ func -- Write Fonction
29330 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29334 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
29335 : LCD_HOME $02 LCD_WRF 100 20_us ;
29337 \ [UNDEFINED] OR [IF]
29339 \ \ https://forth-standard.org/standard/core/OR
29340 \ \ C OR x1 x2 -- x3 logical OR
29348 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
29349 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
29350 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
29351 \ : LCD_FN_SET $20 OR LCD_WrF ;
29352 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
29353 \ : LCD_GOTO $80 OR LCD_WrF ;
29356 \ CODE LCD_RDS \ -- status Read Status
29357 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29358 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29359 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29360 \ COLON \ starts a FORTH word
29361 \ TOP_LCD 2 20_us \ -- %0000_HHHH
29362 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
29363 \ HI2LO \ switch from FORTH to assembler
29364 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
29365 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
29366 \ MOV @RSP+,IP \ restore IP saved by COLON
29370 \ CODE LCD_RDC \ -- char Read Char
29371 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29376 \ ******************************\
29377 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29378 \ ******************************\
29379 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29380 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
29381 BIT.B #SW2,&SW2_IN \ test switch S2
29382 0= IF \ case of switch S2 pressed
29383 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
29385 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
29388 BIT.B #SW1,&SW1_IN \ test switch S1 input
29389 0= IF \ case of Switch S1 pressed
29390 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
29392 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
29396 BW1 \ from quit on truncated RC5 message, repeated RC5 command
29400 \ ******************************\
29401 ASM RC5_INT \ wake up on Px.RC5 change interrupt
29402 \ ******************************\
29403 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
29404 \ ******************************\
29405 \ \ in : SR(9)=old Toggle bit memory (ADD on)
29406 \ \ SMclock = 8|16|24 MHz
29407 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
29408 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
29409 \ \ SR(9)=new Toggle bit memory (ADD on)
29410 \ ******************************\
29411 \ RC5_FirstStartBitHalfCycle: \
29412 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
29413 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29414 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
29415 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
29417 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
29418 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
29420 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
29421 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
29423 MOV #1778,X \ RC5_Period * 1us
29424 MOV #14,W \ count of loop
29426 \ ******************************\
29427 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
29428 \ ******************************\ |
29429 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
29430 \ RC5_Compute_3/4_Period: \ |
29431 RRUM #1,X \ X=1/2 cycle |
29434 ADD X,Y \ Y=3/4 cycle
29435 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
29437 \ ******************************\
29438 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
29439 \ ******************************\
29440 BIT.B #RC5,&IR_IN \ C_flag = IR bit
29441 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
29442 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
29443 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
29444 SUB #1,W \ decrement count loop
29445 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
29446 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
29447 0<> WHILE \ ----> out of loop ----+
29448 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
29450 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
29451 CMP Y,X \ 1 | cycle time out of bound ?
29452 U>= IF \ 2 ^ | yes:
29453 BIC #$30,&RC5_TIM_CTL \ | | stop timer
29454 GOTO BW1 \ | | quit on truncated RC5 message
29456 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
29458 REPEAT \ ----> loop back --+ | with X = new RC5_period value
29459 \ ******************************\ |
29460 \ RC5_SampleEndOf: \ <---------------------+
29461 \ ******************************\
29462 BIC #$30,&RC5_TIM_CTL \ stop timer
29463 \ ******************************\
29464 \ RC5_ComputeNewRC5word \
29465 \ ******************************\
29466 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
29467 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
29468 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
29469 \ ******************************\
29470 \ RC5_ComputeC6bit \
29471 \ ******************************\
29472 BIT #BIT14,T \ test /C6 bit in T
29473 0= IF BIS #BIT6,X \ set C6 bit in X
29474 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
29475 \ ******************************\
29476 \ RC5_CommandByteIsDone \ -- BASE RC5_code
29477 \ ******************************\
29478 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
29479 \ ******************************\
29480 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
29481 XOR @RSP,T \ (new XOR old) Toggle bits
29482 BIT #UF10,T \ repeated RC5_command ?
29483 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
29484 XOR #UF10,0(RSP) \ 5 toggle bit memory
29485 \ ******************************\
29486 \ Display IR_RC5 code \
29487 \ ******************************\
29488 SUB #8,PSP \ TOS -- x x x x TOS
29489 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
29490 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
29491 MOV #$10,&BASEADR \ set hexadecimal base
29492 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
29493 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
29494 LO2HI \ switch from assembler to FORTH
29495 LCD_CLEAR \ set LCD cursor at home
29496 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
29497 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
29498 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
29499 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
29500 HI2LO \ -- switch from FORTH to assembler
29501 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
29502 MOV @PSP+,TOS \ -- TOS
29506 \ ******************************\
29508 \ ******************************\
29510 \ ... \ insert here your background task
29513 CALL &RXON \ comment this line to disable TERMINAL_INPUT
29515 \ ******************************\
29516 \ here start all interrupts \
29517 \ ******************************\
29518 \ here return all interrupts \
29519 \ ******************************\
29522 \ ******************************\
29524 \ ------------------------------\
29525 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
29526 \ ------------------------------\
29527 \ ... \ init specific I/O sys as you want
29528 \ ... \ before executing default WARM
29529 MOV #WARM,X \ ['] WARM
29531 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
29533 \ ------------------------------\
29535 \ ------------------------------\
29536 CODE STOP \ stops multitasking, must to be used before downloading app
29537 \ ------------------------------\
29538 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
29539 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
29540 MOV X,-2(X) \ restore the default background: SLEEP
29542 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
29543 BIC.B #RC5,&IR_IE \ clear RC5_Int
29544 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
29545 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
29546 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
29547 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
29548 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
29549 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
29551 ." RC5toLCD is removed,"
29552 ." type START to restart"
29553 WARM \ performs reset to reset all interrupt vectors.
29555 \ ------------------------------\
29557 \ ------------------------------\
29558 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
29559 \ ------------------------------\
29560 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
29561 \ - - \CNTL Counter lentgh \ 00 = 16 bits
29562 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
29563 \ -- \ID input divider \ 10 = /4
29564 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
29565 \ - \TBCLR TimerB Clear
29568 \ -------------------------------\
29569 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
29570 \ -- \CM Capture Mode
29575 \ --- \OUTMOD \ 011 = set/reset
29581 \ -------------------------------\
29583 \ -------------------------------\
29585 \ ------------------------------\
29586 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
29587 \ ------------------------------\
29588 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
29589 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
29590 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
29591 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
29593 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
29594 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
29596 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
29597 \ ------------------------------\
29598 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
29599 \ ------------------------------\
29600 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
29601 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
29602 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
29603 \ ------------------------------\
29604 BIS.B #LCDVo,&LCDVo_DIR \
29605 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
29606 \ ------------------------------\
29607 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
29608 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
29609 \ ------------------------------\
29610 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
29611 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
29612 \ ******************************\
29614 \ ******************************\
29615 BIS.B #RC5,&IR_IE \ enable RC5_Int
29616 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
29617 MOV #RC5_INT,&IR_Vec \ init interrupt vector
29618 \ ******************************\
29619 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
29620 \ ******************************\
29621 \ %01 0001 0100 \ TAxCTL
29622 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
29623 \ -- \ ID divided by 1
29624 \ -- \ MC MODE = up to TAxCCRn
29625 \ - \ TACLR clear timer count
29628 \ ------------------------------\
29629 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
29630 \ ------------------------------\
29632 \ --- \ TAIDEX pre divisor
29633 \ ------------------------------\
29634 \ %0000 0000 0000 0101 \ TAxCCR0
29635 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
29636 \ ------------------------------\
29637 \ %0000 0000 0001 0000 \ TAxCCTL0
29638 \ - \ CAP capture/compare mode = compare
29641 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
29642 \ ------------------------------\
29643 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
29644 \ ------------------------------\
29645 \ define LPM mode for ACCEPT \
29646 \ ------------------------------\
29647 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
29648 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
29649 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
29650 \ ------------------------------\
29652 \ ------------------------------\
29653 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
29654 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
29655 \ ------------------------------\
29656 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
29657 \ ------------------------------\
29658 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
29659 \ CMP #2,Y \ Power_ON event
29660 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
29662 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
29664 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
29666 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
29668 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
29669 \ ------------------------------\
29671 \ ------------------------------\
29673 \ ------------------------------\
29674 #1000 20_US \ 1- wait 20 ms
29675 %011 TOP_LCD \ 2- send DB5=DB4=1
29676 #205 20_US \ 3- wait 4,1 ms
29677 %011 TOP_LCD \ 4- send again DB5=DB4=1
29678 #5 20_US \ 5- wait 0,1 ms
29679 %011 TOP_LCD \ 6- send again again DB5=DB4=1
29680 #2 20_US \ wait 40 us = LCD cycle
29681 %010 TOP_LCD \ 7- send DB5=1 DB4=0
29682 #2 20_US \ wait 40 us = LCD cycle
29683 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
29684 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
29685 LCD_CLEAR \ 10- "LCD_Clear"
29686 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
29687 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
29688 LCD_CLEAR \ 10- "LCD_Clear"
29689 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
29690 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
29691 CR ." I love you" \ display message on LCD
29692 ['] CR >BODY IS CR \ CR executes its default value
29693 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
29694 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
29695 PWR_STATE ABORT \ init DP and continues with ABORT
29697 \ ------------------------------\
29699 \ ------------------------------\
29700 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
29701 \ ------------------------------\
29702 MOV #SLEEP,X \ replace default background process SLEEP
29703 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
29704 MOV #WARM,X \ replace default WARM
29705 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
29706 MOV X,PC \ then execute new WARM
29708 \ ------------------------------\
29711 ; downloading RC5toLCD.4th is done
29712 RST_HERE ; this app is protected against <reset>
29717 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
29719 [UNDEFINED] MARKER [IF]
29720 \ https://forth-standard.org/standard/core/MARKER
29722 \ ( "<spaces>name" -- )
29723 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
29724 \ with the execution semantics defined below.
29726 \ name Execution: ( -- )
29727 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
29728 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
29729 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
29730 \ not necessarily provided. No other contextual information such as numeric base is affected
29735 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
29736 SUB #2,Y \ 1 Y = LFA
29737 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
29738 ADD #4,&DP \ 3 add 2 cells
29742 MOV @RSP+,IP \ -- PFA
29743 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
29744 MOV @TOS,&INIDP \ set DP value for RST_STATE
29746 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
29753 \ https://forth-standard.org/standard/core/Fetch
29754 \ @ c-addr -- char fetch char from memory
29761 [UNDEFINED] CONSTANT [IF]
29762 \ https://forth-standard.org/standard/core/CONSTANT
29763 \ CONSTANT <name> n -- define a Forth CONSTANT
29767 MOV TOS,-2(W) \ PFA = n
29774 [UNDEFINED] STATE [IF]
29775 \ https://forth-standard.org/standard/core/STATE
29776 \ STATE -- a-addr holds compiler state
29777 STATEADR CONSTANT STATE
29781 \ https://forth-standard.org/standard/core/Equal
29782 \ = x1 x2 -- flag test x1=x2
29789 XOR #-1,TOS \ 1 flag Z = 1
29794 [UNDEFINED] IF [IF]
29795 \ https://forth-standard.org/standard/core/IF
29796 \ IF -- IFadr initialize conditional forward branch
29797 CODE IF \ immediate
29800 MOV &DP,TOS \ -- HERE
29801 ADD #4,&DP \ compile one word, reserve one word
29802 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
29803 ADD #2,TOS \ -- HERE+2=IFadr
29808 [UNDEFINED] THEN [IF]
29809 \ https://forth-standard.org/standard/core/THEN
29810 \ THEN IFadr -- resolve forward branch
29811 CODE THEN \ immediate
29812 MOV &DP,0(TOS) \ -- IFadr
29818 [UNDEFINED] ELSE [IF]
29819 \ https://forth-standard.org/standard/core/ELSE
29820 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
29821 CODE ELSE \ immediate
29822 ADD #4,&DP \ make room to compile two words
29823 MOV &DP,W \ W=HERE+4
29825 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
29827 MOV W,TOS \ -- ELSEadr
29832 [UNDEFINED] DEFER [IF]
29833 \ https://forth-standard.org/standard/core/DEFER
29834 \ DEFER "<spaces>name" --
29835 \ Skip leading space delimiters. Parse name delimited by a space.
29836 \ Create a definition for name with the execution semantics defined below.
29838 \ name Execution: --
29839 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
29840 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
29844 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
29845 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
29851 [UNDEFINED] DEFER! [IF]
29852 \ https://forth-standard.org/standard/core/DEFERStore
29853 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
29854 CODE DEFER! \ xt2 xt1 --
29855 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
29861 [UNDEFINED] IS [IF]
29862 \ https://forth-standard.org/standard/core/IS
29865 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
29866 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
29867 \ or in a definition : ... ['] U. IS DISPLAY ...
29868 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
29870 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
29873 IF POSTPONE ['] POSTPONE DEFER!
29879 [UNDEFINED] >BODY [IF]
29880 \ https://forth-standard.org/standard/core/toBODY
29881 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
29888 \ CODE 20uS \ n -- 8MHz version
29889 \ BEGIN \ 4 + 16 ~ loop
29890 \ MOV #39,rDOCON \ 39
29897 \ MOV #XDOCON,rDOCON \ 2
29902 CODE 20_US \ n -- n * 20 us
29903 BEGIN \ here we presume that LCD_TIM_IFG = 1...
29905 BIT #1,&LCD_TIM_CTL \ 3
29906 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
29907 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
29909 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
29914 CODE TOP_LCD \ LCD Sample
29915 \ \ if write : %xxxx_WWWW --
29916 \ \ if read : -- %0000_RRRR
29917 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
29918 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
29919 0= IF \ write LCD bits pattern
29920 AND.B #LCD_DB,TOS \
29921 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
29922 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29925 THEN \ read LCD bits pattern
29928 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
29929 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
29930 AND.B #LCD_DB,TOS \
29934 CODE LCD_WRC \ char -- Write Char
29935 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29937 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
29938 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
29939 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
29940 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
29941 COLON \ high level word starts here
29942 TOP_LCD 2 20_US \ write high nibble first
29946 CODE LCD_WRF \ func -- Write Fonction
29947 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29951 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
29952 : LCD_HOME $02 LCD_WRF 100 20_us ;
29954 \ [UNDEFINED] OR [IF]
29956 \ \ https://forth-standard.org/standard/core/OR
29957 \ \ C OR x1 x2 -- x3 logical OR
29965 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
29966 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
29967 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
29968 \ : LCD_FN_SET $20 OR LCD_WrF ;
29969 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
29970 \ : LCD_GOTO $80 OR LCD_WrF ;
29973 \ CODE LCD_RDS \ -- status Read Status
29974 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
29975 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
29976 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
29977 \ COLON \ starts a FORTH word
29978 \ TOP_LCD 2 20_us \ -- %0000_HHHH
29979 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
29980 \ HI2LO \ switch from FORTH to assembler
29981 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
29982 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
29983 \ MOV @RSP+,IP \ restore IP saved by COLON
29987 \ CODE LCD_RDC \ -- char Read Char
29988 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
29993 \ ******************************\
29994 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
29995 \ ******************************\
29996 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
29997 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
29998 BIT.B #SW2,&SW2_IN \ test switch S2
29999 0= IF \ case of switch S2 pressed
30000 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
30002 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
30005 BIT.B #SW1,&SW1_IN \ test switch S1 input
30006 0= IF \ case of Switch S1 pressed
30007 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
30009 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
30013 BW1 \ from quit on truncated RC5 message, repeated RC5 command
30017 \ ******************************\
30018 ASM RC5_INT \ wake up on Px.RC5 change interrupt
30019 \ ******************************\
30020 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30021 \ ******************************\
30022 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30023 \ \ SMclock = 8|16|24 MHz
30024 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
30025 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
30026 \ \ SR(9)=new Toggle bit memory (ADD on)
30027 \ ******************************\
30028 \ RC5_FirstStartBitHalfCycle: \
30029 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
30030 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
30031 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
30032 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
30034 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
30035 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
30037 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
30038 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
30040 MOV #1778,X \ RC5_Period * 1us
30041 MOV #14,W \ count of loop
30043 \ ******************************\
30044 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
30045 \ ******************************\ |
30046 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
30047 \ RC5_Compute_3/4_Period: \ |
30048 RRUM #1,X \ X=1/2 cycle |
30051 ADD X,Y \ Y=3/4 cycle
30052 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
30054 \ ******************************\
30055 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
30056 \ ******************************\
30057 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30058 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
30059 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30060 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30061 SUB #1,W \ decrement count loop
30062 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
30063 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30064 0<> WHILE \ ----> out of loop ----+
30065 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
30067 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
30068 CMP Y,X \ 1 | cycle time out of bound ?
30069 U>= IF \ 2 ^ | yes:
30070 BIC #$30,&RC5_TIM_CTL \ | | stop timer
30071 GOTO BW1 \ | | quit on truncated RC5 message
30073 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
30075 REPEAT \ ----> loop back --+ | with X = new RC5_period value
30076 \ ******************************\ |
30077 \ RC5_SampleEndOf: \ <---------------------+
30078 \ ******************************\
30079 BIC #$30,&RC5_TIM_CTL \ stop timer
30080 \ ******************************\
30081 \ RC5_ComputeNewRC5word \
30082 \ ******************************\
30083 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
30084 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
30085 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
30086 \ ******************************\
30087 \ RC5_ComputeC6bit \
30088 \ ******************************\
30089 BIT #BIT14,T \ test /C6 bit in T
30090 0= IF BIS #BIT6,X \ set C6 bit in X
30091 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
30092 \ ******************************\
30093 \ RC5_CommandByteIsDone \ -- BASE RC5_code
30094 \ ******************************\
30095 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30096 \ ******************************\
30097 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
30098 XOR @RSP,T \ (new XOR old) Toggle bits
30099 BIT #UF10,T \ repeated RC5_command ?
30100 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
30101 XOR #UF10,0(RSP) \ 5 toggle bit memory
30102 \ ******************************\
30103 \ Display IR_RC5 code \
30104 \ ******************************\
30105 SUB #8,PSP \ TOS -- x x x x TOS
30106 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
30107 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
30108 MOV #$10,&BASEADR \ set hexadecimal base
30109 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
30110 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
30111 LO2HI \ switch from assembler to FORTH
30112 LCD_CLEAR \ set LCD cursor at home
30113 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
30114 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
30115 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
30116 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
30117 HI2LO \ -- switch from FORTH to assembler
30118 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
30119 MOV @PSP+,TOS \ -- TOS
30123 \ ******************************\
30125 \ ******************************\
30127 \ ... \ insert here your background task
30130 CALL &RXON \ comment this line to disable TERMINAL_INPUT
30132 \ ******************************\
30133 \ here start all interrupts \
30134 \ ******************************\
30135 \ here return all interrupts \
30136 \ ******************************\
30139 \ ******************************\
30141 \ ------------------------------\
30142 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
30143 \ ------------------------------\
30144 \ ... \ init specific I/O sys as you want
30145 \ ... \ before executing default WARM
30146 MOV #WARM,X \ ['] WARM
30148 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
30150 \ ------------------------------\
30152 \ ------------------------------\
30153 CODE STOP \ stops multitasking, must to be used before downloading app
30154 \ ------------------------------\
30155 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
30156 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
30157 MOV X,-2(X) \ restore the default background: SLEEP
30159 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
30160 BIC.B #RC5,&IR_IE \ clear RC5_Int
30161 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
30162 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
30163 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
30164 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
30165 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
30166 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
30168 ." RC5toLCD is removed,"
30169 ." type START to restart"
30170 WARM \ performs reset to reset all interrupt vectors.
30172 \ ------------------------------\
30174 \ ------------------------------\
30175 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
30176 \ ------------------------------\
30177 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
30178 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30179 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30180 \ -- \ID input divider \ 10 = /4
30181 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30182 \ - \TBCLR TimerB Clear
30185 \ -------------------------------\
30186 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30187 \ -- \CM Capture Mode
30192 \ --- \OUTMOD \ 011 = set/reset
30198 \ -------------------------------\
30200 \ -------------------------------\
30202 \ ------------------------------\
30203 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30204 \ ------------------------------\
30205 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30206 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30207 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
30208 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30210 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
30211 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30213 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
30214 \ ------------------------------\
30215 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30216 \ ------------------------------\
30217 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
30218 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30219 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30220 \ ------------------------------\
30221 BIS.B #LCDVo,&LCDVo_DIR \
30222 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
30223 \ ------------------------------\
30224 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30225 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30226 \ ------------------------------\
30227 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30228 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30229 \ ******************************\
30231 \ ******************************\
30232 BIS.B #RC5,&IR_IE \ enable RC5_Int
30233 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30234 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30235 \ ******************************\
30236 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30237 \ ******************************\
30238 \ %01 0001 0100 \ TAxCTL
30239 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
30240 \ -- \ ID divided by 1
30241 \ -- \ MC MODE = up to TAxCCRn
30242 \ - \ TACLR clear timer count
30245 \ ------------------------------\
30246 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
30247 \ ------------------------------\
30249 \ --- \ TAIDEX pre divisor
30250 \ ------------------------------\
30251 \ %0000 0000 0000 0101 \ TAxCCR0
30252 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30253 \ ------------------------------\
30254 \ %0000 0000 0001 0000 \ TAxCCTL0
30255 \ - \ CAP capture/compare mode = compare
30258 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
30259 \ ------------------------------\
30260 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30261 \ ------------------------------\
30262 \ define LPM mode for ACCEPT \
30263 \ ------------------------------\
30264 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30265 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30266 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30267 \ ------------------------------\
30269 \ ------------------------------\
30270 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
30271 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
30272 \ ------------------------------\
30273 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
30274 \ ------------------------------\
30275 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
30276 \ CMP #2,Y \ Power_ON event
30277 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
30279 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
30281 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
30283 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
30285 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
30286 \ ------------------------------\
30288 \ ------------------------------\
30290 \ ------------------------------\
30291 #1000 20_US \ 1- wait 20 ms
30292 %011 TOP_LCD \ 2- send DB5=DB4=1
30293 #205 20_US \ 3- wait 4,1 ms
30294 %011 TOP_LCD \ 4- send again DB5=DB4=1
30295 #5 20_US \ 5- wait 0,1 ms
30296 %011 TOP_LCD \ 6- send again again DB5=DB4=1
30297 #2 20_US \ wait 40 us = LCD cycle
30298 %010 TOP_LCD \ 7- send DB5=1 DB4=0
30299 #2 20_US \ wait 40 us = LCD cycle
30300 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30301 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30302 LCD_CLEAR \ 10- "LCD_Clear"
30303 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30304 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30305 LCD_CLEAR \ 10- "LCD_Clear"
30306 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30307 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30308 CR ." I love you" \ display message on LCD
30309 ['] CR >BODY IS CR \ CR executes its default value
30310 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
30311 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
30312 PWR_STATE ABORT \ init DP and continues with ABORT
30314 \ ------------------------------\
30316 \ ------------------------------\
30317 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
30318 \ ------------------------------\
30319 MOV #SLEEP,X \ replace default background process SLEEP
30320 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
30321 MOV #WARM,X \ replace default WARM
30322 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
30323 MOV X,PC \ then execute new WARM
30325 \ ------------------------------\
30328 ; downloading RC5toLCD.4th is done
30329 RST_HERE ; this app is protected against <reset>
30334 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
30336 [UNDEFINED] MARKER [IF]
30337 \ https://forth-standard.org/standard/core/MARKER
30339 \ ( "<spaces>name" -- )
30340 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
30341 \ with the execution semantics defined below.
30343 \ name Execution: ( -- )
30344 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
30345 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
30346 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
30347 \ not necessarily provided. No other contextual information such as numeric base is affected
30352 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
30353 SUB #2,Y \ 1 Y = LFA
30354 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
30355 ADD #4,&DP \ 3 add 2 cells
30359 MOV @RSP+,IP \ -- PFA
30360 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
30361 MOV @TOS,&INIDP \ set DP value for RST_STATE
30363 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
30370 \ https://forth-standard.org/standard/core/Fetch
30371 \ @ c-addr -- char fetch char from memory
30378 [UNDEFINED] CONSTANT [IF]
30379 \ https://forth-standard.org/standard/core/CONSTANT
30380 \ CONSTANT <name> n -- define a Forth CONSTANT
30384 MOV TOS,-2(W) \ PFA = n
30391 [UNDEFINED] STATE [IF]
30392 \ https://forth-standard.org/standard/core/STATE
30393 \ STATE -- a-addr holds compiler state
30394 STATEADR CONSTANT STATE
30398 \ https://forth-standard.org/standard/core/Equal
30399 \ = x1 x2 -- flag test x1=x2
30406 XOR #-1,TOS \ 1 flag Z = 1
30411 [UNDEFINED] IF [IF]
30412 \ https://forth-standard.org/standard/core/IF
30413 \ IF -- IFadr initialize conditional forward branch
30414 CODE IF \ immediate
30417 MOV &DP,TOS \ -- HERE
30418 ADD #4,&DP \ compile one word, reserve one word
30419 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
30420 ADD #2,TOS \ -- HERE+2=IFadr
30425 [UNDEFINED] THEN [IF]
30426 \ https://forth-standard.org/standard/core/THEN
30427 \ THEN IFadr -- resolve forward branch
30428 CODE THEN \ immediate
30429 MOV &DP,0(TOS) \ -- IFadr
30435 [UNDEFINED] ELSE [IF]
30436 \ https://forth-standard.org/standard/core/ELSE
30437 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
30438 CODE ELSE \ immediate
30439 ADD #4,&DP \ make room to compile two words
30440 MOV &DP,W \ W=HERE+4
30442 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
30444 MOV W,TOS \ -- ELSEadr
30449 [UNDEFINED] DEFER [IF]
30450 \ https://forth-standard.org/standard/core/DEFER
30451 \ DEFER "<spaces>name" --
30452 \ Skip leading space delimiters. Parse name delimited by a space.
30453 \ Create a definition for name with the execution semantics defined below.
30455 \ name Execution: --
30456 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
30457 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
30461 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
30462 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
30468 [UNDEFINED] DEFER! [IF]
30469 \ https://forth-standard.org/standard/core/DEFERStore
30470 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
30471 CODE DEFER! \ xt2 xt1 --
30472 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
30478 [UNDEFINED] IS [IF]
30479 \ https://forth-standard.org/standard/core/IS
30482 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
30483 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
30484 \ or in a definition : ... ['] U. IS DISPLAY ...
30485 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
30487 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
30490 IF POSTPONE ['] POSTPONE DEFER!
30496 [UNDEFINED] >BODY [IF]
30497 \ https://forth-standard.org/standard/core/toBODY
30498 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
30505 \ CODE 20uS \ n -- 8MHz version
30506 \ BEGIN \ 4 + 16 ~ loop
30507 \ MOV #39,rDOCON \ 39
30514 \ MOV #XDOCON,rDOCON \ 2
30519 CODE 20_US \ n -- n * 20 us
30520 BEGIN \ here we presume that LCD_TIM_IFG = 1...
30522 BIT #1,&LCD_TIM_CTL \ 3
30523 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
30524 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
30526 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
30531 CODE TOP_LCD \ LCD Sample
30532 \ \ if write : %xxxx_WWWW --
30533 \ \ if read : -- %0000_RRRR
30534 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
30535 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
30536 0= IF \ write LCD bits pattern
30537 AND.B #LCD_DB,TOS \
30538 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
30539 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30542 THEN \ read LCD bits pattern
30545 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
30546 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
30547 AND.B #LCD_DB,TOS \
30551 CODE LCD_WRC \ char -- Write Char
30552 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30554 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
30555 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
30556 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
30557 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
30558 COLON \ high level word starts here
30559 TOP_LCD 2 20_US \ write high nibble first
30563 CODE LCD_WRF \ func -- Write Fonction
30564 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30568 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
30569 : LCD_HOME $02 LCD_WRF 100 20_us ;
30571 \ [UNDEFINED] OR [IF]
30573 \ \ https://forth-standard.org/standard/core/OR
30574 \ \ C OR x1 x2 -- x3 logical OR
30582 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
30583 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
30584 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
30585 \ : LCD_FN_SET $20 OR LCD_WrF ;
30586 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
30587 \ : LCD_GOTO $80 OR LCD_WrF ;
30590 \ CODE LCD_RDS \ -- status Read Status
30591 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
30592 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
30593 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
30594 \ COLON \ starts a FORTH word
30595 \ TOP_LCD 2 20_us \ -- %0000_HHHH
30596 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
30597 \ HI2LO \ switch from FORTH to assembler
30598 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
30599 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
30600 \ MOV @RSP+,IP \ restore IP saved by COLON
30604 \ CODE LCD_RDC \ -- char Read Char
30605 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
30610 \ ******************************\
30611 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
30612 \ ******************************\
30613 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
30614 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
30615 BIT.B #SW2,&SW2_IN \ test switch S2
30616 0= IF \ case of switch S2 pressed
30617 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
30619 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
30622 BIT.B #SW1,&SW1_IN \ test switch S1 input
30623 0= IF \ case of Switch S1 pressed
30624 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
30626 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
30630 BW1 \ from quit on truncated RC5 message, repeated RC5 command
30634 \ ******************************\
30635 ASM RC5_INT \ wake up on Px.RC5 change interrupt
30636 \ ******************************\
30637 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
30638 \ ******************************\
30639 \ \ in : SR(9)=old Toggle bit memory (ADD on)
30640 \ \ SMclock = 8|16|24 MHz
30641 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
30642 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
30643 \ \ SR(9)=new Toggle bit memory (ADD on)
30644 \ ******************************\
30645 \ RC5_FirstStartBitHalfCycle: \
30646 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
30647 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
30648 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
30649 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
30651 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
30652 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
30654 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
30655 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
30657 MOV #1778,X \ RC5_Period * 1us
30658 MOV #14,W \ count of loop
30660 \ ******************************\
30661 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
30662 \ ******************************\ |
30663 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
30664 \ RC5_Compute_3/4_Period: \ |
30665 RRUM #1,X \ X=1/2 cycle |
30668 ADD X,Y \ Y=3/4 cycle
30669 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
30671 \ ******************************\
30672 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
30673 \ ******************************\
30674 BIT.B #RC5,&IR_IN \ C_flag = IR bit
30675 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
30676 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
30677 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
30678 SUB #1,W \ decrement count loop
30679 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
30680 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
30681 0<> WHILE \ ----> out of loop ----+
30682 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
30684 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
30685 CMP Y,X \ 1 | cycle time out of bound ?
30686 U>= IF \ 2 ^ | yes:
30687 BIC #$30,&RC5_TIM_CTL \ | | stop timer
30688 GOTO BW1 \ | | quit on truncated RC5 message
30690 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
30692 REPEAT \ ----> loop back --+ | with X = new RC5_period value
30693 \ ******************************\ |
30694 \ RC5_SampleEndOf: \ <---------------------+
30695 \ ******************************\
30696 BIC #$30,&RC5_TIM_CTL \ stop timer
30697 \ ******************************\
30698 \ RC5_ComputeNewRC5word \
30699 \ ******************************\
30700 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
30701 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
30702 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
30703 \ ******************************\
30704 \ RC5_ComputeC6bit \
30705 \ ******************************\
30706 BIT #BIT14,T \ test /C6 bit in T
30707 0= IF BIS #BIT6,X \ set C6 bit in X
30708 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
30709 \ ******************************\
30710 \ RC5_CommandByteIsDone \ -- BASE RC5_code
30711 \ ******************************\
30712 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
30713 \ ******************************\
30714 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
30715 XOR @RSP,T \ (new XOR old) Toggle bits
30716 BIT #UF10,T \ repeated RC5_command ?
30717 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
30718 XOR #UF10,0(RSP) \ 5 toggle bit memory
30719 \ ******************************\
30720 \ Display IR_RC5 code \
30721 \ ******************************\
30722 SUB #8,PSP \ TOS -- x x x x TOS
30723 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
30724 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
30725 MOV #$10,&BASEADR \ set hexadecimal base
30726 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
30727 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
30728 LO2HI \ switch from assembler to FORTH
30729 LCD_CLEAR \ set LCD cursor at home
30730 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
30731 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
30732 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
30733 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
30734 HI2LO \ -- switch from FORTH to assembler
30735 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
30736 MOV @PSP+,TOS \ -- TOS
30740 \ ******************************\
30742 \ ******************************\
30744 \ ... \ insert here your background task
30747 CALL &RXON \ comment this line to disable TERMINAL_INPUT
30749 \ ******************************\
30750 \ here start all interrupts \
30751 \ ******************************\
30752 \ here return all interrupts \
30753 \ ******************************\
30756 \ ******************************\
30758 \ ------------------------------\
30759 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
30760 \ ------------------------------\
30761 \ ... \ init specific I/O sys as you want
30762 \ ... \ before executing default WARM
30763 MOV #WARM,X \ ['] WARM
30765 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
30767 \ ------------------------------\
30769 \ ------------------------------\
30770 CODE STOP \ stops multitasking, must to be used before downloading app
30771 \ ------------------------------\
30772 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
30773 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
30774 MOV X,-2(X) \ restore the default background: SLEEP
30776 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
30777 BIC.B #RC5,&IR_IE \ clear RC5_Int
30778 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
30779 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
30780 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
30781 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
30782 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
30783 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
30785 ." RC5toLCD is removed,"
30786 ." type START to restart"
30787 WARM \ performs reset to reset all interrupt vectors.
30789 \ ------------------------------\
30791 \ ------------------------------\
30792 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
30793 \ ------------------------------\
30794 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
30795 \ - - \CNTL Counter lentgh \ 00 = 16 bits
30796 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
30797 \ -- \ID input divider \ 10 = /4
30798 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
30799 \ - \TBCLR TimerB Clear
30802 \ -------------------------------\
30803 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
30804 \ -- \CM Capture Mode
30809 \ --- \OUTMOD \ 011 = set/reset
30815 \ -------------------------------\
30817 \ -------------------------------\
30819 \ ------------------------------\
30820 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
30821 \ ------------------------------\
30822 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
30823 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
30824 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
30825 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
30827 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
30828 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
30830 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
30831 \ ------------------------------\
30832 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
30833 \ ------------------------------\
30834 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
30835 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
30836 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
30837 \ ------------------------------\
30838 BIS.B #LCDVo,&LCDVo_DIR \
30839 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
30840 \ ------------------------------\
30841 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
30842 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
30843 \ ------------------------------\
30844 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
30845 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
30846 \ ******************************\
30848 \ ******************************\
30849 BIS.B #RC5,&IR_IE \ enable RC5_Int
30850 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
30851 MOV #RC5_INT,&IR_Vec \ init interrupt vector
30852 \ ******************************\
30853 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
30854 \ ******************************\
30855 \ %01 0001 0100 \ TAxCTL
30856 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
30857 \ -- \ ID divided by 1
30858 \ -- \ MC MODE = up to TAxCCRn
30859 \ - \ TACLR clear timer count
30862 \ ------------------------------\
30863 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
30864 \ ------------------------------\
30866 \ --- \ TAIDEX pre divisor
30867 \ ------------------------------\
30868 \ %0000 0000 0000 0101 \ TAxCCR0
30869 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
30870 \ ------------------------------\
30871 \ %0000 0000 0001 0000 \ TAxCCTL0
30872 \ - \ CAP capture/compare mode = compare
30875 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
30876 \ ------------------------------\
30877 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
30878 \ ------------------------------\
30879 \ define LPM mode for ACCEPT \
30880 \ ------------------------------\
30881 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
30882 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
30883 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
30884 \ ------------------------------\
30886 \ ------------------------------\
30887 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
30888 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
30889 \ ------------------------------\
30890 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
30891 \ ------------------------------\
30892 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
30893 \ CMP #2,Y \ Power_ON event
30894 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
30896 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
30898 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
30900 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
30902 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
30903 \ ------------------------------\
30905 \ ------------------------------\
30907 \ ------------------------------\
30908 #1000 20_US \ 1- wait 20 ms
30909 %011 TOP_LCD \ 2- send DB5=DB4=1
30910 #205 20_US \ 3- wait 4,1 ms
30911 %011 TOP_LCD \ 4- send again DB5=DB4=1
30912 #5 20_US \ 5- wait 0,1 ms
30913 %011 TOP_LCD \ 6- send again again DB5=DB4=1
30914 #2 20_US \ wait 40 us = LCD cycle
30915 %010 TOP_LCD \ 7- send DB5=1 DB4=0
30916 #2 20_US \ wait 40 us = LCD cycle
30917 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
30918 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
30919 LCD_CLEAR \ 10- "LCD_Clear"
30920 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
30921 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
30922 LCD_CLEAR \ 10- "LCD_Clear"
30923 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
30924 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
30925 CR ." I love you" \ display message on LCD
30926 ['] CR >BODY IS CR \ CR executes its default value
30927 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
30928 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
30929 PWR_STATE ABORT \ init DP and continues with ABORT
30931 \ ------------------------------\
30933 \ ------------------------------\
30934 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
30935 \ ------------------------------\
30936 MOV #SLEEP,X \ replace default background process SLEEP
30937 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
30938 MOV #WARM,X \ replace default WARM
30939 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
30940 MOV X,PC \ then execute new WARM
30942 \ ------------------------------\
30945 ; downloading RC5toLCD.4th is done
30946 RST_HERE ; this app is protected against <reset>
30951 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
30953 [UNDEFINED] MARKER [IF]
30954 \ https://forth-standard.org/standard/core/MARKER
30956 \ ( "<spaces>name" -- )
30957 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
30958 \ with the execution semantics defined below.
30960 \ name Execution: ( -- )
30961 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
30962 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
30963 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
30964 \ not necessarily provided. No other contextual information such as numeric base is affected
30969 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
30970 SUB #2,Y \ 1 Y = LFA
30971 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
30972 ADD #4,&DP \ 3 add 2 cells
30976 MOV @RSP+,IP \ -- PFA
30977 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
30978 MOV @TOS,&INIDP \ set DP value for RST_STATE
30980 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
30987 \ https://forth-standard.org/standard/core/Fetch
30988 \ @ c-addr -- char fetch char from memory
30995 [UNDEFINED] CONSTANT [IF]
30996 \ https://forth-standard.org/standard/core/CONSTANT
30997 \ CONSTANT <name> n -- define a Forth CONSTANT
31001 MOV TOS,-2(W) \ PFA = n
31008 [UNDEFINED] STATE [IF]
31009 \ https://forth-standard.org/standard/core/STATE
31010 \ STATE -- a-addr holds compiler state
31011 STATEADR CONSTANT STATE
31015 \ https://forth-standard.org/standard/core/Equal
31016 \ = x1 x2 -- flag test x1=x2
31023 XOR #-1,TOS \ 1 flag Z = 1
31028 [UNDEFINED] IF [IF]
31029 \ https://forth-standard.org/standard/core/IF
31030 \ IF -- IFadr initialize conditional forward branch
31031 CODE IF \ immediate
31034 MOV &DP,TOS \ -- HERE
31035 ADD #4,&DP \ compile one word, reserve one word
31036 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
31037 ADD #2,TOS \ -- HERE+2=IFadr
31042 [UNDEFINED] THEN [IF]
31043 \ https://forth-standard.org/standard/core/THEN
31044 \ THEN IFadr -- resolve forward branch
31045 CODE THEN \ immediate
31046 MOV &DP,0(TOS) \ -- IFadr
31052 [UNDEFINED] ELSE [IF]
31053 \ https://forth-standard.org/standard/core/ELSE
31054 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
31055 CODE ELSE \ immediate
31056 ADD #4,&DP \ make room to compile two words
31057 MOV &DP,W \ W=HERE+4
31059 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
31061 MOV W,TOS \ -- ELSEadr
31066 [UNDEFINED] DEFER [IF]
31067 \ https://forth-standard.org/standard/core/DEFER
31068 \ DEFER "<spaces>name" --
31069 \ Skip leading space delimiters. Parse name delimited by a space.
31070 \ Create a definition for name with the execution semantics defined below.
31072 \ name Execution: --
31073 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
31074 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
31078 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
31079 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
31085 [UNDEFINED] DEFER! [IF]
31086 \ https://forth-standard.org/standard/core/DEFERStore
31087 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
31088 CODE DEFER! \ xt2 xt1 --
31089 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
31095 [UNDEFINED] IS [IF]
31096 \ https://forth-standard.org/standard/core/IS
31099 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
31100 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
31101 \ or in a definition : ... ['] U. IS DISPLAY ...
31102 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
31104 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
31107 IF POSTPONE ['] POSTPONE DEFER!
31113 [UNDEFINED] >BODY [IF]
31114 \ https://forth-standard.org/standard/core/toBODY
31115 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
31122 \ CODE 20uS \ n -- 8MHz version
31123 \ BEGIN \ 4 + 16 ~ loop
31124 \ MOV #39,rDOCON \ 39
31131 \ MOV #XDOCON,rDOCON \ 2
31136 CODE 20_US \ n -- n * 20 us
31137 BEGIN \ here we presume that LCD_TIM_IFG = 1...
31139 BIT #1,&LCD_TIM_CTL \ 3
31140 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
31141 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
31143 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
31148 CODE TOP_LCD \ LCD Sample
31149 \ \ if write : %xxxx_WWWW --
31150 \ \ if read : -- %0000_RRRR
31151 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31152 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31153 0= IF \ write LCD bits pattern
31154 AND.B #LCD_DB,TOS \
31155 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31156 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31159 THEN \ read LCD bits pattern
31162 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31163 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31164 AND.B #LCD_DB,TOS \
31168 CODE LCD_WRC \ char -- Write Char
31169 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31171 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
31172 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
31173 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31174 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31175 COLON \ high level word starts here
31176 TOP_LCD 2 20_US \ write high nibble first
31180 CODE LCD_WRF \ func -- Write Fonction
31181 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31185 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
31186 : LCD_HOME $02 LCD_WRF 100 20_us ;
31188 \ [UNDEFINED] OR [IF]
31190 \ \ https://forth-standard.org/standard/core/OR
31191 \ \ C OR x1 x2 -- x3 logical OR
31199 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
31200 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
31201 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
31202 \ : LCD_FN_SET $20 OR LCD_WrF ;
31203 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
31204 \ : LCD_GOTO $80 OR LCD_WrF ;
31207 \ CODE LCD_RDS \ -- status Read Status
31208 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31209 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31210 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31211 \ COLON \ starts a FORTH word
31212 \ TOP_LCD 2 20_us \ -- %0000_HHHH
31213 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
31214 \ HI2LO \ switch from FORTH to assembler
31215 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
31216 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
31217 \ MOV @RSP+,IP \ restore IP saved by COLON
31221 \ CODE LCD_RDC \ -- char Read Char
31222 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31227 \ ******************************\
31228 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31229 \ ******************************\
31230 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
31231 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
31232 BIT.B #SW2,&SW2_IN \ test switch S2
31233 0= IF \ case of switch S2 pressed
31234 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
31236 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
31239 BIT.B #SW1,&SW1_IN \ test switch S1 input
31240 0= IF \ case of Switch S1 pressed
31241 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
31243 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
31247 BW1 \ from quit on truncated RC5 message, repeated RC5 command
31251 \ ******************************\
31252 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31253 \ ******************************\
31254 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31255 \ ******************************\
31256 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31257 \ \ SMclock = 8|16|24 MHz
31258 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
31259 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
31260 \ \ SR(9)=new Toggle bit memory (ADD on)
31261 \ ******************************\
31262 \ RC5_FirstStartBitHalfCycle: \
31263 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
31264 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
31265 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
31266 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
31268 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
31269 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
31271 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
31272 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
31274 MOV #1778,X \ RC5_Period * 1us
31275 MOV #14,W \ count of loop
31277 \ ******************************\
31278 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
31279 \ ******************************\ |
31280 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
31281 \ RC5_Compute_3/4_Period: \ |
31282 RRUM #1,X \ X=1/2 cycle |
31285 ADD X,Y \ Y=3/4 cycle
31286 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
31288 \ ******************************\
31289 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
31290 \ ******************************\
31291 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31292 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
31293 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31294 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31295 SUB #1,W \ decrement count loop
31296 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
31297 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31298 0<> WHILE \ ----> out of loop ----+
31299 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
31301 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
31302 CMP Y,X \ 1 | cycle time out of bound ?
31303 U>= IF \ 2 ^ | yes:
31304 BIC #$30,&RC5_TIM_CTL \ | | stop timer
31305 GOTO BW1 \ | | quit on truncated RC5 message
31307 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
31309 REPEAT \ ----> loop back --+ | with X = new RC5_period value
31310 \ ******************************\ |
31311 \ RC5_SampleEndOf: \ <---------------------+
31312 \ ******************************\
31313 BIC #$30,&RC5_TIM_CTL \ stop timer
31314 \ ******************************\
31315 \ RC5_ComputeNewRC5word \
31316 \ ******************************\
31317 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
31318 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
31319 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
31320 \ ******************************\
31321 \ RC5_ComputeC6bit \
31322 \ ******************************\
31323 BIT #BIT14,T \ test /C6 bit in T
31324 0= IF BIS #BIT6,X \ set C6 bit in X
31325 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
31326 \ ******************************\
31327 \ RC5_CommandByteIsDone \ -- BASE RC5_code
31328 \ ******************************\
31329 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
31330 \ ******************************\
31331 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
31332 XOR @RSP,T \ (new XOR old) Toggle bits
31333 BIT #UF10,T \ repeated RC5_command ?
31334 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
31335 XOR #UF10,0(RSP) \ 5 toggle bit memory
31336 \ ******************************\
31337 \ Display IR_RC5 code \
31338 \ ******************************\
31339 SUB #8,PSP \ TOS -- x x x x TOS
31340 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
31341 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
31342 MOV #$10,&BASEADR \ set hexadecimal base
31343 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
31344 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
31345 LO2HI \ switch from assembler to FORTH
31346 LCD_CLEAR \ set LCD cursor at home
31347 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
31348 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
31349 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
31350 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
31351 HI2LO \ -- switch from FORTH to assembler
31352 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
31353 MOV @PSP+,TOS \ -- TOS
31357 \ ******************************\
31359 \ ******************************\
31361 \ ... \ insert here your background task
31364 CALL &RXON \ comment this line to disable TERMINAL_INPUT
31366 \ ******************************\
31367 \ here start all interrupts \
31368 \ ******************************\
31369 \ here return all interrupts \
31370 \ ******************************\
31373 \ ******************************\
31375 \ ------------------------------\
31376 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
31377 \ ------------------------------\
31378 \ ... \ init specific I/O sys as you want
31379 \ ... \ before executing default WARM
31380 MOV #WARM,X \ ['] WARM
31382 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
31384 \ ------------------------------\
31386 \ ------------------------------\
31387 CODE STOP \ stops multitasking, must to be used before downloading app
31388 \ ------------------------------\
31389 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
31390 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
31391 MOV X,-2(X) \ restore the default background: SLEEP
31393 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
31394 BIC.B #RC5,&IR_IE \ clear RC5_Int
31395 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
31396 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
31397 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
31398 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
31399 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
31400 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
31402 ." RC5toLCD is removed,"
31403 ." type START to restart"
31404 WARM \ performs reset to reset all interrupt vectors.
31406 \ ------------------------------\
31408 \ ------------------------------\
31409 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
31410 \ ------------------------------\
31411 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
31412 \ - - \CNTL Counter lentgh \ 00 = 16 bits
31413 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
31414 \ -- \ID input divider \ 10 = /4
31415 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
31416 \ - \TBCLR TimerB Clear
31419 \ -------------------------------\
31420 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
31421 \ -- \CM Capture Mode
31426 \ --- \OUTMOD \ 011 = set/reset
31432 \ -------------------------------\
31434 \ -------------------------------\
31436 \ ------------------------------\
31437 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
31438 \ ------------------------------\
31439 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
31440 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
31441 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
31442 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
31444 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
31445 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
31447 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
31448 \ ------------------------------\
31449 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
31450 \ ------------------------------\
31451 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
31452 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
31453 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
31454 \ ------------------------------\
31455 BIS.B #LCDVo,&LCDVo_DIR \
31456 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
31457 \ ------------------------------\
31458 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
31459 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
31460 \ ------------------------------\
31461 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
31462 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
31463 \ ******************************\
31465 \ ******************************\
31466 BIS.B #RC5,&IR_IE \ enable RC5_Int
31467 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
31468 MOV #RC5_INT,&IR_Vec \ init interrupt vector
31469 \ ******************************\
31470 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
31471 \ ******************************\
31472 \ %01 0001 0100 \ TAxCTL
31473 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
31474 \ -- \ ID divided by 1
31475 \ -- \ MC MODE = up to TAxCCRn
31476 \ - \ TACLR clear timer count
31479 \ ------------------------------\
31480 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
31481 \ ------------------------------\
31483 \ --- \ TAIDEX pre divisor
31484 \ ------------------------------\
31485 \ %0000 0000 0000 0101 \ TAxCCR0
31486 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
31487 \ ------------------------------\
31488 \ %0000 0000 0001 0000 \ TAxCCTL0
31489 \ - \ CAP capture/compare mode = compare
31492 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
31493 \ ------------------------------\
31494 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
31495 \ ------------------------------\
31496 \ define LPM mode for ACCEPT \
31497 \ ------------------------------\
31498 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
31499 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
31500 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
31501 \ ------------------------------\
31503 \ ------------------------------\
31504 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
31505 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
31506 \ ------------------------------\
31507 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
31508 \ ------------------------------\
31509 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
31510 \ CMP #2,Y \ Power_ON event
31511 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
31513 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
31515 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
31517 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
31519 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
31520 \ ------------------------------\
31522 \ ------------------------------\
31524 \ ------------------------------\
31525 #1000 20_US \ 1- wait 20 ms
31526 %011 TOP_LCD \ 2- send DB5=DB4=1
31527 #205 20_US \ 3- wait 4,1 ms
31528 %011 TOP_LCD \ 4- send again DB5=DB4=1
31529 #5 20_US \ 5- wait 0,1 ms
31530 %011 TOP_LCD \ 6- send again again DB5=DB4=1
31531 #2 20_US \ wait 40 us = LCD cycle
31532 %010 TOP_LCD \ 7- send DB5=1 DB4=0
31533 #2 20_US \ wait 40 us = LCD cycle
31534 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
31535 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
31536 LCD_CLEAR \ 10- "LCD_Clear"
31537 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
31538 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
31539 LCD_CLEAR \ 10- "LCD_Clear"
31540 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
31541 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
31542 CR ." I love you" \ display message on LCD
31543 ['] CR >BODY IS CR \ CR executes its default value
31544 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
31545 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
31546 PWR_STATE ABORT \ init DP and continues with ABORT
31548 \ ------------------------------\
31550 \ ------------------------------\
31551 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
31552 \ ------------------------------\
31553 MOV #SLEEP,X \ replace default background process SLEEP
31554 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
31555 MOV #WARM,X \ replace default WARM
31556 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
31557 MOV X,PC \ then execute new WARM
31559 \ ------------------------------\
31562 ; downloading RC5toLCD.4th is done
31563 RST_HERE ; this app is protected against <reset>
31568 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
31570 [UNDEFINED] MARKER [IF]
31571 \ https://forth-standard.org/standard/core/MARKER
31573 \ ( "<spaces>name" -- )
31574 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
31575 \ with the execution semantics defined below.
31577 \ name Execution: ( -- )
31578 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
31579 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
31580 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
31581 \ not necessarily provided. No other contextual information such as numeric base is affected
31586 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
31587 SUB #2,Y \ 1 Y = LFA
31588 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
31589 ADD #4,&DP \ 3 add 2 cells
31593 MOV @RSP+,IP \ -- PFA
31594 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
31595 MOV @TOS,&INIDP \ set DP value for RST_STATE
31597 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
31604 \ https://forth-standard.org/standard/core/Fetch
31605 \ @ c-addr -- char fetch char from memory
31612 [UNDEFINED] CONSTANT [IF]
31613 \ https://forth-standard.org/standard/core/CONSTANT
31614 \ CONSTANT <name> n -- define a Forth CONSTANT
31618 MOV TOS,-2(W) \ PFA = n
31625 [UNDEFINED] STATE [IF]
31626 \ https://forth-standard.org/standard/core/STATE
31627 \ STATE -- a-addr holds compiler state
31628 STATEADR CONSTANT STATE
31632 \ https://forth-standard.org/standard/core/Equal
31633 \ = x1 x2 -- flag test x1=x2
31640 XOR #-1,TOS \ 1 flag Z = 1
31645 [UNDEFINED] IF [IF]
31646 \ https://forth-standard.org/standard/core/IF
31647 \ IF -- IFadr initialize conditional forward branch
31648 CODE IF \ immediate
31651 MOV &DP,TOS \ -- HERE
31652 ADD #4,&DP \ compile one word, reserve one word
31653 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
31654 ADD #2,TOS \ -- HERE+2=IFadr
31659 [UNDEFINED] THEN [IF]
31660 \ https://forth-standard.org/standard/core/THEN
31661 \ THEN IFadr -- resolve forward branch
31662 CODE THEN \ immediate
31663 MOV &DP,0(TOS) \ -- IFadr
31669 [UNDEFINED] ELSE [IF]
31670 \ https://forth-standard.org/standard/core/ELSE
31671 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
31672 CODE ELSE \ immediate
31673 ADD #4,&DP \ make room to compile two words
31674 MOV &DP,W \ W=HERE+4
31676 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
31678 MOV W,TOS \ -- ELSEadr
31683 [UNDEFINED] DEFER [IF]
31684 \ https://forth-standard.org/standard/core/DEFER
31685 \ DEFER "<spaces>name" --
31686 \ Skip leading space delimiters. Parse name delimited by a space.
31687 \ Create a definition for name with the execution semantics defined below.
31689 \ name Execution: --
31690 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
31691 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
31695 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
31696 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
31702 [UNDEFINED] DEFER! [IF]
31703 \ https://forth-standard.org/standard/core/DEFERStore
31704 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
31705 CODE DEFER! \ xt2 xt1 --
31706 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
31712 [UNDEFINED] IS [IF]
31713 \ https://forth-standard.org/standard/core/IS
31716 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
31717 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
31718 \ or in a definition : ... ['] U. IS DISPLAY ...
31719 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
31721 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
31724 IF POSTPONE ['] POSTPONE DEFER!
31730 [UNDEFINED] >BODY [IF]
31731 \ https://forth-standard.org/standard/core/toBODY
31732 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
31739 \ CODE 20uS \ n -- 8MHz version
31740 \ BEGIN \ 4 + 16 ~ loop
31741 \ MOV #39,rDOCON \ 39
31748 \ MOV #XDOCON,rDOCON \ 2
31753 CODE 20_US \ n -- n * 20 us
31754 BEGIN \ here we presume that LCD_TIM_IFG = 1...
31756 BIT #1,&LCD_TIM_CTL \ 3
31757 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
31758 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
31760 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
31765 CODE TOP_LCD \ LCD Sample
31766 \ \ if write : %xxxx_WWWW --
31767 \ \ if read : -- %0000_RRRR
31768 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
31769 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
31770 0= IF \ write LCD bits pattern
31771 AND.B #LCD_DB,TOS \
31772 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
31773 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31776 THEN \ read LCD bits pattern
31779 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
31780 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
31781 AND.B #LCD_DB,TOS \
31785 CODE LCD_WRC \ char -- Write Char
31786 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31788 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
31789 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
31790 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
31791 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
31792 COLON \ high level word starts here
31793 TOP_LCD 2 20_US \ write high nibble first
31797 CODE LCD_WRF \ func -- Write Fonction
31798 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31802 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
31803 : LCD_HOME $02 LCD_WRF 100 20_us ;
31805 \ [UNDEFINED] OR [IF]
31807 \ \ https://forth-standard.org/standard/core/OR
31808 \ \ C OR x1 x2 -- x3 logical OR
31816 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
31817 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
31818 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
31819 \ : LCD_FN_SET $20 OR LCD_WrF ;
31820 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
31821 \ : LCD_GOTO $80 OR LCD_WrF ;
31824 \ CODE LCD_RDS \ -- status Read Status
31825 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
31826 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
31827 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
31828 \ COLON \ starts a FORTH word
31829 \ TOP_LCD 2 20_us \ -- %0000_HHHH
31830 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
31831 \ HI2LO \ switch from FORTH to assembler
31832 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
31833 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
31834 \ MOV @RSP+,IP \ restore IP saved by COLON
31838 \ CODE LCD_RDC \ -- char Read Char
31839 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
31844 \ ******************************\
31845 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
31846 \ ******************************\
31847 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
31848 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
31849 BIT.B #SW2,&SW2_IN \ test switch S2
31850 0= IF \ case of switch S2 pressed
31851 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
31853 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
31856 BIT.B #SW1,&SW1_IN \ test switch S1 input
31857 0= IF \ case of Switch S1 pressed
31858 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
31860 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
31864 BW1 \ from quit on truncated RC5 message, repeated RC5 command
31868 \ ******************************\
31869 ASM RC5_INT \ wake up on Px.RC5 change interrupt
31870 \ ******************************\
31871 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
31872 \ ******************************\
31873 \ \ in : SR(9)=old Toggle bit memory (ADD on)
31874 \ \ SMclock = 8|16|24 MHz
31875 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
31876 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
31877 \ \ SR(9)=new Toggle bit memory (ADD on)
31878 \ ******************************\
31879 \ RC5_FirstStartBitHalfCycle: \
31880 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
31881 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
31882 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
31883 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
31885 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
31886 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
31888 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
31889 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
31891 MOV #1778,X \ RC5_Period * 1us
31892 MOV #14,W \ count of loop
31894 \ ******************************\
31895 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
31896 \ ******************************\ |
31897 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
31898 \ RC5_Compute_3/4_Period: \ |
31899 RRUM #1,X \ X=1/2 cycle |
31902 ADD X,Y \ Y=3/4 cycle
31903 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
31905 \ ******************************\
31906 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
31907 \ ******************************\
31908 BIT.B #RC5,&IR_IN \ C_flag = IR bit
31909 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
31910 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
31911 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
31912 SUB #1,W \ decrement count loop
31913 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
31914 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
31915 0<> WHILE \ ----> out of loop ----+
31916 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
31918 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
31919 CMP Y,X \ 1 | cycle time out of bound ?
31920 U>= IF \ 2 ^ | yes:
31921 BIC #$30,&RC5_TIM_CTL \ | | stop timer
31922 GOTO BW1 \ | | quit on truncated RC5 message
31924 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
31926 REPEAT \ ----> loop back --+ | with X = new RC5_period value
31927 \ ******************************\ |
31928 \ RC5_SampleEndOf: \ <---------------------+
31929 \ ******************************\
31930 BIC #$30,&RC5_TIM_CTL \ stop timer
31931 \ ******************************\
31932 \ RC5_ComputeNewRC5word \
31933 \ ******************************\
31934 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
31935 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
31936 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
31937 \ ******************************\
31938 \ RC5_ComputeC6bit \
31939 \ ******************************\
31940 BIT #BIT14,T \ test /C6 bit in T
31941 0= IF BIS #BIT6,X \ set C6 bit in X
31942 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
31943 \ ******************************\
31944 \ RC5_CommandByteIsDone \ -- BASE RC5_code
31945 \ ******************************\
31946 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
31947 \ ******************************\
31948 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
31949 XOR @RSP,T \ (new XOR old) Toggle bits
31950 BIT #UF10,T \ repeated RC5_command ?
31951 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
31952 XOR #UF10,0(RSP) \ 5 toggle bit memory
31953 \ ******************************\
31954 \ Display IR_RC5 code \
31955 \ ******************************\
31956 SUB #8,PSP \ TOS -- x x x x TOS
31957 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
31958 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
31959 MOV #$10,&BASEADR \ set hexadecimal base
31960 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
31961 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
31962 LO2HI \ switch from assembler to FORTH
31963 LCD_CLEAR \ set LCD cursor at home
31964 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
31965 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
31966 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
31967 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
31968 HI2LO \ -- switch from FORTH to assembler
31969 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
31970 MOV @PSP+,TOS \ -- TOS
31974 \ ******************************\
31976 \ ******************************\
31978 \ ... \ insert here your background task
31981 CALL &RXON \ comment this line to disable TERMINAL_INPUT
31983 \ ******************************\
31984 \ here start all interrupts \
31985 \ ******************************\
31986 \ here return all interrupts \
31987 \ ******************************\
31990 \ ******************************\
31992 \ ------------------------------\
31993 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
31994 \ ------------------------------\
31995 \ ... \ init specific I/O sys as you want
31996 \ ... \ before executing default WARM
31997 MOV #WARM,X \ ['] WARM
31999 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
32001 \ ------------------------------\
32003 \ ------------------------------\
32004 CODE STOP \ stops multitasking, must to be used before downloading app
32005 \ ------------------------------\
32006 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
32007 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
32008 MOV X,-2(X) \ restore the default background: SLEEP
32010 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
32011 BIC.B #RC5,&IR_IE \ clear RC5_Int
32012 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
32013 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
32014 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
32015 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
32016 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
32017 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
32019 ." RC5toLCD is removed,"
32020 ." type START to restart"
32021 WARM \ performs reset to reset all interrupt vectors.
32023 \ ------------------------------\
32025 \ ------------------------------\
32026 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
32027 \ ------------------------------\
32028 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
32029 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32030 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32031 \ -- \ID input divider \ 10 = /4
32032 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
32033 \ - \TBCLR TimerB Clear
32036 \ -------------------------------\
32037 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32038 \ -- \CM Capture Mode
32043 \ --- \OUTMOD \ 011 = set/reset
32049 \ -------------------------------\
32051 \ -------------------------------\
32053 \ ------------------------------\
32054 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
32055 \ ------------------------------\
32056 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
32057 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
32058 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
32059 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
32061 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
32062 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
32064 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
32065 \ ------------------------------\
32066 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
32067 \ ------------------------------\
32068 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
32069 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
32070 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32071 \ ------------------------------\
32072 BIS.B #LCDVo,&LCDVo_DIR \
32073 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
32074 \ ------------------------------\
32075 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32076 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32077 \ ------------------------------\
32078 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32079 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32080 \ ******************************\
32082 \ ******************************\
32083 BIS.B #RC5,&IR_IE \ enable RC5_Int
32084 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32085 MOV #RC5_INT,&IR_Vec \ init interrupt vector
32086 \ ******************************\
32087 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
32088 \ ******************************\
32089 \ %01 0001 0100 \ TAxCTL
32090 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
32091 \ -- \ ID divided by 1
32092 \ -- \ MC MODE = up to TAxCCRn
32093 \ - \ TACLR clear timer count
32096 \ ------------------------------\
32097 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
32098 \ ------------------------------\
32100 \ --- \ TAIDEX pre divisor
32101 \ ------------------------------\
32102 \ %0000 0000 0000 0101 \ TAxCCR0
32103 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
32104 \ ------------------------------\
32105 \ %0000 0000 0001 0000 \ TAxCCTL0
32106 \ - \ CAP capture/compare mode = compare
32109 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
32110 \ ------------------------------\
32111 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
32112 \ ------------------------------\
32113 \ define LPM mode for ACCEPT \
32114 \ ------------------------------\
32115 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32116 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32117 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32118 \ ------------------------------\
32120 \ ------------------------------\
32121 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
32122 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
32123 \ ------------------------------\
32124 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
32125 \ ------------------------------\
32126 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
32127 \ CMP #2,Y \ Power_ON event
32128 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
32130 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
32132 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
32134 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
32136 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
32137 \ ------------------------------\
32139 \ ------------------------------\
32141 \ ------------------------------\
32142 #1000 20_US \ 1- wait 20 ms
32143 %011 TOP_LCD \ 2- send DB5=DB4=1
32144 #205 20_US \ 3- wait 4,1 ms
32145 %011 TOP_LCD \ 4- send again DB5=DB4=1
32146 #5 20_US \ 5- wait 0,1 ms
32147 %011 TOP_LCD \ 6- send again again DB5=DB4=1
32148 #2 20_US \ wait 40 us = LCD cycle
32149 %010 TOP_LCD \ 7- send DB5=1 DB4=0
32150 #2 20_US \ wait 40 us = LCD cycle
32151 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32152 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
32153 LCD_CLEAR \ 10- "LCD_Clear"
32154 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
32155 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
32156 LCD_CLEAR \ 10- "LCD_Clear"
32157 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
32158 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
32159 CR ." I love you" \ display message on LCD
32160 ['] CR >BODY IS CR \ CR executes its default value
32161 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
32162 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
32163 PWR_STATE ABORT \ init DP and continues with ABORT
32165 \ ------------------------------\
32167 \ ------------------------------\
32168 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
32169 \ ------------------------------\
32170 MOV #SLEEP,X \ replace default background process SLEEP
32171 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
32172 MOV #WARM,X \ replace default WARM
32173 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
32174 MOV X,PC \ then execute new WARM
32176 \ ------------------------------\
32179 ; downloading RC5toLCD.4th is done
32180 RST_HERE ; this app is protected against <reset>
32185 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
32187 [UNDEFINED] MARKER [IF]
32188 \ https://forth-standard.org/standard/core/MARKER
32190 \ ( "<spaces>name" -- )
32191 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
32192 \ with the execution semantics defined below.
32194 \ name Execution: ( -- )
32195 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
32196 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
32197 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
32198 \ not necessarily provided. No other contextual information such as numeric base is affected
32203 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
32204 SUB #2,Y \ 1 Y = LFA
32205 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
32206 ADD #4,&DP \ 3 add 2 cells
32210 MOV @RSP+,IP \ -- PFA
32211 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
32212 MOV @TOS,&INIDP \ set DP value for RST_STATE
32214 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
32221 \ https://forth-standard.org/standard/core/Fetch
32222 \ @ c-addr -- char fetch char from memory
32229 [UNDEFINED] CONSTANT [IF]
32230 \ https://forth-standard.org/standard/core/CONSTANT
32231 \ CONSTANT <name> n -- define a Forth CONSTANT
32235 MOV TOS,-2(W) \ PFA = n
32242 [UNDEFINED] STATE [IF]
32243 \ https://forth-standard.org/standard/core/STATE
32244 \ STATE -- a-addr holds compiler state
32245 STATEADR CONSTANT STATE
32249 \ https://forth-standard.org/standard/core/Equal
32250 \ = x1 x2 -- flag test x1=x2
32257 XOR #-1,TOS \ 1 flag Z = 1
32262 [UNDEFINED] IF [IF]
32263 \ https://forth-standard.org/standard/core/IF
32264 \ IF -- IFadr initialize conditional forward branch
32265 CODE IF \ immediate
32268 MOV &DP,TOS \ -- HERE
32269 ADD #4,&DP \ compile one word, reserve one word
32270 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
32271 ADD #2,TOS \ -- HERE+2=IFadr
32276 [UNDEFINED] THEN [IF]
32277 \ https://forth-standard.org/standard/core/THEN
32278 \ THEN IFadr -- resolve forward branch
32279 CODE THEN \ immediate
32280 MOV &DP,0(TOS) \ -- IFadr
32286 [UNDEFINED] ELSE [IF]
32287 \ https://forth-standard.org/standard/core/ELSE
32288 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
32289 CODE ELSE \ immediate
32290 ADD #4,&DP \ make room to compile two words
32291 MOV &DP,W \ W=HERE+4
32293 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
32295 MOV W,TOS \ -- ELSEadr
32300 [UNDEFINED] DEFER [IF]
32301 \ https://forth-standard.org/standard/core/DEFER
32302 \ DEFER "<spaces>name" --
32303 \ Skip leading space delimiters. Parse name delimited by a space.
32304 \ Create a definition for name with the execution semantics defined below.
32306 \ name Execution: --
32307 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
32308 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
32312 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
32313 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
32319 [UNDEFINED] DEFER! [IF]
32320 \ https://forth-standard.org/standard/core/DEFERStore
32321 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
32322 CODE DEFER! \ xt2 xt1 --
32323 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
32329 [UNDEFINED] IS [IF]
32330 \ https://forth-standard.org/standard/core/IS
32333 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
32334 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
32335 \ or in a definition : ... ['] U. IS DISPLAY ...
32336 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
32338 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
32341 IF POSTPONE ['] POSTPONE DEFER!
32347 [UNDEFINED] >BODY [IF]
32348 \ https://forth-standard.org/standard/core/toBODY
32349 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
32356 \ CODE 20uS \ n -- 8MHz version
32357 \ BEGIN \ 4 + 16 ~ loop
32358 \ MOV #39,rDOCON \ 39
32365 \ MOV #XDOCON,rDOCON \ 2
32370 CODE 20_US \ n -- n * 20 us
32371 BEGIN \ here we presume that LCD_TIM_IFG = 1...
32373 BIT #1,&LCD_TIM_CTL \ 3
32374 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
32375 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
32377 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
32382 CODE TOP_LCD \ LCD Sample
32383 \ \ if write : %xxxx_WWWW --
32384 \ \ if read : -- %0000_RRRR
32385 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
32386 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
32387 0= IF \ write LCD bits pattern
32388 AND.B #LCD_DB,TOS \
32389 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
32390 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32393 THEN \ read LCD bits pattern
32396 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
32397 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
32398 AND.B #LCD_DB,TOS \
32402 CODE LCD_WRC \ char -- Write Char
32403 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32405 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
32406 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
32407 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
32408 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
32409 COLON \ high level word starts here
32410 TOP_LCD 2 20_US \ write high nibble first
32414 CODE LCD_WRF \ func -- Write Fonction
32415 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32419 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
32420 : LCD_HOME $02 LCD_WRF 100 20_us ;
32422 \ [UNDEFINED] OR [IF]
32424 \ \ https://forth-standard.org/standard/core/OR
32425 \ \ C OR x1 x2 -- x3 logical OR
32433 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
32434 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
32435 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
32436 \ : LCD_FN_SET $20 OR LCD_WrF ;
32437 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
32438 \ : LCD_GOTO $80 OR LCD_WrF ;
32441 \ CODE LCD_RDS \ -- status Read Status
32442 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
32443 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
32444 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
32445 \ COLON \ starts a FORTH word
32446 \ TOP_LCD 2 20_us \ -- %0000_HHHH
32447 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
32448 \ HI2LO \ switch from FORTH to assembler
32449 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
32450 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
32451 \ MOV @RSP+,IP \ restore IP saved by COLON
32455 \ CODE LCD_RDC \ -- char Read Char
32456 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
32461 \ ******************************\
32462 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
32463 \ ******************************\
32464 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
32465 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
32466 BIT.B #SW2,&SW2_IN \ test switch S2
32467 0= IF \ case of switch S2 pressed
32468 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
32470 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
32473 BIT.B #SW1,&SW1_IN \ test switch S1 input
32474 0= IF \ case of Switch S1 pressed
32475 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
32477 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
32481 BW1 \ from quit on truncated RC5 message, repeated RC5 command
32485 \ ******************************\
32486 ASM RC5_INT \ wake up on Px.RC5 change interrupt
32487 \ ******************************\
32488 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
32489 \ ******************************\
32490 \ \ in : SR(9)=old Toggle bit memory (ADD on)
32491 \ \ SMclock = 8|16|24 MHz
32492 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
32493 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
32494 \ \ SR(9)=new Toggle bit memory (ADD on)
32495 \ ******************************\
32496 \ RC5_FirstStartBitHalfCycle: \
32497 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
32498 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
32499 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
32500 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
32502 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
32503 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
32505 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
32506 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
32508 MOV #1778,X \ RC5_Period * 1us
32509 MOV #14,W \ count of loop
32511 \ ******************************\
32512 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
32513 \ ******************************\ |
32514 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
32515 \ RC5_Compute_3/4_Period: \ |
32516 RRUM #1,X \ X=1/2 cycle |
32519 ADD X,Y \ Y=3/4 cycle
32520 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
32522 \ ******************************\
32523 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
32524 \ ******************************\
32525 BIT.B #RC5,&IR_IN \ C_flag = IR bit
32526 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
32527 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
32528 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
32529 SUB #1,W \ decrement count loop
32530 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
32531 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
32532 0<> WHILE \ ----> out of loop ----+
32533 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
32535 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
32536 CMP Y,X \ 1 | cycle time out of bound ?
32537 U>= IF \ 2 ^ | yes:
32538 BIC #$30,&RC5_TIM_CTL \ | | stop timer
32539 GOTO BW1 \ | | quit on truncated RC5 message
32541 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
32543 REPEAT \ ----> loop back --+ | with X = new RC5_period value
32544 \ ******************************\ |
32545 \ RC5_SampleEndOf: \ <---------------------+
32546 \ ******************************\
32547 BIC #$30,&RC5_TIM_CTL \ stop timer
32548 \ ******************************\
32549 \ RC5_ComputeNewRC5word \
32550 \ ******************************\
32551 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
32552 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
32553 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
32554 \ ******************************\
32555 \ RC5_ComputeC6bit \
32556 \ ******************************\
32557 BIT #BIT14,T \ test /C6 bit in T
32558 0= IF BIS #BIT6,X \ set C6 bit in X
32559 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
32560 \ ******************************\
32561 \ RC5_CommandByteIsDone \ -- BASE RC5_code
32562 \ ******************************\
32563 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
32564 \ ******************************\
32565 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
32566 XOR @RSP,T \ (new XOR old) Toggle bits
32567 BIT #UF10,T \ repeated RC5_command ?
32568 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
32569 XOR #UF10,0(RSP) \ 5 toggle bit memory
32570 \ ******************************\
32571 \ Display IR_RC5 code \
32572 \ ******************************\
32573 SUB #8,PSP \ TOS -- x x x x TOS
32574 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
32575 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
32576 MOV #$10,&BASEADR \ set hexadecimal base
32577 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
32578 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
32579 LO2HI \ switch from assembler to FORTH
32580 LCD_CLEAR \ set LCD cursor at home
32581 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
32582 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
32583 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
32584 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
32585 HI2LO \ -- switch from FORTH to assembler
32586 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
32587 MOV @PSP+,TOS \ -- TOS
32591 \ ******************************\
32593 \ ******************************\
32595 \ ... \ insert here your background task
32598 CALL &RXON \ comment this line to disable TERMINAL_INPUT
32600 \ ******************************\
32601 \ here start all interrupts \
32602 \ ******************************\
32603 \ here return all interrupts \
32604 \ ******************************\
32607 \ ******************************\
32609 \ ------------------------------\
32610 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
32611 \ ------------------------------\
32612 \ ... \ init specific I/O sys as you want
32613 \ ... \ before executing default WARM
32614 MOV #WARM,X \ ['] WARM
32616 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
32618 \ ------------------------------\
32620 \ ------------------------------\
32621 CODE STOP \ stops multitasking, must to be used before downloading app
32622 \ ------------------------------\
32623 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
32624 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
32625 MOV X,-2(X) \ restore the default background: SLEEP
32627 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
32628 BIC.B #RC5,&IR_IE \ clear RC5_Int
32629 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
32630 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
32631 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
32632 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
32633 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
32634 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
32636 ." RC5toLCD is removed,"
32637 ." type START to restart"
32638 WARM \ performs reset to reset all interrupt vectors.
32640 \ ------------------------------\
32642 \ ------------------------------\
32643 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
32644 \ ------------------------------\
32645 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
32646 \ - - \CNTL Counter lentgh \ 00 = 16 bits
32647 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
32648 \ -- \ID input divider \ 10 = /4
32649 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
32650 \ - \TBCLR TimerB Clear
32653 \ -------------------------------\
32654 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
32655 \ -- \CM Capture Mode
32660 \ --- \OUTMOD \ 011 = set/reset
32666 \ -------------------------------\
32668 \ -------------------------------\
32670 \ ------------------------------\
32671 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
32672 \ ------------------------------\
32673 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
32674 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
32675 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
32676 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
32678 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
32679 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
32681 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
32682 \ ------------------------------\
32683 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
32684 \ ------------------------------\
32685 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
32686 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
32687 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
32688 \ ------------------------------\
32689 BIS.B #LCDVo,&LCDVo_DIR \
32690 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
32691 \ ------------------------------\
32692 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
32693 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
32694 \ ------------------------------\
32695 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
32696 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
32697 \ ******************************\
32699 \ ******************************\
32700 BIS.B #RC5,&IR_IE \ enable RC5_Int
32701 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
32702 MOV #RC5_INT,&IR_Vec \ init interrupt vector
32703 \ ******************************\
32704 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
32705 \ ******************************\
32706 \ %01 0001 0100 \ TAxCTL
32707 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
32708 \ -- \ ID divided by 1
32709 \ -- \ MC MODE = up to TAxCCRn
32710 \ - \ TACLR clear timer count
32713 \ ------------------------------\
32714 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
32715 \ ------------------------------\
32717 \ --- \ TAIDEX pre divisor
32718 \ ------------------------------\
32719 \ %0000 0000 0000 0101 \ TAxCCR0
32720 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
32721 \ ------------------------------\
32722 \ %0000 0000 0001 0000 \ TAxCCTL0
32723 \ - \ CAP capture/compare mode = compare
32726 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
32727 \ ------------------------------\
32728 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
32729 \ ------------------------------\
32730 \ define LPM mode for ACCEPT \
32731 \ ------------------------------\
32732 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
32733 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
32734 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
32735 \ ------------------------------\
32737 \ ------------------------------\
32738 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
32739 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
32740 \ ------------------------------\
32741 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
32742 \ ------------------------------\
32743 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
32744 \ CMP #2,Y \ Power_ON event
32745 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
32747 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
32749 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
32751 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
32753 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
32754 \ ------------------------------\
32756 \ ------------------------------\
32758 \ ------------------------------\
32759 #1000 20_US \ 1- wait 20 ms
32760 %011 TOP_LCD \ 2- send DB5=DB4=1
32761 #205 20_US \ 3- wait 4,1 ms
32762 %011 TOP_LCD \ 4- send again DB5=DB4=1
32763 #5 20_US \ 5- wait 0,1 ms
32764 %011 TOP_LCD \ 6- send again again DB5=DB4=1
32765 #2 20_US \ wait 40 us = LCD cycle
32766 %010 TOP_LCD \ 7- send DB5=1 DB4=0
32767 #2 20_US \ wait 40 us = LCD cycle
32768 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
32769 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
32770 LCD_CLEAR \ 10- "LCD_Clear"
32771 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
32772 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
32773 LCD_CLEAR \ 10- "LCD_Clear"
32774 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
32775 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
32776 CR ." I love you" \ display message on LCD
32777 ['] CR >BODY IS CR \ CR executes its default value
32778 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
32779 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
32780 PWR_STATE ABORT \ init DP and continues with ABORT
32782 \ ------------------------------\
32784 \ ------------------------------\
32785 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
32786 \ ------------------------------\
32787 MOV #SLEEP,X \ replace default background process SLEEP
32788 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
32789 MOV #WARM,X \ replace default WARM
32790 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
32791 MOV X,PC \ then execute new WARM
32793 \ ------------------------------\
32796 ; downloading RC5toLCD.4th is done
32797 RST_HERE ; this app is protected against <reset>
32802 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
32804 [UNDEFINED] MARKER [IF]
32805 \ https://forth-standard.org/standard/core/MARKER
32807 \ ( "<spaces>name" -- )
32808 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
32809 \ with the execution semantics defined below.
32811 \ name Execution: ( -- )
32812 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
32813 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
32814 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
32815 \ not necessarily provided. No other contextual information such as numeric base is affected
32820 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
32821 SUB #2,Y \ 1 Y = LFA
32822 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
32823 ADD #4,&DP \ 3 add 2 cells
32827 MOV @RSP+,IP \ -- PFA
32828 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
32829 MOV @TOS,&INIDP \ set DP value for RST_STATE
32831 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
32838 \ https://forth-standard.org/standard/core/Fetch
32839 \ @ c-addr -- char fetch char from memory
32846 [UNDEFINED] CONSTANT [IF]
32847 \ https://forth-standard.org/standard/core/CONSTANT
32848 \ CONSTANT <name> n -- define a Forth CONSTANT
32852 MOV TOS,-2(W) \ PFA = n
32859 [UNDEFINED] STATE [IF]
32860 \ https://forth-standard.org/standard/core/STATE
32861 \ STATE -- a-addr holds compiler state
32862 STATEADR CONSTANT STATE
32866 \ https://forth-standard.org/standard/core/Equal
32867 \ = x1 x2 -- flag test x1=x2
32874 XOR #-1,TOS \ 1 flag Z = 1
32879 [UNDEFINED] IF [IF]
32880 \ https://forth-standard.org/standard/core/IF
32881 \ IF -- IFadr initialize conditional forward branch
32882 CODE IF \ immediate
32885 MOV &DP,TOS \ -- HERE
32886 ADD #4,&DP \ compile one word, reserve one word
32887 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
32888 ADD #2,TOS \ -- HERE+2=IFadr
32893 [UNDEFINED] THEN [IF]
32894 \ https://forth-standard.org/standard/core/THEN
32895 \ THEN IFadr -- resolve forward branch
32896 CODE THEN \ immediate
32897 MOV &DP,0(TOS) \ -- IFadr
32903 [UNDEFINED] ELSE [IF]
32904 \ https://forth-standard.org/standard/core/ELSE
32905 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
32906 CODE ELSE \ immediate
32907 ADD #4,&DP \ make room to compile two words
32908 MOV &DP,W \ W=HERE+4
32910 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
32912 MOV W,TOS \ -- ELSEadr
32917 [UNDEFINED] DEFER [IF]
32918 \ https://forth-standard.org/standard/core/DEFER
32919 \ DEFER "<spaces>name" --
32920 \ Skip leading space delimiters. Parse name delimited by a space.
32921 \ Create a definition for name with the execution semantics defined below.
32923 \ name Execution: --
32924 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
32925 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
32929 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
32930 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
32936 [UNDEFINED] DEFER! [IF]
32937 \ https://forth-standard.org/standard/core/DEFERStore
32938 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
32939 CODE DEFER! \ xt2 xt1 --
32940 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
32946 [UNDEFINED] IS [IF]
32947 \ https://forth-standard.org/standard/core/IS
32950 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
32951 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
32952 \ or in a definition : ... ['] U. IS DISPLAY ...
32953 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
32955 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
32958 IF POSTPONE ['] POSTPONE DEFER!
32964 [UNDEFINED] >BODY [IF]
32965 \ https://forth-standard.org/standard/core/toBODY
32966 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
32973 \ CODE 20uS \ n -- 8MHz version
32974 \ BEGIN \ 4 + 16 ~ loop
32975 \ MOV #39,rDOCON \ 39
32982 \ MOV #XDOCON,rDOCON \ 2
32987 CODE 20_US \ n -- n * 20 us
32988 BEGIN \ here we presume that LCD_TIM_IFG = 1...
32990 BIT #1,&LCD_TIM_CTL \ 3
32991 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
32992 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
32994 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
32999 CODE TOP_LCD \ LCD Sample
33000 \ \ if write : %xxxx_WWWW --
33001 \ \ if read : -- %0000_RRRR
33002 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33003 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33004 0= IF \ write LCD bits pattern
33005 AND.B #LCD_DB,TOS \
33006 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33007 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33010 THEN \ read LCD bits pattern
33013 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33014 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33015 AND.B #LCD_DB,TOS \
33019 CODE LCD_WRC \ char -- Write Char
33020 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33022 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
33023 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
33024 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33025 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33026 COLON \ high level word starts here
33027 TOP_LCD 2 20_US \ write high nibble first
33031 CODE LCD_WRF \ func -- Write Fonction
33032 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33036 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
33037 : LCD_HOME $02 LCD_WRF 100 20_us ;
33039 \ [UNDEFINED] OR [IF]
33041 \ \ https://forth-standard.org/standard/core/OR
33042 \ \ C OR x1 x2 -- x3 logical OR
33050 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
33051 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
33052 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
33053 \ : LCD_FN_SET $20 OR LCD_WrF ;
33054 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
33055 \ : LCD_GOTO $80 OR LCD_WrF ;
33058 \ CODE LCD_RDS \ -- status Read Status
33059 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33060 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33061 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33062 \ COLON \ starts a FORTH word
33063 \ TOP_LCD 2 20_us \ -- %0000_HHHH
33064 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
33065 \ HI2LO \ switch from FORTH to assembler
33066 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
33067 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
33068 \ MOV @RSP+,IP \ restore IP saved by COLON
33072 \ CODE LCD_RDC \ -- char Read Char
33073 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33078 \ ******************************\
33079 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
33080 \ ******************************\
33081 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
33082 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
33083 BIT.B #SW2,&SW2_IN \ test switch S2
33084 0= IF \ case of switch S2 pressed
33085 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
33087 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
33090 BIT.B #SW1,&SW1_IN \ test switch S1 input
33091 0= IF \ case of Switch S1 pressed
33092 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
33094 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
33098 BW1 \ from quit on truncated RC5 message, repeated RC5 command
33102 \ ******************************\
33103 ASM RC5_INT \ wake up on Px.RC5 change interrupt
33104 \ ******************************\
33105 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
33106 \ ******************************\
33107 \ \ in : SR(9)=old Toggle bit memory (ADD on)
33108 \ \ SMclock = 8|16|24 MHz
33109 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
33110 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
33111 \ \ SR(9)=new Toggle bit memory (ADD on)
33112 \ ******************************\
33113 \ RC5_FirstStartBitHalfCycle: \
33114 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
33115 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
33116 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
33117 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
33119 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
33120 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
33122 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
33123 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
33125 MOV #1778,X \ RC5_Period * 1us
33126 MOV #14,W \ count of loop
33128 \ ******************************\
33129 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
33130 \ ******************************\ |
33131 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
33132 \ RC5_Compute_3/4_Period: \ |
33133 RRUM #1,X \ X=1/2 cycle |
33136 ADD X,Y \ Y=3/4 cycle
33137 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
33139 \ ******************************\
33140 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
33141 \ ******************************\
33142 BIT.B #RC5,&IR_IN \ C_flag = IR bit
33143 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
33144 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
33145 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
33146 SUB #1,W \ decrement count loop
33147 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
33148 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
33149 0<> WHILE \ ----> out of loop ----+
33150 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
33152 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
33153 CMP Y,X \ 1 | cycle time out of bound ?
33154 U>= IF \ 2 ^ | yes:
33155 BIC #$30,&RC5_TIM_CTL \ | | stop timer
33156 GOTO BW1 \ | | quit on truncated RC5 message
33158 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
33160 REPEAT \ ----> loop back --+ | with X = new RC5_period value
33161 \ ******************************\ |
33162 \ RC5_SampleEndOf: \ <---------------------+
33163 \ ******************************\
33164 BIC #$30,&RC5_TIM_CTL \ stop timer
33165 \ ******************************\
33166 \ RC5_ComputeNewRC5word \
33167 \ ******************************\
33168 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
33169 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
33170 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
33171 \ ******************************\
33172 \ RC5_ComputeC6bit \
33173 \ ******************************\
33174 BIT #BIT14,T \ test /C6 bit in T
33175 0= IF BIS #BIT6,X \ set C6 bit in X
33176 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
33177 \ ******************************\
33178 \ RC5_CommandByteIsDone \ -- BASE RC5_code
33179 \ ******************************\
33180 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
33181 \ ******************************\
33182 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
33183 XOR @RSP,T \ (new XOR old) Toggle bits
33184 BIT #UF10,T \ repeated RC5_command ?
33185 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
33186 XOR #UF10,0(RSP) \ 5 toggle bit memory
33187 \ ******************************\
33188 \ Display IR_RC5 code \
33189 \ ******************************\
33190 SUB #8,PSP \ TOS -- x x x x TOS
33191 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
33192 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
33193 MOV #$10,&BASEADR \ set hexadecimal base
33194 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
33195 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
33196 LO2HI \ switch from assembler to FORTH
33197 LCD_CLEAR \ set LCD cursor at home
33198 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
33199 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
33200 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
33201 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
33202 HI2LO \ -- switch from FORTH to assembler
33203 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
33204 MOV @PSP+,TOS \ -- TOS
33208 \ ******************************\
33210 \ ******************************\
33212 \ ... \ insert here your background task
33215 CALL &RXON \ comment this line to disable TERMINAL_INPUT
33217 \ ******************************\
33218 \ here start all interrupts \
33219 \ ******************************\
33220 \ here return all interrupts \
33221 \ ******************************\
33224 \ ******************************\
33226 \ ------------------------------\
33227 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
33228 \ ------------------------------\
33229 \ ... \ init specific I/O sys as you want
33230 \ ... \ before executing default WARM
33231 MOV #WARM,X \ ['] WARM
33233 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
33235 \ ------------------------------\
33237 \ ------------------------------\
33238 CODE STOP \ stops multitasking, must to be used before downloading app
33239 \ ------------------------------\
33240 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
33241 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
33242 MOV X,-2(X) \ restore the default background: SLEEP
33244 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
33245 BIC.B #RC5,&IR_IE \ clear RC5_Int
33246 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
33247 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
33248 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
33249 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
33250 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
33251 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
33253 ." RC5toLCD is removed,"
33254 ." type START to restart"
33255 WARM \ performs reset to reset all interrupt vectors.
33257 \ ------------------------------\
33259 \ ------------------------------\
33260 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
33261 \ ------------------------------\
33262 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
33263 \ - - \CNTL Counter lentgh \ 00 = 16 bits
33264 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
33265 \ -- \ID input divider \ 10 = /4
33266 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
33267 \ - \TBCLR TimerB Clear
33270 \ -------------------------------\
33271 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33272 \ -- \CM Capture Mode
33277 \ --- \OUTMOD \ 011 = set/reset
33283 \ -------------------------------\
33285 \ -------------------------------\
33287 \ ------------------------------\
33288 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
33289 \ ------------------------------\
33290 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
33291 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
33292 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
33293 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
33295 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
33296 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
33298 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
33299 \ ------------------------------\
33300 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
33301 \ ------------------------------\
33302 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
33303 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
33304 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33305 \ ------------------------------\
33306 BIS.B #LCDVo,&LCDVo_DIR \
33307 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
33308 \ ------------------------------\
33309 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33310 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33311 \ ------------------------------\
33312 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
33313 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
33314 \ ******************************\
33316 \ ******************************\
33317 BIS.B #RC5,&IR_IE \ enable RC5_Int
33318 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
33319 MOV #RC5_INT,&IR_Vec \ init interrupt vector
33320 \ ******************************\
33321 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
33322 \ ******************************\
33323 \ %01 0001 0100 \ TAxCTL
33324 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
33325 \ -- \ ID divided by 1
33326 \ -- \ MC MODE = up to TAxCCRn
33327 \ - \ TACLR clear timer count
33330 \ ------------------------------\
33331 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
33332 \ ------------------------------\
33334 \ --- \ TAIDEX pre divisor
33335 \ ------------------------------\
33336 \ %0000 0000 0000 0101 \ TAxCCR0
33337 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
33338 \ ------------------------------\
33339 \ %0000 0000 0001 0000 \ TAxCCTL0
33340 \ - \ CAP capture/compare mode = compare
33343 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
33344 \ ------------------------------\
33345 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
33346 \ ------------------------------\
33347 \ define LPM mode for ACCEPT \
33348 \ ------------------------------\
33349 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33350 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33351 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33352 \ ------------------------------\
33354 \ ------------------------------\
33355 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
33356 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
33357 \ ------------------------------\
33358 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
33359 \ ------------------------------\
33360 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
33361 \ CMP #2,Y \ Power_ON event
33362 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
33364 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
33366 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
33368 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
33370 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
33371 \ ------------------------------\
33373 \ ------------------------------\
33375 \ ------------------------------\
33376 #1000 20_US \ 1- wait 20 ms
33377 %011 TOP_LCD \ 2- send DB5=DB4=1
33378 #205 20_US \ 3- wait 4,1 ms
33379 %011 TOP_LCD \ 4- send again DB5=DB4=1
33380 #5 20_US \ 5- wait 0,1 ms
33381 %011 TOP_LCD \ 6- send again again DB5=DB4=1
33382 #2 20_US \ wait 40 us = LCD cycle
33383 %010 TOP_LCD \ 7- send DB5=1 DB4=0
33384 #2 20_US \ wait 40 us = LCD cycle
33385 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
33386 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
33387 LCD_CLEAR \ 10- "LCD_Clear"
33388 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
33389 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
33390 LCD_CLEAR \ 10- "LCD_Clear"
33391 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
33392 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
33393 CR ." I love you" \ display message on LCD
33394 ['] CR >BODY IS CR \ CR executes its default value
33395 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
33396 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
33397 PWR_STATE ABORT \ init DP and continues with ABORT
33399 \ ------------------------------\
33401 \ ------------------------------\
33402 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
33403 \ ------------------------------\
33404 MOV #SLEEP,X \ replace default background process SLEEP
33405 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
33406 MOV #WARM,X \ replace default WARM
33407 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
33408 MOV X,PC \ then execute new WARM
33410 \ ------------------------------\
33413 ; downloading RC5toLCD.4th is done
33414 RST_HERE ; this app is protected against <reset>
33419 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
33421 [UNDEFINED] MARKER [IF]
33422 \ https://forth-standard.org/standard/core/MARKER
33424 \ ( "<spaces>name" -- )
33425 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
33426 \ with the execution semantics defined below.
33428 \ name Execution: ( -- )
33429 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
33430 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
33431 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
33432 \ not necessarily provided. No other contextual information such as numeric base is affected
33437 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
33438 SUB #2,Y \ 1 Y = LFA
33439 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
33440 ADD #4,&DP \ 3 add 2 cells
33444 MOV @RSP+,IP \ -- PFA
33445 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
33446 MOV @TOS,&INIDP \ set DP value for RST_STATE
33448 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
33455 \ https://forth-standard.org/standard/core/Fetch
33456 \ @ c-addr -- char fetch char from memory
33463 [UNDEFINED] CONSTANT [IF]
33464 \ https://forth-standard.org/standard/core/CONSTANT
33465 \ CONSTANT <name> n -- define a Forth CONSTANT
33469 MOV TOS,-2(W) \ PFA = n
33476 [UNDEFINED] STATE [IF]
33477 \ https://forth-standard.org/standard/core/STATE
33478 \ STATE -- a-addr holds compiler state
33479 STATEADR CONSTANT STATE
33483 \ https://forth-standard.org/standard/core/Equal
33484 \ = x1 x2 -- flag test x1=x2
33491 XOR #-1,TOS \ 1 flag Z = 1
33496 [UNDEFINED] IF [IF]
33497 \ https://forth-standard.org/standard/core/IF
33498 \ IF -- IFadr initialize conditional forward branch
33499 CODE IF \ immediate
33502 MOV &DP,TOS \ -- HERE
33503 ADD #4,&DP \ compile one word, reserve one word
33504 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
33505 ADD #2,TOS \ -- HERE+2=IFadr
33510 [UNDEFINED] THEN [IF]
33511 \ https://forth-standard.org/standard/core/THEN
33512 \ THEN IFadr -- resolve forward branch
33513 CODE THEN \ immediate
33514 MOV &DP,0(TOS) \ -- IFadr
33520 [UNDEFINED] ELSE [IF]
33521 \ https://forth-standard.org/standard/core/ELSE
33522 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
33523 CODE ELSE \ immediate
33524 ADD #4,&DP \ make room to compile two words
33525 MOV &DP,W \ W=HERE+4
33527 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
33529 MOV W,TOS \ -- ELSEadr
33534 [UNDEFINED] DEFER [IF]
33535 \ https://forth-standard.org/standard/core/DEFER
33536 \ DEFER "<spaces>name" --
33537 \ Skip leading space delimiters. Parse name delimited by a space.
33538 \ Create a definition for name with the execution semantics defined below.
33540 \ name Execution: --
33541 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
33542 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
33546 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
33547 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
33553 [UNDEFINED] DEFER! [IF]
33554 \ https://forth-standard.org/standard/core/DEFERStore
33555 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
33556 CODE DEFER! \ xt2 xt1 --
33557 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
33563 [UNDEFINED] IS [IF]
33564 \ https://forth-standard.org/standard/core/IS
33567 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
33568 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
33569 \ or in a definition : ... ['] U. IS DISPLAY ...
33570 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
33572 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
33575 IF POSTPONE ['] POSTPONE DEFER!
33581 [UNDEFINED] >BODY [IF]
33582 \ https://forth-standard.org/standard/core/toBODY
33583 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
33590 \ CODE 20uS \ n -- 8MHz version
33591 \ BEGIN \ 4 + 16 ~ loop
33592 \ MOV #39,rDOCON \ 39
33599 \ MOV #XDOCON,rDOCON \ 2
33604 CODE 20_US \ n -- n * 20 us
33605 BEGIN \ here we presume that LCD_TIM_IFG = 1...
33607 BIT #1,&LCD_TIM_CTL \ 3
33608 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
33609 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
33611 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
33616 CODE TOP_LCD \ LCD Sample
33617 \ \ if write : %xxxx_WWWW --
33618 \ \ if read : -- %0000_RRRR
33619 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
33620 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
33621 0= IF \ write LCD bits pattern
33622 AND.B #LCD_DB,TOS \
33623 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
33624 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33627 THEN \ read LCD bits pattern
33630 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
33631 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
33632 AND.B #LCD_DB,TOS \
33636 CODE LCD_WRC \ char -- Write Char
33637 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33639 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
33640 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
33641 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
33642 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
33643 COLON \ high level word starts here
33644 TOP_LCD 2 20_US \ write high nibble first
33648 CODE LCD_WRF \ func -- Write Fonction
33649 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33653 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
33654 : LCD_HOME $02 LCD_WRF 100 20_us ;
33656 \ [UNDEFINED] OR [IF]
33658 \ \ https://forth-standard.org/standard/core/OR
33659 \ \ C OR x1 x2 -- x3 logical OR
33667 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
33668 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
33669 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
33670 \ : LCD_FN_SET $20 OR LCD_WrF ;
33671 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
33672 \ : LCD_GOTO $80 OR LCD_WrF ;
33675 \ CODE LCD_RDS \ -- status Read Status
33676 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
33677 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
33678 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
33679 \ COLON \ starts a FORTH word
33680 \ TOP_LCD 2 20_us \ -- %0000_HHHH
33681 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
33682 \ HI2LO \ switch from FORTH to assembler
33683 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
33684 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
33685 \ MOV @RSP+,IP \ restore IP saved by COLON
33689 \ CODE LCD_RDC \ -- char Read Char
33690 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
33695 \ ******************************\
33696 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
33697 \ ******************************\
33698 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
33699 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
33700 BIT.B #SW2,&SW2_IN \ test switch S2
33701 0= IF \ case of switch S2 pressed
33702 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
33704 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
33707 BIT.B #SW1,&SW1_IN \ test switch S1 input
33708 0= IF \ case of Switch S1 pressed
33709 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
33711 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
33715 BW1 \ from quit on truncated RC5 message, repeated RC5 command
33719 \ ******************************\
33720 ASM RC5_INT \ wake up on Px.RC5 change interrupt
33721 \ ******************************\
33722 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
33723 \ ******************************\
33724 \ \ in : SR(9)=old Toggle bit memory (ADD on)
33725 \ \ SMclock = 8|16|24 MHz
33726 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
33727 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
33728 \ \ SR(9)=new Toggle bit memory (ADD on)
33729 \ ******************************\
33730 \ RC5_FirstStartBitHalfCycle: \
33731 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
33732 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
33733 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
33734 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
33736 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
33737 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
33739 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
33740 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
33742 MOV #1778,X \ RC5_Period * 1us
33743 MOV #14,W \ count of loop
33745 \ ******************************\
33746 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
33747 \ ******************************\ |
33748 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
33749 \ RC5_Compute_3/4_Period: \ |
33750 RRUM #1,X \ X=1/2 cycle |
33753 ADD X,Y \ Y=3/4 cycle
33754 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
33756 \ ******************************\
33757 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
33758 \ ******************************\
33759 BIT.B #RC5,&IR_IN \ C_flag = IR bit
33760 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
33761 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
33762 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
33763 SUB #1,W \ decrement count loop
33764 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
33765 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
33766 0<> WHILE \ ----> out of loop ----+
33767 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
33769 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
33770 CMP Y,X \ 1 | cycle time out of bound ?
33771 U>= IF \ 2 ^ | yes:
33772 BIC #$30,&RC5_TIM_CTL \ | | stop timer
33773 GOTO BW1 \ | | quit on truncated RC5 message
33775 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
33777 REPEAT \ ----> loop back --+ | with X = new RC5_period value
33778 \ ******************************\ |
33779 \ RC5_SampleEndOf: \ <---------------------+
33780 \ ******************************\
33781 BIC #$30,&RC5_TIM_CTL \ stop timer
33782 \ ******************************\
33783 \ RC5_ComputeNewRC5word \
33784 \ ******************************\
33785 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
33786 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
33787 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
33788 \ ******************************\
33789 \ RC5_ComputeC6bit \
33790 \ ******************************\
33791 BIT #BIT14,T \ test /C6 bit in T
33792 0= IF BIS #BIT6,X \ set C6 bit in X
33793 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
33794 \ ******************************\
33795 \ RC5_CommandByteIsDone \ -- BASE RC5_code
33796 \ ******************************\
33797 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
33798 \ ******************************\
33799 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
33800 XOR @RSP,T \ (new XOR old) Toggle bits
33801 BIT #UF10,T \ repeated RC5_command ?
33802 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
33803 XOR #UF10,0(RSP) \ 5 toggle bit memory
33804 \ ******************************\
33805 \ Display IR_RC5 code \
33806 \ ******************************\
33807 SUB #8,PSP \ TOS -- x x x x TOS
33808 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
33809 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
33810 MOV #$10,&BASEADR \ set hexadecimal base
33811 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
33812 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
33813 LO2HI \ switch from assembler to FORTH
33814 LCD_CLEAR \ set LCD cursor at home
33815 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
33816 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
33817 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
33818 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
33819 HI2LO \ -- switch from FORTH to assembler
33820 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
33821 MOV @PSP+,TOS \ -- TOS
33825 \ ******************************\
33827 \ ******************************\
33829 \ ... \ insert here your background task
33832 CALL &RXON \ comment this line to disable TERMINAL_INPUT
33834 \ ******************************\
33835 \ here start all interrupts \
33836 \ ******************************\
33837 \ here return all interrupts \
33838 \ ******************************\
33841 \ ******************************\
33843 \ ------------------------------\
33844 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
33845 \ ------------------------------\
33846 \ ... \ init specific I/O sys as you want
33847 \ ... \ before executing default WARM
33848 MOV #WARM,X \ ['] WARM
33850 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
33852 \ ------------------------------\
33854 \ ------------------------------\
33855 CODE STOP \ stops multitasking, must to be used before downloading app
33856 \ ------------------------------\
33857 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
33858 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
33859 MOV X,-2(X) \ restore the default background: SLEEP
33861 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
33862 BIC.B #RC5,&IR_IE \ clear RC5_Int
33863 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
33864 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
33865 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
33866 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
33867 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
33868 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
33870 ." RC5toLCD is removed,"
33871 ." type START to restart"
33872 WARM \ performs reset to reset all interrupt vectors.
33874 \ ------------------------------\
33876 \ ------------------------------\
33877 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
33878 \ ------------------------------\
33879 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
33880 \ - - \CNTL Counter lentgh \ 00 = 16 bits
33881 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
33882 \ -- \ID input divider \ 10 = /4
33883 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
33884 \ - \TBCLR TimerB Clear
33887 \ -------------------------------\
33888 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
33889 \ -- \CM Capture Mode
33894 \ --- \OUTMOD \ 011 = set/reset
33900 \ -------------------------------\
33902 \ -------------------------------\
33904 \ ------------------------------\
33905 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
33906 \ ------------------------------\
33907 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
33908 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
33909 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
33910 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
33912 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
33913 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
33915 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
33916 \ ------------------------------\
33917 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
33918 \ ------------------------------\
33919 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
33920 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
33921 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
33922 \ ------------------------------\
33923 BIS.B #LCDVo,&LCDVo_DIR \
33924 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
33925 \ ------------------------------\
33926 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
33927 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
33928 \ ------------------------------\
33929 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
33930 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
33931 \ ******************************\
33933 \ ******************************\
33934 BIS.B #RC5,&IR_IE \ enable RC5_Int
33935 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
33936 MOV #RC5_INT,&IR_Vec \ init interrupt vector
33937 \ ******************************\
33938 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
33939 \ ******************************\
33940 \ %01 0001 0100 \ TAxCTL
33941 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
33942 \ -- \ ID divided by 1
33943 \ -- \ MC MODE = up to TAxCCRn
33944 \ - \ TACLR clear timer count
33947 \ ------------------------------\
33948 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
33949 \ ------------------------------\
33951 \ --- \ TAIDEX pre divisor
33952 \ ------------------------------\
33953 \ %0000 0000 0000 0101 \ TAxCCR0
33954 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
33955 \ ------------------------------\
33956 \ %0000 0000 0001 0000 \ TAxCCTL0
33957 \ - \ CAP capture/compare mode = compare
33960 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
33961 \ ------------------------------\
33962 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
33963 \ ------------------------------\
33964 \ define LPM mode for ACCEPT \
33965 \ ------------------------------\
33966 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
33967 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
33968 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
33969 \ ------------------------------\
33971 \ ------------------------------\
33972 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
33973 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
33974 \ ------------------------------\
33975 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
33976 \ ------------------------------\
33977 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
33978 \ CMP #2,Y \ Power_ON event
33979 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
33981 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
33983 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
33985 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
33987 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
33988 \ ------------------------------\
33990 \ ------------------------------\
33992 \ ------------------------------\
33993 #1000 20_US \ 1- wait 20 ms
33994 %011 TOP_LCD \ 2- send DB5=DB4=1
33995 #205 20_US \ 3- wait 4,1 ms
33996 %011 TOP_LCD \ 4- send again DB5=DB4=1
33997 #5 20_US \ 5- wait 0,1 ms
33998 %011 TOP_LCD \ 6- send again again DB5=DB4=1
33999 #2 20_US \ wait 40 us = LCD cycle
34000 %010 TOP_LCD \ 7- send DB5=1 DB4=0
34001 #2 20_US \ wait 40 us = LCD cycle
34002 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34003 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
34004 LCD_CLEAR \ 10- "LCD_Clear"
34005 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
34006 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
34007 LCD_CLEAR \ 10- "LCD_Clear"
34008 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
34009 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
34010 CR ." I love you" \ display message on LCD
34011 ['] CR >BODY IS CR \ CR executes its default value
34012 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
34013 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
34014 PWR_STATE ABORT \ init DP and continues with ABORT
34016 \ ------------------------------\
34018 \ ------------------------------\
34019 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
34020 \ ------------------------------\
34021 MOV #SLEEP,X \ replace default background process SLEEP
34022 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
34023 MOV #WARM,X \ replace default WARM
34024 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
34025 MOV X,PC \ then execute new WARM
34027 \ ------------------------------\
34030 ; downloading RC5toLCD.4th is done
34031 RST_HERE ; this app is protected against <reset>
34036 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
34038 [UNDEFINED] MARKER [IF]
34039 \ https://forth-standard.org/standard/core/MARKER
34041 \ ( "<spaces>name" -- )
34042 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
34043 \ with the execution semantics defined below.
34045 \ name Execution: ( -- )
34046 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
34047 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
34048 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
34049 \ not necessarily provided. No other contextual information such as numeric base is affected
34054 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
34055 SUB #2,Y \ 1 Y = LFA
34056 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
34057 ADD #4,&DP \ 3 add 2 cells
34061 MOV @RSP+,IP \ -- PFA
34062 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
34063 MOV @TOS,&INIDP \ set DP value for RST_STATE
34065 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
34072 \ https://forth-standard.org/standard/core/Fetch
34073 \ @ c-addr -- char fetch char from memory
34080 [UNDEFINED] CONSTANT [IF]
34081 \ https://forth-standard.org/standard/core/CONSTANT
34082 \ CONSTANT <name> n -- define a Forth CONSTANT
34086 MOV TOS,-2(W) \ PFA = n
34093 [UNDEFINED] STATE [IF]
34094 \ https://forth-standard.org/standard/core/STATE
34095 \ STATE -- a-addr holds compiler state
34096 STATEADR CONSTANT STATE
34100 \ https://forth-standard.org/standard/core/Equal
34101 \ = x1 x2 -- flag test x1=x2
34108 XOR #-1,TOS \ 1 flag Z = 1
34113 [UNDEFINED] IF [IF]
34114 \ https://forth-standard.org/standard/core/IF
34115 \ IF -- IFadr initialize conditional forward branch
34116 CODE IF \ immediate
34119 MOV &DP,TOS \ -- HERE
34120 ADD #4,&DP \ compile one word, reserve one word
34121 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
34122 ADD #2,TOS \ -- HERE+2=IFadr
34127 [UNDEFINED] THEN [IF]
34128 \ https://forth-standard.org/standard/core/THEN
34129 \ THEN IFadr -- resolve forward branch
34130 CODE THEN \ immediate
34131 MOV &DP,0(TOS) \ -- IFadr
34137 [UNDEFINED] ELSE [IF]
34138 \ https://forth-standard.org/standard/core/ELSE
34139 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
34140 CODE ELSE \ immediate
34141 ADD #4,&DP \ make room to compile two words
34142 MOV &DP,W \ W=HERE+4
34144 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
34146 MOV W,TOS \ -- ELSEadr
34151 [UNDEFINED] DEFER [IF]
34152 \ https://forth-standard.org/standard/core/DEFER
34153 \ DEFER "<spaces>name" --
34154 \ Skip leading space delimiters. Parse name delimited by a space.
34155 \ Create a definition for name with the execution semantics defined below.
34157 \ name Execution: --
34158 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
34159 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
34163 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
34164 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
34170 [UNDEFINED] DEFER! [IF]
34171 \ https://forth-standard.org/standard/core/DEFERStore
34172 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
34173 CODE DEFER! \ xt2 xt1 --
34174 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
34180 [UNDEFINED] IS [IF]
34181 \ https://forth-standard.org/standard/core/IS
34184 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
34185 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
34186 \ or in a definition : ... ['] U. IS DISPLAY ...
34187 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
34189 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
34192 IF POSTPONE ['] POSTPONE DEFER!
34198 [UNDEFINED] >BODY [IF]
34199 \ https://forth-standard.org/standard/core/toBODY
34200 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
34207 \ CODE 20uS \ n -- 8MHz version
34208 \ BEGIN \ 4 + 16 ~ loop
34209 \ MOV #39,rDOCON \ 39
34216 \ MOV #XDOCON,rDOCON \ 2
34221 CODE 20_US \ n -- n * 20 us
34222 BEGIN \ here we presume that LCD_TIM_IFG = 1...
34224 BIT #1,&LCD_TIM_CTL \ 3
34225 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
34226 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
34228 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
34233 CODE TOP_LCD \ LCD Sample
34234 \ \ if write : %xxxx_WWWW --
34235 \ \ if read : -- %0000_RRRR
34236 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
34237 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
34238 0= IF \ write LCD bits pattern
34239 AND.B #LCD_DB,TOS \
34240 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
34241 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34244 THEN \ read LCD bits pattern
34247 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34248 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
34249 AND.B #LCD_DB,TOS \
34253 CODE LCD_WRC \ char -- Write Char
34254 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34256 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
34257 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
34258 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
34259 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
34260 COLON \ high level word starts here
34261 TOP_LCD 2 20_US \ write high nibble first
34265 CODE LCD_WRF \ func -- Write Fonction
34266 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34270 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
34271 : LCD_HOME $02 LCD_WRF 100 20_us ;
34273 \ [UNDEFINED] OR [IF]
34275 \ \ https://forth-standard.org/standard/core/OR
34276 \ \ C OR x1 x2 -- x3 logical OR
34284 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
34285 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
34286 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
34287 \ : LCD_FN_SET $20 OR LCD_WrF ;
34288 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
34289 \ : LCD_GOTO $80 OR LCD_WrF ;
34292 \ CODE LCD_RDS \ -- status Read Status
34293 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34294 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
34295 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
34296 \ COLON \ starts a FORTH word
34297 \ TOP_LCD 2 20_us \ -- %0000_HHHH
34298 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
34299 \ HI2LO \ switch from FORTH to assembler
34300 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
34301 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
34302 \ MOV @RSP+,IP \ restore IP saved by COLON
34306 \ CODE LCD_RDC \ -- char Read Char
34307 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34312 \ ******************************\
34313 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34314 \ ******************************\
34315 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
34316 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
34317 BIT.B #SW2,&SW2_IN \ test switch S2
34318 0= IF \ case of switch S2 pressed
34319 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
34321 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
34324 BIT.B #SW1,&SW1_IN \ test switch S1 input
34325 0= IF \ case of Switch S1 pressed
34326 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
34328 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
34332 BW1 \ from quit on truncated RC5 message, repeated RC5 command
34336 \ ******************************\
34337 ASM RC5_INT \ wake up on Px.RC5 change interrupt
34338 \ ******************************\
34339 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34340 \ ******************************\
34341 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34342 \ \ SMclock = 8|16|24 MHz
34343 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
34344 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
34345 \ \ SR(9)=new Toggle bit memory (ADD on)
34346 \ ******************************\
34347 \ RC5_FirstStartBitHalfCycle: \
34348 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
34349 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
34350 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
34351 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
34353 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
34354 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
34356 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
34357 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
34359 MOV #1778,X \ RC5_Period * 1us
34360 MOV #14,W \ count of loop
34362 \ ******************************\
34363 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
34364 \ ******************************\ |
34365 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
34366 \ RC5_Compute_3/4_Period: \ |
34367 RRUM #1,X \ X=1/2 cycle |
34370 ADD X,Y \ Y=3/4 cycle
34371 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
34373 \ ******************************\
34374 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
34375 \ ******************************\
34376 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34377 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
34378 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34379 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34380 SUB #1,W \ decrement count loop
34381 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
34382 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
34383 0<> WHILE \ ----> out of loop ----+
34384 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
34386 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
34387 CMP Y,X \ 1 | cycle time out of bound ?
34388 U>= IF \ 2 ^ | yes:
34389 BIC #$30,&RC5_TIM_CTL \ | | stop timer
34390 GOTO BW1 \ | | quit on truncated RC5 message
34392 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
34394 REPEAT \ ----> loop back --+ | with X = new RC5_period value
34395 \ ******************************\ |
34396 \ RC5_SampleEndOf: \ <---------------------+
34397 \ ******************************\
34398 BIC #$30,&RC5_TIM_CTL \ stop timer
34399 \ ******************************\
34400 \ RC5_ComputeNewRC5word \
34401 \ ******************************\
34402 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
34403 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
34404 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
34405 \ ******************************\
34406 \ RC5_ComputeC6bit \
34407 \ ******************************\
34408 BIT #BIT14,T \ test /C6 bit in T
34409 0= IF BIS #BIT6,X \ set C6 bit in X
34410 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
34411 \ ******************************\
34412 \ RC5_CommandByteIsDone \ -- BASE RC5_code
34413 \ ******************************\
34414 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
34415 \ ******************************\
34416 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
34417 XOR @RSP,T \ (new XOR old) Toggle bits
34418 BIT #UF10,T \ repeated RC5_command ?
34419 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
34420 XOR #UF10,0(RSP) \ 5 toggle bit memory
34421 \ ******************************\
34422 \ Display IR_RC5 code \
34423 \ ******************************\
34424 SUB #8,PSP \ TOS -- x x x x TOS
34425 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
34426 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
34427 MOV #$10,&BASEADR \ set hexadecimal base
34428 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
34429 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
34430 LO2HI \ switch from assembler to FORTH
34431 LCD_CLEAR \ set LCD cursor at home
34432 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
34433 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
34434 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
34435 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
34436 HI2LO \ -- switch from FORTH to assembler
34437 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
34438 MOV @PSP+,TOS \ -- TOS
34442 \ ******************************\
34444 \ ******************************\
34446 \ ... \ insert here your background task
34449 CALL &RXON \ comment this line to disable TERMINAL_INPUT
34451 \ ******************************\
34452 \ here start all interrupts \
34453 \ ******************************\
34454 \ here return all interrupts \
34455 \ ******************************\
34458 \ ******************************\
34460 \ ------------------------------\
34461 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
34462 \ ------------------------------\
34463 \ ... \ init specific I/O sys as you want
34464 \ ... \ before executing default WARM
34465 MOV #WARM,X \ ['] WARM
34467 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
34469 \ ------------------------------\
34471 \ ------------------------------\
34472 CODE STOP \ stops multitasking, must to be used before downloading app
34473 \ ------------------------------\
34474 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
34475 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
34476 MOV X,-2(X) \ restore the default background: SLEEP
34478 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
34479 BIC.B #RC5,&IR_IE \ clear RC5_Int
34480 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
34481 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
34482 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
34483 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
34484 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
34485 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
34487 ." RC5toLCD is removed,"
34488 ." type START to restart"
34489 WARM \ performs reset to reset all interrupt vectors.
34491 \ ------------------------------\
34493 \ ------------------------------\
34494 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
34495 \ ------------------------------\
34496 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
34497 \ - - \CNTL Counter lentgh \ 00 = 16 bits
34498 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
34499 \ -- \ID input divider \ 10 = /4
34500 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
34501 \ - \TBCLR TimerB Clear
34504 \ -------------------------------\
34505 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
34506 \ -- \CM Capture Mode
34511 \ --- \OUTMOD \ 011 = set/reset
34517 \ -------------------------------\
34519 \ -------------------------------\
34521 \ ------------------------------\
34522 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
34523 \ ------------------------------\
34524 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
34525 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
34526 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
34527 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
34529 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
34530 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
34532 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
34533 \ ------------------------------\
34534 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
34535 \ ------------------------------\
34536 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
34537 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
34538 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
34539 \ ------------------------------\
34540 BIS.B #LCDVo,&LCDVo_DIR \
34541 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
34542 \ ------------------------------\
34543 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
34544 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
34545 \ ------------------------------\
34546 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
34547 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
34548 \ ******************************\
34550 \ ******************************\
34551 BIS.B #RC5,&IR_IE \ enable RC5_Int
34552 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
34553 MOV #RC5_INT,&IR_Vec \ init interrupt vector
34554 \ ******************************\
34555 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
34556 \ ******************************\
34557 \ %01 0001 0100 \ TAxCTL
34558 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
34559 \ -- \ ID divided by 1
34560 \ -- \ MC MODE = up to TAxCCRn
34561 \ - \ TACLR clear timer count
34564 \ ------------------------------\
34565 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
34566 \ ------------------------------\
34568 \ --- \ TAIDEX pre divisor
34569 \ ------------------------------\
34570 \ %0000 0000 0000 0101 \ TAxCCR0
34571 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
34572 \ ------------------------------\
34573 \ %0000 0000 0001 0000 \ TAxCCTL0
34574 \ - \ CAP capture/compare mode = compare
34577 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
34578 \ ------------------------------\
34579 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
34580 \ ------------------------------\
34581 \ define LPM mode for ACCEPT \
34582 \ ------------------------------\
34583 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
34584 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
34585 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
34586 \ ------------------------------\
34588 \ ------------------------------\
34589 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
34590 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
34591 \ ------------------------------\
34592 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
34593 \ ------------------------------\
34594 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
34595 \ CMP #2,Y \ Power_ON event
34596 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
34598 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
34600 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
34602 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
34604 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
34605 \ ------------------------------\
34607 \ ------------------------------\
34609 \ ------------------------------\
34610 #1000 20_US \ 1- wait 20 ms
34611 %011 TOP_LCD \ 2- send DB5=DB4=1
34612 #205 20_US \ 3- wait 4,1 ms
34613 %011 TOP_LCD \ 4- send again DB5=DB4=1
34614 #5 20_US \ 5- wait 0,1 ms
34615 %011 TOP_LCD \ 6- send again again DB5=DB4=1
34616 #2 20_US \ wait 40 us = LCD cycle
34617 %010 TOP_LCD \ 7- send DB5=1 DB4=0
34618 #2 20_US \ wait 40 us = LCD cycle
34619 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
34620 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
34621 LCD_CLEAR \ 10- "LCD_Clear"
34622 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
34623 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
34624 LCD_CLEAR \ 10- "LCD_Clear"
34625 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
34626 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
34627 CR ." I love you" \ display message on LCD
34628 ['] CR >BODY IS CR \ CR executes its default value
34629 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
34630 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
34631 PWR_STATE ABORT \ init DP and continues with ABORT
34633 \ ------------------------------\
34635 \ ------------------------------\
34636 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
34637 \ ------------------------------\
34638 MOV #SLEEP,X \ replace default background process SLEEP
34639 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
34640 MOV #WARM,X \ replace default WARM
34641 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
34642 MOV X,PC \ then execute new WARM
34644 \ ------------------------------\
34647 ; downloading RC5toLCD.4th is done
34648 RST_HERE ; this app is protected against <reset>
34653 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
34655 [UNDEFINED] MARKER [IF]
34656 \ https://forth-standard.org/standard/core/MARKER
34658 \ ( "<spaces>name" -- )
34659 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
34660 \ with the execution semantics defined below.
34662 \ name Execution: ( -- )
34663 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
34664 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
34665 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
34666 \ not necessarily provided. No other contextual information such as numeric base is affected
34671 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
34672 SUB #2,Y \ 1 Y = LFA
34673 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
34674 ADD #4,&DP \ 3 add 2 cells
34678 MOV @RSP+,IP \ -- PFA
34679 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
34680 MOV @TOS,&INIDP \ set DP value for RST_STATE
34682 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
34689 \ https://forth-standard.org/standard/core/Fetch
34690 \ @ c-addr -- char fetch char from memory
34697 [UNDEFINED] CONSTANT [IF]
34698 \ https://forth-standard.org/standard/core/CONSTANT
34699 \ CONSTANT <name> n -- define a Forth CONSTANT
34703 MOV TOS,-2(W) \ PFA = n
34710 [UNDEFINED] STATE [IF]
34711 \ https://forth-standard.org/standard/core/STATE
34712 \ STATE -- a-addr holds compiler state
34713 STATEADR CONSTANT STATE
34717 \ https://forth-standard.org/standard/core/Equal
34718 \ = x1 x2 -- flag test x1=x2
34725 XOR #-1,TOS \ 1 flag Z = 1
34730 [UNDEFINED] IF [IF]
34731 \ https://forth-standard.org/standard/core/IF
34732 \ IF -- IFadr initialize conditional forward branch
34733 CODE IF \ immediate
34736 MOV &DP,TOS \ -- HERE
34737 ADD #4,&DP \ compile one word, reserve one word
34738 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
34739 ADD #2,TOS \ -- HERE+2=IFadr
34744 [UNDEFINED] THEN [IF]
34745 \ https://forth-standard.org/standard/core/THEN
34746 \ THEN IFadr -- resolve forward branch
34747 CODE THEN \ immediate
34748 MOV &DP,0(TOS) \ -- IFadr
34754 [UNDEFINED] ELSE [IF]
34755 \ https://forth-standard.org/standard/core/ELSE
34756 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
34757 CODE ELSE \ immediate
34758 ADD #4,&DP \ make room to compile two words
34759 MOV &DP,W \ W=HERE+4
34761 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
34763 MOV W,TOS \ -- ELSEadr
34768 [UNDEFINED] DEFER [IF]
34769 \ https://forth-standard.org/standard/core/DEFER
34770 \ DEFER "<spaces>name" --
34771 \ Skip leading space delimiters. Parse name delimited by a space.
34772 \ Create a definition for name with the execution semantics defined below.
34774 \ name Execution: --
34775 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
34776 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
34780 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
34781 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
34787 [UNDEFINED] DEFER! [IF]
34788 \ https://forth-standard.org/standard/core/DEFERStore
34789 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
34790 CODE DEFER! \ xt2 xt1 --
34791 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
34797 [UNDEFINED] IS [IF]
34798 \ https://forth-standard.org/standard/core/IS
34801 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
34802 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
34803 \ or in a definition : ... ['] U. IS DISPLAY ...
34804 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
34806 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
34809 IF POSTPONE ['] POSTPONE DEFER!
34815 [UNDEFINED] >BODY [IF]
34816 \ https://forth-standard.org/standard/core/toBODY
34817 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
34824 \ CODE 20uS \ n -- 8MHz version
34825 \ BEGIN \ 4 + 16 ~ loop
34826 \ MOV #39,rDOCON \ 39
34833 \ MOV #XDOCON,rDOCON \ 2
34838 CODE 20_US \ n -- n * 20 us
34839 BEGIN \ here we presume that LCD_TIM_IFG = 1...
34841 BIT #1,&LCD_TIM_CTL \ 3
34842 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
34843 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
34845 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
34850 CODE TOP_LCD \ LCD Sample
34851 \ \ if write : %xxxx_WWWW --
34852 \ \ if read : -- %0000_RRRR
34853 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
34854 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
34855 0= IF \ write LCD bits pattern
34856 AND.B #LCD_DB,TOS \
34857 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
34858 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34861 THEN \ read LCD bits pattern
34864 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
34865 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
34866 AND.B #LCD_DB,TOS \
34870 CODE LCD_WRC \ char -- Write Char
34871 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34873 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
34874 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
34875 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
34876 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
34877 COLON \ high level word starts here
34878 TOP_LCD 2 20_US \ write high nibble first
34882 CODE LCD_WRF \ func -- Write Fonction
34883 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34887 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
34888 : LCD_HOME $02 LCD_WRF 100 20_us ;
34890 \ [UNDEFINED] OR [IF]
34892 \ \ https://forth-standard.org/standard/core/OR
34893 \ \ C OR x1 x2 -- x3 logical OR
34901 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
34902 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
34903 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
34904 \ : LCD_FN_SET $20 OR LCD_WrF ;
34905 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
34906 \ : LCD_GOTO $80 OR LCD_WrF ;
34909 \ CODE LCD_RDS \ -- status Read Status
34910 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
34911 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
34912 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
34913 \ COLON \ starts a FORTH word
34914 \ TOP_LCD 2 20_us \ -- %0000_HHHH
34915 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
34916 \ HI2LO \ switch from FORTH to assembler
34917 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
34918 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
34919 \ MOV @RSP+,IP \ restore IP saved by COLON
34923 \ CODE LCD_RDC \ -- char Read Char
34924 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
34929 \ ******************************\
34930 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
34931 \ ******************************\
34932 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
34933 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
34934 BIT.B #SW2,&SW2_IN \ test switch S2
34935 0= IF \ case of switch S2 pressed
34936 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
34938 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
34941 BIT.B #SW1,&SW1_IN \ test switch S1 input
34942 0= IF \ case of Switch S1 pressed
34943 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
34945 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
34949 BW1 \ from quit on truncated RC5 message, repeated RC5 command
34953 \ ******************************\
34954 ASM RC5_INT \ wake up on Px.RC5 change interrupt
34955 \ ******************************\
34956 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
34957 \ ******************************\
34958 \ \ in : SR(9)=old Toggle bit memory (ADD on)
34959 \ \ SMclock = 8|16|24 MHz
34960 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
34961 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
34962 \ \ SR(9)=new Toggle bit memory (ADD on)
34963 \ ******************************\
34964 \ RC5_FirstStartBitHalfCycle: \
34965 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
34966 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
34967 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
34968 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
34970 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
34971 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
34973 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
34974 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
34976 MOV #1778,X \ RC5_Period * 1us
34977 MOV #14,W \ count of loop
34979 \ ******************************\
34980 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
34981 \ ******************************\ |
34982 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
34983 \ RC5_Compute_3/4_Period: \ |
34984 RRUM #1,X \ X=1/2 cycle |
34987 ADD X,Y \ Y=3/4 cycle
34988 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
34990 \ ******************************\
34991 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
34992 \ ******************************\
34993 BIT.B #RC5,&IR_IN \ C_flag = IR bit
34994 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
34995 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
34996 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
34997 SUB #1,W \ decrement count loop
34998 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
34999 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
35000 0<> WHILE \ ----> out of loop ----+
35001 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
35003 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
35004 CMP Y,X \ 1 | cycle time out of bound ?
35005 U>= IF \ 2 ^ | yes:
35006 BIC #$30,&RC5_TIM_CTL \ | | stop timer
35007 GOTO BW1 \ | | quit on truncated RC5 message
35009 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
35011 REPEAT \ ----> loop back --+ | with X = new RC5_period value
35012 \ ******************************\ |
35013 \ RC5_SampleEndOf: \ <---------------------+
35014 \ ******************************\
35015 BIC #$30,&RC5_TIM_CTL \ stop timer
35016 \ ******************************\
35017 \ RC5_ComputeNewRC5word \
35018 \ ******************************\
35019 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
35020 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
35021 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
35022 \ ******************************\
35023 \ RC5_ComputeC6bit \
35024 \ ******************************\
35025 BIT #BIT14,T \ test /C6 bit in T
35026 0= IF BIS #BIT6,X \ set C6 bit in X
35027 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
35028 \ ******************************\
35029 \ RC5_CommandByteIsDone \ -- BASE RC5_code
35030 \ ******************************\
35031 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
35032 \ ******************************\
35033 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
35034 XOR @RSP,T \ (new XOR old) Toggle bits
35035 BIT #UF10,T \ repeated RC5_command ?
35036 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
35037 XOR #UF10,0(RSP) \ 5 toggle bit memory
35038 \ ******************************\
35039 \ Display IR_RC5 code \
35040 \ ******************************\
35041 SUB #8,PSP \ TOS -- x x x x TOS
35042 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
35043 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
35044 MOV #$10,&BASEADR \ set hexadecimal base
35045 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
35046 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
35047 LO2HI \ switch from assembler to FORTH
35048 LCD_CLEAR \ set LCD cursor at home
35049 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
35050 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
35051 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
35052 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
35053 HI2LO \ -- switch from FORTH to assembler
35054 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
35055 MOV @PSP+,TOS \ -- TOS
35059 \ ******************************\
35061 \ ******************************\
35063 \ ... \ insert here your background task
35066 CALL &RXON \ comment this line to disable TERMINAL_INPUT
35068 \ ******************************\
35069 \ here start all interrupts \
35070 \ ******************************\
35071 \ here return all interrupts \
35072 \ ******************************\
35075 \ ******************************\
35077 \ ------------------------------\
35078 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
35079 \ ------------------------------\
35080 \ ... \ init specific I/O sys as you want
35081 \ ... \ before executing default WARM
35082 MOV #WARM,X \ ['] WARM
35084 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
35086 \ ------------------------------\
35088 \ ------------------------------\
35089 CODE STOP \ stops multitasking, must to be used before downloading app
35090 \ ------------------------------\
35091 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
35092 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
35093 MOV X,-2(X) \ restore the default background: SLEEP
35095 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
35096 BIC.B #RC5,&IR_IE \ clear RC5_Int
35097 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
35098 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
35099 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
35100 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
35101 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
35102 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
35104 ." RC5toLCD is removed,"
35105 ." type START to restart"
35106 WARM \ performs reset to reset all interrupt vectors.
35108 \ ------------------------------\
35110 \ ------------------------------\
35111 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
35112 \ ------------------------------\
35113 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
35114 \ - - \CNTL Counter lentgh \ 00 = 16 bits
35115 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
35116 \ -- \ID input divider \ 10 = /4
35117 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
35118 \ - \TBCLR TimerB Clear
35121 \ -------------------------------\
35122 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35123 \ -- \CM Capture Mode
35128 \ --- \OUTMOD \ 011 = set/reset
35134 \ -------------------------------\
35136 \ -------------------------------\
35138 \ ------------------------------\
35139 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
35140 \ ------------------------------\
35141 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
35142 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
35143 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
35144 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
35146 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
35147 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
35149 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
35150 \ ------------------------------\
35151 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
35152 \ ------------------------------\
35153 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
35154 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
35155 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35156 \ ------------------------------\
35157 BIS.B #LCDVo,&LCDVo_DIR \
35158 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
35159 \ ------------------------------\
35160 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35161 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35162 \ ------------------------------\
35163 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35164 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35165 \ ******************************\
35167 \ ******************************\
35168 BIS.B #RC5,&IR_IE \ enable RC5_Int
35169 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35170 MOV #RC5_INT,&IR_Vec \ init interrupt vector
35171 \ ******************************\
35172 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
35173 \ ******************************\
35174 \ %01 0001 0100 \ TAxCTL
35175 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
35176 \ -- \ ID divided by 1
35177 \ -- \ MC MODE = up to TAxCCRn
35178 \ - \ TACLR clear timer count
35181 \ ------------------------------\
35182 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
35183 \ ------------------------------\
35185 \ --- \ TAIDEX pre divisor
35186 \ ------------------------------\
35187 \ %0000 0000 0000 0101 \ TAxCCR0
35188 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
35189 \ ------------------------------\
35190 \ %0000 0000 0001 0000 \ TAxCCTL0
35191 \ - \ CAP capture/compare mode = compare
35194 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
35195 \ ------------------------------\
35196 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
35197 \ ------------------------------\
35198 \ define LPM mode for ACCEPT \
35199 \ ------------------------------\
35200 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35201 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35202 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35203 \ ------------------------------\
35205 \ ------------------------------\
35206 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
35207 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
35208 \ ------------------------------\
35209 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
35210 \ ------------------------------\
35211 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
35212 \ CMP #2,Y \ Power_ON event
35213 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
35215 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
35217 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
35219 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
35221 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
35222 \ ------------------------------\
35224 \ ------------------------------\
35226 \ ------------------------------\
35227 #1000 20_US \ 1- wait 20 ms
35228 %011 TOP_LCD \ 2- send DB5=DB4=1
35229 #205 20_US \ 3- wait 4,1 ms
35230 %011 TOP_LCD \ 4- send again DB5=DB4=1
35231 #5 20_US \ 5- wait 0,1 ms
35232 %011 TOP_LCD \ 6- send again again DB5=DB4=1
35233 #2 20_US \ wait 40 us = LCD cycle
35234 %010 TOP_LCD \ 7- send DB5=1 DB4=0
35235 #2 20_US \ wait 40 us = LCD cycle
35236 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35237 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35238 LCD_CLEAR \ 10- "LCD_Clear"
35239 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35240 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35241 LCD_CLEAR \ 10- "LCD_Clear"
35242 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35243 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35244 CR ." I love you" \ display message on LCD
35245 ['] CR >BODY IS CR \ CR executes its default value
35246 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
35247 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
35248 PWR_STATE ABORT \ init DP and continues with ABORT
35250 \ ------------------------------\
35252 \ ------------------------------\
35253 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
35254 \ ------------------------------\
35255 MOV #SLEEP,X \ replace default background process SLEEP
35256 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
35257 MOV #WARM,X \ replace default WARM
35258 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
35259 MOV X,PC \ then execute new WARM
35261 \ ------------------------------\
35264 ; downloading RC5toLCD.4th is done
35265 RST_HERE ; this app is protected against <reset>
35270 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
35272 [UNDEFINED] MARKER [IF]
35273 \ https://forth-standard.org/standard/core/MARKER
35275 \ ( "<spaces>name" -- )
35276 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
35277 \ with the execution semantics defined below.
35279 \ name Execution: ( -- )
35280 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
35281 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
35282 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
35283 \ not necessarily provided. No other contextual information such as numeric base is affected
35288 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
35289 SUB #2,Y \ 1 Y = LFA
35290 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
35291 ADD #4,&DP \ 3 add 2 cells
35295 MOV @RSP+,IP \ -- PFA
35296 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
35297 MOV @TOS,&INIDP \ set DP value for RST_STATE
35299 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
35306 \ https://forth-standard.org/standard/core/Fetch
35307 \ @ c-addr -- char fetch char from memory
35314 [UNDEFINED] CONSTANT [IF]
35315 \ https://forth-standard.org/standard/core/CONSTANT
35316 \ CONSTANT <name> n -- define a Forth CONSTANT
35320 MOV TOS,-2(W) \ PFA = n
35327 [UNDEFINED] STATE [IF]
35328 \ https://forth-standard.org/standard/core/STATE
35329 \ STATE -- a-addr holds compiler state
35330 STATEADR CONSTANT STATE
35334 \ https://forth-standard.org/standard/core/Equal
35335 \ = x1 x2 -- flag test x1=x2
35342 XOR #-1,TOS \ 1 flag Z = 1
35347 [UNDEFINED] IF [IF]
35348 \ https://forth-standard.org/standard/core/IF
35349 \ IF -- IFadr initialize conditional forward branch
35350 CODE IF \ immediate
35353 MOV &DP,TOS \ -- HERE
35354 ADD #4,&DP \ compile one word, reserve one word
35355 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
35356 ADD #2,TOS \ -- HERE+2=IFadr
35361 [UNDEFINED] THEN [IF]
35362 \ https://forth-standard.org/standard/core/THEN
35363 \ THEN IFadr -- resolve forward branch
35364 CODE THEN \ immediate
35365 MOV &DP,0(TOS) \ -- IFadr
35371 [UNDEFINED] ELSE [IF]
35372 \ https://forth-standard.org/standard/core/ELSE
35373 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
35374 CODE ELSE \ immediate
35375 ADD #4,&DP \ make room to compile two words
35376 MOV &DP,W \ W=HERE+4
35378 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
35380 MOV W,TOS \ -- ELSEadr
35385 [UNDEFINED] DEFER [IF]
35386 \ https://forth-standard.org/standard/core/DEFER
35387 \ DEFER "<spaces>name" --
35388 \ Skip leading space delimiters. Parse name delimited by a space.
35389 \ Create a definition for name with the execution semantics defined below.
35391 \ name Execution: --
35392 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
35393 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
35397 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
35398 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
35404 [UNDEFINED] DEFER! [IF]
35405 \ https://forth-standard.org/standard/core/DEFERStore
35406 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
35407 CODE DEFER! \ xt2 xt1 --
35408 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
35414 [UNDEFINED] IS [IF]
35415 \ https://forth-standard.org/standard/core/IS
35418 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
35419 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
35420 \ or in a definition : ... ['] U. IS DISPLAY ...
35421 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
35423 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
35426 IF POSTPONE ['] POSTPONE DEFER!
35432 [UNDEFINED] >BODY [IF]
35433 \ https://forth-standard.org/standard/core/toBODY
35434 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
35441 \ CODE 20uS \ n -- 8MHz version
35442 \ BEGIN \ 4 + 16 ~ loop
35443 \ MOV #39,rDOCON \ 39
35450 \ MOV #XDOCON,rDOCON \ 2
35455 CODE 20_US \ n -- n * 20 us
35456 BEGIN \ here we presume that LCD_TIM_IFG = 1...
35458 BIT #1,&LCD_TIM_CTL \ 3
35459 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
35460 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
35462 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
35467 CODE TOP_LCD \ LCD Sample
35468 \ \ if write : %xxxx_WWWW --
35469 \ \ if read : -- %0000_RRRR
35470 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
35471 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
35472 0= IF \ write LCD bits pattern
35473 AND.B #LCD_DB,TOS \
35474 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
35475 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35478 THEN \ read LCD bits pattern
35481 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
35482 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
35483 AND.B #LCD_DB,TOS \
35487 CODE LCD_WRC \ char -- Write Char
35488 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35490 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
35491 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
35492 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
35493 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
35494 COLON \ high level word starts here
35495 TOP_LCD 2 20_US \ write high nibble first
35499 CODE LCD_WRF \ func -- Write Fonction
35500 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35504 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
35505 : LCD_HOME $02 LCD_WRF 100 20_us ;
35507 \ [UNDEFINED] OR [IF]
35509 \ \ https://forth-standard.org/standard/core/OR
35510 \ \ C OR x1 x2 -- x3 logical OR
35518 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
35519 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
35520 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
35521 \ : LCD_FN_SET $20 OR LCD_WrF ;
35522 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
35523 \ : LCD_GOTO $80 OR LCD_WrF ;
35526 \ CODE LCD_RDS \ -- status Read Status
35527 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
35528 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
35529 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
35530 \ COLON \ starts a FORTH word
35531 \ TOP_LCD 2 20_us \ -- %0000_HHHH
35532 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
35533 \ HI2LO \ switch from FORTH to assembler
35534 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
35535 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
35536 \ MOV @RSP+,IP \ restore IP saved by COLON
35540 \ CODE LCD_RDC \ -- char Read Char
35541 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
35546 \ ******************************\
35547 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
35548 \ ******************************\
35549 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
35550 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
35551 BIT.B #SW2,&SW2_IN \ test switch S2
35552 0= IF \ case of switch S2 pressed
35553 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
35555 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
35558 BIT.B #SW1,&SW1_IN \ test switch S1 input
35559 0= IF \ case of Switch S1 pressed
35560 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
35562 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
35566 BW1 \ from quit on truncated RC5 message, repeated RC5 command
35570 \ ******************************\
35571 ASM RC5_INT \ wake up on Px.RC5 change interrupt
35572 \ ******************************\
35573 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
35574 \ ******************************\
35575 \ \ in : SR(9)=old Toggle bit memory (ADD on)
35576 \ \ SMclock = 8|16|24 MHz
35577 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
35578 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
35579 \ \ SR(9)=new Toggle bit memory (ADD on)
35580 \ ******************************\
35581 \ RC5_FirstStartBitHalfCycle: \
35582 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
35583 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
35584 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
35585 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
35587 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
35588 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
35590 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
35591 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
35593 MOV #1778,X \ RC5_Period * 1us
35594 MOV #14,W \ count of loop
35596 \ ******************************\
35597 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
35598 \ ******************************\ |
35599 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
35600 \ RC5_Compute_3/4_Period: \ |
35601 RRUM #1,X \ X=1/2 cycle |
35604 ADD X,Y \ Y=3/4 cycle
35605 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
35607 \ ******************************\
35608 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
35609 \ ******************************\
35610 BIT.B #RC5,&IR_IN \ C_flag = IR bit
35611 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
35612 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
35613 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
35614 SUB #1,W \ decrement count loop
35615 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
35616 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
35617 0<> WHILE \ ----> out of loop ----+
35618 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
35620 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
35621 CMP Y,X \ 1 | cycle time out of bound ?
35622 U>= IF \ 2 ^ | yes:
35623 BIC #$30,&RC5_TIM_CTL \ | | stop timer
35624 GOTO BW1 \ | | quit on truncated RC5 message
35626 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
35628 REPEAT \ ----> loop back --+ | with X = new RC5_period value
35629 \ ******************************\ |
35630 \ RC5_SampleEndOf: \ <---------------------+
35631 \ ******************************\
35632 BIC #$30,&RC5_TIM_CTL \ stop timer
35633 \ ******************************\
35634 \ RC5_ComputeNewRC5word \
35635 \ ******************************\
35636 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
35637 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
35638 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
35639 \ ******************************\
35640 \ RC5_ComputeC6bit \
35641 \ ******************************\
35642 BIT #BIT14,T \ test /C6 bit in T
35643 0= IF BIS #BIT6,X \ set C6 bit in X
35644 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
35645 \ ******************************\
35646 \ RC5_CommandByteIsDone \ -- BASE RC5_code
35647 \ ******************************\
35648 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
35649 \ ******************************\
35650 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
35651 XOR @RSP,T \ (new XOR old) Toggle bits
35652 BIT #UF10,T \ repeated RC5_command ?
35653 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
35654 XOR #UF10,0(RSP) \ 5 toggle bit memory
35655 \ ******************************\
35656 \ Display IR_RC5 code \
35657 \ ******************************\
35658 SUB #8,PSP \ TOS -- x x x x TOS
35659 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
35660 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
35661 MOV #$10,&BASEADR \ set hexadecimal base
35662 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
35663 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
35664 LO2HI \ switch from assembler to FORTH
35665 LCD_CLEAR \ set LCD cursor at home
35666 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
35667 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
35668 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
35669 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
35670 HI2LO \ -- switch from FORTH to assembler
35671 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
35672 MOV @PSP+,TOS \ -- TOS
35676 \ ******************************\
35678 \ ******************************\
35680 \ ... \ insert here your background task
35683 CALL &RXON \ comment this line to disable TERMINAL_INPUT
35685 \ ******************************\
35686 \ here start all interrupts \
35687 \ ******************************\
35688 \ here return all interrupts \
35689 \ ******************************\
35692 \ ******************************\
35694 \ ------------------------------\
35695 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
35696 \ ------------------------------\
35697 \ ... \ init specific I/O sys as you want
35698 \ ... \ before executing default WARM
35699 MOV #WARM,X \ ['] WARM
35701 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
35703 \ ------------------------------\
35705 \ ------------------------------\
35706 CODE STOP \ stops multitasking, must to be used before downloading app
35707 \ ------------------------------\
35708 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
35709 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
35710 MOV X,-2(X) \ restore the default background: SLEEP
35712 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
35713 BIC.B #RC5,&IR_IE \ clear RC5_Int
35714 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
35715 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
35716 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
35717 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
35718 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
35719 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
35721 ." RC5toLCD is removed,"
35722 ." type START to restart"
35723 WARM \ performs reset to reset all interrupt vectors.
35725 \ ------------------------------\
35727 \ ------------------------------\
35728 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
35729 \ ------------------------------\
35730 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
35731 \ - - \CNTL Counter lentgh \ 00 = 16 bits
35732 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
35733 \ -- \ID input divider \ 10 = /4
35734 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
35735 \ - \TBCLR TimerB Clear
35738 \ -------------------------------\
35739 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
35740 \ -- \CM Capture Mode
35745 \ --- \OUTMOD \ 011 = set/reset
35751 \ -------------------------------\
35753 \ -------------------------------\
35755 \ ------------------------------\
35756 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
35757 \ ------------------------------\
35758 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
35759 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
35760 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
35761 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
35763 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
35764 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
35766 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
35767 \ ------------------------------\
35768 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
35769 \ ------------------------------\
35770 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
35771 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
35772 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
35773 \ ------------------------------\
35774 BIS.B #LCDVo,&LCDVo_DIR \
35775 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
35776 \ ------------------------------\
35777 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
35778 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
35779 \ ------------------------------\
35780 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
35781 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
35782 \ ******************************\
35784 \ ******************************\
35785 BIS.B #RC5,&IR_IE \ enable RC5_Int
35786 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
35787 MOV #RC5_INT,&IR_Vec \ init interrupt vector
35788 \ ******************************\
35789 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
35790 \ ******************************\
35791 \ %01 0001 0100 \ TAxCTL
35792 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
35793 \ -- \ ID divided by 1
35794 \ -- \ MC MODE = up to TAxCCRn
35795 \ - \ TACLR clear timer count
35798 \ ------------------------------\
35799 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
35800 \ ------------------------------\
35802 \ --- \ TAIDEX pre divisor
35803 \ ------------------------------\
35804 \ %0000 0000 0000 0101 \ TAxCCR0
35805 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
35806 \ ------------------------------\
35807 \ %0000 0000 0001 0000 \ TAxCCTL0
35808 \ - \ CAP capture/compare mode = compare
35811 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
35812 \ ------------------------------\
35813 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
35814 \ ------------------------------\
35815 \ define LPM mode for ACCEPT \
35816 \ ------------------------------\
35817 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
35818 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
35819 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
35820 \ ------------------------------\
35822 \ ------------------------------\
35823 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
35824 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
35825 \ ------------------------------\
35826 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
35827 \ ------------------------------\
35828 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
35829 \ CMP #2,Y \ Power_ON event
35830 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
35832 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
35834 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
35836 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
35838 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
35839 \ ------------------------------\
35841 \ ------------------------------\
35843 \ ------------------------------\
35844 #1000 20_US \ 1- wait 20 ms
35845 %011 TOP_LCD \ 2- send DB5=DB4=1
35846 #205 20_US \ 3- wait 4,1 ms
35847 %011 TOP_LCD \ 4- send again DB5=DB4=1
35848 #5 20_US \ 5- wait 0,1 ms
35849 %011 TOP_LCD \ 6- send again again DB5=DB4=1
35850 #2 20_US \ wait 40 us = LCD cycle
35851 %010 TOP_LCD \ 7- send DB5=1 DB4=0
35852 #2 20_US \ wait 40 us = LCD cycle
35853 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
35854 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
35855 LCD_CLEAR \ 10- "LCD_Clear"
35856 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
35857 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
35858 LCD_CLEAR \ 10- "LCD_Clear"
35859 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
35860 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
35861 CR ." I love you" \ display message on LCD
35862 ['] CR >BODY IS CR \ CR executes its default value
35863 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
35864 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
35865 PWR_STATE ABORT \ init DP and continues with ABORT
35867 \ ------------------------------\
35869 \ ------------------------------\
35870 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
35871 \ ------------------------------\
35872 MOV #SLEEP,X \ replace default background process SLEEP
35873 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
35874 MOV #WARM,X \ replace default WARM
35875 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
35876 MOV X,PC \ then execute new WARM
35878 \ ------------------------------\
35881 ; downloading RC5toLCD.4th is done
35882 RST_HERE ; this app is protected against <reset>
35887 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
35889 [UNDEFINED] MARKER [IF]
35890 \ https://forth-standard.org/standard/core/MARKER
35892 \ ( "<spaces>name" -- )
35893 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
35894 \ with the execution semantics defined below.
35896 \ name Execution: ( -- )
35897 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
35898 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
35899 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
35900 \ not necessarily provided. No other contextual information such as numeric base is affected
35905 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
35906 SUB #2,Y \ 1 Y = LFA
35907 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
35908 ADD #4,&DP \ 3 add 2 cells
35912 MOV @RSP+,IP \ -- PFA
35913 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
35914 MOV @TOS,&INIDP \ set DP value for RST_STATE
35916 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
35923 \ https://forth-standard.org/standard/core/Fetch
35924 \ @ c-addr -- char fetch char from memory
35931 [UNDEFINED] CONSTANT [IF]
35932 \ https://forth-standard.org/standard/core/CONSTANT
35933 \ CONSTANT <name> n -- define a Forth CONSTANT
35937 MOV TOS,-2(W) \ PFA = n
35944 [UNDEFINED] STATE [IF]
35945 \ https://forth-standard.org/standard/core/STATE
35946 \ STATE -- a-addr holds compiler state
35947 STATEADR CONSTANT STATE
35951 \ https://forth-standard.org/standard/core/Equal
35952 \ = x1 x2 -- flag test x1=x2
35959 XOR #-1,TOS \ 1 flag Z = 1
35964 [UNDEFINED] IF [IF]
35965 \ https://forth-standard.org/standard/core/IF
35966 \ IF -- IFadr initialize conditional forward branch
35967 CODE IF \ immediate
35970 MOV &DP,TOS \ -- HERE
35971 ADD #4,&DP \ compile one word, reserve one word
35972 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
35973 ADD #2,TOS \ -- HERE+2=IFadr
35978 [UNDEFINED] THEN [IF]
35979 \ https://forth-standard.org/standard/core/THEN
35980 \ THEN IFadr -- resolve forward branch
35981 CODE THEN \ immediate
35982 MOV &DP,0(TOS) \ -- IFadr
35988 [UNDEFINED] ELSE [IF]
35989 \ https://forth-standard.org/standard/core/ELSE
35990 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
35991 CODE ELSE \ immediate
35992 ADD #4,&DP \ make room to compile two words
35993 MOV &DP,W \ W=HERE+4
35995 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
35997 MOV W,TOS \ -- ELSEadr
36002 [UNDEFINED] DEFER [IF]
36003 \ https://forth-standard.org/standard/core/DEFER
36004 \ DEFER "<spaces>name" --
36005 \ Skip leading space delimiters. Parse name delimited by a space.
36006 \ Create a definition for name with the execution semantics defined below.
36008 \ name Execution: --
36009 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
36010 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
36014 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
36015 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
36021 [UNDEFINED] DEFER! [IF]
36022 \ https://forth-standard.org/standard/core/DEFERStore
36023 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
36024 CODE DEFER! \ xt2 xt1 --
36025 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
36031 [UNDEFINED] IS [IF]
36032 \ https://forth-standard.org/standard/core/IS
36035 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
36036 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
36037 \ or in a definition : ... ['] U. IS DISPLAY ...
36038 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
36040 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
36043 IF POSTPONE ['] POSTPONE DEFER!
36049 [UNDEFINED] >BODY [IF]
36050 \ https://forth-standard.org/standard/core/toBODY
36051 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
36058 \ CODE 20uS \ n -- 8MHz version
36059 \ BEGIN \ 4 + 16 ~ loop
36060 \ MOV #39,rDOCON \ 39
36067 \ MOV #XDOCON,rDOCON \ 2
36072 CODE 20_US \ n -- n * 20 us
36073 BEGIN \ here we presume that LCD_TIM_IFG = 1...
36075 BIT #1,&LCD_TIM_CTL \ 3
36076 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
36077 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
36079 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
36084 CODE TOP_LCD \ LCD Sample
36085 \ \ if write : %xxxx_WWWW --
36086 \ \ if read : -- %0000_RRRR
36087 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36088 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36089 0= IF \ write LCD bits pattern
36090 AND.B #LCD_DB,TOS \
36091 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36092 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36095 THEN \ read LCD bits pattern
36098 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36099 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36100 AND.B #LCD_DB,TOS \
36104 CODE LCD_WRC \ char -- Write Char
36105 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36107 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
36108 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
36109 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36110 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36111 COLON \ high level word starts here
36112 TOP_LCD 2 20_US \ write high nibble first
36116 CODE LCD_WRF \ func -- Write Fonction
36117 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36121 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
36122 : LCD_HOME $02 LCD_WRF 100 20_us ;
36124 \ [UNDEFINED] OR [IF]
36126 \ \ https://forth-standard.org/standard/core/OR
36127 \ \ C OR x1 x2 -- x3 logical OR
36135 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
36136 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
36137 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
36138 \ : LCD_FN_SET $20 OR LCD_WrF ;
36139 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
36140 \ : LCD_GOTO $80 OR LCD_WrF ;
36143 \ CODE LCD_RDS \ -- status Read Status
36144 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36145 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36146 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36147 \ COLON \ starts a FORTH word
36148 \ TOP_LCD 2 20_us \ -- %0000_HHHH
36149 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
36150 \ HI2LO \ switch from FORTH to assembler
36151 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
36152 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
36153 \ MOV @RSP+,IP \ restore IP saved by COLON
36157 \ CODE LCD_RDC \ -- char Read Char
36158 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36163 \ ******************************\
36164 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36165 \ ******************************\
36166 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
36167 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
36168 BIT.B #SW2,&SW2_IN \ test switch S2
36169 0= IF \ case of switch S2 pressed
36170 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
36172 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
36175 BIT.B #SW1,&SW1_IN \ test switch S1 input
36176 0= IF \ case of Switch S1 pressed
36177 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
36179 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
36183 BW1 \ from quit on truncated RC5 message, repeated RC5 command
36187 \ ******************************\
36188 ASM RC5_INT \ wake up on Px.RC5 change interrupt
36189 \ ******************************\
36190 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36191 \ ******************************\
36192 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36193 \ \ SMclock = 8|16|24 MHz
36194 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
36195 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
36196 \ \ SR(9)=new Toggle bit memory (ADD on)
36197 \ ******************************\
36198 \ RC5_FirstStartBitHalfCycle: \
36199 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
36200 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
36201 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
36202 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
36204 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
36205 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
36207 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
36208 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
36210 MOV #1778,X \ RC5_Period * 1us
36211 MOV #14,W \ count of loop
36213 \ ******************************\
36214 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
36215 \ ******************************\ |
36216 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
36217 \ RC5_Compute_3/4_Period: \ |
36218 RRUM #1,X \ X=1/2 cycle |
36221 ADD X,Y \ Y=3/4 cycle
36222 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
36224 \ ******************************\
36225 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
36226 \ ******************************\
36227 BIT.B #RC5,&IR_IN \ C_flag = IR bit
36228 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
36229 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
36230 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
36231 SUB #1,W \ decrement count loop
36232 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
36233 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
36234 0<> WHILE \ ----> out of loop ----+
36235 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
36237 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
36238 CMP Y,X \ 1 | cycle time out of bound ?
36239 U>= IF \ 2 ^ | yes:
36240 BIC #$30,&RC5_TIM_CTL \ | | stop timer
36241 GOTO BW1 \ | | quit on truncated RC5 message
36243 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
36245 REPEAT \ ----> loop back --+ | with X = new RC5_period value
36246 \ ******************************\ |
36247 \ RC5_SampleEndOf: \ <---------------------+
36248 \ ******************************\
36249 BIC #$30,&RC5_TIM_CTL \ stop timer
36250 \ ******************************\
36251 \ RC5_ComputeNewRC5word \
36252 \ ******************************\
36253 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
36254 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
36255 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
36256 \ ******************************\
36257 \ RC5_ComputeC6bit \
36258 \ ******************************\
36259 BIT #BIT14,T \ test /C6 bit in T
36260 0= IF BIS #BIT6,X \ set C6 bit in X
36261 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
36262 \ ******************************\
36263 \ RC5_CommandByteIsDone \ -- BASE RC5_code
36264 \ ******************************\
36265 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
36266 \ ******************************\
36267 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
36268 XOR @RSP,T \ (new XOR old) Toggle bits
36269 BIT #UF10,T \ repeated RC5_command ?
36270 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
36271 XOR #UF10,0(RSP) \ 5 toggle bit memory
36272 \ ******************************\
36273 \ Display IR_RC5 code \
36274 \ ******************************\
36275 SUB #8,PSP \ TOS -- x x x x TOS
36276 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
36277 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
36278 MOV #$10,&BASEADR \ set hexadecimal base
36279 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
36280 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
36281 LO2HI \ switch from assembler to FORTH
36282 LCD_CLEAR \ set LCD cursor at home
36283 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
36284 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
36285 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
36286 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
36287 HI2LO \ -- switch from FORTH to assembler
36288 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
36289 MOV @PSP+,TOS \ -- TOS
36293 \ ******************************\
36295 \ ******************************\
36297 \ ... \ insert here your background task
36300 CALL &RXON \ comment this line to disable TERMINAL_INPUT
36302 \ ******************************\
36303 \ here start all interrupts \
36304 \ ******************************\
36305 \ here return all interrupts \
36306 \ ******************************\
36309 \ ******************************\
36311 \ ------------------------------\
36312 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
36313 \ ------------------------------\
36314 \ ... \ init specific I/O sys as you want
36315 \ ... \ before executing default WARM
36316 MOV #WARM,X \ ['] WARM
36318 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
36320 \ ------------------------------\
36322 \ ------------------------------\
36323 CODE STOP \ stops multitasking, must to be used before downloading app
36324 \ ------------------------------\
36325 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
36326 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
36327 MOV X,-2(X) \ restore the default background: SLEEP
36329 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
36330 BIC.B #RC5,&IR_IE \ clear RC5_Int
36331 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
36332 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
36333 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
36334 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
36335 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
36336 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
36338 ." RC5toLCD is removed,"
36339 ." type START to restart"
36340 WARM \ performs reset to reset all interrupt vectors.
36342 \ ------------------------------\
36344 \ ------------------------------\
36345 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
36346 \ ------------------------------\
36347 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
36348 \ - - \CNTL Counter lentgh \ 00 = 16 bits
36349 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
36350 \ -- \ID input divider \ 10 = /4
36351 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
36352 \ - \TBCLR TimerB Clear
36355 \ -------------------------------\
36356 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36357 \ -- \CM Capture Mode
36362 \ --- \OUTMOD \ 011 = set/reset
36368 \ -------------------------------\
36370 \ -------------------------------\
36372 \ ------------------------------\
36373 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
36374 \ ------------------------------\
36375 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
36376 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
36377 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
36378 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
36380 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
36381 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
36383 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
36384 \ ------------------------------\
36385 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
36386 \ ------------------------------\
36387 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
36388 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
36389 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
36390 \ ------------------------------\
36391 BIS.B #LCDVo,&LCDVo_DIR \
36392 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
36393 \ ------------------------------\
36394 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
36395 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
36396 \ ------------------------------\
36397 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
36398 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
36399 \ ******************************\
36401 \ ******************************\
36402 BIS.B #RC5,&IR_IE \ enable RC5_Int
36403 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
36404 MOV #RC5_INT,&IR_Vec \ init interrupt vector
36405 \ ******************************\
36406 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
36407 \ ******************************\
36408 \ %01 0001 0100 \ TAxCTL
36409 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
36410 \ -- \ ID divided by 1
36411 \ -- \ MC MODE = up to TAxCCRn
36412 \ - \ TACLR clear timer count
36415 \ ------------------------------\
36416 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
36417 \ ------------------------------\
36419 \ --- \ TAIDEX pre divisor
36420 \ ------------------------------\
36421 \ %0000 0000 0000 0101 \ TAxCCR0
36422 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
36423 \ ------------------------------\
36424 \ %0000 0000 0001 0000 \ TAxCCTL0
36425 \ - \ CAP capture/compare mode = compare
36428 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
36429 \ ------------------------------\
36430 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
36431 \ ------------------------------\
36432 \ define LPM mode for ACCEPT \
36433 \ ------------------------------\
36434 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
36435 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
36436 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
36437 \ ------------------------------\
36439 \ ------------------------------\
36440 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
36441 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
36442 \ ------------------------------\
36443 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
36444 \ ------------------------------\
36445 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
36446 \ CMP #2,Y \ Power_ON event
36447 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
36449 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
36451 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
36453 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
36455 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
36456 \ ------------------------------\
36458 \ ------------------------------\
36460 \ ------------------------------\
36461 #1000 20_US \ 1- wait 20 ms
36462 %011 TOP_LCD \ 2- send DB5=DB4=1
36463 #205 20_US \ 3- wait 4,1 ms
36464 %011 TOP_LCD \ 4- send again DB5=DB4=1
36465 #5 20_US \ 5- wait 0,1 ms
36466 %011 TOP_LCD \ 6- send again again DB5=DB4=1
36467 #2 20_US \ wait 40 us = LCD cycle
36468 %010 TOP_LCD \ 7- send DB5=1 DB4=0
36469 #2 20_US \ wait 40 us = LCD cycle
36470 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
36471 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
36472 LCD_CLEAR \ 10- "LCD_Clear"
36473 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
36474 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
36475 LCD_CLEAR \ 10- "LCD_Clear"
36476 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
36477 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
36478 CR ." I love you" \ display message on LCD
36479 ['] CR >BODY IS CR \ CR executes its default value
36480 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
36481 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
36482 PWR_STATE ABORT \ init DP and continues with ABORT
36484 \ ------------------------------\
36486 \ ------------------------------\
36487 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
36488 \ ------------------------------\
36489 MOV #SLEEP,X \ replace default background process SLEEP
36490 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
36491 MOV #WARM,X \ replace default WARM
36492 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
36493 MOV X,PC \ then execute new WARM
36495 \ ------------------------------\
36498 ; downloading RC5toLCD.4th is done
36499 RST_HERE ; this app is protected against <reset>
36504 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
36506 [UNDEFINED] MARKER [IF]
36507 \ https://forth-standard.org/standard/core/MARKER
36509 \ ( "<spaces>name" -- )
36510 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
36511 \ with the execution semantics defined below.
36513 \ name Execution: ( -- )
36514 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
36515 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
36516 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
36517 \ not necessarily provided. No other contextual information such as numeric base is affected
36522 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
36523 SUB #2,Y \ 1 Y = LFA
36524 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
36525 ADD #4,&DP \ 3 add 2 cells
36529 MOV @RSP+,IP \ -- PFA
36530 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
36531 MOV @TOS,&INIDP \ set DP value for RST_STATE
36533 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
36540 \ https://forth-standard.org/standard/core/Fetch
36541 \ @ c-addr -- char fetch char from memory
36548 [UNDEFINED] CONSTANT [IF]
36549 \ https://forth-standard.org/standard/core/CONSTANT
36550 \ CONSTANT <name> n -- define a Forth CONSTANT
36554 MOV TOS,-2(W) \ PFA = n
36561 [UNDEFINED] STATE [IF]
36562 \ https://forth-standard.org/standard/core/STATE
36563 \ STATE -- a-addr holds compiler state
36564 STATEADR CONSTANT STATE
36568 \ https://forth-standard.org/standard/core/Equal
36569 \ = x1 x2 -- flag test x1=x2
36576 XOR #-1,TOS \ 1 flag Z = 1
36581 [UNDEFINED] IF [IF]
36582 \ https://forth-standard.org/standard/core/IF
36583 \ IF -- IFadr initialize conditional forward branch
36584 CODE IF \ immediate
36587 MOV &DP,TOS \ -- HERE
36588 ADD #4,&DP \ compile one word, reserve one word
36589 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
36590 ADD #2,TOS \ -- HERE+2=IFadr
36595 [UNDEFINED] THEN [IF]
36596 \ https://forth-standard.org/standard/core/THEN
36597 \ THEN IFadr -- resolve forward branch
36598 CODE THEN \ immediate
36599 MOV &DP,0(TOS) \ -- IFadr
36605 [UNDEFINED] ELSE [IF]
36606 \ https://forth-standard.org/standard/core/ELSE
36607 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
36608 CODE ELSE \ immediate
36609 ADD #4,&DP \ make room to compile two words
36610 MOV &DP,W \ W=HERE+4
36612 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
36614 MOV W,TOS \ -- ELSEadr
36619 [UNDEFINED] DEFER [IF]
36620 \ https://forth-standard.org/standard/core/DEFER
36621 \ DEFER "<spaces>name" --
36622 \ Skip leading space delimiters. Parse name delimited by a space.
36623 \ Create a definition for name with the execution semantics defined below.
36625 \ name Execution: --
36626 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
36627 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
36631 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
36632 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
36638 [UNDEFINED] DEFER! [IF]
36639 \ https://forth-standard.org/standard/core/DEFERStore
36640 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
36641 CODE DEFER! \ xt2 xt1 --
36642 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
36648 [UNDEFINED] IS [IF]
36649 \ https://forth-standard.org/standard/core/IS
36652 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
36653 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
36654 \ or in a definition : ... ['] U. IS DISPLAY ...
36655 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
36657 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
36660 IF POSTPONE ['] POSTPONE DEFER!
36666 [UNDEFINED] >BODY [IF]
36667 \ https://forth-standard.org/standard/core/toBODY
36668 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
36675 \ CODE 20uS \ n -- 8MHz version
36676 \ BEGIN \ 4 + 16 ~ loop
36677 \ MOV #39,rDOCON \ 39
36684 \ MOV #XDOCON,rDOCON \ 2
36689 CODE 20_US \ n -- n * 20 us
36690 BEGIN \ here we presume that LCD_TIM_IFG = 1...
36692 BIT #1,&LCD_TIM_CTL \ 3
36693 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
36694 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
36696 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
36701 CODE TOP_LCD \ LCD Sample
36702 \ \ if write : %xxxx_WWWW --
36703 \ \ if read : -- %0000_RRRR
36704 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
36705 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
36706 0= IF \ write LCD bits pattern
36707 AND.B #LCD_DB,TOS \
36708 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
36709 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36712 THEN \ read LCD bits pattern
36715 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
36716 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
36717 AND.B #LCD_DB,TOS \
36721 CODE LCD_WRC \ char -- Write Char
36722 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36724 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
36725 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
36726 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
36727 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
36728 COLON \ high level word starts here
36729 TOP_LCD 2 20_US \ write high nibble first
36733 CODE LCD_WRF \ func -- Write Fonction
36734 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36738 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
36739 : LCD_HOME $02 LCD_WRF 100 20_us ;
36741 \ [UNDEFINED] OR [IF]
36743 \ \ https://forth-standard.org/standard/core/OR
36744 \ \ C OR x1 x2 -- x3 logical OR
36752 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
36753 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
36754 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
36755 \ : LCD_FN_SET $20 OR LCD_WrF ;
36756 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
36757 \ : LCD_GOTO $80 OR LCD_WrF ;
36760 \ CODE LCD_RDS \ -- status Read Status
36761 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
36762 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
36763 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
36764 \ COLON \ starts a FORTH word
36765 \ TOP_LCD 2 20_us \ -- %0000_HHHH
36766 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
36767 \ HI2LO \ switch from FORTH to assembler
36768 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
36769 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
36770 \ MOV @RSP+,IP \ restore IP saved by COLON
36774 \ CODE LCD_RDC \ -- char Read Char
36775 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
36780 \ ******************************\
36781 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
36782 \ ******************************\
36783 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
36784 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
36785 BIT.B #SW2,&SW2_IN \ test switch S2
36786 0= IF \ case of switch S2 pressed
36787 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
36789 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
36792 BIT.B #SW1,&SW1_IN \ test switch S1 input
36793 0= IF \ case of Switch S1 pressed
36794 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
36796 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
36800 BW1 \ from quit on truncated RC5 message, repeated RC5 command
36804 \ ******************************\
36805 ASM RC5_INT \ wake up on Px.RC5 change interrupt
36806 \ ******************************\
36807 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
36808 \ ******************************\
36809 \ \ in : SR(9)=old Toggle bit memory (ADD on)
36810 \ \ SMclock = 8|16|24 MHz
36811 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
36812 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
36813 \ \ SR(9)=new Toggle bit memory (ADD on)
36814 \ ******************************\
36815 \ RC5_FirstStartBitHalfCycle: \
36816 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
36817 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
36818 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
36819 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
36821 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
36822 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
36824 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
36825 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
36827 MOV #1778,X \ RC5_Period * 1us
36828 MOV #14,W \ count of loop
36830 \ ******************************\
36831 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
36832 \ ******************************\ |
36833 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
36834 \ RC5_Compute_3/4_Period: \ |
36835 RRUM #1,X \ X=1/2 cycle |
36838 ADD X,Y \ Y=3/4 cycle
36839 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
36841 \ ******************************\
36842 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
36843 \ ******************************\
36844 BIT.B #RC5,&IR_IN \ C_flag = IR bit
36845 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
36846 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
36847 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
36848 SUB #1,W \ decrement count loop
36849 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
36850 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
36851 0<> WHILE \ ----> out of loop ----+
36852 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
36854 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
36855 CMP Y,X \ 1 | cycle time out of bound ?
36856 U>= IF \ 2 ^ | yes:
36857 BIC #$30,&RC5_TIM_CTL \ | | stop timer
36858 GOTO BW1 \ | | quit on truncated RC5 message
36860 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
36862 REPEAT \ ----> loop back --+ | with X = new RC5_period value
36863 \ ******************************\ |
36864 \ RC5_SampleEndOf: \ <---------------------+
36865 \ ******************************\
36866 BIC #$30,&RC5_TIM_CTL \ stop timer
36867 \ ******************************\
36868 \ RC5_ComputeNewRC5word \
36869 \ ******************************\
36870 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
36871 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
36872 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
36873 \ ******************************\
36874 \ RC5_ComputeC6bit \
36875 \ ******************************\
36876 BIT #BIT14,T \ test /C6 bit in T
36877 0= IF BIS #BIT6,X \ set C6 bit in X
36878 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
36879 \ ******************************\
36880 \ RC5_CommandByteIsDone \ -- BASE RC5_code
36881 \ ******************************\
36882 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
36883 \ ******************************\
36884 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
36885 XOR @RSP,T \ (new XOR old) Toggle bits
36886 BIT #UF10,T \ repeated RC5_command ?
36887 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
36888 XOR #UF10,0(RSP) \ 5 toggle bit memory
36889 \ ******************************\
36890 \ Display IR_RC5 code \
36891 \ ******************************\
36892 SUB #8,PSP \ TOS -- x x x x TOS
36893 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
36894 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
36895 MOV #$10,&BASEADR \ set hexadecimal base
36896 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
36897 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
36898 LO2HI \ switch from assembler to FORTH
36899 LCD_CLEAR \ set LCD cursor at home
36900 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
36901 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
36902 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
36903 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
36904 HI2LO \ -- switch from FORTH to assembler
36905 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
36906 MOV @PSP+,TOS \ -- TOS
36910 \ ******************************\
36912 \ ******************************\
36914 \ ... \ insert here your background task
36917 CALL &RXON \ comment this line to disable TERMINAL_INPUT
36919 \ ******************************\
36920 \ here start all interrupts \
36921 \ ******************************\
36922 \ here return all interrupts \
36923 \ ******************************\
36926 \ ******************************\
36928 \ ------------------------------\
36929 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
36930 \ ------------------------------\
36931 \ ... \ init specific I/O sys as you want
36932 \ ... \ before executing default WARM
36933 MOV #WARM,X \ ['] WARM
36935 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
36937 \ ------------------------------\
36939 \ ------------------------------\
36940 CODE STOP \ stops multitasking, must to be used before downloading app
36941 \ ------------------------------\
36942 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
36943 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
36944 MOV X,-2(X) \ restore the default background: SLEEP
36946 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
36947 BIC.B #RC5,&IR_IE \ clear RC5_Int
36948 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
36949 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
36950 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
36951 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
36952 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
36953 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
36955 ." RC5toLCD is removed,"
36956 ." type START to restart"
36957 WARM \ performs reset to reset all interrupt vectors.
36959 \ ------------------------------\
36961 \ ------------------------------\
36962 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
36963 \ ------------------------------\
36964 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
36965 \ - - \CNTL Counter lentgh \ 00 = 16 bits
36966 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
36967 \ -- \ID input divider \ 10 = /4
36968 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
36969 \ - \TBCLR TimerB Clear
36972 \ -------------------------------\
36973 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
36974 \ -- \CM Capture Mode
36979 \ --- \OUTMOD \ 011 = set/reset
36985 \ -------------------------------\
36987 \ -------------------------------\
36989 \ ------------------------------\
36990 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
36991 \ ------------------------------\
36992 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
36993 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
36994 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
36995 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
36997 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
36998 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
37000 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
37001 \ ------------------------------\
37002 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
37003 \ ------------------------------\
37004 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
37005 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
37006 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37007 \ ------------------------------\
37008 BIS.B #LCDVo,&LCDVo_DIR \
37009 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
37010 \ ------------------------------\
37011 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37012 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37013 \ ------------------------------\
37014 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37015 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37016 \ ******************************\
37018 \ ******************************\
37019 BIS.B #RC5,&IR_IE \ enable RC5_Int
37020 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37021 MOV #RC5_INT,&IR_Vec \ init interrupt vector
37022 \ ******************************\
37023 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
37024 \ ******************************\
37025 \ %01 0001 0100 \ TAxCTL
37026 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
37027 \ -- \ ID divided by 1
37028 \ -- \ MC MODE = up to TAxCCRn
37029 \ - \ TACLR clear timer count
37032 \ ------------------------------\
37033 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
37034 \ ------------------------------\
37036 \ --- \ TAIDEX pre divisor
37037 \ ------------------------------\
37038 \ %0000 0000 0000 0101 \ TAxCCR0
37039 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
37040 \ ------------------------------\
37041 \ %0000 0000 0001 0000 \ TAxCCTL0
37042 \ - \ CAP capture/compare mode = compare
37045 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
37046 \ ------------------------------\
37047 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
37048 \ ------------------------------\
37049 \ define LPM mode for ACCEPT \
37050 \ ------------------------------\
37051 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37052 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37053 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37054 \ ------------------------------\
37056 \ ------------------------------\
37057 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
37058 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
37059 \ ------------------------------\
37060 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
37061 \ ------------------------------\
37062 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
37063 \ CMP #2,Y \ Power_ON event
37064 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
37066 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
37068 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
37070 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
37072 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
37073 \ ------------------------------\
37075 \ ------------------------------\
37077 \ ------------------------------\
37078 #1000 20_US \ 1- wait 20 ms
37079 %011 TOP_LCD \ 2- send DB5=DB4=1
37080 #205 20_US \ 3- wait 4,1 ms
37081 %011 TOP_LCD \ 4- send again DB5=DB4=1
37082 #5 20_US \ 5- wait 0,1 ms
37083 %011 TOP_LCD \ 6- send again again DB5=DB4=1
37084 #2 20_US \ wait 40 us = LCD cycle
37085 %010 TOP_LCD \ 7- send DB5=1 DB4=0
37086 #2 20_US \ wait 40 us = LCD cycle
37087 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37088 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
37089 LCD_CLEAR \ 10- "LCD_Clear"
37090 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
37091 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
37092 LCD_CLEAR \ 10- "LCD_Clear"
37093 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
37094 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
37095 CR ." I love you" \ display message on LCD
37096 ['] CR >BODY IS CR \ CR executes its default value
37097 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
37098 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
37099 PWR_STATE ABORT \ init DP and continues with ABORT
37101 \ ------------------------------\
37103 \ ------------------------------\
37104 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
37105 \ ------------------------------\
37106 MOV #SLEEP,X \ replace default background process SLEEP
37107 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
37108 MOV #WARM,X \ replace default WARM
37109 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
37110 MOV X,PC \ then execute new WARM
37112 \ ------------------------------\
37115 ; downloading RC5toLCD.4th is done
37116 RST_HERE ; this app is protected against <reset>
37121 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
37123 [UNDEFINED] MARKER [IF]
37124 \ https://forth-standard.org/standard/core/MARKER
37126 \ ( "<spaces>name" -- )
37127 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
37128 \ with the execution semantics defined below.
37130 \ name Execution: ( -- )
37131 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
37132 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
37133 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
37134 \ not necessarily provided. No other contextual information such as numeric base is affected
37139 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
37140 SUB #2,Y \ 1 Y = LFA
37141 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
37142 ADD #4,&DP \ 3 add 2 cells
37146 MOV @RSP+,IP \ -- PFA
37147 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
37148 MOV @TOS,&INIDP \ set DP value for RST_STATE
37150 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
37157 \ https://forth-standard.org/standard/core/Fetch
37158 \ @ c-addr -- char fetch char from memory
37165 [UNDEFINED] CONSTANT [IF]
37166 \ https://forth-standard.org/standard/core/CONSTANT
37167 \ CONSTANT <name> n -- define a Forth CONSTANT
37171 MOV TOS,-2(W) \ PFA = n
37178 [UNDEFINED] STATE [IF]
37179 \ https://forth-standard.org/standard/core/STATE
37180 \ STATE -- a-addr holds compiler state
37181 STATEADR CONSTANT STATE
37185 \ https://forth-standard.org/standard/core/Equal
37186 \ = x1 x2 -- flag test x1=x2
37193 XOR #-1,TOS \ 1 flag Z = 1
37198 [UNDEFINED] IF [IF]
37199 \ https://forth-standard.org/standard/core/IF
37200 \ IF -- IFadr initialize conditional forward branch
37201 CODE IF \ immediate
37204 MOV &DP,TOS \ -- HERE
37205 ADD #4,&DP \ compile one word, reserve one word
37206 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
37207 ADD #2,TOS \ -- HERE+2=IFadr
37212 [UNDEFINED] THEN [IF]
37213 \ https://forth-standard.org/standard/core/THEN
37214 \ THEN IFadr -- resolve forward branch
37215 CODE THEN \ immediate
37216 MOV &DP,0(TOS) \ -- IFadr
37222 [UNDEFINED] ELSE [IF]
37223 \ https://forth-standard.org/standard/core/ELSE
37224 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
37225 CODE ELSE \ immediate
37226 ADD #4,&DP \ make room to compile two words
37227 MOV &DP,W \ W=HERE+4
37229 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
37231 MOV W,TOS \ -- ELSEadr
37236 [UNDEFINED] DEFER [IF]
37237 \ https://forth-standard.org/standard/core/DEFER
37238 \ DEFER "<spaces>name" --
37239 \ Skip leading space delimiters. Parse name delimited by a space.
37240 \ Create a definition for name with the execution semantics defined below.
37242 \ name Execution: --
37243 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
37244 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
37248 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
37249 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
37255 [UNDEFINED] DEFER! [IF]
37256 \ https://forth-standard.org/standard/core/DEFERStore
37257 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
37258 CODE DEFER! \ xt2 xt1 --
37259 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
37265 [UNDEFINED] IS [IF]
37266 \ https://forth-standard.org/standard/core/IS
37269 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
37270 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
37271 \ or in a definition : ... ['] U. IS DISPLAY ...
37272 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
37274 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
37277 IF POSTPONE ['] POSTPONE DEFER!
37283 [UNDEFINED] >BODY [IF]
37284 \ https://forth-standard.org/standard/core/toBODY
37285 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
37292 \ CODE 20uS \ n -- 8MHz version
37293 \ BEGIN \ 4 + 16 ~ loop
37294 \ MOV #39,rDOCON \ 39
37301 \ MOV #XDOCON,rDOCON \ 2
37306 CODE 20_US \ n -- n * 20 us
37307 BEGIN \ here we presume that LCD_TIM_IFG = 1...
37309 BIT #1,&LCD_TIM_CTL \ 3
37310 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
37311 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
37313 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
37318 CODE TOP_LCD \ LCD Sample
37319 \ \ if write : %xxxx_WWWW --
37320 \ \ if read : -- %0000_RRRR
37321 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
37322 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
37323 0= IF \ write LCD bits pattern
37324 AND.B #LCD_DB,TOS \
37325 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
37326 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37329 THEN \ read LCD bits pattern
37332 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37333 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
37334 AND.B #LCD_DB,TOS \
37338 CODE LCD_WRC \ char -- Write Char
37339 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37341 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
37342 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
37343 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
37344 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
37345 COLON \ high level word starts here
37346 TOP_LCD 2 20_US \ write high nibble first
37350 CODE LCD_WRF \ func -- Write Fonction
37351 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37355 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
37356 : LCD_HOME $02 LCD_WRF 100 20_us ;
37358 \ [UNDEFINED] OR [IF]
37360 \ \ https://forth-standard.org/standard/core/OR
37361 \ \ C OR x1 x2 -- x3 logical OR
37369 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
37370 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
37371 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
37372 \ : LCD_FN_SET $20 OR LCD_WrF ;
37373 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
37374 \ : LCD_GOTO $80 OR LCD_WrF ;
37377 \ CODE LCD_RDS \ -- status Read Status
37378 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37379 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
37380 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
37381 \ COLON \ starts a FORTH word
37382 \ TOP_LCD 2 20_us \ -- %0000_HHHH
37383 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
37384 \ HI2LO \ switch from FORTH to assembler
37385 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
37386 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
37387 \ MOV @RSP+,IP \ restore IP saved by COLON
37391 \ CODE LCD_RDC \ -- char Read Char
37392 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37397 \ ******************************\
37398 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
37399 \ ******************************\
37400 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
37401 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
37402 BIT.B #SW2,&SW2_IN \ test switch S2
37403 0= IF \ case of switch S2 pressed
37404 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
37406 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
37409 BIT.B #SW1,&SW1_IN \ test switch S1 input
37410 0= IF \ case of Switch S1 pressed
37411 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
37413 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
37417 BW1 \ from quit on truncated RC5 message, repeated RC5 command
37421 \ ******************************\
37422 ASM RC5_INT \ wake up on Px.RC5 change interrupt
37423 \ ******************************\
37424 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
37425 \ ******************************\
37426 \ \ in : SR(9)=old Toggle bit memory (ADD on)
37427 \ \ SMclock = 8|16|24 MHz
37428 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
37429 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
37430 \ \ SR(9)=new Toggle bit memory (ADD on)
37431 \ ******************************\
37432 \ RC5_FirstStartBitHalfCycle: \
37433 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
37434 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
37435 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
37436 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
37438 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
37439 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
37441 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
37442 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
37444 MOV #1778,X \ RC5_Period * 1us
37445 MOV #14,W \ count of loop
37447 \ ******************************\
37448 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
37449 \ ******************************\ |
37450 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
37451 \ RC5_Compute_3/4_Period: \ |
37452 RRUM #1,X \ X=1/2 cycle |
37455 ADD X,Y \ Y=3/4 cycle
37456 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
37458 \ ******************************\
37459 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
37460 \ ******************************\
37461 BIT.B #RC5,&IR_IN \ C_flag = IR bit
37462 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
37463 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
37464 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
37465 SUB #1,W \ decrement count loop
37466 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
37467 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
37468 0<> WHILE \ ----> out of loop ----+
37469 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
37471 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
37472 CMP Y,X \ 1 | cycle time out of bound ?
37473 U>= IF \ 2 ^ | yes:
37474 BIC #$30,&RC5_TIM_CTL \ | | stop timer
37475 GOTO BW1 \ | | quit on truncated RC5 message
37477 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
37479 REPEAT \ ----> loop back --+ | with X = new RC5_period value
37480 \ ******************************\ |
37481 \ RC5_SampleEndOf: \ <---------------------+
37482 \ ******************************\
37483 BIC #$30,&RC5_TIM_CTL \ stop timer
37484 \ ******************************\
37485 \ RC5_ComputeNewRC5word \
37486 \ ******************************\
37487 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
37488 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
37489 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
37490 \ ******************************\
37491 \ RC5_ComputeC6bit \
37492 \ ******************************\
37493 BIT #BIT14,T \ test /C6 bit in T
37494 0= IF BIS #BIT6,X \ set C6 bit in X
37495 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
37496 \ ******************************\
37497 \ RC5_CommandByteIsDone \ -- BASE RC5_code
37498 \ ******************************\
37499 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
37500 \ ******************************\
37501 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
37502 XOR @RSP,T \ (new XOR old) Toggle bits
37503 BIT #UF10,T \ repeated RC5_command ?
37504 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
37505 XOR #UF10,0(RSP) \ 5 toggle bit memory
37506 \ ******************************\
37507 \ Display IR_RC5 code \
37508 \ ******************************\
37509 SUB #8,PSP \ TOS -- x x x x TOS
37510 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
37511 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
37512 MOV #$10,&BASEADR \ set hexadecimal base
37513 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
37514 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
37515 LO2HI \ switch from assembler to FORTH
37516 LCD_CLEAR \ set LCD cursor at home
37517 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
37518 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
37519 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
37520 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
37521 HI2LO \ -- switch from FORTH to assembler
37522 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
37523 MOV @PSP+,TOS \ -- TOS
37527 \ ******************************\
37529 \ ******************************\
37531 \ ... \ insert here your background task
37534 CALL &RXON \ comment this line to disable TERMINAL_INPUT
37536 \ ******************************\
37537 \ here start all interrupts \
37538 \ ******************************\
37539 \ here return all interrupts \
37540 \ ******************************\
37543 \ ******************************\
37545 \ ------------------------------\
37546 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
37547 \ ------------------------------\
37548 \ ... \ init specific I/O sys as you want
37549 \ ... \ before executing default WARM
37550 MOV #WARM,X \ ['] WARM
37552 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
37554 \ ------------------------------\
37556 \ ------------------------------\
37557 CODE STOP \ stops multitasking, must to be used before downloading app
37558 \ ------------------------------\
37559 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
37560 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
37561 MOV X,-2(X) \ restore the default background: SLEEP
37563 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
37564 BIC.B #RC5,&IR_IE \ clear RC5_Int
37565 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
37566 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
37567 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
37568 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
37569 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
37570 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
37572 ." RC5toLCD is removed,"
37573 ." type START to restart"
37574 WARM \ performs reset to reset all interrupt vectors.
37576 \ ------------------------------\
37578 \ ------------------------------\
37579 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
37580 \ ------------------------------\
37581 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
37582 \ - - \CNTL Counter lentgh \ 00 = 16 bits
37583 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
37584 \ -- \ID input divider \ 10 = /4
37585 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
37586 \ - \TBCLR TimerB Clear
37589 \ -------------------------------\
37590 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
37591 \ -- \CM Capture Mode
37596 \ --- \OUTMOD \ 011 = set/reset
37602 \ -------------------------------\
37604 \ -------------------------------\
37606 \ ------------------------------\
37607 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
37608 \ ------------------------------\
37609 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
37610 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
37611 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
37612 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
37614 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
37615 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
37617 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
37618 \ ------------------------------\
37619 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
37620 \ ------------------------------\
37621 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
37622 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
37623 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
37624 \ ------------------------------\
37625 BIS.B #LCDVo,&LCDVo_DIR \
37626 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
37627 \ ------------------------------\
37628 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
37629 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
37630 \ ------------------------------\
37631 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
37632 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
37633 \ ******************************\
37635 \ ******************************\
37636 BIS.B #RC5,&IR_IE \ enable RC5_Int
37637 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
37638 MOV #RC5_INT,&IR_Vec \ init interrupt vector
37639 \ ******************************\
37640 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
37641 \ ******************************\
37642 \ %01 0001 0100 \ TAxCTL
37643 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
37644 \ -- \ ID divided by 1
37645 \ -- \ MC MODE = up to TAxCCRn
37646 \ - \ TACLR clear timer count
37649 \ ------------------------------\
37650 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
37651 \ ------------------------------\
37653 \ --- \ TAIDEX pre divisor
37654 \ ------------------------------\
37655 \ %0000 0000 0000 0101 \ TAxCCR0
37656 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
37657 \ ------------------------------\
37658 \ %0000 0000 0001 0000 \ TAxCCTL0
37659 \ - \ CAP capture/compare mode = compare
37662 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
37663 \ ------------------------------\
37664 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
37665 \ ------------------------------\
37666 \ define LPM mode for ACCEPT \
37667 \ ------------------------------\
37668 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
37669 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
37670 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
37671 \ ------------------------------\
37673 \ ------------------------------\
37674 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
37675 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
37676 \ ------------------------------\
37677 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
37678 \ ------------------------------\
37679 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
37680 \ CMP #2,Y \ Power_ON event
37681 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
37683 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
37685 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
37687 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
37689 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
37690 \ ------------------------------\
37692 \ ------------------------------\
37694 \ ------------------------------\
37695 #1000 20_US \ 1- wait 20 ms
37696 %011 TOP_LCD \ 2- send DB5=DB4=1
37697 #205 20_US \ 3- wait 4,1 ms
37698 %011 TOP_LCD \ 4- send again DB5=DB4=1
37699 #5 20_US \ 5- wait 0,1 ms
37700 %011 TOP_LCD \ 6- send again again DB5=DB4=1
37701 #2 20_US \ wait 40 us = LCD cycle
37702 %010 TOP_LCD \ 7- send DB5=1 DB4=0
37703 #2 20_US \ wait 40 us = LCD cycle
37704 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
37705 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
37706 LCD_CLEAR \ 10- "LCD_Clear"
37707 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
37708 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
37709 LCD_CLEAR \ 10- "LCD_Clear"
37710 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
37711 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
37712 CR ." I love you" \ display message on LCD
37713 ['] CR >BODY IS CR \ CR executes its default value
37714 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
37715 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
37716 PWR_STATE ABORT \ init DP and continues with ABORT
37718 \ ------------------------------\
37720 \ ------------------------------\
37721 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
37722 \ ------------------------------\
37723 MOV #SLEEP,X \ replace default background process SLEEP
37724 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
37725 MOV #WARM,X \ replace default WARM
37726 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
37727 MOV X,PC \ then execute new WARM
37729 \ ------------------------------\
37732 ; downloading RC5toLCD.4th is done
37733 RST_HERE ; this app is protected against <reset>
37738 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
37740 [UNDEFINED] MARKER [IF]
37741 \ https://forth-standard.org/standard/core/MARKER
37743 \ ( "<spaces>name" -- )
37744 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
37745 \ with the execution semantics defined below.
37747 \ name Execution: ( -- )
37748 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
37749 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
37750 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
37751 \ not necessarily provided. No other contextual information such as numeric base is affected
37756 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
37757 SUB #2,Y \ 1 Y = LFA
37758 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
37759 ADD #4,&DP \ 3 add 2 cells
37763 MOV @RSP+,IP \ -- PFA
37764 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
37765 MOV @TOS,&INIDP \ set DP value for RST_STATE
37767 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
37774 \ https://forth-standard.org/standard/core/Fetch
37775 \ @ c-addr -- char fetch char from memory
37782 [UNDEFINED] CONSTANT [IF]
37783 \ https://forth-standard.org/standard/core/CONSTANT
37784 \ CONSTANT <name> n -- define a Forth CONSTANT
37788 MOV TOS,-2(W) \ PFA = n
37795 [UNDEFINED] STATE [IF]
37796 \ https://forth-standard.org/standard/core/STATE
37797 \ STATE -- a-addr holds compiler state
37798 STATEADR CONSTANT STATE
37802 \ https://forth-standard.org/standard/core/Equal
37803 \ = x1 x2 -- flag test x1=x2
37810 XOR #-1,TOS \ 1 flag Z = 1
37815 [UNDEFINED] IF [IF]
37816 \ https://forth-standard.org/standard/core/IF
37817 \ IF -- IFadr initialize conditional forward branch
37818 CODE IF \ immediate
37821 MOV &DP,TOS \ -- HERE
37822 ADD #4,&DP \ compile one word, reserve one word
37823 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
37824 ADD #2,TOS \ -- HERE+2=IFadr
37829 [UNDEFINED] THEN [IF]
37830 \ https://forth-standard.org/standard/core/THEN
37831 \ THEN IFadr -- resolve forward branch
37832 CODE THEN \ immediate
37833 MOV &DP,0(TOS) \ -- IFadr
37839 [UNDEFINED] ELSE [IF]
37840 \ https://forth-standard.org/standard/core/ELSE
37841 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
37842 CODE ELSE \ immediate
37843 ADD #4,&DP \ make room to compile two words
37844 MOV &DP,W \ W=HERE+4
37846 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
37848 MOV W,TOS \ -- ELSEadr
37853 [UNDEFINED] DEFER [IF]
37854 \ https://forth-standard.org/standard/core/DEFER
37855 \ DEFER "<spaces>name" --
37856 \ Skip leading space delimiters. Parse name delimited by a space.
37857 \ Create a definition for name with the execution semantics defined below.
37859 \ name Execution: --
37860 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
37861 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
37865 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
37866 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
37872 [UNDEFINED] DEFER! [IF]
37873 \ https://forth-standard.org/standard/core/DEFERStore
37874 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
37875 CODE DEFER! \ xt2 xt1 --
37876 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
37882 [UNDEFINED] IS [IF]
37883 \ https://forth-standard.org/standard/core/IS
37886 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
37887 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
37888 \ or in a definition : ... ['] U. IS DISPLAY ...
37889 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
37891 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
37894 IF POSTPONE ['] POSTPONE DEFER!
37900 [UNDEFINED] >BODY [IF]
37901 \ https://forth-standard.org/standard/core/toBODY
37902 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
37909 \ CODE 20uS \ n -- 8MHz version
37910 \ BEGIN \ 4 + 16 ~ loop
37911 \ MOV #39,rDOCON \ 39
37918 \ MOV #XDOCON,rDOCON \ 2
37923 CODE 20_US \ n -- n * 20 us
37924 BEGIN \ here we presume that LCD_TIM_IFG = 1...
37926 BIT #1,&LCD_TIM_CTL \ 3
37927 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
37928 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
37930 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
37935 CODE TOP_LCD \ LCD Sample
37936 \ \ if write : %xxxx_WWWW --
37937 \ \ if read : -- %0000_RRRR
37938 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
37939 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
37940 0= IF \ write LCD bits pattern
37941 AND.B #LCD_DB,TOS \
37942 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
37943 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37946 THEN \ read LCD bits pattern
37949 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
37950 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
37951 AND.B #LCD_DB,TOS \
37955 CODE LCD_WRC \ char -- Write Char
37956 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
37958 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
37959 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
37960 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
37961 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
37962 COLON \ high level word starts here
37963 TOP_LCD 2 20_US \ write high nibble first
37967 CODE LCD_WRF \ func -- Write Fonction
37968 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37972 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
37973 : LCD_HOME $02 LCD_WRF 100 20_us ;
37975 \ [UNDEFINED] OR [IF]
37977 \ \ https://forth-standard.org/standard/core/OR
37978 \ \ C OR x1 x2 -- x3 logical OR
37986 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
37987 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
37988 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
37989 \ : LCD_FN_SET $20 OR LCD_WrF ;
37990 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
37991 \ : LCD_GOTO $80 OR LCD_WrF ;
37994 \ CODE LCD_RDS \ -- status Read Status
37995 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
37996 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
37997 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
37998 \ COLON \ starts a FORTH word
37999 \ TOP_LCD 2 20_us \ -- %0000_HHHH
38000 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
38001 \ HI2LO \ switch from FORTH to assembler
38002 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
38003 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
38004 \ MOV @RSP+,IP \ restore IP saved by COLON
38008 \ CODE LCD_RDC \ -- char Read Char
38009 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38014 \ ******************************\
38015 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
38016 \ ******************************\
38017 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
38018 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
38019 BIT.B #SW2,&SW2_IN \ test switch S2
38020 0= IF \ case of switch S2 pressed
38021 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
38023 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
38026 BIT.B #SW1,&SW1_IN \ test switch S1 input
38027 0= IF \ case of Switch S1 pressed
38028 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
38030 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
38034 BW1 \ from quit on truncated RC5 message, repeated RC5 command
38038 \ ******************************\
38039 ASM RC5_INT \ wake up on Px.RC5 change interrupt
38040 \ ******************************\
38041 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
38042 \ ******************************\
38043 \ \ in : SR(9)=old Toggle bit memory (ADD on)
38044 \ \ SMclock = 8|16|24 MHz
38045 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
38046 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
38047 \ \ SR(9)=new Toggle bit memory (ADD on)
38048 \ ******************************\
38049 \ RC5_FirstStartBitHalfCycle: \
38050 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
38051 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
38052 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
38053 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
38055 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
38056 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
38058 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
38059 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
38061 MOV #1778,X \ RC5_Period * 1us
38062 MOV #14,W \ count of loop
38064 \ ******************************\
38065 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
38066 \ ******************************\ |
38067 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
38068 \ RC5_Compute_3/4_Period: \ |
38069 RRUM #1,X \ X=1/2 cycle |
38072 ADD X,Y \ Y=3/4 cycle
38073 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
38075 \ ******************************\
38076 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
38077 \ ******************************\
38078 BIT.B #RC5,&IR_IN \ C_flag = IR bit
38079 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
38080 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
38081 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
38082 SUB #1,W \ decrement count loop
38083 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
38084 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
38085 0<> WHILE \ ----> out of loop ----+
38086 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
38088 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
38089 CMP Y,X \ 1 | cycle time out of bound ?
38090 U>= IF \ 2 ^ | yes:
38091 BIC #$30,&RC5_TIM_CTL \ | | stop timer
38092 GOTO BW1 \ | | quit on truncated RC5 message
38094 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
38096 REPEAT \ ----> loop back --+ | with X = new RC5_period value
38097 \ ******************************\ |
38098 \ RC5_SampleEndOf: \ <---------------------+
38099 \ ******************************\
38100 BIC #$30,&RC5_TIM_CTL \ stop timer
38101 \ ******************************\
38102 \ RC5_ComputeNewRC5word \
38103 \ ******************************\
38104 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
38105 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
38106 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
38107 \ ******************************\
38108 \ RC5_ComputeC6bit \
38109 \ ******************************\
38110 BIT #BIT14,T \ test /C6 bit in T
38111 0= IF BIS #BIT6,X \ set C6 bit in X
38112 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
38113 \ ******************************\
38114 \ RC5_CommandByteIsDone \ -- BASE RC5_code
38115 \ ******************************\
38116 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
38117 \ ******************************\
38118 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
38119 XOR @RSP,T \ (new XOR old) Toggle bits
38120 BIT #UF10,T \ repeated RC5_command ?
38121 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
38122 XOR #UF10,0(RSP) \ 5 toggle bit memory
38123 \ ******************************\
38124 \ Display IR_RC5 code \
38125 \ ******************************\
38126 SUB #8,PSP \ TOS -- x x x x TOS
38127 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
38128 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
38129 MOV #$10,&BASEADR \ set hexadecimal base
38130 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
38131 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
38132 LO2HI \ switch from assembler to FORTH
38133 LCD_CLEAR \ set LCD cursor at home
38134 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
38135 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
38136 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
38137 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
38138 HI2LO \ -- switch from FORTH to assembler
38139 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
38140 MOV @PSP+,TOS \ -- TOS
38144 \ ******************************\
38146 \ ******************************\
38148 \ ... \ insert here your background task
38151 CALL &RXON \ comment this line to disable TERMINAL_INPUT
38153 \ ******************************\
38154 \ here start all interrupts \
38155 \ ******************************\
38156 \ here return all interrupts \
38157 \ ******************************\
38160 \ ******************************\
38162 \ ------------------------------\
38163 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
38164 \ ------------------------------\
38165 \ ... \ init specific I/O sys as you want
38166 \ ... \ before executing default WARM
38167 MOV #WARM,X \ ['] WARM
38169 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
38171 \ ------------------------------\
38173 \ ------------------------------\
38174 CODE STOP \ stops multitasking, must to be used before downloading app
38175 \ ------------------------------\
38176 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
38177 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
38178 MOV X,-2(X) \ restore the default background: SLEEP
38180 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
38181 BIC.B #RC5,&IR_IE \ clear RC5_Int
38182 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
38183 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
38184 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
38185 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
38186 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
38187 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
38189 ." RC5toLCD is removed,"
38190 ." type START to restart"
38191 WARM \ performs reset to reset all interrupt vectors.
38193 \ ------------------------------\
38195 \ ------------------------------\
38196 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
38197 \ ------------------------------\
38198 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
38199 \ - - \CNTL Counter lentgh \ 00 = 16 bits
38200 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
38201 \ -- \ID input divider \ 10 = /4
38202 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
38203 \ - \TBCLR TimerB Clear
38206 \ -------------------------------\
38207 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38208 \ -- \CM Capture Mode
38213 \ --- \OUTMOD \ 011 = set/reset
38219 \ -------------------------------\
38221 \ -------------------------------\
38223 \ ------------------------------\
38224 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
38225 \ ------------------------------\
38226 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
38227 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
38228 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
38229 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
38231 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
38232 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
38234 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
38235 \ ------------------------------\
38236 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
38237 \ ------------------------------\
38238 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
38239 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
38240 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38241 \ ------------------------------\
38242 BIS.B #LCDVo,&LCDVo_DIR \
38243 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
38244 \ ------------------------------\
38245 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38246 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38247 \ ------------------------------\
38248 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
38249 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
38250 \ ******************************\
38252 \ ******************************\
38253 BIS.B #RC5,&IR_IE \ enable RC5_Int
38254 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
38255 MOV #RC5_INT,&IR_Vec \ init interrupt vector
38256 \ ******************************\
38257 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
38258 \ ******************************\
38259 \ %01 0001 0100 \ TAxCTL
38260 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
38261 \ -- \ ID divided by 1
38262 \ -- \ MC MODE = up to TAxCCRn
38263 \ - \ TACLR clear timer count
38266 \ ------------------------------\
38267 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
38268 \ ------------------------------\
38270 \ --- \ TAIDEX pre divisor
38271 \ ------------------------------\
38272 \ %0000 0000 0000 0101 \ TAxCCR0
38273 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
38274 \ ------------------------------\
38275 \ %0000 0000 0001 0000 \ TAxCCTL0
38276 \ - \ CAP capture/compare mode = compare
38279 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
38280 \ ------------------------------\
38281 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
38282 \ ------------------------------\
38283 \ define LPM mode for ACCEPT \
38284 \ ------------------------------\
38285 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38286 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38287 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38288 \ ------------------------------\
38290 \ ------------------------------\
38291 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
38292 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
38293 \ ------------------------------\
38294 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
38295 \ ------------------------------\
38296 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
38297 \ CMP #2,Y \ Power_ON event
38298 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
38300 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
38302 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
38304 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
38306 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
38307 \ ------------------------------\
38309 \ ------------------------------\
38311 \ ------------------------------\
38312 #1000 20_US \ 1- wait 20 ms
38313 %011 TOP_LCD \ 2- send DB5=DB4=1
38314 #205 20_US \ 3- wait 4,1 ms
38315 %011 TOP_LCD \ 4- send again DB5=DB4=1
38316 #5 20_US \ 5- wait 0,1 ms
38317 %011 TOP_LCD \ 6- send again again DB5=DB4=1
38318 #2 20_US \ wait 40 us = LCD cycle
38319 %010 TOP_LCD \ 7- send DB5=1 DB4=0
38320 #2 20_US \ wait 40 us = LCD cycle
38321 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38322 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38323 LCD_CLEAR \ 10- "LCD_Clear"
38324 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38325 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38326 LCD_CLEAR \ 10- "LCD_Clear"
38327 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38328 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38329 CR ." I love you" \ display message on LCD
38330 ['] CR >BODY IS CR \ CR executes its default value
38331 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
38332 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
38333 PWR_STATE ABORT \ init DP and continues with ABORT
38335 \ ------------------------------\
38337 \ ------------------------------\
38338 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
38339 \ ------------------------------\
38340 MOV #SLEEP,X \ replace default background process SLEEP
38341 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
38342 MOV #WARM,X \ replace default WARM
38343 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
38344 MOV X,PC \ then execute new WARM
38346 \ ------------------------------\
38349 ; downloading RC5toLCD.4th is done
38350 RST_HERE ; this app is protected against <reset>
38355 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
38357 [UNDEFINED] MARKER [IF]
38358 \ https://forth-standard.org/standard/core/MARKER
38360 \ ( "<spaces>name" -- )
38361 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
38362 \ with the execution semantics defined below.
38364 \ name Execution: ( -- )
38365 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
38366 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
38367 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
38368 \ not necessarily provided. No other contextual information such as numeric base is affected
38373 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
38374 SUB #2,Y \ 1 Y = LFA
38375 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
38376 ADD #4,&DP \ 3 add 2 cells
38380 MOV @RSP+,IP \ -- PFA
38381 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
38382 MOV @TOS,&INIDP \ set DP value for RST_STATE
38384 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
38391 \ https://forth-standard.org/standard/core/Fetch
38392 \ @ c-addr -- char fetch char from memory
38399 [UNDEFINED] CONSTANT [IF]
38400 \ https://forth-standard.org/standard/core/CONSTANT
38401 \ CONSTANT <name> n -- define a Forth CONSTANT
38405 MOV TOS,-2(W) \ PFA = n
38412 [UNDEFINED] STATE [IF]
38413 \ https://forth-standard.org/standard/core/STATE
38414 \ STATE -- a-addr holds compiler state
38415 STATEADR CONSTANT STATE
38419 \ https://forth-standard.org/standard/core/Equal
38420 \ = x1 x2 -- flag test x1=x2
38427 XOR #-1,TOS \ 1 flag Z = 1
38432 [UNDEFINED] IF [IF]
38433 \ https://forth-standard.org/standard/core/IF
38434 \ IF -- IFadr initialize conditional forward branch
38435 CODE IF \ immediate
38438 MOV &DP,TOS \ -- HERE
38439 ADD #4,&DP \ compile one word, reserve one word
38440 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
38441 ADD #2,TOS \ -- HERE+2=IFadr
38446 [UNDEFINED] THEN [IF]
38447 \ https://forth-standard.org/standard/core/THEN
38448 \ THEN IFadr -- resolve forward branch
38449 CODE THEN \ immediate
38450 MOV &DP,0(TOS) \ -- IFadr
38456 [UNDEFINED] ELSE [IF]
38457 \ https://forth-standard.org/standard/core/ELSE
38458 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
38459 CODE ELSE \ immediate
38460 ADD #4,&DP \ make room to compile two words
38461 MOV &DP,W \ W=HERE+4
38463 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
38465 MOV W,TOS \ -- ELSEadr
38470 [UNDEFINED] DEFER [IF]
38471 \ https://forth-standard.org/standard/core/DEFER
38472 \ DEFER "<spaces>name" --
38473 \ Skip leading space delimiters. Parse name delimited by a space.
38474 \ Create a definition for name with the execution semantics defined below.
38476 \ name Execution: --
38477 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
38478 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
38482 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
38483 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
38489 [UNDEFINED] DEFER! [IF]
38490 \ https://forth-standard.org/standard/core/DEFERStore
38491 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
38492 CODE DEFER! \ xt2 xt1 --
38493 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
38499 [UNDEFINED] IS [IF]
38500 \ https://forth-standard.org/standard/core/IS
38503 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
38504 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
38505 \ or in a definition : ... ['] U. IS DISPLAY ...
38506 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
38508 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
38511 IF POSTPONE ['] POSTPONE DEFER!
38517 [UNDEFINED] >BODY [IF]
38518 \ https://forth-standard.org/standard/core/toBODY
38519 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
38526 \ CODE 20uS \ n -- 8MHz version
38527 \ BEGIN \ 4 + 16 ~ loop
38528 \ MOV #39,rDOCON \ 39
38535 \ MOV #XDOCON,rDOCON \ 2
38540 CODE 20_US \ n -- n * 20 us
38541 BEGIN \ here we presume that LCD_TIM_IFG = 1...
38543 BIT #1,&LCD_TIM_CTL \ 3
38544 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
38545 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
38547 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
38552 CODE TOP_LCD \ LCD Sample
38553 \ \ if write : %xxxx_WWWW --
38554 \ \ if read : -- %0000_RRRR
38555 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
38556 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
38557 0= IF \ write LCD bits pattern
38558 AND.B #LCD_DB,TOS \
38559 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
38560 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38563 THEN \ read LCD bits pattern
38566 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
38567 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
38568 AND.B #LCD_DB,TOS \
38572 CODE LCD_WRC \ char -- Write Char
38573 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38575 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
38576 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
38577 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
38578 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
38579 COLON \ high level word starts here
38580 TOP_LCD 2 20_US \ write high nibble first
38584 CODE LCD_WRF \ func -- Write Fonction
38585 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38589 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
38590 : LCD_HOME $02 LCD_WRF 100 20_us ;
38592 \ [UNDEFINED] OR [IF]
38594 \ \ https://forth-standard.org/standard/core/OR
38595 \ \ C OR x1 x2 -- x3 logical OR
38603 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
38604 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
38605 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
38606 \ : LCD_FN_SET $20 OR LCD_WrF ;
38607 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
38608 \ : LCD_GOTO $80 OR LCD_WrF ;
38611 \ CODE LCD_RDS \ -- status Read Status
38612 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
38613 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
38614 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
38615 \ COLON \ starts a FORTH word
38616 \ TOP_LCD 2 20_us \ -- %0000_HHHH
38617 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
38618 \ HI2LO \ switch from FORTH to assembler
38619 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
38620 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
38621 \ MOV @RSP+,IP \ restore IP saved by COLON
38625 \ CODE LCD_RDC \ -- char Read Char
38626 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
38631 \ ******************************\
38632 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
38633 \ ******************************\
38634 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
38635 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
38636 BIT.B #SW2,&SW2_IN \ test switch S2
38637 0= IF \ case of switch S2 pressed
38638 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
38640 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
38643 BIT.B #SW1,&SW1_IN \ test switch S1 input
38644 0= IF \ case of Switch S1 pressed
38645 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
38647 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
38651 BW1 \ from quit on truncated RC5 message, repeated RC5 command
38655 \ ******************************\
38656 ASM RC5_INT \ wake up on Px.RC5 change interrupt
38657 \ ******************************\
38658 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
38659 \ ******************************\
38660 \ \ in : SR(9)=old Toggle bit memory (ADD on)
38661 \ \ SMclock = 8|16|24 MHz
38662 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
38663 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
38664 \ \ SR(9)=new Toggle bit memory (ADD on)
38665 \ ******************************\
38666 \ RC5_FirstStartBitHalfCycle: \
38667 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
38668 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
38669 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
38670 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
38672 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
38673 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
38675 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
38676 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
38678 MOV #1778,X \ RC5_Period * 1us
38679 MOV #14,W \ count of loop
38681 \ ******************************\
38682 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
38683 \ ******************************\ |
38684 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
38685 \ RC5_Compute_3/4_Period: \ |
38686 RRUM #1,X \ X=1/2 cycle |
38689 ADD X,Y \ Y=3/4 cycle
38690 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
38692 \ ******************************\
38693 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
38694 \ ******************************\
38695 BIT.B #RC5,&IR_IN \ C_flag = IR bit
38696 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
38697 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
38698 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
38699 SUB #1,W \ decrement count loop
38700 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
38701 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
38702 0<> WHILE \ ----> out of loop ----+
38703 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
38705 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
38706 CMP Y,X \ 1 | cycle time out of bound ?
38707 U>= IF \ 2 ^ | yes:
38708 BIC #$30,&RC5_TIM_CTL \ | | stop timer
38709 GOTO BW1 \ | | quit on truncated RC5 message
38711 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
38713 REPEAT \ ----> loop back --+ | with X = new RC5_period value
38714 \ ******************************\ |
38715 \ RC5_SampleEndOf: \ <---------------------+
38716 \ ******************************\
38717 BIC #$30,&RC5_TIM_CTL \ stop timer
38718 \ ******************************\
38719 \ RC5_ComputeNewRC5word \
38720 \ ******************************\
38721 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
38722 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
38723 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
38724 \ ******************************\
38725 \ RC5_ComputeC6bit \
38726 \ ******************************\
38727 BIT #BIT14,T \ test /C6 bit in T
38728 0= IF BIS #BIT6,X \ set C6 bit in X
38729 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
38730 \ ******************************\
38731 \ RC5_CommandByteIsDone \ -- BASE RC5_code
38732 \ ******************************\
38733 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
38734 \ ******************************\
38735 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
38736 XOR @RSP,T \ (new XOR old) Toggle bits
38737 BIT #UF10,T \ repeated RC5_command ?
38738 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
38739 XOR #UF10,0(RSP) \ 5 toggle bit memory
38740 \ ******************************\
38741 \ Display IR_RC5 code \
38742 \ ******************************\
38743 SUB #8,PSP \ TOS -- x x x x TOS
38744 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
38745 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
38746 MOV #$10,&BASEADR \ set hexadecimal base
38747 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
38748 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
38749 LO2HI \ switch from assembler to FORTH
38750 LCD_CLEAR \ set LCD cursor at home
38751 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
38752 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
38753 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
38754 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
38755 HI2LO \ -- switch from FORTH to assembler
38756 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
38757 MOV @PSP+,TOS \ -- TOS
38761 \ ******************************\
38763 \ ******************************\
38765 \ ... \ insert here your background task
38768 CALL &RXON \ comment this line to disable TERMINAL_INPUT
38770 \ ******************************\
38771 \ here start all interrupts \
38772 \ ******************************\
38773 \ here return all interrupts \
38774 \ ******************************\
38777 \ ******************************\
38779 \ ------------------------------\
38780 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
38781 \ ------------------------------\
38782 \ ... \ init specific I/O sys as you want
38783 \ ... \ before executing default WARM
38784 MOV #WARM,X \ ['] WARM
38786 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
38788 \ ------------------------------\
38790 \ ------------------------------\
38791 CODE STOP \ stops multitasking, must to be used before downloading app
38792 \ ------------------------------\
38793 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
38794 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
38795 MOV X,-2(X) \ restore the default background: SLEEP
38797 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
38798 BIC.B #RC5,&IR_IE \ clear RC5_Int
38799 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
38800 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
38801 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
38802 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
38803 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
38804 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
38806 ." RC5toLCD is removed,"
38807 ." type START to restart"
38808 WARM \ performs reset to reset all interrupt vectors.
38810 \ ------------------------------\
38812 \ ------------------------------\
38813 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
38814 \ ------------------------------\
38815 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
38816 \ - - \CNTL Counter lentgh \ 00 = 16 bits
38817 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
38818 \ -- \ID input divider \ 10 = /4
38819 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
38820 \ - \TBCLR TimerB Clear
38823 \ -------------------------------\
38824 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
38825 \ -- \CM Capture Mode
38830 \ --- \OUTMOD \ 011 = set/reset
38836 \ -------------------------------\
38838 \ -------------------------------\
38840 \ ------------------------------\
38841 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
38842 \ ------------------------------\
38843 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
38844 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
38845 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
38846 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
38848 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
38849 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
38851 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
38852 \ ------------------------------\
38853 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
38854 \ ------------------------------\
38855 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
38856 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
38857 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
38858 \ ------------------------------\
38859 BIS.B #LCDVo,&LCDVo_DIR \
38860 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
38861 \ ------------------------------\
38862 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
38863 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
38864 \ ------------------------------\
38865 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
38866 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
38867 \ ******************************\
38869 \ ******************************\
38870 BIS.B #RC5,&IR_IE \ enable RC5_Int
38871 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
38872 MOV #RC5_INT,&IR_Vec \ init interrupt vector
38873 \ ******************************\
38874 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
38875 \ ******************************\
38876 \ %01 0001 0100 \ TAxCTL
38877 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
38878 \ -- \ ID divided by 1
38879 \ -- \ MC MODE = up to TAxCCRn
38880 \ - \ TACLR clear timer count
38883 \ ------------------------------\
38884 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
38885 \ ------------------------------\
38887 \ --- \ TAIDEX pre divisor
38888 \ ------------------------------\
38889 \ %0000 0000 0000 0101 \ TAxCCR0
38890 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
38891 \ ------------------------------\
38892 \ %0000 0000 0001 0000 \ TAxCCTL0
38893 \ - \ CAP capture/compare mode = compare
38896 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
38897 \ ------------------------------\
38898 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
38899 \ ------------------------------\
38900 \ define LPM mode for ACCEPT \
38901 \ ------------------------------\
38902 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
38903 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
38904 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
38905 \ ------------------------------\
38907 \ ------------------------------\
38908 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
38909 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
38910 \ ------------------------------\
38911 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
38912 \ ------------------------------\
38913 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
38914 \ CMP #2,Y \ Power_ON event
38915 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
38917 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
38919 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
38921 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
38923 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
38924 \ ------------------------------\
38926 \ ------------------------------\
38928 \ ------------------------------\
38929 #1000 20_US \ 1- wait 20 ms
38930 %011 TOP_LCD \ 2- send DB5=DB4=1
38931 #205 20_US \ 3- wait 4,1 ms
38932 %011 TOP_LCD \ 4- send again DB5=DB4=1
38933 #5 20_US \ 5- wait 0,1 ms
38934 %011 TOP_LCD \ 6- send again again DB5=DB4=1
38935 #2 20_US \ wait 40 us = LCD cycle
38936 %010 TOP_LCD \ 7- send DB5=1 DB4=0
38937 #2 20_US \ wait 40 us = LCD cycle
38938 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
38939 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
38940 LCD_CLEAR \ 10- "LCD_Clear"
38941 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
38942 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
38943 LCD_CLEAR \ 10- "LCD_Clear"
38944 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
38945 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
38946 CR ." I love you" \ display message on LCD
38947 ['] CR >BODY IS CR \ CR executes its default value
38948 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
38949 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
38950 PWR_STATE ABORT \ init DP and continues with ABORT
38952 \ ------------------------------\
38954 \ ------------------------------\
38955 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
38956 \ ------------------------------\
38957 MOV #SLEEP,X \ replace default background process SLEEP
38958 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
38959 MOV #WARM,X \ replace default WARM
38960 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
38961 MOV X,PC \ then execute new WARM
38963 \ ------------------------------\
38966 ; downloading RC5toLCD.4th is done
38967 RST_HERE ; this app is protected against <reset>
38972 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
38974 [UNDEFINED] MARKER [IF]
38975 \ https://forth-standard.org/standard/core/MARKER
38977 \ ( "<spaces>name" -- )
38978 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
38979 \ with the execution semantics defined below.
38981 \ name Execution: ( -- )
38982 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
38983 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
38984 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
38985 \ not necessarily provided. No other contextual information such as numeric base is affected
38990 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
38991 SUB #2,Y \ 1 Y = LFA
38992 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
38993 ADD #4,&DP \ 3 add 2 cells
38997 MOV @RSP+,IP \ -- PFA
38998 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
38999 MOV @TOS,&INIDP \ set DP value for RST_STATE
39001 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
39008 \ https://forth-standard.org/standard/core/Fetch
39009 \ @ c-addr -- char fetch char from memory
39016 [UNDEFINED] CONSTANT [IF]
39017 \ https://forth-standard.org/standard/core/CONSTANT
39018 \ CONSTANT <name> n -- define a Forth CONSTANT
39022 MOV TOS,-2(W) \ PFA = n
39029 [UNDEFINED] STATE [IF]
39030 \ https://forth-standard.org/standard/core/STATE
39031 \ STATE -- a-addr holds compiler state
39032 STATEADR CONSTANT STATE
39036 \ https://forth-standard.org/standard/core/Equal
39037 \ = x1 x2 -- flag test x1=x2
39044 XOR #-1,TOS \ 1 flag Z = 1
39049 [UNDEFINED] IF [IF]
39050 \ https://forth-standard.org/standard/core/IF
39051 \ IF -- IFadr initialize conditional forward branch
39052 CODE IF \ immediate
39055 MOV &DP,TOS \ -- HERE
39056 ADD #4,&DP \ compile one word, reserve one word
39057 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
39058 ADD #2,TOS \ -- HERE+2=IFadr
39063 [UNDEFINED] THEN [IF]
39064 \ https://forth-standard.org/standard/core/THEN
39065 \ THEN IFadr -- resolve forward branch
39066 CODE THEN \ immediate
39067 MOV &DP,0(TOS) \ -- IFadr
39073 [UNDEFINED] ELSE [IF]
39074 \ https://forth-standard.org/standard/core/ELSE
39075 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
39076 CODE ELSE \ immediate
39077 ADD #4,&DP \ make room to compile two words
39078 MOV &DP,W \ W=HERE+4
39080 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
39082 MOV W,TOS \ -- ELSEadr
39087 [UNDEFINED] DEFER [IF]
39088 \ https://forth-standard.org/standard/core/DEFER
39089 \ DEFER "<spaces>name" --
39090 \ Skip leading space delimiters. Parse name delimited by a space.
39091 \ Create a definition for name with the execution semantics defined below.
39093 \ name Execution: --
39094 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
39095 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
39099 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
39100 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
39106 [UNDEFINED] DEFER! [IF]
39107 \ https://forth-standard.org/standard/core/DEFERStore
39108 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
39109 CODE DEFER! \ xt2 xt1 --
39110 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
39116 [UNDEFINED] IS [IF]
39117 \ https://forth-standard.org/standard/core/IS
39120 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
39121 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
39122 \ or in a definition : ... ['] U. IS DISPLAY ...
39123 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
39125 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
39128 IF POSTPONE ['] POSTPONE DEFER!
39134 [UNDEFINED] >BODY [IF]
39135 \ https://forth-standard.org/standard/core/toBODY
39136 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
39143 \ CODE 20uS \ n -- 8MHz version
39144 \ BEGIN \ 4 + 16 ~ loop
39145 \ MOV #39,rDOCON \ 39
39152 \ MOV #XDOCON,rDOCON \ 2
39157 CODE 20_US \ n -- n * 20 us
39158 BEGIN \ here we presume that LCD_TIM_IFG = 1...
39160 BIT #1,&LCD_TIM_CTL \ 3
39161 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
39162 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
39164 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
39169 CODE TOP_LCD \ LCD Sample
39170 \ \ if write : %xxxx_WWWW --
39171 \ \ if read : -- %0000_RRRR
39172 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
39173 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
39174 0= IF \ write LCD bits pattern
39175 AND.B #LCD_DB,TOS \
39176 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
39177 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39180 THEN \ read LCD bits pattern
39183 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39184 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
39185 AND.B #LCD_DB,TOS \
39189 CODE LCD_WRC \ char -- Write Char
39190 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39192 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
39193 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
39194 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
39195 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
39196 COLON \ high level word starts here
39197 TOP_LCD 2 20_US \ write high nibble first
39201 CODE LCD_WRF \ func -- Write Fonction
39202 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39206 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
39207 : LCD_HOME $02 LCD_WRF 100 20_us ;
39209 \ [UNDEFINED] OR [IF]
39211 \ \ https://forth-standard.org/standard/core/OR
39212 \ \ C OR x1 x2 -- x3 logical OR
39220 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
39221 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
39222 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
39223 \ : LCD_FN_SET $20 OR LCD_WrF ;
39224 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
39225 \ : LCD_GOTO $80 OR LCD_WrF ;
39228 \ CODE LCD_RDS \ -- status Read Status
39229 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39230 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
39231 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
39232 \ COLON \ starts a FORTH word
39233 \ TOP_LCD 2 20_us \ -- %0000_HHHH
39234 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
39235 \ HI2LO \ switch from FORTH to assembler
39236 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
39237 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
39238 \ MOV @RSP+,IP \ restore IP saved by COLON
39242 \ CODE LCD_RDC \ -- char Read Char
39243 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39248 \ ******************************\
39249 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39250 \ ******************************\
39251 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
39252 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
39253 BIT.B #SW2,&SW2_IN \ test switch S2
39254 0= IF \ case of switch S2 pressed
39255 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
39257 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
39260 BIT.B #SW1,&SW1_IN \ test switch S1 input
39261 0= IF \ case of Switch S1 pressed
39262 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
39264 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
39268 BW1 \ from quit on truncated RC5 message, repeated RC5 command
39272 \ ******************************\
39273 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39274 \ ******************************\
39275 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39276 \ ******************************\
39277 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39278 \ \ SMclock = 8|16|24 MHz
39279 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
39280 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
39281 \ \ SR(9)=new Toggle bit memory (ADD on)
39282 \ ******************************\
39283 \ RC5_FirstStartBitHalfCycle: \
39284 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
39285 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
39286 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
39287 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
39289 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
39290 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
39292 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
39293 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
39295 MOV #1778,X \ RC5_Period * 1us
39296 MOV #14,W \ count of loop
39298 \ ******************************\
39299 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
39300 \ ******************************\ |
39301 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
39302 \ RC5_Compute_3/4_Period: \ |
39303 RRUM #1,X \ X=1/2 cycle |
39306 ADD X,Y \ Y=3/4 cycle
39307 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
39309 \ ******************************\
39310 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
39311 \ ******************************\
39312 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39313 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
39314 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39315 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39316 SUB #1,W \ decrement count loop
39317 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
39318 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39319 0<> WHILE \ ----> out of loop ----+
39320 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
39322 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
39323 CMP Y,X \ 1 | cycle time out of bound ?
39324 U>= IF \ 2 ^ | yes:
39325 BIC #$30,&RC5_TIM_CTL \ | | stop timer
39326 GOTO BW1 \ | | quit on truncated RC5 message
39328 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
39330 REPEAT \ ----> loop back --+ | with X = new RC5_period value
39331 \ ******************************\ |
39332 \ RC5_SampleEndOf: \ <---------------------+
39333 \ ******************************\
39334 BIC #$30,&RC5_TIM_CTL \ stop timer
39335 \ ******************************\
39336 \ RC5_ComputeNewRC5word \
39337 \ ******************************\
39338 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
39339 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
39340 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
39341 \ ******************************\
39342 \ RC5_ComputeC6bit \
39343 \ ******************************\
39344 BIT #BIT14,T \ test /C6 bit in T
39345 0= IF BIS #BIT6,X \ set C6 bit in X
39346 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
39347 \ ******************************\
39348 \ RC5_CommandByteIsDone \ -- BASE RC5_code
39349 \ ******************************\
39350 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
39351 \ ******************************\
39352 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
39353 XOR @RSP,T \ (new XOR old) Toggle bits
39354 BIT #UF10,T \ repeated RC5_command ?
39355 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
39356 XOR #UF10,0(RSP) \ 5 toggle bit memory
39357 \ ******************************\
39358 \ Display IR_RC5 code \
39359 \ ******************************\
39360 SUB #8,PSP \ TOS -- x x x x TOS
39361 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
39362 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
39363 MOV #$10,&BASEADR \ set hexadecimal base
39364 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
39365 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
39366 LO2HI \ switch from assembler to FORTH
39367 LCD_CLEAR \ set LCD cursor at home
39368 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
39369 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
39370 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
39371 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
39372 HI2LO \ -- switch from FORTH to assembler
39373 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
39374 MOV @PSP+,TOS \ -- TOS
39378 \ ******************************\
39380 \ ******************************\
39382 \ ... \ insert here your background task
39385 CALL &RXON \ comment this line to disable TERMINAL_INPUT
39387 \ ******************************\
39388 \ here start all interrupts \
39389 \ ******************************\
39390 \ here return all interrupts \
39391 \ ******************************\
39394 \ ******************************\
39396 \ ------------------------------\
39397 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
39398 \ ------------------------------\
39399 \ ... \ init specific I/O sys as you want
39400 \ ... \ before executing default WARM
39401 MOV #WARM,X \ ['] WARM
39403 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
39405 \ ------------------------------\
39407 \ ------------------------------\
39408 CODE STOP \ stops multitasking, must to be used before downloading app
39409 \ ------------------------------\
39410 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
39411 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
39412 MOV X,-2(X) \ restore the default background: SLEEP
39414 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
39415 BIC.B #RC5,&IR_IE \ clear RC5_Int
39416 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
39417 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
39418 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
39419 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
39420 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
39421 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
39423 ." RC5toLCD is removed,"
39424 ." type START to restart"
39425 WARM \ performs reset to reset all interrupt vectors.
39427 \ ------------------------------\
39429 \ ------------------------------\
39430 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
39431 \ ------------------------------\
39432 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
39433 \ - - \CNTL Counter lentgh \ 00 = 16 bits
39434 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
39435 \ -- \ID input divider \ 10 = /4
39436 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
39437 \ - \TBCLR TimerB Clear
39440 \ -------------------------------\
39441 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
39442 \ -- \CM Capture Mode
39447 \ --- \OUTMOD \ 011 = set/reset
39453 \ -------------------------------\
39455 \ -------------------------------\
39457 \ ------------------------------\
39458 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
39459 \ ------------------------------\
39460 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
39461 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
39462 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
39463 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
39465 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
39466 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
39468 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
39469 \ ------------------------------\
39470 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
39471 \ ------------------------------\
39472 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
39473 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
39474 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
39475 \ ------------------------------\
39476 BIS.B #LCDVo,&LCDVo_DIR \
39477 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
39478 \ ------------------------------\
39479 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
39480 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
39481 \ ------------------------------\
39482 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
39483 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
39484 \ ******************************\
39486 \ ******************************\
39487 BIS.B #RC5,&IR_IE \ enable RC5_Int
39488 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
39489 MOV #RC5_INT,&IR_Vec \ init interrupt vector
39490 \ ******************************\
39491 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
39492 \ ******************************\
39493 \ %01 0001 0100 \ TAxCTL
39494 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
39495 \ -- \ ID divided by 1
39496 \ -- \ MC MODE = up to TAxCCRn
39497 \ - \ TACLR clear timer count
39500 \ ------------------------------\
39501 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
39502 \ ------------------------------\
39504 \ --- \ TAIDEX pre divisor
39505 \ ------------------------------\
39506 \ %0000 0000 0000 0101 \ TAxCCR0
39507 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
39508 \ ------------------------------\
39509 \ %0000 0000 0001 0000 \ TAxCCTL0
39510 \ - \ CAP capture/compare mode = compare
39513 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
39514 \ ------------------------------\
39515 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
39516 \ ------------------------------\
39517 \ define LPM mode for ACCEPT \
39518 \ ------------------------------\
39519 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
39520 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
39521 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
39522 \ ------------------------------\
39524 \ ------------------------------\
39525 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
39526 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
39527 \ ------------------------------\
39528 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
39529 \ ------------------------------\
39530 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
39531 \ CMP #2,Y \ Power_ON event
39532 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
39534 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
39536 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
39538 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
39540 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
39541 \ ------------------------------\
39543 \ ------------------------------\
39545 \ ------------------------------\
39546 #1000 20_US \ 1- wait 20 ms
39547 %011 TOP_LCD \ 2- send DB5=DB4=1
39548 #205 20_US \ 3- wait 4,1 ms
39549 %011 TOP_LCD \ 4- send again DB5=DB4=1
39550 #5 20_US \ 5- wait 0,1 ms
39551 %011 TOP_LCD \ 6- send again again DB5=DB4=1
39552 #2 20_US \ wait 40 us = LCD cycle
39553 %010 TOP_LCD \ 7- send DB5=1 DB4=0
39554 #2 20_US \ wait 40 us = LCD cycle
39555 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
39556 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
39557 LCD_CLEAR \ 10- "LCD_Clear"
39558 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
39559 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
39560 LCD_CLEAR \ 10- "LCD_Clear"
39561 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
39562 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
39563 CR ." I love you" \ display message on LCD
39564 ['] CR >BODY IS CR \ CR executes its default value
39565 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
39566 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
39567 PWR_STATE ABORT \ init DP and continues with ABORT
39569 \ ------------------------------\
39571 \ ------------------------------\
39572 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
39573 \ ------------------------------\
39574 MOV #SLEEP,X \ replace default background process SLEEP
39575 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
39576 MOV #WARM,X \ replace default WARM
39577 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
39578 MOV X,PC \ then execute new WARM
39580 \ ------------------------------\
39583 ; downloading RC5toLCD.4th is done
39584 RST_HERE ; this app is protected against <reset>
39589 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
39591 [UNDEFINED] MARKER [IF]
39592 \ https://forth-standard.org/standard/core/MARKER
39594 \ ( "<spaces>name" -- )
39595 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
39596 \ with the execution semantics defined below.
39598 \ name Execution: ( -- )
39599 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
39600 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
39601 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
39602 \ not necessarily provided. No other contextual information such as numeric base is affected
39607 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
39608 SUB #2,Y \ 1 Y = LFA
39609 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
39610 ADD #4,&DP \ 3 add 2 cells
39614 MOV @RSP+,IP \ -- PFA
39615 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
39616 MOV @TOS,&INIDP \ set DP value for RST_STATE
39618 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
39625 \ https://forth-standard.org/standard/core/Fetch
39626 \ @ c-addr -- char fetch char from memory
39633 [UNDEFINED] CONSTANT [IF]
39634 \ https://forth-standard.org/standard/core/CONSTANT
39635 \ CONSTANT <name> n -- define a Forth CONSTANT
39639 MOV TOS,-2(W) \ PFA = n
39646 [UNDEFINED] STATE [IF]
39647 \ https://forth-standard.org/standard/core/STATE
39648 \ STATE -- a-addr holds compiler state
39649 STATEADR CONSTANT STATE
39653 \ https://forth-standard.org/standard/core/Equal
39654 \ = x1 x2 -- flag test x1=x2
39661 XOR #-1,TOS \ 1 flag Z = 1
39666 [UNDEFINED] IF [IF]
39667 \ https://forth-standard.org/standard/core/IF
39668 \ IF -- IFadr initialize conditional forward branch
39669 CODE IF \ immediate
39672 MOV &DP,TOS \ -- HERE
39673 ADD #4,&DP \ compile one word, reserve one word
39674 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
39675 ADD #2,TOS \ -- HERE+2=IFadr
39680 [UNDEFINED] THEN [IF]
39681 \ https://forth-standard.org/standard/core/THEN
39682 \ THEN IFadr -- resolve forward branch
39683 CODE THEN \ immediate
39684 MOV &DP,0(TOS) \ -- IFadr
39690 [UNDEFINED] ELSE [IF]
39691 \ https://forth-standard.org/standard/core/ELSE
39692 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
39693 CODE ELSE \ immediate
39694 ADD #4,&DP \ make room to compile two words
39695 MOV &DP,W \ W=HERE+4
39697 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
39699 MOV W,TOS \ -- ELSEadr
39704 [UNDEFINED] DEFER [IF]
39705 \ https://forth-standard.org/standard/core/DEFER
39706 \ DEFER "<spaces>name" --
39707 \ Skip leading space delimiters. Parse name delimited by a space.
39708 \ Create a definition for name with the execution semantics defined below.
39710 \ name Execution: --
39711 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
39712 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
39716 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
39717 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
39723 [UNDEFINED] DEFER! [IF]
39724 \ https://forth-standard.org/standard/core/DEFERStore
39725 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
39726 CODE DEFER! \ xt2 xt1 --
39727 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
39733 [UNDEFINED] IS [IF]
39734 \ https://forth-standard.org/standard/core/IS
39737 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
39738 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
39739 \ or in a definition : ... ['] U. IS DISPLAY ...
39740 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
39742 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
39745 IF POSTPONE ['] POSTPONE DEFER!
39751 [UNDEFINED] >BODY [IF]
39752 \ https://forth-standard.org/standard/core/toBODY
39753 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
39760 \ CODE 20uS \ n -- 8MHz version
39761 \ BEGIN \ 4 + 16 ~ loop
39762 \ MOV #39,rDOCON \ 39
39769 \ MOV #XDOCON,rDOCON \ 2
39774 CODE 20_US \ n -- n * 20 us
39775 BEGIN \ here we presume that LCD_TIM_IFG = 1...
39777 BIT #1,&LCD_TIM_CTL \ 3
39778 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
39779 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
39781 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
39786 CODE TOP_LCD \ LCD Sample
39787 \ \ if write : %xxxx_WWWW --
39788 \ \ if read : -- %0000_RRRR
39789 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
39790 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
39791 0= IF \ write LCD bits pattern
39792 AND.B #LCD_DB,TOS \
39793 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
39794 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39797 THEN \ read LCD bits pattern
39800 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
39801 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
39802 AND.B #LCD_DB,TOS \
39806 CODE LCD_WRC \ char -- Write Char
39807 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39809 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
39810 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
39811 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
39812 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
39813 COLON \ high level word starts here
39814 TOP_LCD 2 20_US \ write high nibble first
39818 CODE LCD_WRF \ func -- Write Fonction
39819 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39823 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
39824 : LCD_HOME $02 LCD_WRF 100 20_us ;
39826 \ [UNDEFINED] OR [IF]
39828 \ \ https://forth-standard.org/standard/core/OR
39829 \ \ C OR x1 x2 -- x3 logical OR
39837 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
39838 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
39839 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
39840 \ : LCD_FN_SET $20 OR LCD_WrF ;
39841 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
39842 \ : LCD_GOTO $80 OR LCD_WrF ;
39845 \ CODE LCD_RDS \ -- status Read Status
39846 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
39847 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
39848 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
39849 \ COLON \ starts a FORTH word
39850 \ TOP_LCD 2 20_us \ -- %0000_HHHH
39851 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
39852 \ HI2LO \ switch from FORTH to assembler
39853 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
39854 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
39855 \ MOV @RSP+,IP \ restore IP saved by COLON
39859 \ CODE LCD_RDC \ -- char Read Char
39860 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
39865 \ ******************************\
39866 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
39867 \ ******************************\
39868 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
39869 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
39870 BIT.B #SW2,&SW2_IN \ test switch S2
39871 0= IF \ case of switch S2 pressed
39872 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
39874 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
39877 BIT.B #SW1,&SW1_IN \ test switch S1 input
39878 0= IF \ case of Switch S1 pressed
39879 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
39881 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
39885 BW1 \ from quit on truncated RC5 message, repeated RC5 command
39889 \ ******************************\
39890 ASM RC5_INT \ wake up on Px.RC5 change interrupt
39891 \ ******************************\
39892 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
39893 \ ******************************\
39894 \ \ in : SR(9)=old Toggle bit memory (ADD on)
39895 \ \ SMclock = 8|16|24 MHz
39896 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
39897 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
39898 \ \ SR(9)=new Toggle bit memory (ADD on)
39899 \ ******************************\
39900 \ RC5_FirstStartBitHalfCycle: \
39901 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
39902 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
39903 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
39904 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
39906 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
39907 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
39909 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
39910 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
39912 MOV #1778,X \ RC5_Period * 1us
39913 MOV #14,W \ count of loop
39915 \ ******************************\
39916 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
39917 \ ******************************\ |
39918 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
39919 \ RC5_Compute_3/4_Period: \ |
39920 RRUM #1,X \ X=1/2 cycle |
39923 ADD X,Y \ Y=3/4 cycle
39924 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
39926 \ ******************************\
39927 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
39928 \ ******************************\
39929 BIT.B #RC5,&IR_IN \ C_flag = IR bit
39930 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
39931 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
39932 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
39933 SUB #1,W \ decrement count loop
39934 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
39935 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
39936 0<> WHILE \ ----> out of loop ----+
39937 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
39939 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
39940 CMP Y,X \ 1 | cycle time out of bound ?
39941 U>= IF \ 2 ^ | yes:
39942 BIC #$30,&RC5_TIM_CTL \ | | stop timer
39943 GOTO BW1 \ | | quit on truncated RC5 message
39945 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
39947 REPEAT \ ----> loop back --+ | with X = new RC5_period value
39948 \ ******************************\ |
39949 \ RC5_SampleEndOf: \ <---------------------+
39950 \ ******************************\
39951 BIC #$30,&RC5_TIM_CTL \ stop timer
39952 \ ******************************\
39953 \ RC5_ComputeNewRC5word \
39954 \ ******************************\
39955 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
39956 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
39957 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
39958 \ ******************************\
39959 \ RC5_ComputeC6bit \
39960 \ ******************************\
39961 BIT #BIT14,T \ test /C6 bit in T
39962 0= IF BIS #BIT6,X \ set C6 bit in X
39963 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
39964 \ ******************************\
39965 \ RC5_CommandByteIsDone \ -- BASE RC5_code
39966 \ ******************************\
39967 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
39968 \ ******************************\
39969 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
39970 XOR @RSP,T \ (new XOR old) Toggle bits
39971 BIT #UF10,T \ repeated RC5_command ?
39972 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
39973 XOR #UF10,0(RSP) \ 5 toggle bit memory
39974 \ ******************************\
39975 \ Display IR_RC5 code \
39976 \ ******************************\
39977 SUB #8,PSP \ TOS -- x x x x TOS
39978 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
39979 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
39980 MOV #$10,&BASEADR \ set hexadecimal base
39981 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
39982 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
39983 LO2HI \ switch from assembler to FORTH
39984 LCD_CLEAR \ set LCD cursor at home
39985 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
39986 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
39987 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
39988 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
39989 HI2LO \ -- switch from FORTH to assembler
39990 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
39991 MOV @PSP+,TOS \ -- TOS
39995 \ ******************************\
39997 \ ******************************\
39999 \ ... \ insert here your background task
40002 CALL &RXON \ comment this line to disable TERMINAL_INPUT
40004 \ ******************************\
40005 \ here start all interrupts \
40006 \ ******************************\
40007 \ here return all interrupts \
40008 \ ******************************\
40011 \ ******************************\
40013 \ ------------------------------\
40014 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
40015 \ ------------------------------\
40016 \ ... \ init specific I/O sys as you want
40017 \ ... \ before executing default WARM
40018 MOV #WARM,X \ ['] WARM
40020 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
40022 \ ------------------------------\
40024 \ ------------------------------\
40025 CODE STOP \ stops multitasking, must to be used before downloading app
40026 \ ------------------------------\
40027 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
40028 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
40029 MOV X,-2(X) \ restore the default background: SLEEP
40031 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
40032 BIC.B #RC5,&IR_IE \ clear RC5_Int
40033 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
40034 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
40035 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
40036 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
40037 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
40038 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
40040 ." RC5toLCD is removed,"
40041 ." type START to restart"
40042 WARM \ performs reset to reset all interrupt vectors.
40044 \ ------------------------------\
40046 \ ------------------------------\
40047 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
40048 \ ------------------------------\
40049 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
40050 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40051 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40052 \ -- \ID input divider \ 10 = /4
40053 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
40054 \ - \TBCLR TimerB Clear
40057 \ -------------------------------\
40058 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40059 \ -- \CM Capture Mode
40064 \ --- \OUTMOD \ 011 = set/reset
40070 \ -------------------------------\
40072 \ -------------------------------\
40074 \ ------------------------------\
40075 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
40076 \ ------------------------------\
40077 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
40078 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
40079 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
40080 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
40082 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
40083 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
40085 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
40086 \ ------------------------------\
40087 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
40088 \ ------------------------------\
40089 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
40090 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
40091 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40092 \ ------------------------------\
40093 BIS.B #LCDVo,&LCDVo_DIR \
40094 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
40095 \ ------------------------------\
40096 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40097 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40098 \ ------------------------------\
40099 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40100 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40101 \ ******************************\
40103 \ ******************************\
40104 BIS.B #RC5,&IR_IE \ enable RC5_Int
40105 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40106 MOV #RC5_INT,&IR_Vec \ init interrupt vector
40107 \ ******************************\
40108 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
40109 \ ******************************\
40110 \ %01 0001 0100 \ TAxCTL
40111 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
40112 \ -- \ ID divided by 1
40113 \ -- \ MC MODE = up to TAxCCRn
40114 \ - \ TACLR clear timer count
40117 \ ------------------------------\
40118 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
40119 \ ------------------------------\
40121 \ --- \ TAIDEX pre divisor
40122 \ ------------------------------\
40123 \ %0000 0000 0000 0101 \ TAxCCR0
40124 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
40125 \ ------------------------------\
40126 \ %0000 0000 0001 0000 \ TAxCCTL0
40127 \ - \ CAP capture/compare mode = compare
40130 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
40131 \ ------------------------------\
40132 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
40133 \ ------------------------------\
40134 \ define LPM mode for ACCEPT \
40135 \ ------------------------------\
40136 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40137 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40138 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40139 \ ------------------------------\
40141 \ ------------------------------\
40142 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
40143 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
40144 \ ------------------------------\
40145 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
40146 \ ------------------------------\
40147 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
40148 \ CMP #2,Y \ Power_ON event
40149 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
40151 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
40153 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
40155 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
40157 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
40158 \ ------------------------------\
40160 \ ------------------------------\
40162 \ ------------------------------\
40163 #1000 20_US \ 1- wait 20 ms
40164 %011 TOP_LCD \ 2- send DB5=DB4=1
40165 #205 20_US \ 3- wait 4,1 ms
40166 %011 TOP_LCD \ 4- send again DB5=DB4=1
40167 #5 20_US \ 5- wait 0,1 ms
40168 %011 TOP_LCD \ 6- send again again DB5=DB4=1
40169 #2 20_US \ wait 40 us = LCD cycle
40170 %010 TOP_LCD \ 7- send DB5=1 DB4=0
40171 #2 20_US \ wait 40 us = LCD cycle
40172 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40173 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40174 LCD_CLEAR \ 10- "LCD_Clear"
40175 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40176 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40177 LCD_CLEAR \ 10- "LCD_Clear"
40178 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40179 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40180 CR ." I love you" \ display message on LCD
40181 ['] CR >BODY IS CR \ CR executes its default value
40182 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
40183 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
40184 PWR_STATE ABORT \ init DP and continues with ABORT
40186 \ ------------------------------\
40188 \ ------------------------------\
40189 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
40190 \ ------------------------------\
40191 MOV #SLEEP,X \ replace default background process SLEEP
40192 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
40193 MOV #WARM,X \ replace default WARM
40194 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
40195 MOV X,PC \ then execute new WARM
40197 \ ------------------------------\
40200 ; downloading RC5toLCD.4th is done
40201 RST_HERE ; this app is protected against <reset>
40206 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
40208 [UNDEFINED] MARKER [IF]
40209 \ https://forth-standard.org/standard/core/MARKER
40211 \ ( "<spaces>name" -- )
40212 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
40213 \ with the execution semantics defined below.
40215 \ name Execution: ( -- )
40216 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
40217 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
40218 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
40219 \ not necessarily provided. No other contextual information such as numeric base is affected
40224 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
40225 SUB #2,Y \ 1 Y = LFA
40226 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
40227 ADD #4,&DP \ 3 add 2 cells
40231 MOV @RSP+,IP \ -- PFA
40232 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
40233 MOV @TOS,&INIDP \ set DP value for RST_STATE
40235 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
40242 \ https://forth-standard.org/standard/core/Fetch
40243 \ @ c-addr -- char fetch char from memory
40250 [UNDEFINED] CONSTANT [IF]
40251 \ https://forth-standard.org/standard/core/CONSTANT
40252 \ CONSTANT <name> n -- define a Forth CONSTANT
40256 MOV TOS,-2(W) \ PFA = n
40263 [UNDEFINED] STATE [IF]
40264 \ https://forth-standard.org/standard/core/STATE
40265 \ STATE -- a-addr holds compiler state
40266 STATEADR CONSTANT STATE
40270 \ https://forth-standard.org/standard/core/Equal
40271 \ = x1 x2 -- flag test x1=x2
40278 XOR #-1,TOS \ 1 flag Z = 1
40283 [UNDEFINED] IF [IF]
40284 \ https://forth-standard.org/standard/core/IF
40285 \ IF -- IFadr initialize conditional forward branch
40286 CODE IF \ immediate
40289 MOV &DP,TOS \ -- HERE
40290 ADD #4,&DP \ compile one word, reserve one word
40291 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
40292 ADD #2,TOS \ -- HERE+2=IFadr
40297 [UNDEFINED] THEN [IF]
40298 \ https://forth-standard.org/standard/core/THEN
40299 \ THEN IFadr -- resolve forward branch
40300 CODE THEN \ immediate
40301 MOV &DP,0(TOS) \ -- IFadr
40307 [UNDEFINED] ELSE [IF]
40308 \ https://forth-standard.org/standard/core/ELSE
40309 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
40310 CODE ELSE \ immediate
40311 ADD #4,&DP \ make room to compile two words
40312 MOV &DP,W \ W=HERE+4
40314 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
40316 MOV W,TOS \ -- ELSEadr
40321 [UNDEFINED] DEFER [IF]
40322 \ https://forth-standard.org/standard/core/DEFER
40323 \ DEFER "<spaces>name" --
40324 \ Skip leading space delimiters. Parse name delimited by a space.
40325 \ Create a definition for name with the execution semantics defined below.
40327 \ name Execution: --
40328 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
40329 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
40333 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
40334 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
40340 [UNDEFINED] DEFER! [IF]
40341 \ https://forth-standard.org/standard/core/DEFERStore
40342 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
40343 CODE DEFER! \ xt2 xt1 --
40344 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
40350 [UNDEFINED] IS [IF]
40351 \ https://forth-standard.org/standard/core/IS
40354 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
40355 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
40356 \ or in a definition : ... ['] U. IS DISPLAY ...
40357 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
40359 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
40362 IF POSTPONE ['] POSTPONE DEFER!
40368 [UNDEFINED] >BODY [IF]
40369 \ https://forth-standard.org/standard/core/toBODY
40370 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
40377 \ CODE 20uS \ n -- 8MHz version
40378 \ BEGIN \ 4 + 16 ~ loop
40379 \ MOV #39,rDOCON \ 39
40386 \ MOV #XDOCON,rDOCON \ 2
40391 CODE 20_US \ n -- n * 20 us
40392 BEGIN \ here we presume that LCD_TIM_IFG = 1...
40394 BIT #1,&LCD_TIM_CTL \ 3
40395 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
40396 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
40398 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
40403 CODE TOP_LCD \ LCD Sample
40404 \ \ if write : %xxxx_WWWW --
40405 \ \ if read : -- %0000_RRRR
40406 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
40407 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
40408 0= IF \ write LCD bits pattern
40409 AND.B #LCD_DB,TOS \
40410 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
40411 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40414 THEN \ read LCD bits pattern
40417 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
40418 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
40419 AND.B #LCD_DB,TOS \
40423 CODE LCD_WRC \ char -- Write Char
40424 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40426 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
40427 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
40428 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
40429 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
40430 COLON \ high level word starts here
40431 TOP_LCD 2 20_US \ write high nibble first
40435 CODE LCD_WRF \ func -- Write Fonction
40436 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40440 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
40441 : LCD_HOME $02 LCD_WRF 100 20_us ;
40443 \ [UNDEFINED] OR [IF]
40445 \ \ https://forth-standard.org/standard/core/OR
40446 \ \ C OR x1 x2 -- x3 logical OR
40454 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
40455 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
40456 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
40457 \ : LCD_FN_SET $20 OR LCD_WrF ;
40458 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
40459 \ : LCD_GOTO $80 OR LCD_WrF ;
40462 \ CODE LCD_RDS \ -- status Read Status
40463 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
40464 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
40465 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
40466 \ COLON \ starts a FORTH word
40467 \ TOP_LCD 2 20_us \ -- %0000_HHHH
40468 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
40469 \ HI2LO \ switch from FORTH to assembler
40470 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
40471 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
40472 \ MOV @RSP+,IP \ restore IP saved by COLON
40476 \ CODE LCD_RDC \ -- char Read Char
40477 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
40482 \ ******************************\
40483 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
40484 \ ******************************\
40485 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
40486 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
40487 BIT.B #SW2,&SW2_IN \ test switch S2
40488 0= IF \ case of switch S2 pressed
40489 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
40491 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
40494 BIT.B #SW1,&SW1_IN \ test switch S1 input
40495 0= IF \ case of Switch S1 pressed
40496 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
40498 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
40502 BW1 \ from quit on truncated RC5 message, repeated RC5 command
40506 \ ******************************\
40507 ASM RC5_INT \ wake up on Px.RC5 change interrupt
40508 \ ******************************\
40509 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
40510 \ ******************************\
40511 \ \ in : SR(9)=old Toggle bit memory (ADD on)
40512 \ \ SMclock = 8|16|24 MHz
40513 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
40514 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
40515 \ \ SR(9)=new Toggle bit memory (ADD on)
40516 \ ******************************\
40517 \ RC5_FirstStartBitHalfCycle: \
40518 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
40519 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
40520 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
40521 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
40523 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
40524 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
40526 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
40527 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
40529 MOV #1778,X \ RC5_Period * 1us
40530 MOV #14,W \ count of loop
40532 \ ******************************\
40533 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
40534 \ ******************************\ |
40535 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
40536 \ RC5_Compute_3/4_Period: \ |
40537 RRUM #1,X \ X=1/2 cycle |
40540 ADD X,Y \ Y=3/4 cycle
40541 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
40543 \ ******************************\
40544 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
40545 \ ******************************\
40546 BIT.B #RC5,&IR_IN \ C_flag = IR bit
40547 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
40548 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
40549 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
40550 SUB #1,W \ decrement count loop
40551 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
40552 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
40553 0<> WHILE \ ----> out of loop ----+
40554 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
40556 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
40557 CMP Y,X \ 1 | cycle time out of bound ?
40558 U>= IF \ 2 ^ | yes:
40559 BIC #$30,&RC5_TIM_CTL \ | | stop timer
40560 GOTO BW1 \ | | quit on truncated RC5 message
40562 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
40564 REPEAT \ ----> loop back --+ | with X = new RC5_period value
40565 \ ******************************\ |
40566 \ RC5_SampleEndOf: \ <---------------------+
40567 \ ******************************\
40568 BIC #$30,&RC5_TIM_CTL \ stop timer
40569 \ ******************************\
40570 \ RC5_ComputeNewRC5word \
40571 \ ******************************\
40572 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
40573 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
40574 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
40575 \ ******************************\
40576 \ RC5_ComputeC6bit \
40577 \ ******************************\
40578 BIT #BIT14,T \ test /C6 bit in T
40579 0= IF BIS #BIT6,X \ set C6 bit in X
40580 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
40581 \ ******************************\
40582 \ RC5_CommandByteIsDone \ -- BASE RC5_code
40583 \ ******************************\
40584 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
40585 \ ******************************\
40586 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
40587 XOR @RSP,T \ (new XOR old) Toggle bits
40588 BIT #UF10,T \ repeated RC5_command ?
40589 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
40590 XOR #UF10,0(RSP) \ 5 toggle bit memory
40591 \ ******************************\
40592 \ Display IR_RC5 code \
40593 \ ******************************\
40594 SUB #8,PSP \ TOS -- x x x x TOS
40595 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
40596 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
40597 MOV #$10,&BASEADR \ set hexadecimal base
40598 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
40599 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
40600 LO2HI \ switch from assembler to FORTH
40601 LCD_CLEAR \ set LCD cursor at home
40602 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
40603 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
40604 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
40605 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
40606 HI2LO \ -- switch from FORTH to assembler
40607 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
40608 MOV @PSP+,TOS \ -- TOS
40612 \ ******************************\
40614 \ ******************************\
40616 \ ... \ insert here your background task
40619 CALL &RXON \ comment this line to disable TERMINAL_INPUT
40621 \ ******************************\
40622 \ here start all interrupts \
40623 \ ******************************\
40624 \ here return all interrupts \
40625 \ ******************************\
40628 \ ******************************\
40630 \ ------------------------------\
40631 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
40632 \ ------------------------------\
40633 \ ... \ init specific I/O sys as you want
40634 \ ... \ before executing default WARM
40635 MOV #WARM,X \ ['] WARM
40637 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
40639 \ ------------------------------\
40641 \ ------------------------------\
40642 CODE STOP \ stops multitasking, must to be used before downloading app
40643 \ ------------------------------\
40644 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
40645 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
40646 MOV X,-2(X) \ restore the default background: SLEEP
40648 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
40649 BIC.B #RC5,&IR_IE \ clear RC5_Int
40650 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
40651 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
40652 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
40653 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
40654 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
40655 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
40657 ." RC5toLCD is removed,"
40658 ." type START to restart"
40659 WARM \ performs reset to reset all interrupt vectors.
40661 \ ------------------------------\
40663 \ ------------------------------\
40664 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
40665 \ ------------------------------\
40666 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
40667 \ - - \CNTL Counter lentgh \ 00 = 16 bits
40668 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
40669 \ -- \ID input divider \ 10 = /4
40670 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
40671 \ - \TBCLR TimerB Clear
40674 \ -------------------------------\
40675 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
40676 \ -- \CM Capture Mode
40681 \ --- \OUTMOD \ 011 = set/reset
40687 \ -------------------------------\
40689 \ -------------------------------\
40691 \ ------------------------------\
40692 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
40693 \ ------------------------------\
40694 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
40695 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
40696 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
40697 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
40699 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
40700 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
40702 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
40703 \ ------------------------------\
40704 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
40705 \ ------------------------------\
40706 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
40707 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
40708 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
40709 \ ------------------------------\
40710 BIS.B #LCDVo,&LCDVo_DIR \
40711 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
40712 \ ------------------------------\
40713 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
40714 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
40715 \ ------------------------------\
40716 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
40717 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
40718 \ ******************************\
40720 \ ******************************\
40721 BIS.B #RC5,&IR_IE \ enable RC5_Int
40722 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
40723 MOV #RC5_INT,&IR_Vec \ init interrupt vector
40724 \ ******************************\
40725 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
40726 \ ******************************\
40727 \ %01 0001 0100 \ TAxCTL
40728 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
40729 \ -- \ ID divided by 1
40730 \ -- \ MC MODE = up to TAxCCRn
40731 \ - \ TACLR clear timer count
40734 \ ------------------------------\
40735 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
40736 \ ------------------------------\
40738 \ --- \ TAIDEX pre divisor
40739 \ ------------------------------\
40740 \ %0000 0000 0000 0101 \ TAxCCR0
40741 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
40742 \ ------------------------------\
40743 \ %0000 0000 0001 0000 \ TAxCCTL0
40744 \ - \ CAP capture/compare mode = compare
40747 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
40748 \ ------------------------------\
40749 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
40750 \ ------------------------------\
40751 \ define LPM mode for ACCEPT \
40752 \ ------------------------------\
40753 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
40754 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
40755 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
40756 \ ------------------------------\
40758 \ ------------------------------\
40759 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
40760 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
40761 \ ------------------------------\
40762 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
40763 \ ------------------------------\
40764 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
40765 \ CMP #2,Y \ Power_ON event
40766 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
40768 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
40770 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
40772 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
40774 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
40775 \ ------------------------------\
40777 \ ------------------------------\
40779 \ ------------------------------\
40780 #1000 20_US \ 1- wait 20 ms
40781 %011 TOP_LCD \ 2- send DB5=DB4=1
40782 #205 20_US \ 3- wait 4,1 ms
40783 %011 TOP_LCD \ 4- send again DB5=DB4=1
40784 #5 20_US \ 5- wait 0,1 ms
40785 %011 TOP_LCD \ 6- send again again DB5=DB4=1
40786 #2 20_US \ wait 40 us = LCD cycle
40787 %010 TOP_LCD \ 7- send DB5=1 DB4=0
40788 #2 20_US \ wait 40 us = LCD cycle
40789 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
40790 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
40791 LCD_CLEAR \ 10- "LCD_Clear"
40792 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
40793 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
40794 LCD_CLEAR \ 10- "LCD_Clear"
40795 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
40796 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
40797 CR ." I love you" \ display message on LCD
40798 ['] CR >BODY IS CR \ CR executes its default value
40799 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
40800 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
40801 PWR_STATE ABORT \ init DP and continues with ABORT
40803 \ ------------------------------\
40805 \ ------------------------------\
40806 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
40807 \ ------------------------------\
40808 MOV #SLEEP,X \ replace default background process SLEEP
40809 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
40810 MOV #WARM,X \ replace default WARM
40811 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
40812 MOV X,PC \ then execute new WARM
40814 \ ------------------------------\
40817 ; downloading RC5toLCD.4th is done
40818 RST_HERE ; this app is protected against <reset>
40823 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
40825 [UNDEFINED] MARKER [IF]
40826 \ https://forth-standard.org/standard/core/MARKER
40828 \ ( "<spaces>name" -- )
40829 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
40830 \ with the execution semantics defined below.
40832 \ name Execution: ( -- )
40833 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
40834 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
40835 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
40836 \ not necessarily provided. No other contextual information such as numeric base is affected
40841 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
40842 SUB #2,Y \ 1 Y = LFA
40843 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
40844 ADD #4,&DP \ 3 add 2 cells
40848 MOV @RSP+,IP \ -- PFA
40849 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
40850 MOV @TOS,&INIDP \ set DP value for RST_STATE
40852 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
40859 \ https://forth-standard.org/standard/core/Fetch
40860 \ @ c-addr -- char fetch char from memory
40867 [UNDEFINED] CONSTANT [IF]
40868 \ https://forth-standard.org/standard/core/CONSTANT
40869 \ CONSTANT <name> n -- define a Forth CONSTANT
40873 MOV TOS,-2(W) \ PFA = n
40880 [UNDEFINED] STATE [IF]
40881 \ https://forth-standard.org/standard/core/STATE
40882 \ STATE -- a-addr holds compiler state
40883 STATEADR CONSTANT STATE
40887 \ https://forth-standard.org/standard/core/Equal
40888 \ = x1 x2 -- flag test x1=x2
40895 XOR #-1,TOS \ 1 flag Z = 1
40900 [UNDEFINED] IF [IF]
40901 \ https://forth-standard.org/standard/core/IF
40902 \ IF -- IFadr initialize conditional forward branch
40903 CODE IF \ immediate
40906 MOV &DP,TOS \ -- HERE
40907 ADD #4,&DP \ compile one word, reserve one word
40908 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
40909 ADD #2,TOS \ -- HERE+2=IFadr
40914 [UNDEFINED] THEN [IF]
40915 \ https://forth-standard.org/standard/core/THEN
40916 \ THEN IFadr -- resolve forward branch
40917 CODE THEN \ immediate
40918 MOV &DP,0(TOS) \ -- IFadr
40924 [UNDEFINED] ELSE [IF]
40925 \ https://forth-standard.org/standard/core/ELSE
40926 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
40927 CODE ELSE \ immediate
40928 ADD #4,&DP \ make room to compile two words
40929 MOV &DP,W \ W=HERE+4
40931 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
40933 MOV W,TOS \ -- ELSEadr
40938 [UNDEFINED] DEFER [IF]
40939 \ https://forth-standard.org/standard/core/DEFER
40940 \ DEFER "<spaces>name" --
40941 \ Skip leading space delimiters. Parse name delimited by a space.
40942 \ Create a definition for name with the execution semantics defined below.
40944 \ name Execution: --
40945 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
40946 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
40950 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
40951 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
40957 [UNDEFINED] DEFER! [IF]
40958 \ https://forth-standard.org/standard/core/DEFERStore
40959 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
40960 CODE DEFER! \ xt2 xt1 --
40961 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
40967 [UNDEFINED] IS [IF]
40968 \ https://forth-standard.org/standard/core/IS
40971 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
40972 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
40973 \ or in a definition : ... ['] U. IS DISPLAY ...
40974 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
40976 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
40979 IF POSTPONE ['] POSTPONE DEFER!
40985 [UNDEFINED] >BODY [IF]
40986 \ https://forth-standard.org/standard/core/toBODY
40987 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
40994 \ CODE 20uS \ n -- 8MHz version
40995 \ BEGIN \ 4 + 16 ~ loop
40996 \ MOV #39,rDOCON \ 39
41003 \ MOV #XDOCON,rDOCON \ 2
41008 CODE 20_US \ n -- n * 20 us
41009 BEGIN \ here we presume that LCD_TIM_IFG = 1...
41011 BIT #1,&LCD_TIM_CTL \ 3
41012 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
41013 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
41015 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
41020 CODE TOP_LCD \ LCD Sample
41021 \ \ if write : %xxxx_WWWW --
41022 \ \ if read : -- %0000_RRRR
41023 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
41024 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
41025 0= IF \ write LCD bits pattern
41026 AND.B #LCD_DB,TOS \
41027 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
41028 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41031 THEN \ read LCD bits pattern
41034 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41035 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41036 AND.B #LCD_DB,TOS \
41040 CODE LCD_WRC \ char -- Write Char
41041 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41043 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
41044 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
41045 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41046 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41047 COLON \ high level word starts here
41048 TOP_LCD 2 20_US \ write high nibble first
41052 CODE LCD_WRF \ func -- Write Fonction
41053 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41057 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
41058 : LCD_HOME $02 LCD_WRF 100 20_us ;
41060 \ [UNDEFINED] OR [IF]
41062 \ \ https://forth-standard.org/standard/core/OR
41063 \ \ C OR x1 x2 -- x3 logical OR
41071 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
41072 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
41073 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
41074 \ : LCD_FN_SET $20 OR LCD_WrF ;
41075 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
41076 \ : LCD_GOTO $80 OR LCD_WrF ;
41079 \ CODE LCD_RDS \ -- status Read Status
41080 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41081 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41082 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41083 \ COLON \ starts a FORTH word
41084 \ TOP_LCD 2 20_us \ -- %0000_HHHH
41085 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
41086 \ HI2LO \ switch from FORTH to assembler
41087 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
41088 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
41089 \ MOV @RSP+,IP \ restore IP saved by COLON
41093 \ CODE LCD_RDC \ -- char Read Char
41094 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41099 \ ******************************\
41100 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41101 \ ******************************\
41102 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
41103 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
41104 BIT.B #SW2,&SW2_IN \ test switch S2
41105 0= IF \ case of switch S2 pressed
41106 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
41108 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
41111 BIT.B #SW1,&SW1_IN \ test switch S1 input
41112 0= IF \ case of Switch S1 pressed
41113 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
41115 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
41119 BW1 \ from quit on truncated RC5 message, repeated RC5 command
41123 \ ******************************\
41124 ASM RC5_INT \ wake up on Px.RC5 change interrupt
41125 \ ******************************\
41126 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41127 \ ******************************\
41128 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41129 \ \ SMclock = 8|16|24 MHz
41130 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
41131 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
41132 \ \ SR(9)=new Toggle bit memory (ADD on)
41133 \ ******************************\
41134 \ RC5_FirstStartBitHalfCycle: \
41135 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
41136 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
41137 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
41138 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
41140 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
41141 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
41143 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
41144 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
41146 MOV #1778,X \ RC5_Period * 1us
41147 MOV #14,W \ count of loop
41149 \ ******************************\
41150 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
41151 \ ******************************\ |
41152 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
41153 \ RC5_Compute_3/4_Period: \ |
41154 RRUM #1,X \ X=1/2 cycle |
41157 ADD X,Y \ Y=3/4 cycle
41158 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
41160 \ ******************************\
41161 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
41162 \ ******************************\
41163 BIT.B #RC5,&IR_IN \ C_flag = IR bit
41164 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
41165 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
41166 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
41167 SUB #1,W \ decrement count loop
41168 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
41169 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
41170 0<> WHILE \ ----> out of loop ----+
41171 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
41173 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
41174 CMP Y,X \ 1 | cycle time out of bound ?
41175 U>= IF \ 2 ^ | yes:
41176 BIC #$30,&RC5_TIM_CTL \ | | stop timer
41177 GOTO BW1 \ | | quit on truncated RC5 message
41179 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
41181 REPEAT \ ----> loop back --+ | with X = new RC5_period value
41182 \ ******************************\ |
41183 \ RC5_SampleEndOf: \ <---------------------+
41184 \ ******************************\
41185 BIC #$30,&RC5_TIM_CTL \ stop timer
41186 \ ******************************\
41187 \ RC5_ComputeNewRC5word \
41188 \ ******************************\
41189 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
41190 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
41191 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
41192 \ ******************************\
41193 \ RC5_ComputeC6bit \
41194 \ ******************************\
41195 BIT #BIT14,T \ test /C6 bit in T
41196 0= IF BIS #BIT6,X \ set C6 bit in X
41197 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
41198 \ ******************************\
41199 \ RC5_CommandByteIsDone \ -- BASE RC5_code
41200 \ ******************************\
41201 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
41202 \ ******************************\
41203 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
41204 XOR @RSP,T \ (new XOR old) Toggle bits
41205 BIT #UF10,T \ repeated RC5_command ?
41206 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
41207 XOR #UF10,0(RSP) \ 5 toggle bit memory
41208 \ ******************************\
41209 \ Display IR_RC5 code \
41210 \ ******************************\
41211 SUB #8,PSP \ TOS -- x x x x TOS
41212 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
41213 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
41214 MOV #$10,&BASEADR \ set hexadecimal base
41215 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
41216 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
41217 LO2HI \ switch from assembler to FORTH
41218 LCD_CLEAR \ set LCD cursor at home
41219 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
41220 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
41221 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
41222 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
41223 HI2LO \ -- switch from FORTH to assembler
41224 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
41225 MOV @PSP+,TOS \ -- TOS
41229 \ ******************************\
41231 \ ******************************\
41233 \ ... \ insert here your background task
41236 CALL &RXON \ comment this line to disable TERMINAL_INPUT
41238 \ ******************************\
41239 \ here start all interrupts \
41240 \ ******************************\
41241 \ here return all interrupts \
41242 \ ******************************\
41245 \ ******************************\
41247 \ ------------------------------\
41248 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
41249 \ ------------------------------\
41250 \ ... \ init specific I/O sys as you want
41251 \ ... \ before executing default WARM
41252 MOV #WARM,X \ ['] WARM
41254 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
41256 \ ------------------------------\
41258 \ ------------------------------\
41259 CODE STOP \ stops multitasking, must to be used before downloading app
41260 \ ------------------------------\
41261 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
41262 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
41263 MOV X,-2(X) \ restore the default background: SLEEP
41265 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
41266 BIC.B #RC5,&IR_IE \ clear RC5_Int
41267 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
41268 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
41269 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
41270 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
41271 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
41272 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
41274 ." RC5toLCD is removed,"
41275 ." type START to restart"
41276 WARM \ performs reset to reset all interrupt vectors.
41278 \ ------------------------------\
41280 \ ------------------------------\
41281 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
41282 \ ------------------------------\
41283 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
41284 \ - - \CNTL Counter lentgh \ 00 = 16 bits
41285 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
41286 \ -- \ID input divider \ 10 = /4
41287 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
41288 \ - \TBCLR TimerB Clear
41291 \ -------------------------------\
41292 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41293 \ -- \CM Capture Mode
41298 \ --- \OUTMOD \ 011 = set/reset
41304 \ -------------------------------\
41306 \ -------------------------------\
41308 \ ------------------------------\
41309 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
41310 \ ------------------------------\
41311 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
41312 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
41313 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
41314 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
41316 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
41317 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
41319 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
41320 \ ------------------------------\
41321 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
41322 \ ------------------------------\
41323 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
41324 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
41325 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41326 \ ------------------------------\
41327 BIS.B #LCDVo,&LCDVo_DIR \
41328 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
41329 \ ------------------------------\
41330 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41331 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41332 \ ------------------------------\
41333 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
41334 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
41335 \ ******************************\
41337 \ ******************************\
41338 BIS.B #RC5,&IR_IE \ enable RC5_Int
41339 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
41340 MOV #RC5_INT,&IR_Vec \ init interrupt vector
41341 \ ******************************\
41342 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
41343 \ ******************************\
41344 \ %01 0001 0100 \ TAxCTL
41345 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
41346 \ -- \ ID divided by 1
41347 \ -- \ MC MODE = up to TAxCCRn
41348 \ - \ TACLR clear timer count
41351 \ ------------------------------\
41352 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
41353 \ ------------------------------\
41355 \ --- \ TAIDEX pre divisor
41356 \ ------------------------------\
41357 \ %0000 0000 0000 0101 \ TAxCCR0
41358 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
41359 \ ------------------------------\
41360 \ %0000 0000 0001 0000 \ TAxCCTL0
41361 \ - \ CAP capture/compare mode = compare
41364 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
41365 \ ------------------------------\
41366 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
41367 \ ------------------------------\
41368 \ define LPM mode for ACCEPT \
41369 \ ------------------------------\
41370 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41371 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41372 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41373 \ ------------------------------\
41375 \ ------------------------------\
41376 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
41377 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
41378 \ ------------------------------\
41379 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
41380 \ ------------------------------\
41381 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
41382 \ CMP #2,Y \ Power_ON event
41383 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
41385 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
41387 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
41389 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
41391 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
41392 \ ------------------------------\
41394 \ ------------------------------\
41396 \ ------------------------------\
41397 #1000 20_US \ 1- wait 20 ms
41398 %011 TOP_LCD \ 2- send DB5=DB4=1
41399 #205 20_US \ 3- wait 4,1 ms
41400 %011 TOP_LCD \ 4- send again DB5=DB4=1
41401 #5 20_US \ 5- wait 0,1 ms
41402 %011 TOP_LCD \ 6- send again again DB5=DB4=1
41403 #2 20_US \ wait 40 us = LCD cycle
41404 %010 TOP_LCD \ 7- send DB5=1 DB4=0
41405 #2 20_US \ wait 40 us = LCD cycle
41406 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
41407 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
41408 LCD_CLEAR \ 10- "LCD_Clear"
41409 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
41410 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
41411 LCD_CLEAR \ 10- "LCD_Clear"
41412 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
41413 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
41414 CR ." I love you" \ display message on LCD
41415 ['] CR >BODY IS CR \ CR executes its default value
41416 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
41417 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
41418 PWR_STATE ABORT \ init DP and continues with ABORT
41420 \ ------------------------------\
41422 \ ------------------------------\
41423 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
41424 \ ------------------------------\
41425 MOV #SLEEP,X \ replace default background process SLEEP
41426 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
41427 MOV #WARM,X \ replace default WARM
41428 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
41429 MOV X,PC \ then execute new WARM
41431 \ ------------------------------\
41434 ; downloading RC5toLCD.4th is done
41435 RST_HERE ; this app is protected against <reset>
41440 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
41442 [UNDEFINED] MARKER [IF]
41443 \ https://forth-standard.org/standard/core/MARKER
41445 \ ( "<spaces>name" -- )
41446 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
41447 \ with the execution semantics defined below.
41449 \ name Execution: ( -- )
41450 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
41451 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
41452 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
41453 \ not necessarily provided. No other contextual information such as numeric base is affected
41458 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
41459 SUB #2,Y \ 1 Y = LFA
41460 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
41461 ADD #4,&DP \ 3 add 2 cells
41465 MOV @RSP+,IP \ -- PFA
41466 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
41467 MOV @TOS,&INIDP \ set DP value for RST_STATE
41469 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
41476 \ https://forth-standard.org/standard/core/Fetch
41477 \ @ c-addr -- char fetch char from memory
41484 [UNDEFINED] CONSTANT [IF]
41485 \ https://forth-standard.org/standard/core/CONSTANT
41486 \ CONSTANT <name> n -- define a Forth CONSTANT
41490 MOV TOS,-2(W) \ PFA = n
41497 [UNDEFINED] STATE [IF]
41498 \ https://forth-standard.org/standard/core/STATE
41499 \ STATE -- a-addr holds compiler state
41500 STATEADR CONSTANT STATE
41504 \ https://forth-standard.org/standard/core/Equal
41505 \ = x1 x2 -- flag test x1=x2
41512 XOR #-1,TOS \ 1 flag Z = 1
41517 [UNDEFINED] IF [IF]
41518 \ https://forth-standard.org/standard/core/IF
41519 \ IF -- IFadr initialize conditional forward branch
41520 CODE IF \ immediate
41523 MOV &DP,TOS \ -- HERE
41524 ADD #4,&DP \ compile one word, reserve one word
41525 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
41526 ADD #2,TOS \ -- HERE+2=IFadr
41531 [UNDEFINED] THEN [IF]
41532 \ https://forth-standard.org/standard/core/THEN
41533 \ THEN IFadr -- resolve forward branch
41534 CODE THEN \ immediate
41535 MOV &DP,0(TOS) \ -- IFadr
41541 [UNDEFINED] ELSE [IF]
41542 \ https://forth-standard.org/standard/core/ELSE
41543 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
41544 CODE ELSE \ immediate
41545 ADD #4,&DP \ make room to compile two words
41546 MOV &DP,W \ W=HERE+4
41548 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
41550 MOV W,TOS \ -- ELSEadr
41555 [UNDEFINED] DEFER [IF]
41556 \ https://forth-standard.org/standard/core/DEFER
41557 \ DEFER "<spaces>name" --
41558 \ Skip leading space delimiters. Parse name delimited by a space.
41559 \ Create a definition for name with the execution semantics defined below.
41561 \ name Execution: --
41562 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
41563 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
41567 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
41568 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
41574 [UNDEFINED] DEFER! [IF]
41575 \ https://forth-standard.org/standard/core/DEFERStore
41576 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
41577 CODE DEFER! \ xt2 xt1 --
41578 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
41584 [UNDEFINED] IS [IF]
41585 \ https://forth-standard.org/standard/core/IS
41588 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
41589 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
41590 \ or in a definition : ... ['] U. IS DISPLAY ...
41591 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
41593 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
41596 IF POSTPONE ['] POSTPONE DEFER!
41602 [UNDEFINED] >BODY [IF]
41603 \ https://forth-standard.org/standard/core/toBODY
41604 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
41611 \ CODE 20uS \ n -- 8MHz version
41612 \ BEGIN \ 4 + 16 ~ loop
41613 \ MOV #39,rDOCON \ 39
41620 \ MOV #XDOCON,rDOCON \ 2
41625 CODE 20_US \ n -- n * 20 us
41626 BEGIN \ here we presume that LCD_TIM_IFG = 1...
41628 BIT #1,&LCD_TIM_CTL \ 3
41629 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
41630 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
41632 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
41637 CODE TOP_LCD \ LCD Sample
41638 \ \ if write : %xxxx_WWWW --
41639 \ \ if read : -- %0000_RRRR
41640 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
41641 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
41642 0= IF \ write LCD bits pattern
41643 AND.B #LCD_DB,TOS \
41644 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
41645 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41648 THEN \ read LCD bits pattern
41651 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
41652 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
41653 AND.B #LCD_DB,TOS \
41657 CODE LCD_WRC \ char -- Write Char
41658 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41660 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
41661 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
41662 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
41663 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
41664 COLON \ high level word starts here
41665 TOP_LCD 2 20_US \ write high nibble first
41669 CODE LCD_WRF \ func -- Write Fonction
41670 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41674 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
41675 : LCD_HOME $02 LCD_WRF 100 20_us ;
41677 \ [UNDEFINED] OR [IF]
41679 \ \ https://forth-standard.org/standard/core/OR
41680 \ \ C OR x1 x2 -- x3 logical OR
41688 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
41689 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
41690 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
41691 \ : LCD_FN_SET $20 OR LCD_WrF ;
41692 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
41693 \ : LCD_GOTO $80 OR LCD_WrF ;
41696 \ CODE LCD_RDS \ -- status Read Status
41697 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
41698 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
41699 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
41700 \ COLON \ starts a FORTH word
41701 \ TOP_LCD 2 20_us \ -- %0000_HHHH
41702 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
41703 \ HI2LO \ switch from FORTH to assembler
41704 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
41705 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
41706 \ MOV @RSP+,IP \ restore IP saved by COLON
41710 \ CODE LCD_RDC \ -- char Read Char
41711 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
41716 \ ******************************\
41717 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
41718 \ ******************************\
41719 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
41720 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
41721 BIT.B #SW2,&SW2_IN \ test switch S2
41722 0= IF \ case of switch S2 pressed
41723 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
41725 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
41728 BIT.B #SW1,&SW1_IN \ test switch S1 input
41729 0= IF \ case of Switch S1 pressed
41730 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
41732 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
41736 BW1 \ from quit on truncated RC5 message, repeated RC5 command
41740 \ ******************************\
41741 ASM RC5_INT \ wake up on Px.RC5 change interrupt
41742 \ ******************************\
41743 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
41744 \ ******************************\
41745 \ \ in : SR(9)=old Toggle bit memory (ADD on)
41746 \ \ SMclock = 8|16|24 MHz
41747 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
41748 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
41749 \ \ SR(9)=new Toggle bit memory (ADD on)
41750 \ ******************************\
41751 \ RC5_FirstStartBitHalfCycle: \
41752 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
41753 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
41754 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
41755 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
41757 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
41758 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
41760 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
41761 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
41763 MOV #1778,X \ RC5_Period * 1us
41764 MOV #14,W \ count of loop
41766 \ ******************************\
41767 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
41768 \ ******************************\ |
41769 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
41770 \ RC5_Compute_3/4_Period: \ |
41771 RRUM #1,X \ X=1/2 cycle |
41774 ADD X,Y \ Y=3/4 cycle
41775 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
41777 \ ******************************\
41778 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
41779 \ ******************************\
41780 BIT.B #RC5,&IR_IN \ C_flag = IR bit
41781 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
41782 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
41783 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
41784 SUB #1,W \ decrement count loop
41785 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
41786 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
41787 0<> WHILE \ ----> out of loop ----+
41788 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
41790 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
41791 CMP Y,X \ 1 | cycle time out of bound ?
41792 U>= IF \ 2 ^ | yes:
41793 BIC #$30,&RC5_TIM_CTL \ | | stop timer
41794 GOTO BW1 \ | | quit on truncated RC5 message
41796 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
41798 REPEAT \ ----> loop back --+ | with X = new RC5_period value
41799 \ ******************************\ |
41800 \ RC5_SampleEndOf: \ <---------------------+
41801 \ ******************************\
41802 BIC #$30,&RC5_TIM_CTL \ stop timer
41803 \ ******************************\
41804 \ RC5_ComputeNewRC5word \
41805 \ ******************************\
41806 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
41807 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
41808 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
41809 \ ******************************\
41810 \ RC5_ComputeC6bit \
41811 \ ******************************\
41812 BIT #BIT14,T \ test /C6 bit in T
41813 0= IF BIS #BIT6,X \ set C6 bit in X
41814 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
41815 \ ******************************\
41816 \ RC5_CommandByteIsDone \ -- BASE RC5_code
41817 \ ******************************\
41818 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
41819 \ ******************************\
41820 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
41821 XOR @RSP,T \ (new XOR old) Toggle bits
41822 BIT #UF10,T \ repeated RC5_command ?
41823 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
41824 XOR #UF10,0(RSP) \ 5 toggle bit memory
41825 \ ******************************\
41826 \ Display IR_RC5 code \
41827 \ ******************************\
41828 SUB #8,PSP \ TOS -- x x x x TOS
41829 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
41830 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
41831 MOV #$10,&BASEADR \ set hexadecimal base
41832 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
41833 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
41834 LO2HI \ switch from assembler to FORTH
41835 LCD_CLEAR \ set LCD cursor at home
41836 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
41837 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
41838 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
41839 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
41840 HI2LO \ -- switch from FORTH to assembler
41841 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
41842 MOV @PSP+,TOS \ -- TOS
41846 \ ******************************\
41848 \ ******************************\
41850 \ ... \ insert here your background task
41853 CALL &RXON \ comment this line to disable TERMINAL_INPUT
41855 \ ******************************\
41856 \ here start all interrupts \
41857 \ ******************************\
41858 \ here return all interrupts \
41859 \ ******************************\
41862 \ ******************************\
41864 \ ------------------------------\
41865 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
41866 \ ------------------------------\
41867 \ ... \ init specific I/O sys as you want
41868 \ ... \ before executing default WARM
41869 MOV #WARM,X \ ['] WARM
41871 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
41873 \ ------------------------------\
41875 \ ------------------------------\
41876 CODE STOP \ stops multitasking, must to be used before downloading app
41877 \ ------------------------------\
41878 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
41879 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
41880 MOV X,-2(X) \ restore the default background: SLEEP
41882 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
41883 BIC.B #RC5,&IR_IE \ clear RC5_Int
41884 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
41885 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
41886 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
41887 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
41888 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
41889 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
41891 ." RC5toLCD is removed,"
41892 ." type START to restart"
41893 WARM \ performs reset to reset all interrupt vectors.
41895 \ ------------------------------\
41897 \ ------------------------------\
41898 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
41899 \ ------------------------------\
41900 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
41901 \ - - \CNTL Counter lentgh \ 00 = 16 bits
41902 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
41903 \ -- \ID input divider \ 10 = /4
41904 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
41905 \ - \TBCLR TimerB Clear
41908 \ -------------------------------\
41909 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
41910 \ -- \CM Capture Mode
41915 \ --- \OUTMOD \ 011 = set/reset
41921 \ -------------------------------\
41923 \ -------------------------------\
41925 \ ------------------------------\
41926 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
41927 \ ------------------------------\
41928 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
41929 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
41930 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
41931 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
41933 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
41934 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
41936 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
41937 \ ------------------------------\
41938 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
41939 \ ------------------------------\
41940 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
41941 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
41942 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
41943 \ ------------------------------\
41944 BIS.B #LCDVo,&LCDVo_DIR \
41945 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
41946 \ ------------------------------\
41947 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
41948 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
41949 \ ------------------------------\
41950 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
41951 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
41952 \ ******************************\
41954 \ ******************************\
41955 BIS.B #RC5,&IR_IE \ enable RC5_Int
41956 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
41957 MOV #RC5_INT,&IR_Vec \ init interrupt vector
41958 \ ******************************\
41959 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
41960 \ ******************************\
41961 \ %01 0001 0100 \ TAxCTL
41962 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
41963 \ -- \ ID divided by 1
41964 \ -- \ MC MODE = up to TAxCCRn
41965 \ - \ TACLR clear timer count
41968 \ ------------------------------\
41969 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
41970 \ ------------------------------\
41972 \ --- \ TAIDEX pre divisor
41973 \ ------------------------------\
41974 \ %0000 0000 0000 0101 \ TAxCCR0
41975 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
41976 \ ------------------------------\
41977 \ %0000 0000 0001 0000 \ TAxCCTL0
41978 \ - \ CAP capture/compare mode = compare
41981 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
41982 \ ------------------------------\
41983 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
41984 \ ------------------------------\
41985 \ define LPM mode for ACCEPT \
41986 \ ------------------------------\
41987 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
41988 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
41989 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
41990 \ ------------------------------\
41992 \ ------------------------------\
41993 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
41994 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
41995 \ ------------------------------\
41996 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
41997 \ ------------------------------\
41998 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
41999 \ CMP #2,Y \ Power_ON event
42000 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
42002 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
42004 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
42006 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
42008 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
42009 \ ------------------------------\
42011 \ ------------------------------\
42013 \ ------------------------------\
42014 #1000 20_US \ 1- wait 20 ms
42015 %011 TOP_LCD \ 2- send DB5=DB4=1
42016 #205 20_US \ 3- wait 4,1 ms
42017 %011 TOP_LCD \ 4- send again DB5=DB4=1
42018 #5 20_US \ 5- wait 0,1 ms
42019 %011 TOP_LCD \ 6- send again again DB5=DB4=1
42020 #2 20_US \ wait 40 us = LCD cycle
42021 %010 TOP_LCD \ 7- send DB5=1 DB4=0
42022 #2 20_US \ wait 40 us = LCD cycle
42023 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
42024 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
42025 LCD_CLEAR \ 10- "LCD_Clear"
42026 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
42027 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
42028 LCD_CLEAR \ 10- "LCD_Clear"
42029 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
42030 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
42031 CR ." I love you" \ display message on LCD
42032 ['] CR >BODY IS CR \ CR executes its default value
42033 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
42034 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
42035 PWR_STATE ABORT \ init DP and continues with ABORT
42037 \ ------------------------------\
42039 \ ------------------------------\
42040 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
42041 \ ------------------------------\
42042 MOV #SLEEP,X \ replace default background process SLEEP
42043 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
42044 MOV #WARM,X \ replace default WARM
42045 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
42046 MOV X,PC \ then execute new WARM
42048 \ ------------------------------\
42051 ; downloading RC5toLCD.4th is done
42052 RST_HERE ; this app is protected against <reset>
42057 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
42059 [UNDEFINED] MARKER [IF]
42060 \ https://forth-standard.org/standard/core/MARKER
42062 \ ( "<spaces>name" -- )
42063 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
42064 \ with the execution semantics defined below.
42066 \ name Execution: ( -- )
42067 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
42068 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
42069 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
42070 \ not necessarily provided. No other contextual information such as numeric base is affected
42075 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
42076 SUB #2,Y \ 1 Y = LFA
42077 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
42078 ADD #4,&DP \ 3 add 2 cells
42082 MOV @RSP+,IP \ -- PFA
42083 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
42084 MOV @TOS,&INIDP \ set DP value for RST_STATE
42086 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
42093 \ https://forth-standard.org/standard/core/Fetch
42094 \ @ c-addr -- char fetch char from memory
42101 [UNDEFINED] CONSTANT [IF]
42102 \ https://forth-standard.org/standard/core/CONSTANT
42103 \ CONSTANT <name> n -- define a Forth CONSTANT
42107 MOV TOS,-2(W) \ PFA = n
42114 [UNDEFINED] STATE [IF]
42115 \ https://forth-standard.org/standard/core/STATE
42116 \ STATE -- a-addr holds compiler state
42117 STATEADR CONSTANT STATE
42121 \ https://forth-standard.org/standard/core/Equal
42122 \ = x1 x2 -- flag test x1=x2
42129 XOR #-1,TOS \ 1 flag Z = 1
42134 [UNDEFINED] IF [IF]
42135 \ https://forth-standard.org/standard/core/IF
42136 \ IF -- IFadr initialize conditional forward branch
42137 CODE IF \ immediate
42140 MOV &DP,TOS \ -- HERE
42141 ADD #4,&DP \ compile one word, reserve one word
42142 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
42143 ADD #2,TOS \ -- HERE+2=IFadr
42148 [UNDEFINED] THEN [IF]
42149 \ https://forth-standard.org/standard/core/THEN
42150 \ THEN IFadr -- resolve forward branch
42151 CODE THEN \ immediate
42152 MOV &DP,0(TOS) \ -- IFadr
42158 [UNDEFINED] ELSE [IF]
42159 \ https://forth-standard.org/standard/core/ELSE
42160 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
42161 CODE ELSE \ immediate
42162 ADD #4,&DP \ make room to compile two words
42163 MOV &DP,W \ W=HERE+4
42165 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
42167 MOV W,TOS \ -- ELSEadr
42172 [UNDEFINED] DEFER [IF]
42173 \ https://forth-standard.org/standard/core/DEFER
42174 \ DEFER "<spaces>name" --
42175 \ Skip leading space delimiters. Parse name delimited by a space.
42176 \ Create a definition for name with the execution semantics defined below.
42178 \ name Execution: --
42179 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
42180 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
42184 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
42185 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
42191 [UNDEFINED] DEFER! [IF]
42192 \ https://forth-standard.org/standard/core/DEFERStore
42193 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
42194 CODE DEFER! \ xt2 xt1 --
42195 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
42201 [UNDEFINED] IS [IF]
42202 \ https://forth-standard.org/standard/core/IS
42205 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
42206 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
42207 \ or in a definition : ... ['] U. IS DISPLAY ...
42208 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
42210 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
42213 IF POSTPONE ['] POSTPONE DEFER!
42219 [UNDEFINED] >BODY [IF]
42220 \ https://forth-standard.org/standard/core/toBODY
42221 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
42228 \ CODE 20uS \ n -- 8MHz version
42229 \ BEGIN \ 4 + 16 ~ loop
42230 \ MOV #39,rDOCON \ 39
42237 \ MOV #XDOCON,rDOCON \ 2
42242 CODE 20_US \ n -- n * 20 us
42243 BEGIN \ here we presume that LCD_TIM_IFG = 1...
42245 BIT #1,&LCD_TIM_CTL \ 3
42246 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
42247 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
42249 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
42254 CODE TOP_LCD \ LCD Sample
42255 \ \ if write : %xxxx_WWWW --
42256 \ \ if read : -- %0000_RRRR
42257 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
42258 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
42259 0= IF \ write LCD bits pattern
42260 AND.B #LCD_DB,TOS \
42261 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
42262 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42265 THEN \ read LCD bits pattern
42268 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42269 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
42270 AND.B #LCD_DB,TOS \
42274 CODE LCD_WRC \ char -- Write Char
42275 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42277 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
42278 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
42279 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
42280 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
42281 COLON \ high level word starts here
42282 TOP_LCD 2 20_US \ write high nibble first
42286 CODE LCD_WRF \ func -- Write Fonction
42287 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42291 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
42292 : LCD_HOME $02 LCD_WRF 100 20_us ;
42294 \ [UNDEFINED] OR [IF]
42296 \ \ https://forth-standard.org/standard/core/OR
42297 \ \ C OR x1 x2 -- x3 logical OR
42305 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
42306 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
42307 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
42308 \ : LCD_FN_SET $20 OR LCD_WrF ;
42309 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
42310 \ : LCD_GOTO $80 OR LCD_WrF ;
42313 \ CODE LCD_RDS \ -- status Read Status
42314 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42315 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
42316 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
42317 \ COLON \ starts a FORTH word
42318 \ TOP_LCD 2 20_us \ -- %0000_HHHH
42319 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
42320 \ HI2LO \ switch from FORTH to assembler
42321 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
42322 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
42323 \ MOV @RSP+,IP \ restore IP saved by COLON
42327 \ CODE LCD_RDC \ -- char Read Char
42328 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42333 \ ******************************\
42334 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
42335 \ ******************************\
42336 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
42337 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
42338 BIT.B #SW2,&SW2_IN \ test switch S2
42339 0= IF \ case of switch S2 pressed
42340 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
42342 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
42345 BIT.B #SW1,&SW1_IN \ test switch S1 input
42346 0= IF \ case of Switch S1 pressed
42347 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
42349 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
42353 BW1 \ from quit on truncated RC5 message, repeated RC5 command
42357 \ ******************************\
42358 ASM RC5_INT \ wake up on Px.RC5 change interrupt
42359 \ ******************************\
42360 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
42361 \ ******************************\
42362 \ \ in : SR(9)=old Toggle bit memory (ADD on)
42363 \ \ SMclock = 8|16|24 MHz
42364 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
42365 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
42366 \ \ SR(9)=new Toggle bit memory (ADD on)
42367 \ ******************************\
42368 \ RC5_FirstStartBitHalfCycle: \
42369 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
42370 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
42371 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
42372 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
42374 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
42375 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
42377 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
42378 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
42380 MOV #1778,X \ RC5_Period * 1us
42381 MOV #14,W \ count of loop
42383 \ ******************************\
42384 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
42385 \ ******************************\ |
42386 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
42387 \ RC5_Compute_3/4_Period: \ |
42388 RRUM #1,X \ X=1/2 cycle |
42391 ADD X,Y \ Y=3/4 cycle
42392 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
42394 \ ******************************\
42395 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
42396 \ ******************************\
42397 BIT.B #RC5,&IR_IN \ C_flag = IR bit
42398 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
42399 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
42400 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
42401 SUB #1,W \ decrement count loop
42402 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
42403 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
42404 0<> WHILE \ ----> out of loop ----+
42405 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
42407 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
42408 CMP Y,X \ 1 | cycle time out of bound ?
42409 U>= IF \ 2 ^ | yes:
42410 BIC #$30,&RC5_TIM_CTL \ | | stop timer
42411 GOTO BW1 \ | | quit on truncated RC5 message
42413 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
42415 REPEAT \ ----> loop back --+ | with X = new RC5_period value
42416 \ ******************************\ |
42417 \ RC5_SampleEndOf: \ <---------------------+
42418 \ ******************************\
42419 BIC #$30,&RC5_TIM_CTL \ stop timer
42420 \ ******************************\
42421 \ RC5_ComputeNewRC5word \
42422 \ ******************************\
42423 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
42424 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
42425 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
42426 \ ******************************\
42427 \ RC5_ComputeC6bit \
42428 \ ******************************\
42429 BIT #BIT14,T \ test /C6 bit in T
42430 0= IF BIS #BIT6,X \ set C6 bit in X
42431 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
42432 \ ******************************\
42433 \ RC5_CommandByteIsDone \ -- BASE RC5_code
42434 \ ******************************\
42435 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
42436 \ ******************************\
42437 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
42438 XOR @RSP,T \ (new XOR old) Toggle bits
42439 BIT #UF10,T \ repeated RC5_command ?
42440 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
42441 XOR #UF10,0(RSP) \ 5 toggle bit memory
42442 \ ******************************\
42443 \ Display IR_RC5 code \
42444 \ ******************************\
42445 SUB #8,PSP \ TOS -- x x x x TOS
42446 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
42447 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
42448 MOV #$10,&BASEADR \ set hexadecimal base
42449 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
42450 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
42451 LO2HI \ switch from assembler to FORTH
42452 LCD_CLEAR \ set LCD cursor at home
42453 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
42454 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
42455 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
42456 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
42457 HI2LO \ -- switch from FORTH to assembler
42458 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
42459 MOV @PSP+,TOS \ -- TOS
42463 \ ******************************\
42465 \ ******************************\
42467 \ ... \ insert here your background task
42470 CALL &RXON \ comment this line to disable TERMINAL_INPUT
42472 \ ******************************\
42473 \ here start all interrupts \
42474 \ ******************************\
42475 \ here return all interrupts \
42476 \ ******************************\
42479 \ ******************************\
42481 \ ------------------------------\
42482 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
42483 \ ------------------------------\
42484 \ ... \ init specific I/O sys as you want
42485 \ ... \ before executing default WARM
42486 MOV #WARM,X \ ['] WARM
42488 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
42490 \ ------------------------------\
42492 \ ------------------------------\
42493 CODE STOP \ stops multitasking, must to be used before downloading app
42494 \ ------------------------------\
42495 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
42496 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
42497 MOV X,-2(X) \ restore the default background: SLEEP
42499 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
42500 BIC.B #RC5,&IR_IE \ clear RC5_Int
42501 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
42502 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
42503 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
42504 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
42505 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
42506 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
42508 ." RC5toLCD is removed,"
42509 ." type START to restart"
42510 WARM \ performs reset to reset all interrupt vectors.
42512 \ ------------------------------\
42514 \ ------------------------------\
42515 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
42516 \ ------------------------------\
42517 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
42518 \ - - \CNTL Counter lentgh \ 00 = 16 bits
42519 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
42520 \ -- \ID input divider \ 10 = /4
42521 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
42522 \ - \TBCLR TimerB Clear
42525 \ -------------------------------\
42526 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
42527 \ -- \CM Capture Mode
42532 \ --- \OUTMOD \ 011 = set/reset
42538 \ -------------------------------\
42540 \ -------------------------------\
42542 \ ------------------------------\
42543 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
42544 \ ------------------------------\
42545 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
42546 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
42547 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
42548 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
42550 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
42551 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
42553 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
42554 \ ------------------------------\
42555 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
42556 \ ------------------------------\
42557 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
42558 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
42559 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
42560 \ ------------------------------\
42561 BIS.B #LCDVo,&LCDVo_DIR \
42562 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
42563 \ ------------------------------\
42564 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
42565 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
42566 \ ------------------------------\
42567 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
42568 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
42569 \ ******************************\
42571 \ ******************************\
42572 BIS.B #RC5,&IR_IE \ enable RC5_Int
42573 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
42574 MOV #RC5_INT,&IR_Vec \ init interrupt vector
42575 \ ******************************\
42576 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
42577 \ ******************************\
42578 \ %01 0001 0100 \ TAxCTL
42579 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
42580 \ -- \ ID divided by 1
42581 \ -- \ MC MODE = up to TAxCCRn
42582 \ - \ TACLR clear timer count
42585 \ ------------------------------\
42586 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
42587 \ ------------------------------\
42589 \ --- \ TAIDEX pre divisor
42590 \ ------------------------------\
42591 \ %0000 0000 0000 0101 \ TAxCCR0
42592 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
42593 \ ------------------------------\
42594 \ %0000 0000 0001 0000 \ TAxCCTL0
42595 \ - \ CAP capture/compare mode = compare
42598 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
42599 \ ------------------------------\
42600 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
42601 \ ------------------------------\
42602 \ define LPM mode for ACCEPT \
42603 \ ------------------------------\
42604 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
42605 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
42606 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
42607 \ ------------------------------\
42609 \ ------------------------------\
42610 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
42611 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
42612 \ ------------------------------\
42613 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
42614 \ ------------------------------\
42615 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
42616 \ CMP #2,Y \ Power_ON event
42617 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
42619 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
42621 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
42623 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
42625 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
42626 \ ------------------------------\
42628 \ ------------------------------\
42630 \ ------------------------------\
42631 #1000 20_US \ 1- wait 20 ms
42632 %011 TOP_LCD \ 2- send DB5=DB4=1
42633 #205 20_US \ 3- wait 4,1 ms
42634 %011 TOP_LCD \ 4- send again DB5=DB4=1
42635 #5 20_US \ 5- wait 0,1 ms
42636 %011 TOP_LCD \ 6- send again again DB5=DB4=1
42637 #2 20_US \ wait 40 us = LCD cycle
42638 %010 TOP_LCD \ 7- send DB5=1 DB4=0
42639 #2 20_US \ wait 40 us = LCD cycle
42640 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
42641 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
42642 LCD_CLEAR \ 10- "LCD_Clear"
42643 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
42644 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
42645 LCD_CLEAR \ 10- "LCD_Clear"
42646 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
42647 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
42648 CR ." I love you" \ display message on LCD
42649 ['] CR >BODY IS CR \ CR executes its default value
42650 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
42651 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
42652 PWR_STATE ABORT \ init DP and continues with ABORT
42654 \ ------------------------------\
42656 \ ------------------------------\
42657 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
42658 \ ------------------------------\
42659 MOV #SLEEP,X \ replace default background process SLEEP
42660 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
42661 MOV #WARM,X \ replace default WARM
42662 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
42663 MOV X,PC \ then execute new WARM
42665 \ ------------------------------\
42668 ; downloading RC5toLCD.4th is done
42669 RST_HERE ; this app is protected against <reset>
42674 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
42676 [UNDEFINED] MARKER [IF]
42677 \ https://forth-standard.org/standard/core/MARKER
42679 \ ( "<spaces>name" -- )
42680 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
42681 \ with the execution semantics defined below.
42683 \ name Execution: ( -- )
42684 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
42685 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
42686 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
42687 \ not necessarily provided. No other contextual information such as numeric base is affected
42692 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
42693 SUB #2,Y \ 1 Y = LFA
42694 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
42695 ADD #4,&DP \ 3 add 2 cells
42699 MOV @RSP+,IP \ -- PFA
42700 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
42701 MOV @TOS,&INIDP \ set DP value for RST_STATE
42703 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
42710 \ https://forth-standard.org/standard/core/Fetch
42711 \ @ c-addr -- char fetch char from memory
42718 [UNDEFINED] CONSTANT [IF]
42719 \ https://forth-standard.org/standard/core/CONSTANT
42720 \ CONSTANT <name> n -- define a Forth CONSTANT
42724 MOV TOS,-2(W) \ PFA = n
42731 [UNDEFINED] STATE [IF]
42732 \ https://forth-standard.org/standard/core/STATE
42733 \ STATE -- a-addr holds compiler state
42734 STATEADR CONSTANT STATE
42738 \ https://forth-standard.org/standard/core/Equal
42739 \ = x1 x2 -- flag test x1=x2
42746 XOR #-1,TOS \ 1 flag Z = 1
42751 [UNDEFINED] IF [IF]
42752 \ https://forth-standard.org/standard/core/IF
42753 \ IF -- IFadr initialize conditional forward branch
42754 CODE IF \ immediate
42757 MOV &DP,TOS \ -- HERE
42758 ADD #4,&DP \ compile one word, reserve one word
42759 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
42760 ADD #2,TOS \ -- HERE+2=IFadr
42765 [UNDEFINED] THEN [IF]
42766 \ https://forth-standard.org/standard/core/THEN
42767 \ THEN IFadr -- resolve forward branch
42768 CODE THEN \ immediate
42769 MOV &DP,0(TOS) \ -- IFadr
42775 [UNDEFINED] ELSE [IF]
42776 \ https://forth-standard.org/standard/core/ELSE
42777 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
42778 CODE ELSE \ immediate
42779 ADD #4,&DP \ make room to compile two words
42780 MOV &DP,W \ W=HERE+4
42782 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
42784 MOV W,TOS \ -- ELSEadr
42789 [UNDEFINED] DEFER [IF]
42790 \ https://forth-standard.org/standard/core/DEFER
42791 \ DEFER "<spaces>name" --
42792 \ Skip leading space delimiters. Parse name delimited by a space.
42793 \ Create a definition for name with the execution semantics defined below.
42795 \ name Execution: --
42796 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
42797 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
42801 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
42802 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
42808 [UNDEFINED] DEFER! [IF]
42809 \ https://forth-standard.org/standard/core/DEFERStore
42810 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
42811 CODE DEFER! \ xt2 xt1 --
42812 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
42818 [UNDEFINED] IS [IF]
42819 \ https://forth-standard.org/standard/core/IS
42822 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
42823 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
42824 \ or in a definition : ... ['] U. IS DISPLAY ...
42825 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
42827 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
42830 IF POSTPONE ['] POSTPONE DEFER!
42836 [UNDEFINED] >BODY [IF]
42837 \ https://forth-standard.org/standard/core/toBODY
42838 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
42845 \ CODE 20uS \ n -- 8MHz version
42846 \ BEGIN \ 4 + 16 ~ loop
42847 \ MOV #39,rDOCON \ 39
42854 \ MOV #XDOCON,rDOCON \ 2
42859 CODE 20_US \ n -- n * 20 us
42860 BEGIN \ here we presume that LCD_TIM_IFG = 1...
42862 BIT #1,&LCD_TIM_CTL \ 3
42863 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
42864 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
42866 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
42871 CODE TOP_LCD \ LCD Sample
42872 \ \ if write : %xxxx_WWWW --
42873 \ \ if read : -- %0000_RRRR
42874 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
42875 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
42876 0= IF \ write LCD bits pattern
42877 AND.B #LCD_DB,TOS \
42878 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
42879 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42882 THEN \ read LCD bits pattern
42885 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
42886 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
42887 AND.B #LCD_DB,TOS \
42891 CODE LCD_WRC \ char -- Write Char
42892 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42894 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
42895 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
42896 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
42897 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
42898 COLON \ high level word starts here
42899 TOP_LCD 2 20_US \ write high nibble first
42903 CODE LCD_WRF \ func -- Write Fonction
42904 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42908 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
42909 : LCD_HOME $02 LCD_WRF 100 20_us ;
42911 \ [UNDEFINED] OR [IF]
42913 \ \ https://forth-standard.org/standard/core/OR
42914 \ \ C OR x1 x2 -- x3 logical OR
42922 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
42923 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
42924 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
42925 \ : LCD_FN_SET $20 OR LCD_WrF ;
42926 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
42927 \ : LCD_GOTO $80 OR LCD_WrF ;
42930 \ CODE LCD_RDS \ -- status Read Status
42931 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
42932 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
42933 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
42934 \ COLON \ starts a FORTH word
42935 \ TOP_LCD 2 20_us \ -- %0000_HHHH
42936 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
42937 \ HI2LO \ switch from FORTH to assembler
42938 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
42939 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
42940 \ MOV @RSP+,IP \ restore IP saved by COLON
42944 \ CODE LCD_RDC \ -- char Read Char
42945 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
42950 \ ******************************\
42951 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
42952 \ ******************************\
42953 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
42954 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
42955 BIT.B #SW2,&SW2_IN \ test switch S2
42956 0= IF \ case of switch S2 pressed
42957 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
42959 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
42962 BIT.B #SW1,&SW1_IN \ test switch S1 input
42963 0= IF \ case of Switch S1 pressed
42964 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
42966 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
42970 BW1 \ from quit on truncated RC5 message, repeated RC5 command
42974 \ ******************************\
42975 ASM RC5_INT \ wake up on Px.RC5 change interrupt
42976 \ ******************************\
42977 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
42978 \ ******************************\
42979 \ \ in : SR(9)=old Toggle bit memory (ADD on)
42980 \ \ SMclock = 8|16|24 MHz
42981 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
42982 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
42983 \ \ SR(9)=new Toggle bit memory (ADD on)
42984 \ ******************************\
42985 \ RC5_FirstStartBitHalfCycle: \
42986 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
42987 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
42988 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
42989 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
42991 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
42992 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
42994 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
42995 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
42997 MOV #1778,X \ RC5_Period * 1us
42998 MOV #14,W \ count of loop
43000 \ ******************************\
43001 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
43002 \ ******************************\ |
43003 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
43004 \ RC5_Compute_3/4_Period: \ |
43005 RRUM #1,X \ X=1/2 cycle |
43008 ADD X,Y \ Y=3/4 cycle
43009 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
43011 \ ******************************\
43012 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
43013 \ ******************************\
43014 BIT.B #RC5,&IR_IN \ C_flag = IR bit
43015 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
43016 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
43017 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
43018 SUB #1,W \ decrement count loop
43019 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
43020 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
43021 0<> WHILE \ ----> out of loop ----+
43022 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
43024 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
43025 CMP Y,X \ 1 | cycle time out of bound ?
43026 U>= IF \ 2 ^ | yes:
43027 BIC #$30,&RC5_TIM_CTL \ | | stop timer
43028 GOTO BW1 \ | | quit on truncated RC5 message
43030 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
43032 REPEAT \ ----> loop back --+ | with X = new RC5_period value
43033 \ ******************************\ |
43034 \ RC5_SampleEndOf: \ <---------------------+
43035 \ ******************************\
43036 BIC #$30,&RC5_TIM_CTL \ stop timer
43037 \ ******************************\
43038 \ RC5_ComputeNewRC5word \
43039 \ ******************************\
43040 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
43041 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
43042 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
43043 \ ******************************\
43044 \ RC5_ComputeC6bit \
43045 \ ******************************\
43046 BIT #BIT14,T \ test /C6 bit in T
43047 0= IF BIS #BIT6,X \ set C6 bit in X
43048 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
43049 \ ******************************\
43050 \ RC5_CommandByteIsDone \ -- BASE RC5_code
43051 \ ******************************\
43052 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
43053 \ ******************************\
43054 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
43055 XOR @RSP,T \ (new XOR old) Toggle bits
43056 BIT #UF10,T \ repeated RC5_command ?
43057 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
43058 XOR #UF10,0(RSP) \ 5 toggle bit memory
43059 \ ******************************\
43060 \ Display IR_RC5 code \
43061 \ ******************************\
43062 SUB #8,PSP \ TOS -- x x x x TOS
43063 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
43064 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
43065 MOV #$10,&BASEADR \ set hexadecimal base
43066 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
43067 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
43068 LO2HI \ switch from assembler to FORTH
43069 LCD_CLEAR \ set LCD cursor at home
43070 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
43071 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
43072 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
43073 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
43074 HI2LO \ -- switch from FORTH to assembler
43075 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
43076 MOV @PSP+,TOS \ -- TOS
43080 \ ******************************\
43082 \ ******************************\
43084 \ ... \ insert here your background task
43087 CALL &RXON \ comment this line to disable TERMINAL_INPUT
43089 \ ******************************\
43090 \ here start all interrupts \
43091 \ ******************************\
43092 \ here return all interrupts \
43093 \ ******************************\
43096 \ ******************************\
43098 \ ------------------------------\
43099 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
43100 \ ------------------------------\
43101 \ ... \ init specific I/O sys as you want
43102 \ ... \ before executing default WARM
43103 MOV #WARM,X \ ['] WARM
43105 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
43107 \ ------------------------------\
43109 \ ------------------------------\
43110 CODE STOP \ stops multitasking, must to be used before downloading app
43111 \ ------------------------------\
43112 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
43113 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
43114 MOV X,-2(X) \ restore the default background: SLEEP
43116 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
43117 BIC.B #RC5,&IR_IE \ clear RC5_Int
43118 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
43119 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
43120 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
43121 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
43122 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
43123 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
43125 ." RC5toLCD is removed,"
43126 ." type START to restart"
43127 WARM \ performs reset to reset all interrupt vectors.
43129 \ ------------------------------\
43131 \ ------------------------------\
43132 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
43133 \ ------------------------------\
43134 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
43135 \ - - \CNTL Counter lentgh \ 00 = 16 bits
43136 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
43137 \ -- \ID input divider \ 10 = /4
43138 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
43139 \ - \TBCLR TimerB Clear
43142 \ -------------------------------\
43143 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
43144 \ -- \CM Capture Mode
43149 \ --- \OUTMOD \ 011 = set/reset
43155 \ -------------------------------\
43157 \ -------------------------------\
43159 \ ------------------------------\
43160 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
43161 \ ------------------------------\
43162 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
43163 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
43164 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
43165 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
43167 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
43168 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
43170 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
43171 \ ------------------------------\
43172 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
43173 \ ------------------------------\
43174 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
43175 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
43176 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
43177 \ ------------------------------\
43178 BIS.B #LCDVo,&LCDVo_DIR \
43179 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
43180 \ ------------------------------\
43181 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
43182 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
43183 \ ------------------------------\
43184 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
43185 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
43186 \ ******************************\
43188 \ ******************************\
43189 BIS.B #RC5,&IR_IE \ enable RC5_Int
43190 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
43191 MOV #RC5_INT,&IR_Vec \ init interrupt vector
43192 \ ******************************\
43193 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
43194 \ ******************************\
43195 \ %01 0001 0100 \ TAxCTL
43196 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
43197 \ -- \ ID divided by 1
43198 \ -- \ MC MODE = up to TAxCCRn
43199 \ - \ TACLR clear timer count
43202 \ ------------------------------\
43203 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
43204 \ ------------------------------\
43206 \ --- \ TAIDEX pre divisor
43207 \ ------------------------------\
43208 \ %0000 0000 0000 0101 \ TAxCCR0
43209 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
43210 \ ------------------------------\
43211 \ %0000 0000 0001 0000 \ TAxCCTL0
43212 \ - \ CAP capture/compare mode = compare
43215 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
43216 \ ------------------------------\
43217 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
43218 \ ------------------------------\
43219 \ define LPM mode for ACCEPT \
43220 \ ------------------------------\
43221 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43222 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43223 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43224 \ ------------------------------\
43226 \ ------------------------------\
43227 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
43228 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
43229 \ ------------------------------\
43230 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
43231 \ ------------------------------\
43232 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
43233 \ CMP #2,Y \ Power_ON event
43234 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
43236 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
43238 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
43240 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
43242 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
43243 \ ------------------------------\
43245 \ ------------------------------\
43247 \ ------------------------------\
43248 #1000 20_US \ 1- wait 20 ms
43249 %011 TOP_LCD \ 2- send DB5=DB4=1
43250 #205 20_US \ 3- wait 4,1 ms
43251 %011 TOP_LCD \ 4- send again DB5=DB4=1
43252 #5 20_US \ 5- wait 0,1 ms
43253 %011 TOP_LCD \ 6- send again again DB5=DB4=1
43254 #2 20_US \ wait 40 us = LCD cycle
43255 %010 TOP_LCD \ 7- send DB5=1 DB4=0
43256 #2 20_US \ wait 40 us = LCD cycle
43257 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43258 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
43259 LCD_CLEAR \ 10- "LCD_Clear"
43260 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
43261 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
43262 LCD_CLEAR \ 10- "LCD_Clear"
43263 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
43264 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
43265 CR ." I love you" \ display message on LCD
43266 ['] CR >BODY IS CR \ CR executes its default value
43267 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
43268 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
43269 PWR_STATE ABORT \ init DP and continues with ABORT
43271 \ ------------------------------\
43273 \ ------------------------------\
43274 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
43275 \ ------------------------------\
43276 MOV #SLEEP,X \ replace default background process SLEEP
43277 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
43278 MOV #WARM,X \ replace default WARM
43279 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
43280 MOV X,PC \ then execute new WARM
43282 \ ------------------------------\
43285 ; downloading RC5toLCD.4th is done
43286 RST_HERE ; this app is protected against <reset>
43291 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
43293 [UNDEFINED] MARKER [IF]
43294 \ https://forth-standard.org/standard/core/MARKER
43296 \ ( "<spaces>name" -- )
43297 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
43298 \ with the execution semantics defined below.
43300 \ name Execution: ( -- )
43301 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
43302 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
43303 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
43304 \ not necessarily provided. No other contextual information such as numeric base is affected
43309 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
43310 SUB #2,Y \ 1 Y = LFA
43311 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
43312 ADD #4,&DP \ 3 add 2 cells
43316 MOV @RSP+,IP \ -- PFA
43317 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
43318 MOV @TOS,&INIDP \ set DP value for RST_STATE
43320 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
43327 \ https://forth-standard.org/standard/core/Fetch
43328 \ @ c-addr -- char fetch char from memory
43335 [UNDEFINED] CONSTANT [IF]
43336 \ https://forth-standard.org/standard/core/CONSTANT
43337 \ CONSTANT <name> n -- define a Forth CONSTANT
43341 MOV TOS,-2(W) \ PFA = n
43348 [UNDEFINED] STATE [IF]
43349 \ https://forth-standard.org/standard/core/STATE
43350 \ STATE -- a-addr holds compiler state
43351 STATEADR CONSTANT STATE
43355 \ https://forth-standard.org/standard/core/Equal
43356 \ = x1 x2 -- flag test x1=x2
43363 XOR #-1,TOS \ 1 flag Z = 1
43368 [UNDEFINED] IF [IF]
43369 \ https://forth-standard.org/standard/core/IF
43370 \ IF -- IFadr initialize conditional forward branch
43371 CODE IF \ immediate
43374 MOV &DP,TOS \ -- HERE
43375 ADD #4,&DP \ compile one word, reserve one word
43376 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
43377 ADD #2,TOS \ -- HERE+2=IFadr
43382 [UNDEFINED] THEN [IF]
43383 \ https://forth-standard.org/standard/core/THEN
43384 \ THEN IFadr -- resolve forward branch
43385 CODE THEN \ immediate
43386 MOV &DP,0(TOS) \ -- IFadr
43392 [UNDEFINED] ELSE [IF]
43393 \ https://forth-standard.org/standard/core/ELSE
43394 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
43395 CODE ELSE \ immediate
43396 ADD #4,&DP \ make room to compile two words
43397 MOV &DP,W \ W=HERE+4
43399 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
43401 MOV W,TOS \ -- ELSEadr
43406 [UNDEFINED] DEFER [IF]
43407 \ https://forth-standard.org/standard/core/DEFER
43408 \ DEFER "<spaces>name" --
43409 \ Skip leading space delimiters. Parse name delimited by a space.
43410 \ Create a definition for name with the execution semantics defined below.
43412 \ name Execution: --
43413 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
43414 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
43418 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
43419 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
43425 [UNDEFINED] DEFER! [IF]
43426 \ https://forth-standard.org/standard/core/DEFERStore
43427 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
43428 CODE DEFER! \ xt2 xt1 --
43429 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
43435 [UNDEFINED] IS [IF]
43436 \ https://forth-standard.org/standard/core/IS
43439 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
43440 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
43441 \ or in a definition : ... ['] U. IS DISPLAY ...
43442 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
43444 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
43447 IF POSTPONE ['] POSTPONE DEFER!
43453 [UNDEFINED] >BODY [IF]
43454 \ https://forth-standard.org/standard/core/toBODY
43455 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
43462 \ CODE 20uS \ n -- 8MHz version
43463 \ BEGIN \ 4 + 16 ~ loop
43464 \ MOV #39,rDOCON \ 39
43471 \ MOV #XDOCON,rDOCON \ 2
43476 CODE 20_US \ n -- n * 20 us
43477 BEGIN \ here we presume that LCD_TIM_IFG = 1...
43479 BIT #1,&LCD_TIM_CTL \ 3
43480 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
43481 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
43483 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
43488 CODE TOP_LCD \ LCD Sample
43489 \ \ if write : %xxxx_WWWW --
43490 \ \ if read : -- %0000_RRRR
43491 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
43492 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
43493 0= IF \ write LCD bits pattern
43494 AND.B #LCD_DB,TOS \
43495 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
43496 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43499 THEN \ read LCD bits pattern
43502 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
43503 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
43504 AND.B #LCD_DB,TOS \
43508 CODE LCD_WRC \ char -- Write Char
43509 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43511 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
43512 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
43513 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
43514 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
43515 COLON \ high level word starts here
43516 TOP_LCD 2 20_US \ write high nibble first
43520 CODE LCD_WRF \ func -- Write Fonction
43521 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43525 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
43526 : LCD_HOME $02 LCD_WRF 100 20_us ;
43528 \ [UNDEFINED] OR [IF]
43530 \ \ https://forth-standard.org/standard/core/OR
43531 \ \ C OR x1 x2 -- x3 logical OR
43539 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
43540 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
43541 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
43542 \ : LCD_FN_SET $20 OR LCD_WrF ;
43543 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
43544 \ : LCD_GOTO $80 OR LCD_WrF ;
43547 \ CODE LCD_RDS \ -- status Read Status
43548 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
43549 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
43550 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
43551 \ COLON \ starts a FORTH word
43552 \ TOP_LCD 2 20_us \ -- %0000_HHHH
43553 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
43554 \ HI2LO \ switch from FORTH to assembler
43555 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
43556 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
43557 \ MOV @RSP+,IP \ restore IP saved by COLON
43561 \ CODE LCD_RDC \ -- char Read Char
43562 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
43567 \ ******************************\
43568 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
43569 \ ******************************\
43570 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
43571 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
43572 BIT.B #SW2,&SW2_IN \ test switch S2
43573 0= IF \ case of switch S2 pressed
43574 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
43576 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
43579 BIT.B #SW1,&SW1_IN \ test switch S1 input
43580 0= IF \ case of Switch S1 pressed
43581 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
43583 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
43587 BW1 \ from quit on truncated RC5 message, repeated RC5 command
43591 \ ******************************\
43592 ASM RC5_INT \ wake up on Px.RC5 change interrupt
43593 \ ******************************\
43594 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
43595 \ ******************************\
43596 \ \ in : SR(9)=old Toggle bit memory (ADD on)
43597 \ \ SMclock = 8|16|24 MHz
43598 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
43599 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
43600 \ \ SR(9)=new Toggle bit memory (ADD on)
43601 \ ******************************\
43602 \ RC5_FirstStartBitHalfCycle: \
43603 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
43604 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
43605 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
43606 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
43608 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
43609 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
43611 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
43612 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
43614 MOV #1778,X \ RC5_Period * 1us
43615 MOV #14,W \ count of loop
43617 \ ******************************\
43618 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
43619 \ ******************************\ |
43620 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
43621 \ RC5_Compute_3/4_Period: \ |
43622 RRUM #1,X \ X=1/2 cycle |
43625 ADD X,Y \ Y=3/4 cycle
43626 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
43628 \ ******************************\
43629 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
43630 \ ******************************\
43631 BIT.B #RC5,&IR_IN \ C_flag = IR bit
43632 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
43633 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
43634 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
43635 SUB #1,W \ decrement count loop
43636 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
43637 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
43638 0<> WHILE \ ----> out of loop ----+
43639 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
43641 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
43642 CMP Y,X \ 1 | cycle time out of bound ?
43643 U>= IF \ 2 ^ | yes:
43644 BIC #$30,&RC5_TIM_CTL \ | | stop timer
43645 GOTO BW1 \ | | quit on truncated RC5 message
43647 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
43649 REPEAT \ ----> loop back --+ | with X = new RC5_period value
43650 \ ******************************\ |
43651 \ RC5_SampleEndOf: \ <---------------------+
43652 \ ******************************\
43653 BIC #$30,&RC5_TIM_CTL \ stop timer
43654 \ ******************************\
43655 \ RC5_ComputeNewRC5word \
43656 \ ******************************\
43657 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
43658 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
43659 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
43660 \ ******************************\
43661 \ RC5_ComputeC6bit \
43662 \ ******************************\
43663 BIT #BIT14,T \ test /C6 bit in T
43664 0= IF BIS #BIT6,X \ set C6 bit in X
43665 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
43666 \ ******************************\
43667 \ RC5_CommandByteIsDone \ -- BASE RC5_code
43668 \ ******************************\
43669 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
43670 \ ******************************\
43671 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
43672 XOR @RSP,T \ (new XOR old) Toggle bits
43673 BIT #UF10,T \ repeated RC5_command ?
43674 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
43675 XOR #UF10,0(RSP) \ 5 toggle bit memory
43676 \ ******************************\
43677 \ Display IR_RC5 code \
43678 \ ******************************\
43679 SUB #8,PSP \ TOS -- x x x x TOS
43680 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
43681 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
43682 MOV #$10,&BASEADR \ set hexadecimal base
43683 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
43684 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
43685 LO2HI \ switch from assembler to FORTH
43686 LCD_CLEAR \ set LCD cursor at home
43687 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
43688 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
43689 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
43690 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
43691 HI2LO \ -- switch from FORTH to assembler
43692 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
43693 MOV @PSP+,TOS \ -- TOS
43697 \ ******************************\
43699 \ ******************************\
43701 \ ... \ insert here your background task
43704 CALL &RXON \ comment this line to disable TERMINAL_INPUT
43706 \ ******************************\
43707 \ here start all interrupts \
43708 \ ******************************\
43709 \ here return all interrupts \
43710 \ ******************************\
43713 \ ******************************\
43715 \ ------------------------------\
43716 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
43717 \ ------------------------------\
43718 \ ... \ init specific I/O sys as you want
43719 \ ... \ before executing default WARM
43720 MOV #WARM,X \ ['] WARM
43722 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
43724 \ ------------------------------\
43726 \ ------------------------------\
43727 CODE STOP \ stops multitasking, must to be used before downloading app
43728 \ ------------------------------\
43729 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
43730 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
43731 MOV X,-2(X) \ restore the default background: SLEEP
43733 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
43734 BIC.B #RC5,&IR_IE \ clear RC5_Int
43735 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
43736 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
43737 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
43738 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
43739 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
43740 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
43742 ." RC5toLCD is removed,"
43743 ." type START to restart"
43744 WARM \ performs reset to reset all interrupt vectors.
43746 \ ------------------------------\
43748 \ ------------------------------\
43749 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
43750 \ ------------------------------\
43751 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
43752 \ - - \CNTL Counter lentgh \ 00 = 16 bits
43753 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
43754 \ -- \ID input divider \ 10 = /4
43755 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
43756 \ - \TBCLR TimerB Clear
43759 \ -------------------------------\
43760 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
43761 \ -- \CM Capture Mode
43766 \ --- \OUTMOD \ 011 = set/reset
43772 \ -------------------------------\
43774 \ -------------------------------\
43776 \ ------------------------------\
43777 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
43778 \ ------------------------------\
43779 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
43780 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
43781 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
43782 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
43784 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
43785 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
43787 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
43788 \ ------------------------------\
43789 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
43790 \ ------------------------------\
43791 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
43792 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
43793 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
43794 \ ------------------------------\
43795 BIS.B #LCDVo,&LCDVo_DIR \
43796 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
43797 \ ------------------------------\
43798 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
43799 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
43800 \ ------------------------------\
43801 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
43802 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
43803 \ ******************************\
43805 \ ******************************\
43806 BIS.B #RC5,&IR_IE \ enable RC5_Int
43807 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
43808 MOV #RC5_INT,&IR_Vec \ init interrupt vector
43809 \ ******************************\
43810 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
43811 \ ******************************\
43812 \ %01 0001 0100 \ TAxCTL
43813 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
43814 \ -- \ ID divided by 1
43815 \ -- \ MC MODE = up to TAxCCRn
43816 \ - \ TACLR clear timer count
43819 \ ------------------------------\
43820 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
43821 \ ------------------------------\
43823 \ --- \ TAIDEX pre divisor
43824 \ ------------------------------\
43825 \ %0000 0000 0000 0101 \ TAxCCR0
43826 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
43827 \ ------------------------------\
43828 \ %0000 0000 0001 0000 \ TAxCCTL0
43829 \ - \ CAP capture/compare mode = compare
43832 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
43833 \ ------------------------------\
43834 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
43835 \ ------------------------------\
43836 \ define LPM mode for ACCEPT \
43837 \ ------------------------------\
43838 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
43839 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
43840 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
43841 \ ------------------------------\
43843 \ ------------------------------\
43844 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
43845 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
43846 \ ------------------------------\
43847 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
43848 \ ------------------------------\
43849 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
43850 \ CMP #2,Y \ Power_ON event
43851 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
43853 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
43855 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
43857 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
43859 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
43860 \ ------------------------------\
43862 \ ------------------------------\
43864 \ ------------------------------\
43865 #1000 20_US \ 1- wait 20 ms
43866 %011 TOP_LCD \ 2- send DB5=DB4=1
43867 #205 20_US \ 3- wait 4,1 ms
43868 %011 TOP_LCD \ 4- send again DB5=DB4=1
43869 #5 20_US \ 5- wait 0,1 ms
43870 %011 TOP_LCD \ 6- send again again DB5=DB4=1
43871 #2 20_US \ wait 40 us = LCD cycle
43872 %010 TOP_LCD \ 7- send DB5=1 DB4=0
43873 #2 20_US \ wait 40 us = LCD cycle
43874 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
43875 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
43876 LCD_CLEAR \ 10- "LCD_Clear"
43877 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
43878 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
43879 LCD_CLEAR \ 10- "LCD_Clear"
43880 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
43881 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
43882 CR ." I love you" \ display message on LCD
43883 ['] CR >BODY IS CR \ CR executes its default value
43884 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
43885 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
43886 PWR_STATE ABORT \ init DP and continues with ABORT
43888 \ ------------------------------\
43890 \ ------------------------------\
43891 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
43892 \ ------------------------------\
43893 MOV #SLEEP,X \ replace default background process SLEEP
43894 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
43895 MOV #WARM,X \ replace default WARM
43896 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
43897 MOV X,PC \ then execute new WARM
43899 \ ------------------------------\
43902 ; downloading RC5toLCD.4th is done
43903 RST_HERE ; this app is protected against <reset>
43908 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
43910 [UNDEFINED] MARKER [IF]
43911 \ https://forth-standard.org/standard/core/MARKER
43913 \ ( "<spaces>name" -- )
43914 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
43915 \ with the execution semantics defined below.
43917 \ name Execution: ( -- )
43918 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
43919 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
43920 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
43921 \ not necessarily provided. No other contextual information such as numeric base is affected
43926 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
43927 SUB #2,Y \ 1 Y = LFA
43928 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
43929 ADD #4,&DP \ 3 add 2 cells
43933 MOV @RSP+,IP \ -- PFA
43934 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
43935 MOV @TOS,&INIDP \ set DP value for RST_STATE
43937 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
43944 \ https://forth-standard.org/standard/core/Fetch
43945 \ @ c-addr -- char fetch char from memory
43952 [UNDEFINED] CONSTANT [IF]
43953 \ https://forth-standard.org/standard/core/CONSTANT
43954 \ CONSTANT <name> n -- define a Forth CONSTANT
43958 MOV TOS,-2(W) \ PFA = n
43965 [UNDEFINED] STATE [IF]
43966 \ https://forth-standard.org/standard/core/STATE
43967 \ STATE -- a-addr holds compiler state
43968 STATEADR CONSTANT STATE
43972 \ https://forth-standard.org/standard/core/Equal
43973 \ = x1 x2 -- flag test x1=x2
43980 XOR #-1,TOS \ 1 flag Z = 1
43985 [UNDEFINED] IF [IF]
43986 \ https://forth-standard.org/standard/core/IF
43987 \ IF -- IFadr initialize conditional forward branch
43988 CODE IF \ immediate
43991 MOV &DP,TOS \ -- HERE
43992 ADD #4,&DP \ compile one word, reserve one word
43993 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
43994 ADD #2,TOS \ -- HERE+2=IFadr
43999 [UNDEFINED] THEN [IF]
44000 \ https://forth-standard.org/standard/core/THEN
44001 \ THEN IFadr -- resolve forward branch
44002 CODE THEN \ immediate
44003 MOV &DP,0(TOS) \ -- IFadr
44009 [UNDEFINED] ELSE [IF]
44010 \ https://forth-standard.org/standard/core/ELSE
44011 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
44012 CODE ELSE \ immediate
44013 ADD #4,&DP \ make room to compile two words
44014 MOV &DP,W \ W=HERE+4
44016 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
44018 MOV W,TOS \ -- ELSEadr
44023 [UNDEFINED] DEFER [IF]
44024 \ https://forth-standard.org/standard/core/DEFER
44025 \ DEFER "<spaces>name" --
44026 \ Skip leading space delimiters. Parse name delimited by a space.
44027 \ Create a definition for name with the execution semantics defined below.
44029 \ name Execution: --
44030 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
44031 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
44035 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
44036 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
44042 [UNDEFINED] DEFER! [IF]
44043 \ https://forth-standard.org/standard/core/DEFERStore
44044 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
44045 CODE DEFER! \ xt2 xt1 --
44046 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
44052 [UNDEFINED] IS [IF]
44053 \ https://forth-standard.org/standard/core/IS
44056 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
44057 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
44058 \ or in a definition : ... ['] U. IS DISPLAY ...
44059 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
44061 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
44064 IF POSTPONE ['] POSTPONE DEFER!
44070 [UNDEFINED] >BODY [IF]
44071 \ https://forth-standard.org/standard/core/toBODY
44072 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
44079 \ CODE 20uS \ n -- 8MHz version
44080 \ BEGIN \ 4 + 16 ~ loop
44081 \ MOV #39,rDOCON \ 39
44088 \ MOV #XDOCON,rDOCON \ 2
44093 CODE 20_US \ n -- n * 20 us
44094 BEGIN \ here we presume that LCD_TIM_IFG = 1...
44096 BIT #1,&LCD_TIM_CTL \ 3
44097 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
44098 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
44100 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
44105 CODE TOP_LCD \ LCD Sample
44106 \ \ if write : %xxxx_WWWW --
44107 \ \ if read : -- %0000_RRRR
44108 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
44109 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
44110 0= IF \ write LCD bits pattern
44111 AND.B #LCD_DB,TOS \
44112 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
44113 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44116 THEN \ read LCD bits pattern
44119 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44120 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
44121 AND.B #LCD_DB,TOS \
44125 CODE LCD_WRC \ char -- Write Char
44126 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44128 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
44129 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
44130 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
44131 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
44132 COLON \ high level word starts here
44133 TOP_LCD 2 20_US \ write high nibble first
44137 CODE LCD_WRF \ func -- Write Fonction
44138 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44142 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
44143 : LCD_HOME $02 LCD_WRF 100 20_us ;
44145 \ [UNDEFINED] OR [IF]
44147 \ \ https://forth-standard.org/standard/core/OR
44148 \ \ C OR x1 x2 -- x3 logical OR
44156 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
44157 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
44158 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
44159 \ : LCD_FN_SET $20 OR LCD_WrF ;
44160 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
44161 \ : LCD_GOTO $80 OR LCD_WrF ;
44164 \ CODE LCD_RDS \ -- status Read Status
44165 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44166 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
44167 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
44168 \ COLON \ starts a FORTH word
44169 \ TOP_LCD 2 20_us \ -- %0000_HHHH
44170 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
44171 \ HI2LO \ switch from FORTH to assembler
44172 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
44173 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
44174 \ MOV @RSP+,IP \ restore IP saved by COLON
44178 \ CODE LCD_RDC \ -- char Read Char
44179 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44184 \ ******************************\
44185 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
44186 \ ******************************\
44187 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
44188 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
44189 BIT.B #SW2,&SW2_IN \ test switch S2
44190 0= IF \ case of switch S2 pressed
44191 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
44193 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
44196 BIT.B #SW1,&SW1_IN \ test switch S1 input
44197 0= IF \ case of Switch S1 pressed
44198 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
44200 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
44204 BW1 \ from quit on truncated RC5 message, repeated RC5 command
44208 \ ******************************\
44209 ASM RC5_INT \ wake up on Px.RC5 change interrupt
44210 \ ******************************\
44211 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
44212 \ ******************************\
44213 \ \ in : SR(9)=old Toggle bit memory (ADD on)
44214 \ \ SMclock = 8|16|24 MHz
44215 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
44216 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
44217 \ \ SR(9)=new Toggle bit memory (ADD on)
44218 \ ******************************\
44219 \ RC5_FirstStartBitHalfCycle: \
44220 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
44221 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
44222 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
44223 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
44225 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
44226 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
44228 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
44229 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
44231 MOV #1778,X \ RC5_Period * 1us
44232 MOV #14,W \ count of loop
44234 \ ******************************\
44235 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
44236 \ ******************************\ |
44237 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
44238 \ RC5_Compute_3/4_Period: \ |
44239 RRUM #1,X \ X=1/2 cycle |
44242 ADD X,Y \ Y=3/4 cycle
44243 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
44245 \ ******************************\
44246 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
44247 \ ******************************\
44248 BIT.B #RC5,&IR_IN \ C_flag = IR bit
44249 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
44250 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
44251 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
44252 SUB #1,W \ decrement count loop
44253 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
44254 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
44255 0<> WHILE \ ----> out of loop ----+
44256 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
44258 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
44259 CMP Y,X \ 1 | cycle time out of bound ?
44260 U>= IF \ 2 ^ | yes:
44261 BIC #$30,&RC5_TIM_CTL \ | | stop timer
44262 GOTO BW1 \ | | quit on truncated RC5 message
44264 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
44266 REPEAT \ ----> loop back --+ | with X = new RC5_period value
44267 \ ******************************\ |
44268 \ RC5_SampleEndOf: \ <---------------------+
44269 \ ******************************\
44270 BIC #$30,&RC5_TIM_CTL \ stop timer
44271 \ ******************************\
44272 \ RC5_ComputeNewRC5word \
44273 \ ******************************\
44274 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
44275 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
44276 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
44277 \ ******************************\
44278 \ RC5_ComputeC6bit \
44279 \ ******************************\
44280 BIT #BIT14,T \ test /C6 bit in T
44281 0= IF BIS #BIT6,X \ set C6 bit in X
44282 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
44283 \ ******************************\
44284 \ RC5_CommandByteIsDone \ -- BASE RC5_code
44285 \ ******************************\
44286 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
44287 \ ******************************\
44288 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
44289 XOR @RSP,T \ (new XOR old) Toggle bits
44290 BIT #UF10,T \ repeated RC5_command ?
44291 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
44292 XOR #UF10,0(RSP) \ 5 toggle bit memory
44293 \ ******************************\
44294 \ Display IR_RC5 code \
44295 \ ******************************\
44296 SUB #8,PSP \ TOS -- x x x x TOS
44297 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
44298 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
44299 MOV #$10,&BASEADR \ set hexadecimal base
44300 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
44301 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
44302 LO2HI \ switch from assembler to FORTH
44303 LCD_CLEAR \ set LCD cursor at home
44304 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
44305 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
44306 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
44307 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
44308 HI2LO \ -- switch from FORTH to assembler
44309 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
44310 MOV @PSP+,TOS \ -- TOS
44314 \ ******************************\
44316 \ ******************************\
44318 \ ... \ insert here your background task
44321 CALL &RXON \ comment this line to disable TERMINAL_INPUT
44323 \ ******************************\
44324 \ here start all interrupts \
44325 \ ******************************\
44326 \ here return all interrupts \
44327 \ ******************************\
44330 \ ******************************\
44332 \ ------------------------------\
44333 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
44334 \ ------------------------------\
44335 \ ... \ init specific I/O sys as you want
44336 \ ... \ before executing default WARM
44337 MOV #WARM,X \ ['] WARM
44339 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
44341 \ ------------------------------\
44343 \ ------------------------------\
44344 CODE STOP \ stops multitasking, must to be used before downloading app
44345 \ ------------------------------\
44346 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
44347 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
44348 MOV X,-2(X) \ restore the default background: SLEEP
44350 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
44351 BIC.B #RC5,&IR_IE \ clear RC5_Int
44352 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
44353 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
44354 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
44355 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
44356 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
44357 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
44359 ." RC5toLCD is removed,"
44360 ." type START to restart"
44361 WARM \ performs reset to reset all interrupt vectors.
44363 \ ------------------------------\
44365 \ ------------------------------\
44366 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
44367 \ ------------------------------\
44368 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
44369 \ - - \CNTL Counter lentgh \ 00 = 16 bits
44370 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
44371 \ -- \ID input divider \ 10 = /4
44372 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
44373 \ - \TBCLR TimerB Clear
44376 \ -------------------------------\
44377 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
44378 \ -- \CM Capture Mode
44383 \ --- \OUTMOD \ 011 = set/reset
44389 \ -------------------------------\
44391 \ -------------------------------\
44393 \ ------------------------------\
44394 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
44395 \ ------------------------------\
44396 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
44397 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
44398 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
44399 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
44401 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
44402 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
44404 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
44405 \ ------------------------------\
44406 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
44407 \ ------------------------------\
44408 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
44409 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
44410 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
44411 \ ------------------------------\
44412 BIS.B #LCDVo,&LCDVo_DIR \
44413 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
44414 \ ------------------------------\
44415 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
44416 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
44417 \ ------------------------------\
44418 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
44419 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
44420 \ ******************************\
44422 \ ******************************\
44423 BIS.B #RC5,&IR_IE \ enable RC5_Int
44424 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
44425 MOV #RC5_INT,&IR_Vec \ init interrupt vector
44426 \ ******************************\
44427 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
44428 \ ******************************\
44429 \ %01 0001 0100 \ TAxCTL
44430 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
44431 \ -- \ ID divided by 1
44432 \ -- \ MC MODE = up to TAxCCRn
44433 \ - \ TACLR clear timer count
44436 \ ------------------------------\
44437 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
44438 \ ------------------------------\
44440 \ --- \ TAIDEX pre divisor
44441 \ ------------------------------\
44442 \ %0000 0000 0000 0101 \ TAxCCR0
44443 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
44444 \ ------------------------------\
44445 \ %0000 0000 0001 0000 \ TAxCCTL0
44446 \ - \ CAP capture/compare mode = compare
44449 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
44450 \ ------------------------------\
44451 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
44452 \ ------------------------------\
44453 \ define LPM mode for ACCEPT \
44454 \ ------------------------------\
44455 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
44456 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
44457 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
44458 \ ------------------------------\
44460 \ ------------------------------\
44461 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
44462 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
44463 \ ------------------------------\
44464 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
44465 \ ------------------------------\
44466 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
44467 \ CMP #2,Y \ Power_ON event
44468 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
44470 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
44472 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
44474 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
44476 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
44477 \ ------------------------------\
44479 \ ------------------------------\
44481 \ ------------------------------\
44482 #1000 20_US \ 1- wait 20 ms
44483 %011 TOP_LCD \ 2- send DB5=DB4=1
44484 #205 20_US \ 3- wait 4,1 ms
44485 %011 TOP_LCD \ 4- send again DB5=DB4=1
44486 #5 20_US \ 5- wait 0,1 ms
44487 %011 TOP_LCD \ 6- send again again DB5=DB4=1
44488 #2 20_US \ wait 40 us = LCD cycle
44489 %010 TOP_LCD \ 7- send DB5=1 DB4=0
44490 #2 20_US \ wait 40 us = LCD cycle
44491 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
44492 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
44493 LCD_CLEAR \ 10- "LCD_Clear"
44494 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
44495 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
44496 LCD_CLEAR \ 10- "LCD_Clear"
44497 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
44498 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
44499 CR ." I love you" \ display message on LCD
44500 ['] CR >BODY IS CR \ CR executes its default value
44501 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
44502 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
44503 PWR_STATE ABORT \ init DP and continues with ABORT
44505 \ ------------------------------\
44507 \ ------------------------------\
44508 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
44509 \ ------------------------------\
44510 MOV #SLEEP,X \ replace default background process SLEEP
44511 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
44512 MOV #WARM,X \ replace default WARM
44513 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
44514 MOV X,PC \ then execute new WARM
44516 \ ------------------------------\
44519 ; downloading RC5toLCD.4th is done
44520 RST_HERE ; this app is protected against <reset>
44525 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
44527 [UNDEFINED] MARKER [IF]
44528 \ https://forth-standard.org/standard/core/MARKER
44530 \ ( "<spaces>name" -- )
44531 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
44532 \ with the execution semantics defined below.
44534 \ name Execution: ( -- )
44535 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
44536 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
44537 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
44538 \ not necessarily provided. No other contextual information such as numeric base is affected
44543 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
44544 SUB #2,Y \ 1 Y = LFA
44545 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
44546 ADD #4,&DP \ 3 add 2 cells
44550 MOV @RSP+,IP \ -- PFA
44551 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
44552 MOV @TOS,&INIDP \ set DP value for RST_STATE
44554 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
44561 \ https://forth-standard.org/standard/core/Fetch
44562 \ @ c-addr -- char fetch char from memory
44569 [UNDEFINED] CONSTANT [IF]
44570 \ https://forth-standard.org/standard/core/CONSTANT
44571 \ CONSTANT <name> n -- define a Forth CONSTANT
44575 MOV TOS,-2(W) \ PFA = n
44582 [UNDEFINED] STATE [IF]
44583 \ https://forth-standard.org/standard/core/STATE
44584 \ STATE -- a-addr holds compiler state
44585 STATEADR CONSTANT STATE
44589 \ https://forth-standard.org/standard/core/Equal
44590 \ = x1 x2 -- flag test x1=x2
44597 XOR #-1,TOS \ 1 flag Z = 1
44602 [UNDEFINED] IF [IF]
44603 \ https://forth-standard.org/standard/core/IF
44604 \ IF -- IFadr initialize conditional forward branch
44605 CODE IF \ immediate
44608 MOV &DP,TOS \ -- HERE
44609 ADD #4,&DP \ compile one word, reserve one word
44610 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
44611 ADD #2,TOS \ -- HERE+2=IFadr
44616 [UNDEFINED] THEN [IF]
44617 \ https://forth-standard.org/standard/core/THEN
44618 \ THEN IFadr -- resolve forward branch
44619 CODE THEN \ immediate
44620 MOV &DP,0(TOS) \ -- IFadr
44626 [UNDEFINED] ELSE [IF]
44627 \ https://forth-standard.org/standard/core/ELSE
44628 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
44629 CODE ELSE \ immediate
44630 ADD #4,&DP \ make room to compile two words
44631 MOV &DP,W \ W=HERE+4
44633 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
44635 MOV W,TOS \ -- ELSEadr
44640 [UNDEFINED] DEFER [IF]
44641 \ https://forth-standard.org/standard/core/DEFER
44642 \ DEFER "<spaces>name" --
44643 \ Skip leading space delimiters. Parse name delimited by a space.
44644 \ Create a definition for name with the execution semantics defined below.
44646 \ name Execution: --
44647 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
44648 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
44652 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
44653 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
44659 [UNDEFINED] DEFER! [IF]
44660 \ https://forth-standard.org/standard/core/DEFERStore
44661 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
44662 CODE DEFER! \ xt2 xt1 --
44663 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
44669 [UNDEFINED] IS [IF]
44670 \ https://forth-standard.org/standard/core/IS
44673 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
44674 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
44675 \ or in a definition : ... ['] U. IS DISPLAY ...
44676 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
44678 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
44681 IF POSTPONE ['] POSTPONE DEFER!
44687 [UNDEFINED] >BODY [IF]
44688 \ https://forth-standard.org/standard/core/toBODY
44689 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
44696 \ CODE 20uS \ n -- 8MHz version
44697 \ BEGIN \ 4 + 16 ~ loop
44698 \ MOV #39,rDOCON \ 39
44705 \ MOV #XDOCON,rDOCON \ 2
44710 CODE 20_US \ n -- n * 20 us
44711 BEGIN \ here we presume that LCD_TIM_IFG = 1...
44713 BIT #1,&LCD_TIM_CTL \ 3
44714 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
44715 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
44717 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
44722 CODE TOP_LCD \ LCD Sample
44723 \ \ if write : %xxxx_WWWW --
44724 \ \ if read : -- %0000_RRRR
44725 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
44726 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
44727 0= IF \ write LCD bits pattern
44728 AND.B #LCD_DB,TOS \
44729 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
44730 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44733 THEN \ read LCD bits pattern
44736 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
44737 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
44738 AND.B #LCD_DB,TOS \
44742 CODE LCD_WRC \ char -- Write Char
44743 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44745 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
44746 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
44747 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
44748 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
44749 COLON \ high level word starts here
44750 TOP_LCD 2 20_US \ write high nibble first
44754 CODE LCD_WRF \ func -- Write Fonction
44755 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44759 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
44760 : LCD_HOME $02 LCD_WRF 100 20_us ;
44762 \ [UNDEFINED] OR [IF]
44764 \ \ https://forth-standard.org/standard/core/OR
44765 \ \ C OR x1 x2 -- x3 logical OR
44773 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
44774 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
44775 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
44776 \ : LCD_FN_SET $20 OR LCD_WrF ;
44777 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
44778 \ : LCD_GOTO $80 OR LCD_WrF ;
44781 \ CODE LCD_RDS \ -- status Read Status
44782 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
44783 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
44784 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
44785 \ COLON \ starts a FORTH word
44786 \ TOP_LCD 2 20_us \ -- %0000_HHHH
44787 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
44788 \ HI2LO \ switch from FORTH to assembler
44789 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
44790 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
44791 \ MOV @RSP+,IP \ restore IP saved by COLON
44795 \ CODE LCD_RDC \ -- char Read Char
44796 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
44801 \ ******************************\
44802 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
44803 \ ******************************\
44804 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
44805 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
44806 BIT.B #SW2,&SW2_IN \ test switch S2
44807 0= IF \ case of switch S2 pressed
44808 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
44810 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
44813 BIT.B #SW1,&SW1_IN \ test switch S1 input
44814 0= IF \ case of Switch S1 pressed
44815 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
44817 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
44821 BW1 \ from quit on truncated RC5 message, repeated RC5 command
44825 \ ******************************\
44826 ASM RC5_INT \ wake up on Px.RC5 change interrupt
44827 \ ******************************\
44828 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
44829 \ ******************************\
44830 \ \ in : SR(9)=old Toggle bit memory (ADD on)
44831 \ \ SMclock = 8|16|24 MHz
44832 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
44833 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
44834 \ \ SR(9)=new Toggle bit memory (ADD on)
44835 \ ******************************\
44836 \ RC5_FirstStartBitHalfCycle: \
44837 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
44838 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
44839 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
44840 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
44842 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
44843 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
44845 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
44846 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
44848 MOV #1778,X \ RC5_Period * 1us
44849 MOV #14,W \ count of loop
44851 \ ******************************\
44852 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
44853 \ ******************************\ |
44854 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
44855 \ RC5_Compute_3/4_Period: \ |
44856 RRUM #1,X \ X=1/2 cycle |
44859 ADD X,Y \ Y=3/4 cycle
44860 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
44862 \ ******************************\
44863 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
44864 \ ******************************\
44865 BIT.B #RC5,&IR_IN \ C_flag = IR bit
44866 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
44867 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
44868 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
44869 SUB #1,W \ decrement count loop
44870 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
44871 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
44872 0<> WHILE \ ----> out of loop ----+
44873 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
44875 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
44876 CMP Y,X \ 1 | cycle time out of bound ?
44877 U>= IF \ 2 ^ | yes:
44878 BIC #$30,&RC5_TIM_CTL \ | | stop timer
44879 GOTO BW1 \ | | quit on truncated RC5 message
44881 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
44883 REPEAT \ ----> loop back --+ | with X = new RC5_period value
44884 \ ******************************\ |
44885 \ RC5_SampleEndOf: \ <---------------------+
44886 \ ******************************\
44887 BIC #$30,&RC5_TIM_CTL \ stop timer
44888 \ ******************************\
44889 \ RC5_ComputeNewRC5word \
44890 \ ******************************\
44891 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
44892 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
44893 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
44894 \ ******************************\
44895 \ RC5_ComputeC6bit \
44896 \ ******************************\
44897 BIT #BIT14,T \ test /C6 bit in T
44898 0= IF BIS #BIT6,X \ set C6 bit in X
44899 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
44900 \ ******************************\
44901 \ RC5_CommandByteIsDone \ -- BASE RC5_code
44902 \ ******************************\
44903 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
44904 \ ******************************\
44905 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
44906 XOR @RSP,T \ (new XOR old) Toggle bits
44907 BIT #UF10,T \ repeated RC5_command ?
44908 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
44909 XOR #UF10,0(RSP) \ 5 toggle bit memory
44910 \ ******************************\
44911 \ Display IR_RC5 code \
44912 \ ******************************\
44913 SUB #8,PSP \ TOS -- x x x x TOS
44914 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
44915 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
44916 MOV #$10,&BASEADR \ set hexadecimal base
44917 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
44918 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
44919 LO2HI \ switch from assembler to FORTH
44920 LCD_CLEAR \ set LCD cursor at home
44921 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
44922 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
44923 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
44924 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
44925 HI2LO \ -- switch from FORTH to assembler
44926 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
44927 MOV @PSP+,TOS \ -- TOS
44931 \ ******************************\
44933 \ ******************************\
44935 \ ... \ insert here your background task
44938 CALL &RXON \ comment this line to disable TERMINAL_INPUT
44940 \ ******************************\
44941 \ here start all interrupts \
44942 \ ******************************\
44943 \ here return all interrupts \
44944 \ ******************************\
44947 \ ******************************\
44949 \ ------------------------------\
44950 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
44951 \ ------------------------------\
44952 \ ... \ init specific I/O sys as you want
44953 \ ... \ before executing default WARM
44954 MOV #WARM,X \ ['] WARM
44956 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
44958 \ ------------------------------\
44960 \ ------------------------------\
44961 CODE STOP \ stops multitasking, must to be used before downloading app
44962 \ ------------------------------\
44963 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
44964 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
44965 MOV X,-2(X) \ restore the default background: SLEEP
44967 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
44968 BIC.B #RC5,&IR_IE \ clear RC5_Int
44969 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
44970 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
44971 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
44972 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
44973 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
44974 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
44976 ." RC5toLCD is removed,"
44977 ." type START to restart"
44978 WARM \ performs reset to reset all interrupt vectors.
44980 \ ------------------------------\
44982 \ ------------------------------\
44983 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
44984 \ ------------------------------\
44985 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
44986 \ - - \CNTL Counter lentgh \ 00 = 16 bits
44987 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
44988 \ -- \ID input divider \ 10 = /4
44989 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
44990 \ - \TBCLR TimerB Clear
44993 \ -------------------------------\
44994 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
44995 \ -- \CM Capture Mode
45000 \ --- \OUTMOD \ 011 = set/reset
45006 \ -------------------------------\
45008 \ -------------------------------\
45010 \ ------------------------------\
45011 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
45012 \ ------------------------------\
45013 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
45014 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
45015 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
45016 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
45018 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
45019 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
45021 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
45022 \ ------------------------------\
45023 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
45024 \ ------------------------------\
45025 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
45026 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
45027 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45028 \ ------------------------------\
45029 BIS.B #LCDVo,&LCDVo_DIR \
45030 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
45031 \ ------------------------------\
45032 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45033 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45034 \ ------------------------------\
45035 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
45036 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
45037 \ ******************************\
45039 \ ******************************\
45040 BIS.B #RC5,&IR_IE \ enable RC5_Int
45041 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
45042 MOV #RC5_INT,&IR_Vec \ init interrupt vector
45043 \ ******************************\
45044 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
45045 \ ******************************\
45046 \ %01 0001 0100 \ TAxCTL
45047 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
45048 \ -- \ ID divided by 1
45049 \ -- \ MC MODE = up to TAxCCRn
45050 \ - \ TACLR clear timer count
45053 \ ------------------------------\
45054 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
45055 \ ------------------------------\
45057 \ --- \ TAIDEX pre divisor
45058 \ ------------------------------\
45059 \ %0000 0000 0000 0101 \ TAxCCR0
45060 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
45061 \ ------------------------------\
45062 \ %0000 0000 0001 0000 \ TAxCCTL0
45063 \ - \ CAP capture/compare mode = compare
45066 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
45067 \ ------------------------------\
45068 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
45069 \ ------------------------------\
45070 \ define LPM mode for ACCEPT \
45071 \ ------------------------------\
45072 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45073 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45074 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45075 \ ------------------------------\
45077 \ ------------------------------\
45078 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
45079 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
45080 \ ------------------------------\
45081 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
45082 \ ------------------------------\
45083 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
45084 \ CMP #2,Y \ Power_ON event
45085 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
45087 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
45089 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
45091 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
45093 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
45094 \ ------------------------------\
45096 \ ------------------------------\
45098 \ ------------------------------\
45099 #1000 20_US \ 1- wait 20 ms
45100 %011 TOP_LCD \ 2- send DB5=DB4=1
45101 #205 20_US \ 3- wait 4,1 ms
45102 %011 TOP_LCD \ 4- send again DB5=DB4=1
45103 #5 20_US \ 5- wait 0,1 ms
45104 %011 TOP_LCD \ 6- send again again DB5=DB4=1
45105 #2 20_US \ wait 40 us = LCD cycle
45106 %010 TOP_LCD \ 7- send DB5=1 DB4=0
45107 #2 20_US \ wait 40 us = LCD cycle
45108 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45109 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
45110 LCD_CLEAR \ 10- "LCD_Clear"
45111 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
45112 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
45113 LCD_CLEAR \ 10- "LCD_Clear"
45114 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
45115 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
45116 CR ." I love you" \ display message on LCD
45117 ['] CR >BODY IS CR \ CR executes its default value
45118 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
45119 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
45120 PWR_STATE ABORT \ init DP and continues with ABORT
45122 \ ------------------------------\
45124 \ ------------------------------\
45125 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
45126 \ ------------------------------\
45127 MOV #SLEEP,X \ replace default background process SLEEP
45128 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
45129 MOV #WARM,X \ replace default WARM
45130 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
45131 MOV X,PC \ then execute new WARM
45133 \ ------------------------------\
45136 ; downloading RC5toLCD.4th is done
45137 RST_HERE ; this app is protected against <reset>
45142 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
45144 [UNDEFINED] MARKER [IF]
45145 \ https://forth-standard.org/standard/core/MARKER
45147 \ ( "<spaces>name" -- )
45148 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
45149 \ with the execution semantics defined below.
45151 \ name Execution: ( -- )
45152 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
45153 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
45154 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
45155 \ not necessarily provided. No other contextual information such as numeric base is affected
45160 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
45161 SUB #2,Y \ 1 Y = LFA
45162 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
45163 ADD #4,&DP \ 3 add 2 cells
45167 MOV @RSP+,IP \ -- PFA
45168 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
45169 MOV @TOS,&INIDP \ set DP value for RST_STATE
45171 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
45178 \ https://forth-standard.org/standard/core/Fetch
45179 \ @ c-addr -- char fetch char from memory
45186 [UNDEFINED] CONSTANT [IF]
45187 \ https://forth-standard.org/standard/core/CONSTANT
45188 \ CONSTANT <name> n -- define a Forth CONSTANT
45192 MOV TOS,-2(W) \ PFA = n
45199 [UNDEFINED] STATE [IF]
45200 \ https://forth-standard.org/standard/core/STATE
45201 \ STATE -- a-addr holds compiler state
45202 STATEADR CONSTANT STATE
45206 \ https://forth-standard.org/standard/core/Equal
45207 \ = x1 x2 -- flag test x1=x2
45214 XOR #-1,TOS \ 1 flag Z = 1
45219 [UNDEFINED] IF [IF]
45220 \ https://forth-standard.org/standard/core/IF
45221 \ IF -- IFadr initialize conditional forward branch
45222 CODE IF \ immediate
45225 MOV &DP,TOS \ -- HERE
45226 ADD #4,&DP \ compile one word, reserve one word
45227 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
45228 ADD #2,TOS \ -- HERE+2=IFadr
45233 [UNDEFINED] THEN [IF]
45234 \ https://forth-standard.org/standard/core/THEN
45235 \ THEN IFadr -- resolve forward branch
45236 CODE THEN \ immediate
45237 MOV &DP,0(TOS) \ -- IFadr
45243 [UNDEFINED] ELSE [IF]
45244 \ https://forth-standard.org/standard/core/ELSE
45245 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
45246 CODE ELSE \ immediate
45247 ADD #4,&DP \ make room to compile two words
45248 MOV &DP,W \ W=HERE+4
45250 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
45252 MOV W,TOS \ -- ELSEadr
45257 [UNDEFINED] DEFER [IF]
45258 \ https://forth-standard.org/standard/core/DEFER
45259 \ DEFER "<spaces>name" --
45260 \ Skip leading space delimiters. Parse name delimited by a space.
45261 \ Create a definition for name with the execution semantics defined below.
45263 \ name Execution: --
45264 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
45265 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
45269 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
45270 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
45276 [UNDEFINED] DEFER! [IF]
45277 \ https://forth-standard.org/standard/core/DEFERStore
45278 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
45279 CODE DEFER! \ xt2 xt1 --
45280 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
45286 [UNDEFINED] IS [IF]
45287 \ https://forth-standard.org/standard/core/IS
45290 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
45291 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
45292 \ or in a definition : ... ['] U. IS DISPLAY ...
45293 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
45295 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
45298 IF POSTPONE ['] POSTPONE DEFER!
45304 [UNDEFINED] >BODY [IF]
45305 \ https://forth-standard.org/standard/core/toBODY
45306 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
45313 \ CODE 20uS \ n -- 8MHz version
45314 \ BEGIN \ 4 + 16 ~ loop
45315 \ MOV #39,rDOCON \ 39
45322 \ MOV #XDOCON,rDOCON \ 2
45327 CODE 20_US \ n -- n * 20 us
45328 BEGIN \ here we presume that LCD_TIM_IFG = 1...
45330 BIT #1,&LCD_TIM_CTL \ 3
45331 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
45332 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
45334 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
45339 CODE TOP_LCD \ LCD Sample
45340 \ \ if write : %xxxx_WWWW --
45341 \ \ if read : -- %0000_RRRR
45342 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
45343 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
45344 0= IF \ write LCD bits pattern
45345 AND.B #LCD_DB,TOS \
45346 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
45347 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45350 THEN \ read LCD bits pattern
45353 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45354 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
45355 AND.B #LCD_DB,TOS \
45359 CODE LCD_WRC \ char -- Write Char
45360 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45362 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
45363 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
45364 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
45365 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
45366 COLON \ high level word starts here
45367 TOP_LCD 2 20_US \ write high nibble first
45371 CODE LCD_WRF \ func -- Write Fonction
45372 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45376 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
45377 : LCD_HOME $02 LCD_WRF 100 20_us ;
45379 \ [UNDEFINED] OR [IF]
45381 \ \ https://forth-standard.org/standard/core/OR
45382 \ \ C OR x1 x2 -- x3 logical OR
45390 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
45391 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
45392 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
45393 \ : LCD_FN_SET $20 OR LCD_WrF ;
45394 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
45395 \ : LCD_GOTO $80 OR LCD_WrF ;
45398 \ CODE LCD_RDS \ -- status Read Status
45399 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45400 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
45401 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
45402 \ COLON \ starts a FORTH word
45403 \ TOP_LCD 2 20_us \ -- %0000_HHHH
45404 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
45405 \ HI2LO \ switch from FORTH to assembler
45406 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
45407 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
45408 \ MOV @RSP+,IP \ restore IP saved by COLON
45412 \ CODE LCD_RDC \ -- char Read Char
45413 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45418 \ ******************************\
45419 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
45420 \ ******************************\
45421 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
45422 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
45423 BIT.B #SW2,&SW2_IN \ test switch S2
45424 0= IF \ case of switch S2 pressed
45425 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
45427 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
45430 BIT.B #SW1,&SW1_IN \ test switch S1 input
45431 0= IF \ case of Switch S1 pressed
45432 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
45434 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
45438 BW1 \ from quit on truncated RC5 message, repeated RC5 command
45442 \ ******************************\
45443 ASM RC5_INT \ wake up on Px.RC5 change interrupt
45444 \ ******************************\
45445 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
45446 \ ******************************\
45447 \ \ in : SR(9)=old Toggle bit memory (ADD on)
45448 \ \ SMclock = 8|16|24 MHz
45449 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
45450 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
45451 \ \ SR(9)=new Toggle bit memory (ADD on)
45452 \ ******************************\
45453 \ RC5_FirstStartBitHalfCycle: \
45454 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
45455 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
45456 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
45457 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
45459 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
45460 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
45462 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
45463 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
45465 MOV #1778,X \ RC5_Period * 1us
45466 MOV #14,W \ count of loop
45468 \ ******************************\
45469 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
45470 \ ******************************\ |
45471 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
45472 \ RC5_Compute_3/4_Period: \ |
45473 RRUM #1,X \ X=1/2 cycle |
45476 ADD X,Y \ Y=3/4 cycle
45477 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
45479 \ ******************************\
45480 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
45481 \ ******************************\
45482 BIT.B #RC5,&IR_IN \ C_flag = IR bit
45483 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
45484 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
45485 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
45486 SUB #1,W \ decrement count loop
45487 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
45488 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
45489 0<> WHILE \ ----> out of loop ----+
45490 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
45492 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
45493 CMP Y,X \ 1 | cycle time out of bound ?
45494 U>= IF \ 2 ^ | yes:
45495 BIC #$30,&RC5_TIM_CTL \ | | stop timer
45496 GOTO BW1 \ | | quit on truncated RC5 message
45498 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
45500 REPEAT \ ----> loop back --+ | with X = new RC5_period value
45501 \ ******************************\ |
45502 \ RC5_SampleEndOf: \ <---------------------+
45503 \ ******************************\
45504 BIC #$30,&RC5_TIM_CTL \ stop timer
45505 \ ******************************\
45506 \ RC5_ComputeNewRC5word \
45507 \ ******************************\
45508 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
45509 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
45510 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
45511 \ ******************************\
45512 \ RC5_ComputeC6bit \
45513 \ ******************************\
45514 BIT #BIT14,T \ test /C6 bit in T
45515 0= IF BIS #BIT6,X \ set C6 bit in X
45516 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
45517 \ ******************************\
45518 \ RC5_CommandByteIsDone \ -- BASE RC5_code
45519 \ ******************************\
45520 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
45521 \ ******************************\
45522 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
45523 XOR @RSP,T \ (new XOR old) Toggle bits
45524 BIT #UF10,T \ repeated RC5_command ?
45525 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
45526 XOR #UF10,0(RSP) \ 5 toggle bit memory
45527 \ ******************************\
45528 \ Display IR_RC5 code \
45529 \ ******************************\
45530 SUB #8,PSP \ TOS -- x x x x TOS
45531 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
45532 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
45533 MOV #$10,&BASEADR \ set hexadecimal base
45534 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
45535 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
45536 LO2HI \ switch from assembler to FORTH
45537 LCD_CLEAR \ set LCD cursor at home
45538 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
45539 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
45540 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
45541 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
45542 HI2LO \ -- switch from FORTH to assembler
45543 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
45544 MOV @PSP+,TOS \ -- TOS
45548 \ ******************************\
45550 \ ******************************\
45552 \ ... \ insert here your background task
45555 CALL &RXON \ comment this line to disable TERMINAL_INPUT
45557 \ ******************************\
45558 \ here start all interrupts \
45559 \ ******************************\
45560 \ here return all interrupts \
45561 \ ******************************\
45564 \ ******************************\
45566 \ ------------------------------\
45567 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
45568 \ ------------------------------\
45569 \ ... \ init specific I/O sys as you want
45570 \ ... \ before executing default WARM
45571 MOV #WARM,X \ ['] WARM
45573 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
45575 \ ------------------------------\
45577 \ ------------------------------\
45578 CODE STOP \ stops multitasking, must to be used before downloading app
45579 \ ------------------------------\
45580 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
45581 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
45582 MOV X,-2(X) \ restore the default background: SLEEP
45584 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
45585 BIC.B #RC5,&IR_IE \ clear RC5_Int
45586 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
45587 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
45588 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
45589 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
45590 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
45591 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
45593 ." RC5toLCD is removed,"
45594 ." type START to restart"
45595 WARM \ performs reset to reset all interrupt vectors.
45597 \ ------------------------------\
45599 \ ------------------------------\
45600 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
45601 \ ------------------------------\
45602 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
45603 \ - - \CNTL Counter lentgh \ 00 = 16 bits
45604 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
45605 \ -- \ID input divider \ 10 = /4
45606 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
45607 \ - \TBCLR TimerB Clear
45610 \ -------------------------------\
45611 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
45612 \ -- \CM Capture Mode
45617 \ --- \OUTMOD \ 011 = set/reset
45623 \ -------------------------------\
45625 \ -------------------------------\
45627 \ ------------------------------\
45628 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
45629 \ ------------------------------\
45630 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
45631 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
45632 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
45633 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
45635 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
45636 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
45638 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
45639 \ ------------------------------\
45640 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
45641 \ ------------------------------\
45642 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
45643 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
45644 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
45645 \ ------------------------------\
45646 BIS.B #LCDVo,&LCDVo_DIR \
45647 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
45648 \ ------------------------------\
45649 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
45650 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
45651 \ ------------------------------\
45652 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
45653 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
45654 \ ******************************\
45656 \ ******************************\
45657 BIS.B #RC5,&IR_IE \ enable RC5_Int
45658 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
45659 MOV #RC5_INT,&IR_Vec \ init interrupt vector
45660 \ ******************************\
45661 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
45662 \ ******************************\
45663 \ %01 0001 0100 \ TAxCTL
45664 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
45665 \ -- \ ID divided by 1
45666 \ -- \ MC MODE = up to TAxCCRn
45667 \ - \ TACLR clear timer count
45670 \ ------------------------------\
45671 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
45672 \ ------------------------------\
45674 \ --- \ TAIDEX pre divisor
45675 \ ------------------------------\
45676 \ %0000 0000 0000 0101 \ TAxCCR0
45677 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
45678 \ ------------------------------\
45679 \ %0000 0000 0001 0000 \ TAxCCTL0
45680 \ - \ CAP capture/compare mode = compare
45683 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
45684 \ ------------------------------\
45685 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
45686 \ ------------------------------\
45687 \ define LPM mode for ACCEPT \
45688 \ ------------------------------\
45689 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
45690 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
45691 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
45692 \ ------------------------------\
45694 \ ------------------------------\
45695 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
45696 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
45697 \ ------------------------------\
45698 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
45699 \ ------------------------------\
45700 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
45701 \ CMP #2,Y \ Power_ON event
45702 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
45704 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
45706 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
45708 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
45710 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
45711 \ ------------------------------\
45713 \ ------------------------------\
45715 \ ------------------------------\
45716 #1000 20_US \ 1- wait 20 ms
45717 %011 TOP_LCD \ 2- send DB5=DB4=1
45718 #205 20_US \ 3- wait 4,1 ms
45719 %011 TOP_LCD \ 4- send again DB5=DB4=1
45720 #5 20_US \ 5- wait 0,1 ms
45721 %011 TOP_LCD \ 6- send again again DB5=DB4=1
45722 #2 20_US \ wait 40 us = LCD cycle
45723 %010 TOP_LCD \ 7- send DB5=1 DB4=0
45724 #2 20_US \ wait 40 us = LCD cycle
45725 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
45726 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
45727 LCD_CLEAR \ 10- "LCD_Clear"
45728 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
45729 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
45730 LCD_CLEAR \ 10- "LCD_Clear"
45731 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
45732 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
45733 CR ." I love you" \ display message on LCD
45734 ['] CR >BODY IS CR \ CR executes its default value
45735 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
45736 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
45737 PWR_STATE ABORT \ init DP and continues with ABORT
45739 \ ------------------------------\
45741 \ ------------------------------\
45742 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
45743 \ ------------------------------\
45744 MOV #SLEEP,X \ replace default background process SLEEP
45745 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
45746 MOV #WARM,X \ replace default WARM
45747 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
45748 MOV X,PC \ then execute new WARM
45750 \ ------------------------------\
45753 ; downloading RC5toLCD.4th is done
45754 RST_HERE ; this app is protected against <reset>
45759 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
45761 [UNDEFINED] MARKER [IF]
45762 \ https://forth-standard.org/standard/core/MARKER
45764 \ ( "<spaces>name" -- )
45765 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
45766 \ with the execution semantics defined below.
45768 \ name Execution: ( -- )
45769 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
45770 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
45771 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
45772 \ not necessarily provided. No other contextual information such as numeric base is affected
45777 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
45778 SUB #2,Y \ 1 Y = LFA
45779 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
45780 ADD #4,&DP \ 3 add 2 cells
45784 MOV @RSP+,IP \ -- PFA
45785 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
45786 MOV @TOS,&INIDP \ set DP value for RST_STATE
45788 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
45795 \ https://forth-standard.org/standard/core/Fetch
45796 \ @ c-addr -- char fetch char from memory
45803 [UNDEFINED] CONSTANT [IF]
45804 \ https://forth-standard.org/standard/core/CONSTANT
45805 \ CONSTANT <name> n -- define a Forth CONSTANT
45809 MOV TOS,-2(W) \ PFA = n
45816 [UNDEFINED] STATE [IF]
45817 \ https://forth-standard.org/standard/core/STATE
45818 \ STATE -- a-addr holds compiler state
45819 STATEADR CONSTANT STATE
45823 \ https://forth-standard.org/standard/core/Equal
45824 \ = x1 x2 -- flag test x1=x2
45831 XOR #-1,TOS \ 1 flag Z = 1
45836 [UNDEFINED] IF [IF]
45837 \ https://forth-standard.org/standard/core/IF
45838 \ IF -- IFadr initialize conditional forward branch
45839 CODE IF \ immediate
45842 MOV &DP,TOS \ -- HERE
45843 ADD #4,&DP \ compile one word, reserve one word
45844 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
45845 ADD #2,TOS \ -- HERE+2=IFadr
45850 [UNDEFINED] THEN [IF]
45851 \ https://forth-standard.org/standard/core/THEN
45852 \ THEN IFadr -- resolve forward branch
45853 CODE THEN \ immediate
45854 MOV &DP,0(TOS) \ -- IFadr
45860 [UNDEFINED] ELSE [IF]
45861 \ https://forth-standard.org/standard/core/ELSE
45862 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
45863 CODE ELSE \ immediate
45864 ADD #4,&DP \ make room to compile two words
45865 MOV &DP,W \ W=HERE+4
45867 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
45869 MOV W,TOS \ -- ELSEadr
45874 [UNDEFINED] DEFER [IF]
45875 \ https://forth-standard.org/standard/core/DEFER
45876 \ DEFER "<spaces>name" --
45877 \ Skip leading space delimiters. Parse name delimited by a space.
45878 \ Create a definition for name with the execution semantics defined below.
45880 \ name Execution: --
45881 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
45882 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
45886 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
45887 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
45893 [UNDEFINED] DEFER! [IF]
45894 \ https://forth-standard.org/standard/core/DEFERStore
45895 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
45896 CODE DEFER! \ xt2 xt1 --
45897 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
45903 [UNDEFINED] IS [IF]
45904 \ https://forth-standard.org/standard/core/IS
45907 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
45908 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
45909 \ or in a definition : ... ['] U. IS DISPLAY ...
45910 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
45912 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
45915 IF POSTPONE ['] POSTPONE DEFER!
45921 [UNDEFINED] >BODY [IF]
45922 \ https://forth-standard.org/standard/core/toBODY
45923 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
45930 \ CODE 20uS \ n -- 8MHz version
45931 \ BEGIN \ 4 + 16 ~ loop
45932 \ MOV #39,rDOCON \ 39
45939 \ MOV #XDOCON,rDOCON \ 2
45944 CODE 20_US \ n -- n * 20 us
45945 BEGIN \ here we presume that LCD_TIM_IFG = 1...
45947 BIT #1,&LCD_TIM_CTL \ 3
45948 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
45949 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
45951 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
45956 CODE TOP_LCD \ LCD Sample
45957 \ \ if write : %xxxx_WWWW --
45958 \ \ if read : -- %0000_RRRR
45959 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
45960 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
45961 0= IF \ write LCD bits pattern
45962 AND.B #LCD_DB,TOS \
45963 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
45964 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45967 THEN \ read LCD bits pattern
45970 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
45971 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
45972 AND.B #LCD_DB,TOS \
45976 CODE LCD_WRC \ char -- Write Char
45977 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
45979 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
45980 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
45981 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
45982 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
45983 COLON \ high level word starts here
45984 TOP_LCD 2 20_US \ write high nibble first
45988 CODE LCD_WRF \ func -- Write Fonction
45989 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
45993 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
45994 : LCD_HOME $02 LCD_WRF 100 20_us ;
45996 \ [UNDEFINED] OR [IF]
45998 \ \ https://forth-standard.org/standard/core/OR
45999 \ \ C OR x1 x2 -- x3 logical OR
46007 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
46008 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
46009 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
46010 \ : LCD_FN_SET $20 OR LCD_WrF ;
46011 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
46012 \ : LCD_GOTO $80 OR LCD_WrF ;
46015 \ CODE LCD_RDS \ -- status Read Status
46016 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
46017 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
46018 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
46019 \ COLON \ starts a FORTH word
46020 \ TOP_LCD 2 20_us \ -- %0000_HHHH
46021 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
46022 \ HI2LO \ switch from FORTH to assembler
46023 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
46024 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
46025 \ MOV @RSP+,IP \ restore IP saved by COLON
46029 \ CODE LCD_RDC \ -- char Read Char
46030 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
46035 \ ******************************\
46036 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
46037 \ ******************************\
46038 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
46039 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
46040 BIT.B #SW2,&SW2_IN \ test switch S2
46041 0= IF \ case of switch S2 pressed
46042 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
46044 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
46047 BIT.B #SW1,&SW1_IN \ test switch S1 input
46048 0= IF \ case of Switch S1 pressed
46049 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
46051 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
46055 BW1 \ from quit on truncated RC5 message, repeated RC5 command
46059 \ ******************************\
46060 ASM RC5_INT \ wake up on Px.RC5 change interrupt
46061 \ ******************************\
46062 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
46063 \ ******************************\
46064 \ \ in : SR(9)=old Toggle bit memory (ADD on)
46065 \ \ SMclock = 8|16|24 MHz
46066 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
46067 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
46068 \ \ SR(9)=new Toggle bit memory (ADD on)
46069 \ ******************************\
46070 \ RC5_FirstStartBitHalfCycle: \
46071 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
46072 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
46073 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
46074 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
46076 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
46077 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
46079 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
46080 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
46082 MOV #1778,X \ RC5_Period * 1us
46083 MOV #14,W \ count of loop
46085 \ ******************************\
46086 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
46087 \ ******************************\ |
46088 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
46089 \ RC5_Compute_3/4_Period: \ |
46090 RRUM #1,X \ X=1/2 cycle |
46093 ADD X,Y \ Y=3/4 cycle
46094 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
46096 \ ******************************\
46097 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
46098 \ ******************************\
46099 BIT.B #RC5,&IR_IN \ C_flag = IR bit
46100 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
46101 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
46102 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
46103 SUB #1,W \ decrement count loop
46104 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
46105 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
46106 0<> WHILE \ ----> out of loop ----+
46107 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
46109 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
46110 CMP Y,X \ 1 | cycle time out of bound ?
46111 U>= IF \ 2 ^ | yes:
46112 BIC #$30,&RC5_TIM_CTL \ | | stop timer
46113 GOTO BW1 \ | | quit on truncated RC5 message
46115 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
46117 REPEAT \ ----> loop back --+ | with X = new RC5_period value
46118 \ ******************************\ |
46119 \ RC5_SampleEndOf: \ <---------------------+
46120 \ ******************************\
46121 BIC #$30,&RC5_TIM_CTL \ stop timer
46122 \ ******************************\
46123 \ RC5_ComputeNewRC5word \
46124 \ ******************************\
46125 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
46126 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
46127 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
46128 \ ******************************\
46129 \ RC5_ComputeC6bit \
46130 \ ******************************\
46131 BIT #BIT14,T \ test /C6 bit in T
46132 0= IF BIS #BIT6,X \ set C6 bit in X
46133 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
46134 \ ******************************\
46135 \ RC5_CommandByteIsDone \ -- BASE RC5_code
46136 \ ******************************\
46137 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
46138 \ ******************************\
46139 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
46140 XOR @RSP,T \ (new XOR old) Toggle bits
46141 BIT #UF10,T \ repeated RC5_command ?
46142 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
46143 XOR #UF10,0(RSP) \ 5 toggle bit memory
46144 \ ******************************\
46145 \ Display IR_RC5 code \
46146 \ ******************************\
46147 SUB #8,PSP \ TOS -- x x x x TOS
46148 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
46149 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
46150 MOV #$10,&BASEADR \ set hexadecimal base
46151 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
46152 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
46153 LO2HI \ switch from assembler to FORTH
46154 LCD_CLEAR \ set LCD cursor at home
46155 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
46156 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
46157 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
46158 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
46159 HI2LO \ -- switch from FORTH to assembler
46160 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
46161 MOV @PSP+,TOS \ -- TOS
46165 \ ******************************\
46167 \ ******************************\
46169 \ ... \ insert here your background task
46172 CALL &RXON \ comment this line to disable TERMINAL_INPUT
46174 \ ******************************\
46175 \ here start all interrupts \
46176 \ ******************************\
46177 \ here return all interrupts \
46178 \ ******************************\
46181 \ ******************************\
46183 \ ------------------------------\
46184 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
46185 \ ------------------------------\
46186 \ ... \ init specific I/O sys as you want
46187 \ ... \ before executing default WARM
46188 MOV #WARM,X \ ['] WARM
46190 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
46192 \ ------------------------------\
46194 \ ------------------------------\
46195 CODE STOP \ stops multitasking, must to be used before downloading app
46196 \ ------------------------------\
46197 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
46198 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
46199 MOV X,-2(X) \ restore the default background: SLEEP
46201 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
46202 BIC.B #RC5,&IR_IE \ clear RC5_Int
46203 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
46204 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
46205 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
46206 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
46207 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
46208 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
46210 ." RC5toLCD is removed,"
46211 ." type START to restart"
46212 WARM \ performs reset to reset all interrupt vectors.
46214 \ ------------------------------\
46216 \ ------------------------------\
46217 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
46218 \ ------------------------------\
46219 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
46220 \ - - \CNTL Counter lentgh \ 00 = 16 bits
46221 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
46222 \ -- \ID input divider \ 10 = /4
46223 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
46224 \ - \TBCLR TimerB Clear
46227 \ -------------------------------\
46228 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
46229 \ -- \CM Capture Mode
46234 \ --- \OUTMOD \ 011 = set/reset
46240 \ -------------------------------\
46242 \ -------------------------------\
46244 \ ------------------------------\
46245 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
46246 \ ------------------------------\
46247 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
46248 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
46249 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
46250 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
46252 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
46253 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
46255 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
46256 \ ------------------------------\
46257 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
46258 \ ------------------------------\
46259 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
46260 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
46261 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
46262 \ ------------------------------\
46263 BIS.B #LCDVo,&LCDVo_DIR \
46264 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
46265 \ ------------------------------\
46266 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
46267 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
46268 \ ------------------------------\
46269 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
46270 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
46271 \ ******************************\
46273 \ ******************************\
46274 BIS.B #RC5,&IR_IE \ enable RC5_Int
46275 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
46276 MOV #RC5_INT,&IR_Vec \ init interrupt vector
46277 \ ******************************\
46278 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
46279 \ ******************************\
46280 \ %01 0001 0100 \ TAxCTL
46281 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
46282 \ -- \ ID divided by 1
46283 \ -- \ MC MODE = up to TAxCCRn
46284 \ - \ TACLR clear timer count
46287 \ ------------------------------\
46288 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
46289 \ ------------------------------\
46291 \ --- \ TAIDEX pre divisor
46292 \ ------------------------------\
46293 \ %0000 0000 0000 0101 \ TAxCCR0
46294 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
46295 \ ------------------------------\
46296 \ %0000 0000 0001 0000 \ TAxCCTL0
46297 \ - \ CAP capture/compare mode = compare
46300 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
46301 \ ------------------------------\
46302 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
46303 \ ------------------------------\
46304 \ define LPM mode for ACCEPT \
46305 \ ------------------------------\
46306 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
46307 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
46308 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
46309 \ ------------------------------\
46311 \ ------------------------------\
46312 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
46313 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
46314 \ ------------------------------\
46315 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
46316 \ ------------------------------\
46317 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
46318 \ CMP #2,Y \ Power_ON event
46319 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
46321 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
46323 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
46325 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
46327 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
46328 \ ------------------------------\
46330 \ ------------------------------\
46332 \ ------------------------------\
46333 #1000 20_US \ 1- wait 20 ms
46334 %011 TOP_LCD \ 2- send DB5=DB4=1
46335 #205 20_US \ 3- wait 4,1 ms
46336 %011 TOP_LCD \ 4- send again DB5=DB4=1
46337 #5 20_US \ 5- wait 0,1 ms
46338 %011 TOP_LCD \ 6- send again again DB5=DB4=1
46339 #2 20_US \ wait 40 us = LCD cycle
46340 %010 TOP_LCD \ 7- send DB5=1 DB4=0
46341 #2 20_US \ wait 40 us = LCD cycle
46342 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
46343 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
46344 LCD_CLEAR \ 10- "LCD_Clear"
46345 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
46346 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
46347 LCD_CLEAR \ 10- "LCD_Clear"
46348 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
46349 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
46350 CR ." I love you" \ display message on LCD
46351 ['] CR >BODY IS CR \ CR executes its default value
46352 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
46353 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
46354 PWR_STATE ABORT \ init DP and continues with ABORT
46356 \ ------------------------------\
46358 \ ------------------------------\
46359 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
46360 \ ------------------------------\
46361 MOV #SLEEP,X \ replace default background process SLEEP
46362 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
46363 MOV #WARM,X \ replace default WARM
46364 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
46365 MOV X,PC \ then execute new WARM
46367 \ ------------------------------\
46370 ; downloading RC5toLCD.4th is done
46371 RST_HERE ; this app is protected against <reset>
46376 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
46378 [UNDEFINED] MARKER [IF]
46379 \ https://forth-standard.org/standard/core/MARKER
46381 \ ( "<spaces>name" -- )
46382 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
46383 \ with the execution semantics defined below.
46385 \ name Execution: ( -- )
46386 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
46387 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
46388 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
46389 \ not necessarily provided. No other contextual information such as numeric base is affected
46394 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
46395 SUB #2,Y \ 1 Y = LFA
46396 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
46397 ADD #4,&DP \ 3 add 2 cells
46401 MOV @RSP+,IP \ -- PFA
46402 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
46403 MOV @TOS,&INIDP \ set DP value for RST_STATE
46405 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
46412 \ https://forth-standard.org/standard/core/Fetch
46413 \ @ c-addr -- char fetch char from memory
46420 [UNDEFINED] CONSTANT [IF]
46421 \ https://forth-standard.org/standard/core/CONSTANT
46422 \ CONSTANT <name> n -- define a Forth CONSTANT
46426 MOV TOS,-2(W) \ PFA = n
46433 [UNDEFINED] STATE [IF]
46434 \ https://forth-standard.org/standard/core/STATE
46435 \ STATE -- a-addr holds compiler state
46436 STATEADR CONSTANT STATE
46440 \ https://forth-standard.org/standard/core/Equal
46441 \ = x1 x2 -- flag test x1=x2
46448 XOR #-1,TOS \ 1 flag Z = 1
46453 [UNDEFINED] IF [IF]
46454 \ https://forth-standard.org/standard/core/IF
46455 \ IF -- IFadr initialize conditional forward branch
46456 CODE IF \ immediate
46459 MOV &DP,TOS \ -- HERE
46460 ADD #4,&DP \ compile one word, reserve one word
46461 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
46462 ADD #2,TOS \ -- HERE+2=IFadr
46467 [UNDEFINED] THEN [IF]
46468 \ https://forth-standard.org/standard/core/THEN
46469 \ THEN IFadr -- resolve forward branch
46470 CODE THEN \ immediate
46471 MOV &DP,0(TOS) \ -- IFadr
46477 [UNDEFINED] ELSE [IF]
46478 \ https://forth-standard.org/standard/core/ELSE
46479 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
46480 CODE ELSE \ immediate
46481 ADD #4,&DP \ make room to compile two words
46482 MOV &DP,W \ W=HERE+4
46484 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
46486 MOV W,TOS \ -- ELSEadr
46491 [UNDEFINED] DEFER [IF]
46492 \ https://forth-standard.org/standard/core/DEFER
46493 \ DEFER "<spaces>name" --
46494 \ Skip leading space delimiters. Parse name delimited by a space.
46495 \ Create a definition for name with the execution semantics defined below.
46497 \ name Execution: --
46498 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
46499 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
46503 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
46504 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
46510 [UNDEFINED] DEFER! [IF]
46511 \ https://forth-standard.org/standard/core/DEFERStore
46512 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
46513 CODE DEFER! \ xt2 xt1 --
46514 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
46520 [UNDEFINED] IS [IF]
46521 \ https://forth-standard.org/standard/core/IS
46524 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
46525 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
46526 \ or in a definition : ... ['] U. IS DISPLAY ...
46527 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
46529 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
46532 IF POSTPONE ['] POSTPONE DEFER!
46538 [UNDEFINED] >BODY [IF]
46539 \ https://forth-standard.org/standard/core/toBODY
46540 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
46547 \ CODE 20uS \ n -- 8MHz version
46548 \ BEGIN \ 4 + 16 ~ loop
46549 \ MOV #39,rDOCON \ 39
46556 \ MOV #XDOCON,rDOCON \ 2
46561 CODE 20_US \ n -- n * 20 us
46562 BEGIN \ here we presume that LCD_TIM_IFG = 1...
46564 BIT #1,&LCD_TIM_CTL \ 3
46565 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
46566 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
46568 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
46573 CODE TOP_LCD \ LCD Sample
46574 \ \ if write : %xxxx_WWWW --
46575 \ \ if read : -- %0000_RRRR
46576 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
46577 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
46578 0= IF \ write LCD bits pattern
46579 AND.B #LCD_DB,TOS \
46580 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
46581 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
46584 THEN \ read LCD bits pattern
46587 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
46588 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
46589 AND.B #LCD_DB,TOS \
46593 CODE LCD_WRC \ char -- Write Char
46594 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
46596 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
46597 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
46598 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
46599 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
46600 COLON \ high level word starts here
46601 TOP_LCD 2 20_US \ write high nibble first
46605 CODE LCD_WRF \ func -- Write Fonction
46606 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
46610 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
46611 : LCD_HOME $02 LCD_WRF 100 20_us ;
46613 \ [UNDEFINED] OR [IF]
46615 \ \ https://forth-standard.org/standard/core/OR
46616 \ \ C OR x1 x2 -- x3 logical OR
46624 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
46625 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
46626 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
46627 \ : LCD_FN_SET $20 OR LCD_WrF ;
46628 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
46629 \ : LCD_GOTO $80 OR LCD_WrF ;
46632 \ CODE LCD_RDS \ -- status Read Status
46633 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
46634 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
46635 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
46636 \ COLON \ starts a FORTH word
46637 \ TOP_LCD 2 20_us \ -- %0000_HHHH
46638 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
46639 \ HI2LO \ switch from FORTH to assembler
46640 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
46641 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
46642 \ MOV @RSP+,IP \ restore IP saved by COLON
46646 \ CODE LCD_RDC \ -- char Read Char
46647 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
46652 \ ******************************\
46653 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
46654 \ ******************************\
46655 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
46656 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
46657 BIT.B #SW2,&SW2_IN \ test switch S2
46658 0= IF \ case of switch S2 pressed
46659 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
46661 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
46664 BIT.B #SW1,&SW1_IN \ test switch S1 input
46665 0= IF \ case of Switch S1 pressed
46666 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
46668 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
46672 BW1 \ from quit on truncated RC5 message, repeated RC5 command
46676 \ ******************************\
46677 ASM RC5_INT \ wake up on Px.RC5 change interrupt
46678 \ ******************************\
46679 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
46680 \ ******************************\
46681 \ \ in : SR(9)=old Toggle bit memory (ADD on)
46682 \ \ SMclock = 8|16|24 MHz
46683 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
46684 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
46685 \ \ SR(9)=new Toggle bit memory (ADD on)
46686 \ ******************************\
46687 \ RC5_FirstStartBitHalfCycle: \
46688 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
46689 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
46690 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
46691 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
46693 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
46694 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
46696 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
46697 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
46699 MOV #1778,X \ RC5_Period * 1us
46700 MOV #14,W \ count of loop
46702 \ ******************************\
46703 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
46704 \ ******************************\ |
46705 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
46706 \ RC5_Compute_3/4_Period: \ |
46707 RRUM #1,X \ X=1/2 cycle |
46710 ADD X,Y \ Y=3/4 cycle
46711 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
46713 \ ******************************\
46714 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
46715 \ ******************************\
46716 BIT.B #RC5,&IR_IN \ C_flag = IR bit
46717 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
46718 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
46719 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
46720 SUB #1,W \ decrement count loop
46721 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
46722 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
46723 0<> WHILE \ ----> out of loop ----+
46724 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
46726 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
46727 CMP Y,X \ 1 | cycle time out of bound ?
46728 U>= IF \ 2 ^ | yes:
46729 BIC #$30,&RC5_TIM_CTL \ | | stop timer
46730 GOTO BW1 \ | | quit on truncated RC5 message
46732 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
46734 REPEAT \ ----> loop back --+ | with X = new RC5_period value
46735 \ ******************************\ |
46736 \ RC5_SampleEndOf: \ <---------------------+
46737 \ ******************************\
46738 BIC #$30,&RC5_TIM_CTL \ stop timer
46739 \ ******************************\
46740 \ RC5_ComputeNewRC5word \
46741 \ ******************************\
46742 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
46743 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
46744 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
46745 \ ******************************\
46746 \ RC5_ComputeC6bit \
46747 \ ******************************\
46748 BIT #BIT14,T \ test /C6 bit in T
46749 0= IF BIS #BIT6,X \ set C6 bit in X
46750 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
46751 \ ******************************\
46752 \ RC5_CommandByteIsDone \ -- BASE RC5_code
46753 \ ******************************\
46754 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
46755 \ ******************************\
46756 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
46757 XOR @RSP,T \ (new XOR old) Toggle bits
46758 BIT #UF10,T \ repeated RC5_command ?
46759 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
46760 XOR #UF10,0(RSP) \ 5 toggle bit memory
46761 \ ******************************\
46762 \ Display IR_RC5 code \
46763 \ ******************************\
46764 SUB #8,PSP \ TOS -- x x x x TOS
46765 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
46766 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
46767 MOV #$10,&BASEADR \ set hexadecimal base
46768 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
46769 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
46770 LO2HI \ switch from assembler to FORTH
46771 LCD_CLEAR \ set LCD cursor at home
46772 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
46773 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
46774 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
46775 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
46776 HI2LO \ -- switch from FORTH to assembler
46777 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
46778 MOV @PSP+,TOS \ -- TOS
46782 \ ******************************\
46784 \ ******************************\
46786 \ ... \ insert here your background task
46789 CALL &RXON \ comment this line to disable TERMINAL_INPUT
46791 \ ******************************\
46792 \ here start all interrupts \
46793 \ ******************************\
46794 \ here return all interrupts \
46795 \ ******************************\
46798 \ ******************************\
46800 \ ------------------------------\
46801 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
46802 \ ------------------------------\
46803 \ ... \ init specific I/O sys as you want
46804 \ ... \ before executing default WARM
46805 MOV #WARM,X \ ['] WARM
46807 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
46809 \ ------------------------------\
46811 \ ------------------------------\
46812 CODE STOP \ stops multitasking, must to be used before downloading app
46813 \ ------------------------------\
46814 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
46815 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
46816 MOV X,-2(X) \ restore the default background: SLEEP
46818 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
46819 BIC.B #RC5,&IR_IE \ clear RC5_Int
46820 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
46821 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
46822 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
46823 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
46824 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
46825 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
46827 ." RC5toLCD is removed,"
46828 ." type START to restart"
46829 WARM \ performs reset to reset all interrupt vectors.
46831 \ ------------------------------\
46833 \ ------------------------------\
46834 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
46835 \ ------------------------------\
46836 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
46837 \ - - \CNTL Counter lentgh \ 00 = 16 bits
46838 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
46839 \ -- \ID input divider \ 10 = /4
46840 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
46841 \ - \TBCLR TimerB Clear
46844 \ -------------------------------\
46845 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
46846 \ -- \CM Capture Mode
46851 \ --- \OUTMOD \ 011 = set/reset
46857 \ -------------------------------\
46859 \ -------------------------------\
46861 \ ------------------------------\
46862 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
46863 \ ------------------------------\
46864 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
46865 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
46866 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
46867 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
46869 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
46870 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
46872 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
46873 \ ------------------------------\
46874 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
46875 \ ------------------------------\
46876 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
46877 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
46878 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
46879 \ ------------------------------\
46880 BIS.B #LCDVo,&LCDVo_DIR \
46881 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
46882 \ ------------------------------\
46883 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
46884 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
46885 \ ------------------------------\
46886 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
46887 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
46888 \ ******************************\
46890 \ ******************************\
46891 BIS.B #RC5,&IR_IE \ enable RC5_Int
46892 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
46893 MOV #RC5_INT,&IR_Vec \ init interrupt vector
46894 \ ******************************\
46895 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
46896 \ ******************************\
46897 \ %01 0001 0100 \ TAxCTL
46898 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
46899 \ -- \ ID divided by 1
46900 \ -- \ MC MODE = up to TAxCCRn
46901 \ - \ TACLR clear timer count
46904 \ ------------------------------\
46905 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
46906 \ ------------------------------\
46908 \ --- \ TAIDEX pre divisor
46909 \ ------------------------------\
46910 \ %0000 0000 0000 0101 \ TAxCCR0
46911 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
46912 \ ------------------------------\
46913 \ %0000 0000 0001 0000 \ TAxCCTL0
46914 \ - \ CAP capture/compare mode = compare
46917 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
46918 \ ------------------------------\
46919 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
46920 \ ------------------------------\
46921 \ define LPM mode for ACCEPT \
46922 \ ------------------------------\
46923 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
46924 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
46925 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
46926 \ ------------------------------\
46928 \ ------------------------------\
46929 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
46930 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
46931 \ ------------------------------\
46932 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
46933 \ ------------------------------\
46934 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
46935 \ CMP #2,Y \ Power_ON event
46936 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
46938 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
46940 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
46942 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
46944 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
46945 \ ------------------------------\
46947 \ ------------------------------\
46949 \ ------------------------------\
46950 #1000 20_US \ 1- wait 20 ms
46951 %011 TOP_LCD \ 2- send DB5=DB4=1
46952 #205 20_US \ 3- wait 4,1 ms
46953 %011 TOP_LCD \ 4- send again DB5=DB4=1
46954 #5 20_US \ 5- wait 0,1 ms
46955 %011 TOP_LCD \ 6- send again again DB5=DB4=1
46956 #2 20_US \ wait 40 us = LCD cycle
46957 %010 TOP_LCD \ 7- send DB5=1 DB4=0
46958 #2 20_US \ wait 40 us = LCD cycle
46959 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
46960 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
46961 LCD_CLEAR \ 10- "LCD_Clear"
46962 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
46963 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
46964 LCD_CLEAR \ 10- "LCD_Clear"
46965 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
46966 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
46967 CR ." I love you" \ display message on LCD
46968 ['] CR >BODY IS CR \ CR executes its default value
46969 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
46970 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
46971 PWR_STATE ABORT \ init DP and continues with ABORT
46973 \ ------------------------------\
46975 \ ------------------------------\
46976 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
46977 \ ------------------------------\
46978 MOV #SLEEP,X \ replace default background process SLEEP
46979 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
46980 MOV #WARM,X \ replace default WARM
46981 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
46982 MOV X,PC \ then execute new WARM
46984 \ ------------------------------\
46987 ; downloading RC5toLCD.4th is done
46988 RST_HERE ; this app is protected against <reset>
46993 [DEFINED] {RC5TOLCD} [IF] {RC5TOLCD} [THEN] \ remove application
46995 [UNDEFINED] MARKER [IF]
46996 \ https://forth-standard.org/standard/core/MARKER
46998 \ ( "<spaces>name" -- )
46999 \ Skip leading space delimiters. Parse name delimited by a space. Create a definition for name
47000 \ with the execution semantics defined below.
47002 \ name Execution: ( -- )
47003 \ Restore all dictionary allocation and search order pointers to the state they had just prior to the
47004 \ definition of name. Remove the definition of name and all subsequent definitions. Restoration
47005 \ of any structures still existing that could refer to deleted definitions or deallocated data space is
47006 \ not necessarily provided. No other contextual information such as numeric base is affected
47011 MOV &LASTVOC,0(W) \ [BODY] = LASTVOC
47012 SUB #2,Y \ 1 Y = LFA
47013 MOV Y,2(W) \ 3 [BODY+2] = LFA = DP to be restored
47014 ADD #4,&DP \ 3 add 2 cells
47018 MOV @RSP+,IP \ -- PFA
47019 MOV @TOS+,&INIVOC \ set VOC_LINK value for RST_STATE
47020 MOV @TOS,&INIDP \ set DP value for RST_STATE
47022 MOV #RST_STATE,PC \ execute RST_STATE, PWR_STATE then STATE_DOES
47029 \ https://forth-standard.org/standard/core/Fetch
47030 \ @ c-addr -- char fetch char from memory
47037 [UNDEFINED] CONSTANT [IF]
47038 \ https://forth-standard.org/standard/core/CONSTANT
47039 \ CONSTANT <name> n -- define a Forth CONSTANT
47043 MOV TOS,-2(W) \ PFA = n
47050 [UNDEFINED] STATE [IF]
47051 \ https://forth-standard.org/standard/core/STATE
47052 \ STATE -- a-addr holds compiler state
47053 STATEADR CONSTANT STATE
47057 \ https://forth-standard.org/standard/core/Equal
47058 \ = x1 x2 -- flag test x1=x2
47065 XOR #-1,TOS \ 1 flag Z = 1
47070 [UNDEFINED] IF [IF]
47071 \ https://forth-standard.org/standard/core/IF
47072 \ IF -- IFadr initialize conditional forward branch
47073 CODE IF \ immediate
47076 MOV &DP,TOS \ -- HERE
47077 ADD #4,&DP \ compile one word, reserve one word
47078 MOV #QFBRAN,0(TOS) \ -- HERE compile QFBRAN
47079 ADD #2,TOS \ -- HERE+2=IFadr
47084 [UNDEFINED] THEN [IF]
47085 \ https://forth-standard.org/standard/core/THEN
47086 \ THEN IFadr -- resolve forward branch
47087 CODE THEN \ immediate
47088 MOV &DP,0(TOS) \ -- IFadr
47094 [UNDEFINED] ELSE [IF]
47095 \ https://forth-standard.org/standard/core/ELSE
47096 \ ELSE IFadr -- ELSEadr resolve forward IF branch, leave ELSEadr on stack
47097 CODE ELSE \ immediate
47098 ADD #4,&DP \ make room to compile two words
47099 MOV &DP,W \ W=HERE+4
47101 MOV W,0(TOS) \ HERE+4 ==> [IFadr]
47103 MOV W,TOS \ -- ELSEadr
47108 [UNDEFINED] DEFER [IF]
47109 \ https://forth-standard.org/standard/core/DEFER
47110 \ DEFER "<spaces>name" --
47111 \ Skip leading space delimiters. Parse name delimited by a space.
47112 \ Create a definition for name with the execution semantics defined below.
47114 \ name Execution: --
47115 \ Execute the xt that name is set to execute, i.e. NEXT (nothing),
47116 \ until the phrase ' word IS name is executed, causing a new value of xt to be assigned to name.
47120 MOV #$4030,-4(W) \ CFA = MOV @PC+,PC = BR MOV @IP+,PC
47121 MOV #NEXT_ADR,-2(W) \ PFA = address of MOV @IP+,PC to do nothing.
47127 [UNDEFINED] DEFER! [IF]
47128 \ https://forth-standard.org/standard/core/DEFERStore
47129 \ Set the word xt1 to execute xt2. An ambiguous condition exists if xt1 is not for a word defined by DEFER.
47130 CODE DEFER! \ xt2 xt1 --
47131 MOV @PSP+,2(TOS) \ -- xt1=CFA_DEFER xt2 --> [CFA_DEFER+2]
47137 [UNDEFINED] IS [IF]
47138 \ https://forth-standard.org/standard/core/IS
47141 \ DEFER DISPLAY create a "do nothing" definition (2 CELLS)
47142 \ inline command : ' U. IS DISPLAY U. becomes the runtime of the word DISPLAY
47143 \ or in a definition : ... ['] U. IS DISPLAY ...
47144 \ KEY, EMIT, CR, ACCEPT and WARM are examples of DEFERred words
47146 \ as IS replaces the PFA value of any word, it's a TO alias for VARIABLE and CONSTANT words...
47149 IF POSTPONE ['] POSTPONE DEFER!
47155 [UNDEFINED] >BODY [IF]
47156 \ https://forth-standard.org/standard/core/toBODY
47157 \ >BODY -- addr leave BODY of a CREATEd word\ also leave default ACTION-OF primary DEFERred word
47164 \ CODE 20uS \ n -- 8MHz version
47165 \ BEGIN \ 4 + 16 ~ loop
47166 \ MOV #39,rDOCON \ 39
47173 \ MOV #XDOCON,rDOCON \ 2
47178 CODE 20_US \ n -- n * 20 us
47179 BEGIN \ here we presume that LCD_TIM_IFG = 1...
47181 BIT #1,&LCD_TIM_CTL \ 3
47182 0<> UNTIL \ 2 loop until LCD_TIM_IFG set
47183 BIC #1,&LCD_TIM_CTL \ 3 clear LCD_TIM_IFG
47185 U< UNTIL \ 2 ...so add a dummy loop with U< instead of 0=
47190 CODE TOP_LCD \ LCD Sample
47191 \ \ if write : %xxxx_WWWW --
47192 \ \ if read : -- %0000_RRRR
47193 BIS.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 0-->1
47194 BIT.B #LCD_RW,&LCD_CMD_IN \ lcd_rw test
47195 0= IF \ write LCD bits pattern
47196 AND.B #LCD_DB,TOS \
47197 MOV.B TOS,&LCD_DB_OUT \ send LCD_Data
47198 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
47201 THEN \ read LCD bits pattern
47204 BIC.B #LCD_EN,&LCD_CMD_OUT \ lcd_en 1-->0 ==> strobe data
47205 MOV.B &LCD_DB_IN,TOS \ get LCD_Data
47206 AND.B #LCD_DB,TOS \
47210 CODE LCD_WRC \ char -- Write Char
47211 BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
47213 MOV TOS,0(PSP) \ -- %xxxx_LLLL %HHHH_LLLL
47214 RRUM #4,TOS \ -- %xxxx_LLLL %xxxx_HHHH
47215 BIC.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=0
47216 BIS.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as output
47217 COLON \ high level word starts here
47218 TOP_LCD 2 20_US \ write high nibble first
47222 CODE LCD_WRF \ func -- Write Fonction
47223 BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
47227 : LCD_CLEAR $01 LCD_WRF 100 20_us ; \ $01 LCD_WrF 80 20_us ==> bad init !
47228 : LCD_HOME $02 LCD_WRF 100 20_us ;
47230 \ [UNDEFINED] OR [IF]
47232 \ \ https://forth-standard.org/standard/core/OR
47233 \ \ C OR x1 x2 -- x3 logical OR
47241 \ : LCD_ENTRY_SET $04 OR LCD_WrF ;
47242 \ : LCD_DSP_CTRL $08 OR LCD_WrF ;
47243 \ : LCD_DSP_SHIFT $10 OR LCD_WrF ;
47244 \ : LCD_FN_SET $20 OR LCD_WrF ;
47245 \ : LCD_CGRAM_SET $40 OR LCD_WrF ;
47246 \ : LCD_GOTO $80 OR LCD_WrF ;
47249 \ CODE LCD_RDS \ -- status Read Status
47250 \ BIC.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=0
47251 \ BW1 BIC.B #LCD_DB,&LCD_DB_DIR \ LCD_Data as intput
47252 \ BIS.B #LCD_RW,&LCD_CMD_OUT \ lcd_rw=1
47253 \ COLON \ starts a FORTH word
47254 \ TOP_LCD 2 20_us \ -- %0000_HHHH
47255 \ TOP_LCD 2 20_us \ -- %0000_HHHH %0000_LLLL
47256 \ HI2LO \ switch from FORTH to assembler
47257 \ RLAM #4,0(PSP) \ -- %HHHH_0000 %0000_LLLL
47258 \ ADD.B @PSP+,TOS \ -- %HHHH_LLLL
47259 \ MOV @RSP+,IP \ restore IP saved by COLON
47263 \ CODE LCD_RDC \ -- char Read Char
47264 \ BIS.B #LCD_RS,&LCD_CMD_OUT \ lcd_rs=1
47269 \ ******************************\
47270 ASM WDT_INT \ Watchdog interrupt routine, warning : not FORTH executable !
47271 \ ******************************\
47272 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
47273 \ XOR.B #LED1,&LED1_OUT \ to visualise WDT
47274 BIT.B #SW2,&SW2_IN \ test switch S2
47275 0= IF \ case of switch S2 pressed
47276 CMP #19,&LCD_TIM_CCRn \ maxi Ton = 19/20 & VDD=3V6 ==> LCD_Vo = -1V4
47278 ADD #1,&LCD_TIM_CCRn \ action for switch S2 (P2.5) : 150 mV / increment
47281 BIT.B #SW1,&SW1_IN \ test switch S1 input
47282 0= IF \ case of Switch S1 pressed
47283 CMP #3,&LCD_TIM_CCRn \ mini Ton = 3/20 & VDD=3V6 ==> LCD_Vo = 0V
47285 SUB #1,&LCD_TIM_CCRn \ action for switch S1 (P2.6) : -150 mV / decrement
47289 BW1 \ from quit on truncated RC5 message, repeated RC5 command
47293 \ ******************************\
47294 ASM RC5_INT \ wake up on Px.RC5 change interrupt
47295 \ ******************************\
47296 \ IR_RC5 driver \ IP,S,T,W,X,Y registers are free for use
47297 \ ******************************\
47298 \ \ in : SR(9)=old Toggle bit memory (ADD on)
47299 \ \ SMclock = 8|16|24 MHz
47300 \ \ use : T,W,X,Y, RC5_TIM_ timer, RC5_TIM_R register
47301 \ \ out : X = 0 C6 C5 C4 C3 C2 C1 C0
47302 \ \ SR(9)=new Toggle bit memory (ADD on)
47303 \ ******************************\
47304 \ RC5_FirstStartBitHalfCycle: \
47305 \ ******************************\ division in RC5_TIM_CTL (SMCLK/1|SMCLK/1|SMCLK/2|SMCLK/4|SMCLK/8)
47306 ADD #2,RSP \ 1 smart and fast RETI with GIE=0
47307 \ FREQ_KHZ @ 8000 = [IF] \ 8 MHz ?
47308 \ MOV #0,&RC5_TIM_EX0 \ predivide by 1 in RC5_TIM_EX0 register, reset value
47310 FREQ_KHZ @ 16000 = [IF] \ 16 MHz ?
47311 MOV #1,&RC5_TIM_EX0 \ predivide by 2 in RC5_TIM_EX0 register
47313 FREQ_KHZ @ 24000 = [IF] \ 24 MHz ?
47314 MOV #2,&RC5_TIM_EX0 \ predivide by 3 in RC5_TIM_EX0 register
47316 MOV #1778,X \ RC5_Period * 1us
47317 MOV #14,W \ count of loop
47319 \ ******************************\
47320 \ RC5_HalfCycle \ <--- loop back ---+ with readjusted RC5_Period
47321 \ ******************************\ |
47322 MOV #%1011100100,&RC5_TIM_CTL \ (re)start timer_A | SMCLK/8 time interval,free running,clear RC5_TIM__IFG and RC5_TIM_R
47323 \ RC5_Compute_3/4_Period: \ |
47324 RRUM #1,X \ X=1/2 cycle |
47327 ADD X,Y \ Y=3/4 cycle
47328 BEGIN CMP Y,&RC5_TIM_R \ 3 wait 1/2 + 3/4 cycle = n+1/4 cycles
47330 \ ******************************\
47331 \ RC5_SampleOnFirstQuarter \ at n+1/4 cycles, we sample RC5_input, ST2/C6 bit first
47332 \ ******************************\
47333 BIT.B #RC5,&IR_IN \ C_flag = IR bit
47334 ADDC T,T \ C_flag <-- T(15):T(0) <-- C_flag
47335 MOV.B &IR_IN,&IR_IES \ preset Px_IES.y state for next IFG
47336 BIC.B #RC5,&IR_IFG \ clear Px_IFG.y after 4/4 cycle pin change
47337 SUB #1,W \ decrement count loop
47338 \ \ count = 13 ==> T = x x x x x x x x |x x x x x x x /C6
47339 \ \ count = 0 ==> T = x x /C6 Tg A4 A3 A2 A1|A0 C5 C4 C3 C2 C1 C0 1
47340 0<> WHILE \ ----> out of loop ----+
47341 ADD X,Y \ | Y = n+3/4 cycles = time out because n+1/2 cycles edge is always present
47343 MOV &RC5_TIM_R,X \ 3 | X grows from n+1/4 up to n+3/4 cycles
47344 CMP Y,X \ 1 | cycle time out of bound ?
47345 U>= IF \ 2 ^ | yes:
47346 BIC #$30,&RC5_TIM_CTL \ | | stop timer
47347 GOTO BW1 \ | | quit on truncated RC5 message
47349 BIT.B #RC5,&IR_IFG \ 3 | | n+1/2 cycles edge is always present
47351 REPEAT \ ----> loop back --+ | with X = new RC5_period value
47352 \ ******************************\ |
47353 \ RC5_SampleEndOf: \ <---------------------+
47354 \ ******************************\
47355 BIC #$30,&RC5_TIM_CTL \ stop timer
47356 \ ******************************\
47357 \ RC5_ComputeNewRC5word \
47358 \ ******************************\
47359 RLAM #1,T \ T = x /C6 Tg A4 A3 A2 A1 A0|C5 C4 C3 C2 C1 C0 1 0
47360 MOV.B T,X \ X = C5 C4 C3 C2 C1 C0 1 0
47361 RRUM #2,X \ X = 0 0 C5 C4 C3 C2 C1 C0
47362 \ ******************************\
47363 \ RC5_ComputeC6bit \
47364 \ ******************************\
47365 BIT #BIT14,T \ test /C6 bit in T
47366 0= IF BIS #BIT6,X \ set C6 bit in X
47367 THEN \ X = 0 C6 C5 C4 C3 C2 C1 C0
47368 \ ******************************\
47369 \ RC5_CommandByteIsDone \ -- BASE RC5_code
47370 \ ******************************\
47371 \ Only New_RC5_Command ADD_ON \ use SR(9) bit as toggle bit
47372 \ ******************************\
47373 RRUM #3,T \ new toggle bit = T(13) ==> T(10)
47374 XOR @RSP,T \ (new XOR old) Toggle bits
47375 BIT #UF10,T \ repeated RC5_command ?
47376 0= ?GOTO BW1 \ yes, RETI without UF10 change and without action !
47377 XOR #UF10,0(RSP) \ 5 toggle bit memory
47378 \ ******************************\
47379 \ Display IR_RC5 code \
47380 \ ******************************\
47381 SUB #8,PSP \ TOS -- x x x x TOS
47382 MOV TOS,6(PSP) \ -- Save_TOS x x x TOS
47383 MOV &BASEADR,4(PSP) \ -- Save_TOS Save_Base x x TOS
47384 MOV #$10,&BASEADR \ set hexadecimal base
47385 MOV X,0(PSP) \ -- Save_TOS Save_Base x RC5_code TOS convert number to ascii low word = RC5 byte
47386 MOV #0,TOS \ -- Save_TOS Save_Base x RC5_code 0 convert number to ascii high word = 0
47387 LO2HI \ switch from assembler to FORTH
47388 LCD_CLEAR \ set LCD cursor at home
47389 <# # #S #36 HOLD #> \ 32 bits conversion as "$xx"
47390 ['] LCD_WRC IS EMIT \ redirect EMIT to LCD
47391 TYPE \ -- Save_TOS Save_Base x adr cnt display "$xx" on LCD
47392 ['] EMIT >BODY IS EMIT \ -- Save_TOS Save_Base TOS restore EMIT
47393 HI2LO \ -- switch from FORTH to assembler
47394 MOV @PSP+,&BASEADR \ -- Save_TOS TOS restore current BASE
47395 MOV @PSP+,TOS \ -- TOS
47399 \ ******************************\
47401 \ ******************************\
47403 \ ... \ insert here your background task
47406 CALL &RXON \ comment this line to disable TERMINAL_INPUT
47408 \ ******************************\
47409 \ here start all interrupts \
47410 \ ******************************\
47411 \ here return all interrupts \
47412 \ ******************************\
47415 \ ******************************\
47417 \ ------------------------------\
47418 ASM SYS_OUT \ system OUT init, replaces WARM at the request of STOP.
47419 \ ------------------------------\
47420 \ ... \ init specific I/O sys as you want
47421 \ ... \ before executing default WARM
47422 MOV #WARM,X \ ['] WARM
47424 MOV X,PC \ EXECUTE (which activates IO and TERMINAL)
47426 \ ------------------------------\
47428 \ ------------------------------\
47429 CODE STOP \ stops multitasking, must to be used before downloading app
47430 \ ------------------------------\
47431 BW1 MOV #SLEEP,X \ the ASM word SLEEP is only visible in mode assembler.
47432 ADD #4,X \ X = BODY of SLEEP, X-2 = PFA of SLEEP
47433 MOV X,-2(X) \ restore the default background: SLEEP
47435 MOV #SYS_OUT,2(X) \ default WARM is replaced by JMJ_BOX SYS_OUT (ended by default WARM)
47436 BIC.B #RC5,&IR_IE \ clear RC5_Int
47437 BIC.B #RC5,&IR_IFG \ clear RC5_Int flag
47438 MOV #0,&LCD_TIM_CTL \ stop LCD_TIMER
47439 MOV #0,&WDT_TIM_CTL \ stop WDT_TIMER
47440 MOV #0,&WDT_TIM_CCTL0 \ clear CCIFG0 disable CCIE0
47441 CALL #INIT_VECT \ reset all vectors other than TERMINAL_int
47442 COLON \ restore default action of primary DEFERred word WARM (FORTH version)
47444 ." RC5toLCD is removed,"
47445 ." type START to restart"
47446 WARM \ performs reset to reset all interrupt vectors.
47448 \ ------------------------------\
47450 \ ------------------------------\
47451 CODE SYS_INIT \ this routine completes the init of system, i.e. FORTH + this app.
47452 \ ------------------------------\
47453 \ LCD_TIM_CTL = %0000 0010 1001 0100\$3C0
47454 \ - - \CNTL Counter lentgh \ 00 = 16 bits
47455 \ -- \TBSSEL TimerB clock select \ 10 = SMCLK
47456 \ -- \ID input divider \ 10 = /4
47457 \ -- \MC Mode Control \ 01 = up to LCD_TIM_CCR0
47458 \ - \TBCLR TimerB Clear
47461 \ -------------------------------\
47462 \ LCD_TIM_CCTLx = %0000 0000 0110 0000\$3C{2,4,6,8,A,C,E}
47463 \ -- \CM Capture Mode
47468 \ --- \OUTMOD \ 011 = set/reset
47474 \ -------------------------------\
47476 \ -------------------------------\
47478 \ ------------------------------\
47479 \ set LCD_TIM_ to make 50kHz PWM \ for LCD_Vo; works without interrupt
47480 \ ------------------------------\
47481 MOV #%10_1101_0100,&LCD_TIM_CTL \ SMCLK/8, up mode, clear timer, no int
47482 \ MOV #0,&LCD_TIM_EX0 \ predivide by 1 in LCD_TIM_EX0 register (8 MHZ)
47483 FREQ_KHZ @ 16000 = [IF] \ if 16 MHz
47484 MOV #1,&LCD_TIM_EX0 \ predivide by 2 in LCD_TIM_EX0 register (16 MHZ)
47486 FREQ_KHZ @ 24000 = [IF] \ if 24 MHz
47487 MOV #2,&LCD_TIM_EX0 \ predivide by 3 in LCD_TIM_EX0 register (24 MHZ)
47489 MOV #19,&LCD_TIM_CCR0 \ 19+1=20*1us=20us
47490 \ ------------------------------\
47491 \ set LCD_TIM_.2 to generate PWM for LCD_Vo
47492 \ ------------------------------\
47493 MOV #%0110_0000,&LCD_TIM_CCTLn \ output mode = set/reset \ clear CCIFG
47494 MOV #10,&LCD_TIM_CCRn \ contrast adjust : 10/20 ==> LCD_Vo = -0V6|+3V6 (Vcc=3V6)
47495 \ MOV #12,&LCD_TIM_CCRn \ contrast adjust : 12/20 ==> LCD_Vo = -1V4|+3V3 (Vcc=3V3)
47496 \ ------------------------------\
47497 BIS.B #LCDVo,&LCDVo_DIR \
47498 BIS.B #LCDVo,&LCDVo_SEL \ SEL.2
47499 \ ------------------------------\
47500 BIS.B #LCD_CMD,&LCD_CMD_DIR \ lcd_cmd as outputs
47501 BIC.B #LCD_CMD,&LCD_CMD_REN \ lcd_cmd pullup/down disable
47502 \ ------------------------------\
47503 BIS.B #LCD_DB,&LCD_DB_DIR \ as output, wired to DB(4-7) LCD_Data
47504 BIC.B #LCD_DB,&LCD_DB_REN \ LCD_Data pullup/down disable
47505 \ ******************************\
47507 \ ******************************\
47508 BIS.B #RC5,&IR_IE \ enable RC5_Int
47509 BIC.B #RC5,&IR_IFG \ reset RC5_Int flag
47510 MOV #RC5_INT,&IR_Vec \ init interrupt vector
47511 \ ******************************\
47512 \ init WatchDog WDT_TIM_ \ eUSCI_A0 (FORTH terminal) has higher priority than WDT_TIM_
47513 \ ******************************\
47514 \ %01 0001 0100 \ TAxCTL
47515 \ -- \ TASSEL CLK = ACLK = LFXT = 32768 Hz
47516 \ -- \ ID divided by 1
47517 \ -- \ MC MODE = up to TAxCCRn
47518 \ - \ TACLR clear timer count
47521 \ ------------------------------\
47522 MOV #%01_0001_0100,&WDT_TIM_CTL \ start WDT_TIM_, ACLK, up mode, disable int,
47523 \ ------------------------------\
47525 \ --- \ TAIDEX pre divisor
47526 \ ------------------------------\
47527 \ %0000 0000 0000 0101 \ TAxCCR0
47528 MOV ##3276,&WDT_TIM_CCR0 \ else init WDT_TIM_ for LFXT: 32768/20=1638 ==> 100ms
47529 \ ------------------------------\
47530 \ %0000 0000 0001 0000 \ TAxCCTL0
47531 \ - \ CAP capture/compare mode = compare
47534 MOV #%10000,&WDT_TIM_CCTL0 \ enable compare interrupt, clear CCIFG0
47535 \ ------------------------------\
47536 MOV #WDT_INT,&WDT_TIM_0_Vec \ for only CCIFG0 int, this interrupt clears automatically CCIFG0
47537 \ ------------------------------\
47538 \ define LPM mode for ACCEPT \
47539 \ ------------------------------\
47540 \ MOV #LPM4,&LPM_MODE \ with MSP430FR59xx
47541 \ MOV #LPM2,&LPM_MODE \ with MSP430FR57xx, terminal input don't work for LPMx > 2
47542 \ \ with MSP430FR2xxx, terminal input don't work for LPMx > 0 ; LPM0 is the default value
47543 \ ------------------------------\
47545 \ ------------------------------\
47546 BIC #1,&PM5CTL0 \ activate all previous I/O settings; if not activated, nothing works after reset !
47547 BIS.B #TERM_BUS,&TERM_SEL \ Configure pins TXD & RXD for TERM_UART use, otherwise no TERMINAL !
47548 \ ------------------------------\
47549 \ RESET events handling \ search "SYSRSTIV" in your MSP430FRxxxx datasheet
47550 \ ------------------------------\
47551 MOV &SAVE_SYSRSTIV,Y \ Y = SYSRSTIV register memory
47552 \ CMP #2,Y \ Power_ON event
47553 \ 0= ?GOTO BW1 \ uncomment if you want to loose application in this case...
47555 0= ?GOTO BW1 \ hardware RESET performs STOP. Should be mandatory...
47557 \ 0= ?GOTO BW1 \ COLD event performs STOP... uncomment if it's that you want.
47559 \ 0= ?GOTO BW1 \ fault event (violation memory protected areas) performs STOP
47561 \ U>= ?GOTO BW1 \ all other fault events + Deep Reset perform STOP
47562 \ ------------------------------\
47564 \ ------------------------------\
47566 \ ------------------------------\
47567 #1000 20_US \ 1- wait 20 ms
47568 %011 TOP_LCD \ 2- send DB5=DB4=1
47569 #205 20_US \ 3- wait 4,1 ms
47570 %011 TOP_LCD \ 4- send again DB5=DB4=1
47571 #5 20_US \ 5- wait 0,1 ms
47572 %011 TOP_LCD \ 6- send again again DB5=DB4=1
47573 #2 20_US \ wait 40 us = LCD cycle
47574 %010 TOP_LCD \ 7- send DB5=1 DB4=0
47575 #2 20_US \ wait 40 us = LCD cycle
47576 %00101000 LCD_WRF \ 8- %001DNFxx "FonctionSet" D=8/4 DataBus width, Number of lines=2/1, Font bold/normal
47577 %1000 LCD_WRF \ 9- %1DCB "DisplayControl" : Display off, Cursor off, Blink off.
47578 LCD_CLEAR \ 10- "LCD_Clear"
47579 %0110 LCD_WRF \ 11- %01xx "LCD_EntrySet" : address and cursor shift after writing in RAM
47580 %1100 LCD_WRF \ 12- %1DCB "DisplayControl" : Display on, Cursor off, Blink off.
47581 LCD_CLEAR \ 10- "LCD_Clear"
47582 ['] LCD_HOME IS CR \ ' CR redirected to LCD_HOME
47583 ['] LCD_WRC IS EMIT \ ' EMIT redirected to LCD_WrC
47584 CR ." I love you" \ display message on LCD
47585 ['] CR >BODY IS CR \ CR executes its default value
47586 ['] EMIT >BODY IS EMIT \ EMIT executes its defaulte value
47587 ." RC5toLCD is running. Type STOP to quit" \ display message on FastForth Terminal
47588 PWR_STATE ABORT \ init DP and continues with ABORT
47590 \ ------------------------------\
47592 \ ------------------------------\
47593 CODE START \ this routine replaces WARM and SLEEP default values by these of this application.
47594 \ ------------------------------\
47595 MOV #SLEEP,X \ replace default background process SLEEP
47596 MOV #BACKGROUND,2(X) \ by RC5toLCD BACKGROUND
47597 MOV #WARM,X \ replace default WARM
47598 MOV #SYS_INIT,2(X) \ by RC5toLCD SYS_INIT
47599 MOV X,PC \ then execute new WARM
47601 \ ------------------------------\
47604 ; downloading RC5toLCD.4th is done
47605 RST_HERE ; this app is protected against <reset>